react-native-canvas icon indicating copy to clipboard operation
react-native-canvas copied to clipboard

PutImageData draws only part of the image

Open felixkhulis opened this issue 6 years ago • 7 comments

hi, when i use getImageData manipulate pixels and then putImageData the result that is that a smaller version of the image is drawn even though i want to the entire canvas.

you can reproduce this in your example file where the purple rectangle is not covered completely by a black one. example code:

handleImageData(canvas) { canvas.width = 100; canvas.height = 100;

const context = canvas.getContext('2d');
context.fillStyle = 'purple';
context.fillRect(0, 0, 100, 100);

context.getImageData(0, 0, 100, 100).then(imageData => {
  const data = Object.values(imageData.data);
  const length = Object.keys(data).length;
  for (let i = 0; i < length; i += 4) {
    data[i] = 0;
    data[i + 1] = 0;
    data[i + 2] = 0;
  }
  const imgData = new ImageData(canvas, data, 100, 100);
  context.putImageData(imgData, 0, 0);
});

}

to my understanding this should cover the original purple rectangle with a black one since you change all the pixels to black. Note: that this code works as expected on web. actual result expected result

felixkhulis avatar Nov 06 '19 19:11 felixkhulis

first image is actual result which doesn't cover the entire purple rectangle second image is the correct behaviour and expected result of the above code

felixkhulis avatar Nov 06 '19 19:11 felixkhulis

I am having the same issue as well. Was this ever resolved? image

jorgem0 avatar Jul 03 '20 03:07 jorgem0

After looking at this closer, it seems that getImageData is only getting 1/9th of the data (the top left corner). This issue was resolved by multiplying the canvas.width and canvas.height by 3.

context.getImageData(0, 0, 3*canvas.width, 3*canvas.height).then(async imageData => {...

const imgData = await new ImageData(canvas, data, Math.ceil(3*canvas.width), Math.ceil(3*canvas.height));

image

jorgem0 avatar Jul 03 '20 04:07 jorgem0

I'm guessing the bug has to do with the code for fixing the resolution of the canvas to match the resolution factor of the device. PRs are welcome

iddan avatar Jul 05 '20 21:07 iddan

+1

FarazzShaikh avatar Jul 06 '20 18:07 FarazzShaikh

However, when I try it on the Android simulator, it does not capture the full image. The fix above was on iPhone 11 Pro Max (it also works on the iPad simulator) but when I switch over to Pixel 3 XL, I get the image below. However, it works fine on Pixel 3. Any ideas on how to make it work for all devices? Would I need to know the resolution of the canvas to the resolution factor of the device?

image

jorgem0 avatar Jul 11 '20 23:07 jorgem0

Edit-Edit: Okay, seemed to have figured it out. Just used PixelRatio.get() instead. It just so happens that for iPhones the PixelRatio is 3 which is why the original comment of x3 was working. https://reactnative.dev/docs/pixelratio

context.getImageData(0, 0, Math.ceil(PixelRatio.get() * canvas.width), Math.ceil(PixelRatio.get() * canvas.height)).then(async imageData => {...

const imgData = await new ImageData(canvas, data, Math.ceil(PixelRatio.get() * canvas.width), Math.ceil(PixelRatio.get() * canvas.height))

image

jorgem0 avatar Jul 12 '20 01:07 jorgem0