进行画布图像像素操作的步骤是啥?

Posted

技术标签:

【中文标题】进行画布图像像素操作的步骤是啥?【英文标题】:What are the steps to do canvas image pixel manipulation?进行画布图像像素操作的步骤是什么? 【发布时间】:2021-04-20 22:11:11 【问题描述】:

好吧,我一直在尝试对画布上的图像进行像素操作。

基本上,我想要实现的是用其他自定义颜色交换/替换图像中已经上传到画布上的颜色。正如您在所附图片中看到的那样,我的画布设计师上传了图片,设计师的左下角有来自图像的带有项目符号的颜色(图像中存在带有项目符号的颜色),上面是我的自定义调色板。

这是我在将图像上传到画布后交换/替换图像颜色的步骤

    将图像上传到画布 点击画布上上传图片的颜色复选框(例如,用图片中显示的复选框选中紫色) 单击自定义调色板中的任何颜色(例如图像中显示的黄色)以替换图像中的颜色(例如,紫色应替换为图像中的黄色)

这是迄今为止我对像素操作所做的工作。在选中图像中的颜色框后单击自定义颜色,就会触发以下部分

 jQuery('ul').on('click','li.licolors',function() 
                    console.log("licolors");
                    var activeObject = canvas.getActiveObject();
                    if (activeObject && (activeObject.type === 'path')) 
                        activeObject.set("stroke",jQuery(this).css('background-color'));
                        activeObject.dirty = true;
                        canvas.renderAll();
                        updateCanvasState();
                    
                    else if(activeObject && (activeObject.type === "image"))
                        if($('.checkboxlicolorsfromimage').is(':checked'))
                            var colorfromimage = $('.checkboxlicolorsfromimage').val().split(",");//splitting color of checked checkbox purple rgb(83,70,128,255)
                            var Rcfi = colorfromimage[0];//Red from image
                            console.log(Rcfi);
                            var Gcfi = colorfromimage[1];//Green from image
                            console.log(Gcfi)
                            var Bcfi = colorfromimage[2];//Blue from image
                            console.log("bcfi"+Bcfi);
                            var Acfi = colorfromimage[3];//Alpha from image
                            var colortoimage = getRGB(jQuery(this).css('background-color'));//this variable holds rgbvalue (yellow color rgb(255, 205, 0)) which I have to apply to the image
                            var Rcti = colortoimage.red;//Red apply to image
                            console.log(Rcti);
                            var Gcti = colortoimage.green;//Green apply to image
                            console.log(Gcti);
                            var Bcti = colortoimage.blue;//Blue apply to image
                            console.log(Bcti);
                            var target = new Image();
                            target.src = canvas.toDataURL();
                            canvas.getContext('2d').drawImage(target,0,0);
                            const imageData = canvas.getContext('2d').getImageData(0, 0, target.width, target.height);
                            for (var i = 0; i < imageData.data.length; i += 4) 
                                if(parseInt(imageData.data[i]) == parseInt(Rcti))console.log(imageData.data[i]);
                                    imageData.data[i] = Rcfi;//Red
                                    console.log(Rcfi);
                                
                                if(parseInt(imageData.data[i + 1]) == parseInt(Gcti))console.log(imageData.data[i + 1]);
                                    imageData.data[i + 1] = Gcfi;//Green
                                    console.log(Gcfi);
                                
                                if(parseInt(imageData.data[i + 2]) == parseInt(Bcti))console.log(imageData.data[i + 2]);
                                    imageData.data[i + 2] = Bcfi;//Blue
                                    console.log(Bcfi);
                                
                            
                            canvas.getContext('2d').putImageData(imageData, 0, 0);
                            activeObject.dirty = true;
                            canvas.renderAll();
                            updateCanvasState();
                        
                    
                );

我没有收到任何错误或警告,我可以在控制台中看到我能够运行上述代码,但它没有在画布上已上传的图像中交换我的颜色。

    是否可以在图像上传到画布后交换/替换图像中的颜色?然后用我们自己的颜色交换/替换特定的颜色通道 我发现的大部分参考资料都在图片.onload 上 https://pictureelement.github.io/html5tech/canvas-pixel-manipulation-and-animations.html https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas https://www.tutorialspoint.com/Change-colour-of-an-image-drawn-on-an-HTML5-canvas-element

【问题讨论】:

你试过用调试器调试代码吗? 您是否想要进行精确的颜色匹配 - 因为它看起来好像您的图像在颜色方面非常复杂。 是的,通过在我的浏览器控制台中放置断点来调试它,我可以看到我的 console.logs 在控制台中打印像素 我的几块钱不禁对您已正确更新画布的可能性视而不见,但不知何故又用canvas.renderAllupdateCanvasState 调用它。你试过绝育它们吗?我所期待的最后一件事是图像数据被放回 - 我不熟悉的其他东西,所以它是我的主要嫌疑人。 是的,我相信应该可以用我的自定义颜色像素替换特定的颜色像素,不确定是否仅在图像为.onload 时有效,或者在上传到画布后有效 【参考方案1】:

我会把这个留在这里让你玩。我做的最后一件事实际上是putImageData。我想问题在于我不认识的位之一,正如 cmets 中提到的那样。

"use strict";
//window.addEventListener('load', onLoadedCreateB64url, false);
window.addEventListener('load', onLoadedUseEmbeddedImage, false);

// 33x33 pixel image of front wheel
var b64ImgSrc2 = 'data:image/png;base64,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';

function onLoadedUseEmbeddedImage(evt)

    let img = document.querySelector('img');
    img.addEventListener('load', imgLoaded, false);
    img.src = b64ImgSrc2;


function imgLoaded(evt)

    let img = this;
    let can = document.querySelector('canvas');
    let ctx = can.getContext('2d');
    can.width = img.naturalWidth;
    can.height = img.naturalHeight;
    ctx.drawImage(img, 0, 0);
    
    
    //141,127,143 - a few vertical pixels on right hand side of rim
    
   // color: #8d7f8f;

    recolourInPlace(can, 141,127,143, 255,0,0)



function onLoadedCreateB64url(evt)

    let img = document.querySelector('img');
    
    let can = document.querySelector('canvas');
    can.width = img.naturalWidth;
    can.height = img.naturalHeight;
    
    let ctx = can.getContext('2d');
    ctx.drawImage(img,0,0);
    
    let src = can.toDataURL();
    console.log(src);


function recolourInPlace(canvas, rin,bin,gin, rout,gout,bout)

    let ctx = canvas.getContext('2d');
    let imgData = ctx.getImageData(0,0, canvas.width, canvas.height);
    let width = canvas.width, height = canvas.height;
    let data = imgData.data;
    
    for (var y=0; y<height; y++)
    
        for (var x=0; x<width; x++)
        
            let index = ((y*width)+x) *4;
            if (data[index+0]==rin && data[index+1]==bin && data[index+2]==gin)
            
                data[index+0] = rout;
                data[index+1] = gout;
                data[index+2] = bout;
            
        
    
    ctx.putImageData(imgData, 0, 0);
    <img/>
    <canvas></canvas>

【讨论】:

以上是关于进行画布图像像素操作的步骤是啥?的主要内容,如果未能解决你的问题,请参考以下文章

画布中图像的 CORS 设置

柔化javascript画布图像中的边缘

Kivy:用画布为图像制作动画的正确方法是啥?

每天学一个jquery插件-一像素画布1

我们如何在 php 中使用织物 Js 对画布上的图像执行相同的操作(缩放和旋转)?

为啥画布会弄乱我的图像颜色?