如何将图像转换为像素,对其进行编辑,并在Javascript中绘制编辑后的图像



我是JS的新手,我想学习如何执行以下操作:

获取图像数据(将其转换为像素数组,以便我可以对其进行编辑(,然后从像素编辑函数返回编辑后的数组,以便我可以使用这些编辑的值来绘制编辑后的图像。

我什至不确定这是否是解决这个问题的方法,但这是我到目前为止得到的:

var img = new Image();
img.src = 'img.png';
var canvas = document.getElementById('canvas');
var canvasEdited =  document.getElementById('canvasEdited');
var ctx = canvas.getContext('2d');
var arr = [];
img.onload = function() {
ctx.drawImage(img, 0, 0);
function editPixels(ctx) {
for (i of ctx) {
// edit pixels values 
arr.push(i - 10);    
}
}
console.log(arr);
function drawEditedImage() {
var ctxEdited = canvasEdited.getContext('2d');
ctxEdited.drawImage(img, 0, 0);
}
};

控制台输出显示一个带有length:0的数组。

为什么它不将编辑过的像素推送到arr

我没有其他人那么快,但我还是决定发布我的答案,因为它仍然有一些附加值(分解、base64、受污染的画布提及......

我假设您想通过画布更改图像的像素数据。

首先,将图像渲染到画布。你已经做对了:

var canvasEdited =  document.getElementById('canvasEdited');
var ctxEdited = canvasEdited.getContext('2d');
ctxEdited.drawImage(img, 0, 0, canvasEdited.width, canvasEdited.height);

然后,取出像素数据:

var imageData = ctxEdited.getImageData(0, 0, canvasEdited.width, canvasEdited.height);
// you will get an array of pixel data
// this array consists of rgba values
// each 'set' of four stands for red, green, blue and alpha

然后,对它执行一些操作,在此示例中将其变为灰色:

for(var i = 0; i < imageData.length; i += 4) {
var brightness = 0.34 * imageData[i] + 0.5 * imageData[i + 1] + 0.16 * imageData[i + 2];
imageData[i] = brightness;
imageData[i + 1] = brightness;
imageData[i + 2] = brightness;
}

然后,将更改的像素数据绘制回画布上:

ctxEdited.putImageData(imageData, 0, 0);

如果您想在画布之外重复使用该图像,可以像这样将其转换为 base64M

var base64URI = canvasEdited.toDataURL();

然后,可以将该数据设置为元素的源,如下所示:

img.src = base64URI;

注意事项:

  • 您必须通过本地主机或Web服务器打开页面,否则浏览器将阻止它。(除非您设置了正确的标志(

  • 您无法从受污染的画布中获取像素数据。当您绘制未指定 crossOrigin 的图像时,会发生这种情况。在 https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image 阅读更多相关信息

有很多问题需要解决。如果要从画布获取图像数据,则图像需要位于同一域中。更容易修复的是 base64 格式。不是网址。因此,将您的图像转换为 base64 字符串。

您不会在任何地方调用编辑像素,即使您在某个地方调用它并且没有在问题中提及,请形成您的论点,清楚地表明您正在传递上下文而不是图像数据。

使用 getImageData 和 putImageData 在画布中获取和设置数据。

需要更改 For 循环,以便不会在 alpha 数据上设置负值。图像数据的格式为 rgba。

由于您没有提到如何操作像素。我只是将 rgb 值减少 100 以显示原始图像和新图像之间的差异。

var img = new Image();
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsBAMAAACLU5NGAAAAG1BMVEXMzMyWlpa3t7eqqqqcnJyjo6PFxcWxsbG+vr6NAD6nAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACjklEQVR4nO3XO2/bMBDA8fNTGn2OlGS00S8QAWnnaKi7xnBQdJSBFl3joY/RRpHv3SNFykYtdKOm/w8BHOkOIM3HkRYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/uddvWvsI38sj+7xT/2lJ2n8WH64iMbkdCaqurTPteqda98eX6+zKnu9OkdDckIH3W21kbmWlR5F9rrT+6ukTMv3ettFY3JC9UZyfZBJ0czrZxuWjXwtr5KmRSOnmy4ak9PJ3bc+PMveJvJ0a+OwslfNv1knG6Ks7KIhOaGxulYXsl7YmNy1j/XV4nLRXLtoSE4oczN2epLK5mRSuj/x/7tuPImfOfHDKXnRRUNyaq6l17bhu7aX/q1N1fY8Va7TIRqSE/tuS2a78i3Nludu7QsbsW4+54dlFw3JadVqM1Uf3b6XqSsO+4V/n+nrtGt7qrZdYzQkp6WuFLUtNW3DYebqzXoZk0ZqWzZGQ3LqblmLvhFtRq5Ho9Ct9c25OI1c52M0JKftlrzpc+9ozfSilOfbctjRsv226FtbtuBvLpJmOuza8hW7Zyfa4lpeJFl5H24nZr/Fz4srReNQt9ahW5nGpn8d/azFaEhOyJ8hNi+HtnBn5yrvClcsW+44slmL0UPyKj8Jh0/fmVjd12HxV+3hM+CZ6DZUFW4Q9+GOcPShuT6sw5o/3PovEKMhOaG5frZBWPXdt2a2xkMV2JeNuNI62H1LqmJXF9J3O7XbQ65t4xP9+OguFMPdTr9Zkd9I313eLaxt28X5VtUuqAPe5eVH/ckalPyl/THzFn/5jF0H9qEMZC/Fz4toTAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEjpL514clJrNSt2AAAAAElFTkSuQmCC';
var canvas = document.getElementById('canvas');
var canvasEdited =  document.getElementById('canvasEdited');
var ctx = canvas.getContext('2d');
var arr = [];
img.onload = function() {
ctx.drawImage(img, 0, 0);
var imageData = ctx.getImageData(0,0, canvas.width, canvas.height)
editPixels(imageData.data);
drawEditedImage( imageData);
};
function editPixels(imgData) {
for (var i=0; i < imgData.length; i += 4) {
imgData[i] = imgData[i] - 100;
imgData[i+1] = imgData[i+1] - 100;
imgData[i+2] = imgData[i+2] - 100;
}
}
function drawEditedImage(newData) {
var ctxEdited = canvasEdited.getContext('2d');
ctxEdited.putImageData(newData, 0, 0);
}

JSFIDDLE for the same https://jsfiddle.net/karthick6891/3yhyyLyf/

我使用以下方法来检查给定像素是否不透明

canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 4 + 3] !== 0

画布数据以 rgba 格式返回,因此您需要要在 rgba 值中指定的颜色。

//red
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 4] = 0;
//green
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 1] = 0;
//blue
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 2] = 0;
//alpha
canvas.getImageData[((mousePos.y - canvas.y) * canvaswidth + (mousePos.x - canvas.x)) * 2] = 0;

通常,在游戏中编辑图像将使用屏幕外画布,其中包含所有游戏元素的精灵表。

最新更新