Automattic / Automattic/node-canvas
Rendering errors when drawImage width or height exceeds 32766
- Dominant language
- JavaScript
- Stars
- 10.7k
- Forks
- 1.2k
- Avg merge
- 4d 8h
- Merged PRs (30d)
- 1
Description
## Issue
I tracked down a user issue in a software of mine where node-canvas did not draw anything while a standard browser Canvas implementation had no problem rendering the same scene. It was a large scene but I was able to track it down to a single drawImage call with a width larger than 32768. The canvas itself is pretty small but the intention of the user was to scale up the image drawn to it to only see a small part in the middle of it, so this resulted in a transformation matrix with scale factor 20 which together with the canvas size and the image size resulted in an actual image width of >=32768.
I simplified the example code so there isn't even a transformation taking place. Just a drawImage with a large width. The same happens when using a small width but using a scale transformation.
## Steps to Reproduce
```js
import { writeFile } from "node:fs/promises";
import { createCanvas, loadImage } from "canvas";
// Image of a green pixel. Loaded from data URL for convenience of this demo.
// Content doesn't matter, can even be a large JPEG file, same result
const green = await loadImage("data:image/gif;base64,R0lGODdhAQABAIABAAD/AP///ywAAAAAAQABAAACAkQBADs=");
// Create 100x100 Canvas and fill it with red color (So when result is red, there is something going wrong)
const canvas = createCanvas(100, 100);
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(0, 0, 100, 100);
// The stretch width of the drawn image:
// With width 32766 everything is rendered correctly
// With width 32767 the drawImage doesn't draw the image anymore
// With width 32768 even stuff after the drawImage is not rendered anymore. The canvas is dead.
const width = 32768;
// Stretch green pixel image over the canvas
ctx.drawImage(green, 0, 0, width, 100);
// Draw a black cross. Will not be rendered when previous image width is larger than 32767
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.moveTo(0, 100);
ctx.lineTo(100, 0);
ctx.lineWidth = 3;
ctx.strokeStyle = "#000";
ctx.stroke();
await writeFile("/tmp/out.png", canvas.toBuffer("image/png"));
```
The expected result is always this (And node-canvas renders it correctly with `width` variable set up to 32766:

With `width` variable set to 32767 the result is this instead (drawImage does nothing):

With `width` variable set to 32768 or higher the result is this (Nothing is rendered at all anymore):

The number 32768 suggests that it has something to do with a signed 16 bit integer data type somewhere in the code which should be 32/64 bit integer or even a float/double maybe?
## Your Environment
* Node Canvas v2.11.0 (Also tried older v2.10 and master branch)
* Node v18.14.0
* Debian Linux 11
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.