getImageData() 没有 return 正确的 RGB 值(显示 P3 图像)
getImageData() does not return correct RGB values (Display P3 image)
我编写了一个从图像中提取像素颜色的网站。我通过使用 getImageData on a canvas holding the image. However, I do not manage to get the correct values for this sample image.
来做到这一点
使用Pillow提取时,比如第一个像素颜色(x=0,y=0)它returns(49,97,172,255)为RGBA颜色space.
from PIL import Image
im = Image.open('image.png').convert('RGBA')
pix = im.load()
print(pix[0, 0])
另外 Java 给了我相同的结果:
BufferedImage bufferedImage = ImageIO.read(new File("image.png"));
int rawRGB = bufferedImage.getRGB(0, 0);
Color color = new Color(rawRGB);
但是,当我使用 HTML canvas 时,我通过 getImageData 获得以下值:(27,98,178,255).
let image = new Image();
const reader = new FileReader();
image.addEventListener('load', function () {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0, 0);
let data = ctx.getImageData(0, 0, 1, 1).data;
document.getElementById('imageData').innerHTML = data;
});
image.addEventListener('load', function () {
let canvas = document.createElement('canvas');
let gl = canvas.getContext("webgl2");
gl.activeTexture(gl.TEXTURE0);
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this);
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
let data = new Uint8Array(1 * 1 * 4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data);
document.getElementById('webGl').innerHTML = data;
});
reader.addEventListener('load', (event) => {
image.src = event.target.result;
});
var fileToRead = document.getElementById("yourFile");
fileToRead.addEventListener("change", function (event) {
var files = fileToRead.files;
if (files.length) {
reader.readAsDataURL(event.target.files[0]);
}
}, false);
<pre>Expected: 49,97,172,255<br>
ImageData: <span id="imageData"></span><br>
WebGL: <span id="webGl"></span><br></pre>
<input type="file" id="yourFile" name="file">
我不明白为什么会这样,也不明白浏览器是如何得出这些值的。我试过 Chrome 和 Firefox,它们都显示了相同的错误值。我读过 但我不知道这会对我的结果产生怎样的影响,因为图片没有使用 alpha 通道。如有任何帮助,我们将不胜感激!
这是因为此图像的颜色配置文件设置为 P3,而 webGL 和 2D 上下文的默认颜色-space 是 sRGB,这意味着它们会转换图像的颜色。
现在有个好消息,canvas 2D API 最近扩展到支持 P3 颜色-space,这是最新的 Chrome和 Safari 浏览器(Firefox 和 WebGL 应该会很快跟进)。
要享受此功能,您需要使用 colorSpace: "display-p3"
选项创建您的上下文:
const input = document.querySelector("input");
input.oninput = async(evt) => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d", {
colorSpace: "display-p3"
});
if (!(ctx.getContextAttributes?.().colorSpace === "display-p3")) {
console.warn("your browser doesn't support the colorSpace setting");
}
const image = new Image();
image.src = URL.createObjectURL(input.files[0]);
await image.decode();
// not resizing the canvas to save memory since we're only interested in top-left pixel
ctx.drawImage(image, 0, 0);
const { data } = ctx.getImageData(0, 0, 1, 1);
console.log(data);
};
<input type="file">
我编写了一个从图像中提取像素颜色的网站。我通过使用 getImageData on a canvas holding the image. However, I do not manage to get the correct values for this sample image.
来做到这一点使用Pillow提取时,比如第一个像素颜色(x=0,y=0)它returns(49,97,172,255)为RGBA颜色space.
from PIL import Image
im = Image.open('image.png').convert('RGBA')
pix = im.load()
print(pix[0, 0])
另外 Java 给了我相同的结果:
BufferedImage bufferedImage = ImageIO.read(new File("image.png"));
int rawRGB = bufferedImage.getRGB(0, 0);
Color color = new Color(rawRGB);
但是,当我使用 HTML canvas 时,我通过 getImageData 获得以下值:(27,98,178,255).
let image = new Image();
const reader = new FileReader();
image.addEventListener('load', function () {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0, 0);
let data = ctx.getImageData(0, 0, 1, 1).data;
document.getElementById('imageData').innerHTML = data;
});
image.addEventListener('load', function () {
let canvas = document.createElement('canvas');
let gl = canvas.getContext("webgl2");
gl.activeTexture(gl.TEXTURE0);
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this);
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
let data = new Uint8Array(1 * 1 * 4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data);
document.getElementById('webGl').innerHTML = data;
});
reader.addEventListener('load', (event) => {
image.src = event.target.result;
});
var fileToRead = document.getElementById("yourFile");
fileToRead.addEventListener("change", function (event) {
var files = fileToRead.files;
if (files.length) {
reader.readAsDataURL(event.target.files[0]);
}
}, false);
<pre>Expected: 49,97,172,255<br>
ImageData: <span id="imageData"></span><br>
WebGL: <span id="webGl"></span><br></pre>
<input type="file" id="yourFile" name="file">
我不明白为什么会这样,也不明白浏览器是如何得出这些值的。我试过 Chrome 和 Firefox,它们都显示了相同的错误值。我读过
这是因为此图像的颜色配置文件设置为 P3,而 webGL 和 2D 上下文的默认颜色-space 是 sRGB,这意味着它们会转换图像的颜色。
现在有个好消息,canvas 2D API 最近扩展到支持 P3 颜色-space,这是最新的 Chrome和 Safari 浏览器(Firefox 和 WebGL 应该会很快跟进)。
要享受此功能,您需要使用 colorSpace: "display-p3"
选项创建您的上下文:
const input = document.querySelector("input");
input.oninput = async(evt) => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d", {
colorSpace: "display-p3"
});
if (!(ctx.getContextAttributes?.().colorSpace === "display-p3")) {
console.warn("your browser doesn't support the colorSpace setting");
}
const image = new Image();
image.src = URL.createObjectURL(input.files[0]);
await image.decode();
// not resizing the canvas to save memory since we're only interested in top-left pixel
ctx.drawImage(image, 0, 0);
const { data } = ctx.getImageData(0, 0, 1, 1);
console.log(data);
};
<input type="file">