I have the following function to make a “padding” for an input image:
-
Create a canvas with extra padding.
-
Fill the whole canvas with
whitecolor (it must not be transparent). -
Draw the image at the Padding. The problem happens no matter if I specify the width or height in
drawImagecall 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
dataUrlis obtained through anothercanvas.toDataURL()because I captured it from avideoelement). When debugging and replacedataUrlinput with another image, I cannot reproduce the issue. -
Adding another
fillRectcall to fill in the bottom works:
ctx.fillRect(
0, canvas.height - paddingH,
canvas.width, paddingH);
Still I don’t understand why it’s happening.
