vin*_*000 71 javascript html5 canvas getimagedata
是否可以在鼠标下方获取RGB值像素?有一个完整的例子吗?这是我到目前为止所拥有的:
<script>
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'Your URL';
img.onload = function(){
ctx.drawImage(img,0,0);
};
canvas.onmousemove = function(e) {
var mouseX, mouseY;
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
var c = ctx.getImageData(mouseX, mouseY, 1, 1).data;
$('#ttip').css({'left':mouseX+20, 'top':mouseY+20}).html(c[0]+'-'+c[1]+'-'+c[2]);
};
}
</script>
Run Code Online (Sandbox Code Playgroud)
Way*_*ett 138
这是一个完整的,独立的例子.首先,使用以下HTML:
<canvas id="example" width="200" height="60"></canvas>
<div id="status"></div>
Run Code Online (Sandbox Code Playgroud)
相关的JavaScript:
// set up some sample squares
var example = document.getElementById('example');
var context = example.getContext('2d');
context.fillStyle = "rgb(255,0,0)";
context.fillRect(0, 0, 50, 50);
context.fillStyle = "rgb(0,0,255)";
context.fillRect(55, 0, 50, 50);
$('#example').mousemove(function(e) {
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
var coord = "x=" + x + ", y=" + y;
var c = this.getContext('2d');
var p = c.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
$('#status').html(coord + "<br>" + hex);
});
Run Code Online (Sandbox Code Playgroud)
上面的代码假定存在jQuery和以下实用程序函数:
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
return undefined;
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
Run Code Online (Sandbox Code Playgroud)
在JSFIDDLE上查看它的实际操作:
Dan*_*ger 16
如果您需要获取矩形区域的平均颜色,而不是单个像素的颜色,请看一下另一个问题:
\n\n无论如何,两者都是以非常相似的方式完成的:
\n要获取单个像素的颜色,您首先需要将该图像绘制到画布上,您已经完成了此操作:
\nconst image = document.getElementById(\'image\');\nconst canvas = document.createElement(\'canvas\');\nconst context = canvas.getContext(\'2d\');\nconst width = image.width;\nconst height = image.height;\n\ncanvas.width = width;\ncanvas.height = height;\n\ncontext.drawImage(image, 0, 0, width, height);\nRun Code Online (Sandbox Code Playgroud)\n然后获取单个像素的值,如下所示:
\nconst data = context.getImageData(X, Y, 1, 1).data;\n\n// RED = data[0]\n// GREEN = data[1]\n// BLUE = data[2]\n// ALPHA = data[3]\nRun Code Online (Sandbox Code Playgroud)\n您需要使用相同的CanvasRenderingContext2D.getImageData()来获取整个图像的值,您可以通过更改其第三个和第四个参数来实现。该函数的签名是:
\nImageData ctx.getImageData(sx, sy, sw, sh);\nRun Code Online (Sandbox Code Playgroud)\nsx:从中提取 ImageData 的矩形左上角的 x 坐标。sy:从中提取 ImageData 的矩形左上角的 y 坐标。sw:将从中提取图像数据的矩形的宽度。sh:将从中提取 ImageData 的矩形的高度。您可以看到它返回一个ImageData对象,无论它是什么。这里重要的部分是该对象有一个.data包含我们所有像素值的属性。
但是,请注意,.data属性是一维的Uint8ClampedArray,这意味着所有像素的组件都已被展平,因此您将得到如下所示的内容:
假设您有一个如下所示的 2x2 图像:
\n RED PIXEL | GREEN PIXEL\nBLUE PIXEL | TRANSPARENT PIXEL\nRun Code Online (Sandbox Code Playgroud)\n然后,你会像这样得到它们:
\n[ 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0 ]\n| RED PIXEL | GREEN PIXEL | BLUE PIXEL | TRANSPAERENT PIXEL |\n| 1ST PIXEL | 2ND PIXEL | 3RD PIXEL | 4TH PIXEL | \nRun Code Online (Sandbox Code Playgroud)\n由于调用getImageData是一个缓慢的操作,您只需调用一次即可获取所有图像的数据(sw=图像宽度,sh=图像高度)。
然后,在上面的示例中,如果您想访问 的组件TRANSPARENT PIXEL,即该假想x = 1, y = 1图像位置处的组件,您将i在其ImageData\'sdata属性中找到它的第一个索引,如下所示:
const i = (y * imageData.width + x) * 4;\nRun Code Online (Sandbox Code Playgroud)\nconst image = document.getElementById(\'image\');\nconst canvas = document.createElement(\'canvas\');\nconst context = canvas.getContext(\'2d\');\nconst width = image.width;\nconst height = image.height;\n\ncanvas.width = width;\ncanvas.height = height;\n\ncontext.drawImage(image, 0, 0, width, height);\nRun Code Online (Sandbox Code Playgroud)\r\nconst data = context.getImageData(X, Y, 1, 1).data;\n\n// RED = data[0]\n// GREEN = data[1]\n// BLUE = data[2]\n// ALPHA = data[3]\nRun Code Online (Sandbox Code Playgroud)\r\nImageData ctx.getImageData(sx, sy, sw, sh);\nRun Code Online (Sandbox Code Playgroud)\r\n\xe2\x9a\xa0\xef\xb8\x8f 注意,我使用小数据 URI 来避免Cross-Origin在包含外部图像时出现问题,或者在尝试使用较长的数据 URI 时避免出现大于允许值的答案。
如果将光标移动到星号形状的边界周围,您有时会看到avgSolidColor红色,但您正在采样的像素看起来是白色的。这是因为即使R该像素的分量可能较高,但 Alpha 通道较低,因此颜色实际上是几乎透明的红色阴影,但avgSolidColor忽略了这一点。
另一方面,avgAlphaColor看起来粉红色。嗯,这实际上不是真的,它只是看起来粉红色的,因为我们现在使用 Alpha 通道,这使得它半透明,并允许我们看到页面的背景,在本例中是白色的。
那么,我们能做些什么来解决这个问题呢?好吧,事实证明我们只需要使用 alpha 通道及其倒数作为权重来计算新样本的分量,在本例中将其与白色合并,因为这是我们用作背景的颜色。
\n这意味着如果像素为R, G, B, A,其中A位于区间 中[0, 1],我们将计算 alpha 通道的倒数 ,iA以及加权样本的分量如下:
const iA = 1 - A;\nconst wR = (R * A + 255 * iA) | 0;\nconst wG = (G * A + 255 * iA) | 0;\nconst wB = (B * A + 255 * iA) | 0;\nRun Code Online (Sandbox Code Playgroud)\n请注意像素越透明(A接近 0),颜色越浅。
我知道这是一个老问题,但这里有另一种选择.我将图像数据存储在一个数组中,然后,在画布上的鼠标移动事件中:
var index = (Math.floor(y) * canvasWidth + Math.floor(x)) * 4
var r = data[index]
var g = data[index + 1]
var b = data[index + 2]
var a = data[index + 3]
Run Code Online (Sandbox Code Playgroud)
比每次获取imageData容易得多.
合并StackOverflow中的各种引用(包括上面的文章)和其他站点,我使用javascript和JQuery:
<html>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script src="jquery.js"></script>
<script type="text/javascript">
window.onload = function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var img = new Image();
img.src = 'photo_apple.jpg';
context.drawImage(img, 0, 0);
};
function findPos(obj){
var current_left = 0, current_top = 0;
if (obj.offsetParent){
do{
current_left += obj.offsetLeft;
current_top += obj.offsetTop;
}while(obj = obj.offsetParent);
return {x: current_left, y: current_top};
}
return undefined;
}
function rgbToHex(r, g, b){
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
$('#myCanvas').click(function(e){
var position = findPos(this);
var x = e.pageX - position.x;
var y = e.pageY - position.y;
var coordinate = "x=" + x + ", y=" + y;
var canvas = this.getContext('2d');
var p = canvas.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
alert("HEX: " + hex);
});
</script>
<img src="photo_apple.jpg"/>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
这是我的完整解决方案.在这里我只使用了画布和一个图像,但是如果你需要<map>在图像上使用它,它也是可能的.
每次调用 getImageData 都会减慢进程...为了加快速度,我建议存储图像数据,然后您可以轻松快速地获取 pix 值,因此请执行以下操作以获得更好的性能
// keep it global
let imgData = false; // initially no image data we have
// create some function block
if(imgData === false){
// fetch once canvas data
var ctx = canvas.getContext("2d");
imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
}
// Prepare your X Y coordinates which you will be fetching from your mouse loc
let x = 100; //
let y = 100;
// locate index of current pixel
let index = (y * imgData.width + x) * 4;
let red = imgData.data[index];
let green = imgData.data[index+1];
let blue = imgData.data[index+2];
let alpha = imgData.data[index+3];
// Output
console.log('pix x ' + x +' y '+y+ ' index '+index +' COLOR '+red+','+green+','+blue+','+alpha);
Run Code Online (Sandbox Code Playgroud)