Reputation: 5319
I found that getImageData
of an HTML canvas seems to return incorrect byte values.
I generated a 1x1 px image with the following Python code:
from PIL import Image
import numpy as np
a = np.array([[[12, 187, 146, 62]]], dtype=np.uint8)
Image.fromarray(a).save('image.png')
I converted the image to base64 to include it in this code snippet:
let image = document.createElement('img');
image.addEventListener('load', () => {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
let data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
document.body.innerHTML = data;
});
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGPg2T3JDgADyAGYmiSbAQAAAABJRU5ErkJggg==";
When run in Firefox, it shows 12,189,148,62
. In Chromium it shows 12,185,144,62
. But the original values are 12,187,146,62
.
Can anyone explain this?
Upvotes: 4
Views: 328
Reputation: 54026
I can confirm that FF (Firefox) does indeed return the pixel value as [12,189,148,62]
When rendering to the canvas pixels are processed according to the value of globalCompositeOperation
which defaults to "source-over"
. The calculation is performed on pre multiplied alpha values for which FF seams to be rounding incorrectly.
Note that turning off alpha canvas.getContext("2d", {alpha: false})
for CanvasRenderingContext2D the resulting pixels are FF [3,46,36,255]
and Chrome [3,45,35,255]
.
Chrome has the correct values as shown in the following snippet.
// correct pre mult alpha
console.log([12,187,146].map(c => Math.round(c * 62 / 255)) + "");
FF is rounding up for some reason and I would consider this a bug
This rounding error (in FF) is then effecting the result of "source-over"
compositing when alpha: true
resulting in the higher than expected values.
For more information on compositing W3C Compositing and Blending
I can not suggest a fix, only to say that Chrome is rendering the image correctly, while FF is not.
Upvotes: 1