I have the following function to make a “padding” for an input image:
-
Create a canvas with extra padding.
-
Fill the whole canvas with
white
color (it must not be transparent). -
Draw the image at the Padding. The problem happens no matter if I specify the width or height in
drawImage
call or not.
const Padding = 0.2;
// ...
async #padInput(dataUrl: string): Promise<string> {
const img = await new Promise<HTMLImageElement>((r, rej) => {
const img = new Image();
img.onload = () => r(img);
img.onerror = rej;
img.src = dataUrl;
});
const canvas = document.createElement("canvas");
canvas.width = Math.ceil(img.naturalWidth * (1 + Padding * 2));
canvas.height = Math.ceil(img.naturalHeight * (1 + Padding * 2));
const ctx = canvas.getContext("2d")!;
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(
img,
Math.ceil(img.naturalWidth * Padding),
Math.ceil(img.naturalHeight * Padding),
img.naturalWidth,
img.naturalHeight,
);
return canvas.toDataURL();
}
Strangely enough, the output image is like this (copied into a image editor so you can see the transparent part clearly):
I set some breakpoint and the canvas
size is correct, after fillRect
the whole canvas is correctly filled with white
but right after drawImage
is called, the bottom becomes transparent.
What may cause this problem?
Additional info:
-
It may be caused by data obtained from another canvas (the input
dataUrl
is obtained through anothercanvas.toDataURL()
because I captured it from avideo
element). When debugging and replacedataUrl
input with another image, I cannot reproduce the issue. -
Adding another
fillRect
call to fill in the bottom works:
ctx.fillRect(
0, canvas.height - paddingH,
canvas.width, paddingH);
Still I don’t understand why it’s happening.