Brooooooklyn / canvas

High performance skia binding to Node.js. Zero system dependencies and pure npm packages without any postinstall scripts nor node-gyp.
https://vercel.skia.rs
MIT License
1.78k stars 76 forks source link

SKRSContext2D.drawImage() method does nothing in 0.1.55 when first argument is an Image #891

Closed gomander closed 2 months ago

gomander commented 2 months ago

Hi, it's me again (sorry). After upgrading to 0.1.55, I'm still getting the same blank result from my test image code as 0.1.54, though for different reasons. It seems that the .drawImage() method on SKRSContext2D works fine when provided a Canvas, but doesn't work when passed an Image.

Again, it's possible that I'm doing something wrong, but here's the result of my testing:

  const canvas = createCanvas(4, 4)
  const context = canvas.getContext('2d')
  const image = new Image()
  image.src = Buffer.from('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA1SURBVBhXY/j//z8DAwMQ/88C0Yo+/xm2/Wf4fwPEmQCUZZjyn0ENKMCQ95/hziaG/x4M/wFfsBfivq1KhgAAAABJRU5ErkJggg==')
  image.onload = () => {
    console.log('Image loaded', image.width, image.height, image.src) // src is correct now

    const initialBuffer = canvas.toBuffer('image/png')
    console.log('Initial buffer size:', initialBuffer.byteLength) // blank canvas is 98 bytes

    context.drawImage(image, 0, 0)

    const contextImageData = context.getImageData(0, 0, canvas.width, canvas.height)
    console.log('Image data:', contextImageData.data) // Uint8ClampedArray(64) [0, 0, 0...]
    // I think this shows that the image is not drawn to the canvas

    const buffer = canvas.toBuffer('image/png')
    console.log('Final buffer size:', buffer.byteLength) // still 98 bytes
    // in 0.1.53, the resulting buffer is 144 bytes and the image is correct
    // in 0.1.55, the image is blank
  }
rambo-panda commented 2 months ago

I have the same issue, I suspect the issue lies in the asynchronous retrieval of values in drawImage during this modification https://github.com/Brooooooklyn/canvas/pull/872.

the following are the verification steps

 image.onload = () => {
+  setTimeout(() => {
     console.log("Image loaded", image.width, image.height, image.src); // src is correct now

     const initialBuffer = canvas.toBuffer("image/png");
@@ -27,4 +28,5 @@ image.onload = () => {
     console.log("Final buffer size:", buffer.byteLength); //  114bytes
+  }, 0);
 };

or you can do this

await new Promise(r => image.onload = r);
// do something 
rambo-panda commented 2 months ago

I have the same issue, I suspect the issue lies in the asynchronous retrieval of values in drawImage during this modification #872.

the following are the verification steps

 image.onload = () => {
+  setTimeout(() => {
     console.log("Image loaded", image.width, image.height, image.src); // src is correct now

     const initialBuffer = canvas.toBuffer("image/png");
@@ -27,4 +28,5 @@ image.onload = () => {
     console.log("Final buffer size:", buffer.byteLength); //  114bytes
+  }, 0);
 };

or you can do this

await new Promise(r => image.onload = r);
// do something 

https://github.com/Brooooooklyn/canvas/blob/8ca3a9e55d583aa437996a18e3432ceabd477967/src/image.rs#L431-L437 the onloafd before the bitmap Assignment Operation

gomander commented 2 months ago

I have the same issue, I suspect the issue lies in the asynchronous retrieval of values in drawImage during this modification #872.

the following are the verification steps

 image.onload = () => {
+  setTimeout(() => {
     console.log("Image loaded", image.width, image.height, image.src); // src is correct now

     const initialBuffer = canvas.toBuffer("image/png");
@@ -27,4 +28,5 @@ image.onload = () => {
     console.log("Final buffer size:", buffer.byteLength); //  114bytes
+  }, 0);
 };

or you can do this

await new Promise(r => image.onload = r);
// do something 

Just got to test this out for myself, works great! The latter solution is especially neat. Thanks for the tip!

twlite commented 2 months ago

does this work with const image = await loadImage(src)?

gomander commented 2 months ago

does this work with const image = await loadImage(src)?

It does! This simplifies things a fair bit, so thank you.