如何更改图像中的像素

Posted

技术标签:

【中文标题】如何更改图像中的像素【英文标题】:How to change the pixels in an image 【发布时间】:2011-01-17 01:40:23 【问题描述】:

我实际上尝试执行以下操作:我已在 bitmapdata 对象中加载了一个外部图像,并从中创建了一个位图,我将其附加到 sprite/MovieClip 以便在其上添加鼠标事件。现在在前面的逻辑下,我加载了两个相同大小的图像(比如说圆圈),一个具有特定颜色并被黑色前景圆圈覆盖。当我按下鼠标左键并按住它时,我想要移动鼠标以擦除前景圆圈的像素,因此背景图像开始出现。我试图做到这一点,但没有运气。在我的最佳尝试中,我实现了在前景图像中画一条线,但我无法显示背景!

package

    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.BlendMode;

    public class Test2 extends MovieClip
    
        // properties - state

        // to attach the image and have mouse events
        private var frontImage:Sprite;
        private var backImage:Sprite;

        // to load the image
        private var myLoader:Loader;

        // to get the bitmap data of the image
        private var frontBitmapData:BitmapData;
        private var frontBitmap:Bitmap;

        // test
        private var frontMask:Bitmap;

        // constructor
        function Test2():void
        
            // load the background image            
            backImage = new Sprite();
            attachImageToSprite1(new URLRequest("btest.jpg"));
            backImage.mouseEnabled = false;
            this.addChild( backImage );

            // load the front image 
            frontImage = new Sprite();
            attachImageToSprite2(new URLRequest("test.jpg"));
            frontImage.mouseEnabled = true; // enable mouse
            frontImage.buttonMode = true;   // set button mode 
            this.addChild(frontImage);  // load to stage

            this.frontImage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            this.frontImage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        

        // methods
        private function attachImageToSprite1(Name:URLRequest):void
        
            this.myLoader = new Loader();
            this.myLoader.load(Name);
            this.myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete1);
        

        private function attachImageToSprite2(Name:URLRequest):void
        
            this.myLoader = new Loader();
            this.myLoader.load(Name);
            this.myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete2);
        

        private function getImageBitmapDataFromSprite(srcImage:Sprite):BitmapData
        
            var tmpBitmapData:BitmapData = new BitmapData(frontImage.width, frontImage.height, true, 0xFFCCCCCC);
            tmpBitmapData.lock();
            tmpBitmapData.draw(frontImage);
            tmpBitmapData.unlock();
            return tmpBitmapData;
        

        private function isPixelAlpha(bitmapdata:BitmapData):Boolean
        
            var pixelValue:uint = bitmapdata.getPixel32(mouseX, mouseY);
            var alphaValue:uint = pixelValue >> 24 & 0xFF;
            //var red:uint = pixelValue >> 16 & 0xFF;
            //var green:uint = pixelValue >> 8 & 0xFF;
            //var blue:uint = pixelValue & 0xFF;
            return (alphaValue == 0x00) ? true : false;
        

        private function deletePixelUnderMouse(bitmapdata:BitmapData, bitmap:Bitmap):void
        
            bitmapdata.lock();
            if ( !isPixelAlpha(bitmapdata) ) 
                bitmapdata.setPixel32(mouseX, mouseY, 0xFF << 24);  // how to make the current pixel's alpha
                                                                   // equal to zero.
            bitmap = new Bitmap(bitmapdata);
            bitmap.x = frontImage.x;
            bitmap.y = frontImage.y;
            this.frontImage.addChild(bitmap);
            bitmapdata.unlock();
        

        // events
        public function onLoadComplete1(e:Event):void
        
            frontImage.addChild(this.myLoader.content);
        

        public function onLoadComplete2(e:Event):void
        
            backImage.addChild(this.myLoader.content);
        

        public function onMouseDown(e:MouseEvent):void
        
            // delete a pixel from the sprite under the mouse
            frontBitmapData = getImageBitmapDataFromSprite(frontImage);
            deletePixelUnderMouse(frontBitmapData, frontBitmap);
            frontImage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseDown);
            trace("start");
        

        public function onMouseUp(e:MouseEvent):void
        
            frontImage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseDown);
            trace("stop")
        
    

【问题讨论】:

请格式化您的问题。此外,您可能更容易在精灵内部绘制并将其用作蒙版以获得“显示”效果,我猜您正在追求 【参考方案1】:

不确定我是否正确,但如果您想要“显示”效果,例如绘制蒙版以显示隐藏的图像,这可以更容易实现:

var bitmapToReveal:BitmapData = new BitmapToReveal(0,0);
var brush:BitmapData = new Brush(0,0);
var canvasData:BitmapData = new BitmapData(bitmapToReveal.width,bitmapToReveal.height,true,0x00FFFFFF);
var cursor:Point = new Point();//used as destination point when painting
var zero:Point = new Point();//reused for painting
var reveal:Bitmap = new Bitmap(bitmapToReveal);
var canvas:Bitmap = new Bitmap(canvasData);
reveal.cacheAsBitmap = canvas.cacheAsBitmap = true;
addChild(reveal);
addChild(canvas);
reveal.mask = canvas;

stage.addEventListener(MouseEvent.MOUSE_DOWN, brushDown);
stage.addEventListener(MouseEvent.MOUSE_UP, brushUp);

function brushDown(event:MouseEvent):void 
    this.addEventListener(Event.ENTER_FRAME, paint);

function brushUp(event:MouseEvent):void 
    this.removeEventListener(Event.ENTER_FRAME, paint);

function paint(event:Event):void 
    cursor.x = mouseX-brush.width*.5;
    cursor.y = mouseY-brush.height*.5;
    canvasData.copyPixels(brush,brush.rect,cursor,brush,zero,true);

我正在使用库中的两个位图(bitmapToReveal 和画笔)。 主要看的是copyPixels() 方法。我复制 将位图刷入画布(一个空的透明位图数据), 使用偏移光标位置(使画笔居中),并使用 alpha 通道来做到这一点。请注意,我已将 cacheAsBitmap 设置为 true 对于掩码和掩码。你需要这样做才能得到一个透明的面具, 这是效果的关键。

结果如下:

您可以“绘制”面具here。 CS4 来源是here。

HTH, 乔治

【讨论】:

还有别的东西......我可以使用另一个对象,比如精灵而不是画笔对象吗? 当然可以。使用此设置的最简单方法是使用 draw() 制作剪辑的 BitmapData 版本,应该就是这样......只需将第 2 行的声明替换为: var brushClip:MovieClip = new SpriteBrush(); var 刷子:BitmapData = new BitmapData(brushClip.width,brushClip.height,true,0x00FFFFFF);或者,您可以附加精灵并继续执行类似 canvas.draw(brushClip,brushClip.transform.matrix); 的操作。这将复制应用了翻译的画笔,假设您将更新它的位置以跟随鼠标。 见 lifesine.eu/so/changePixels/bitmapPaint2.fla 和 lifesine.eu/so/changePixels/bitmapPaint3.fla 祝你好运! 如果我有几个相同大小的不同背景图像和相同数量的相同前景图像覆盖它们,其中图像是 jpg 文件,你有什么建议? 不确定我是否理解。你的意思是你有不同的图像要显示,每个图像都有一个自定义关联的“画笔”,你想要像图层这样的东西? '不同的背景图像' = 要'显示'的图像? - '相同数量的前景图像' = 每个背景的自定义“画笔”以显示?

以上是关于如何更改图像中的像素的主要内容,如果未能解决你的问题,请参考以下文章

无法更改图像 Mat opencv 中的所有像素

如何在opencv中更改实验室垫中的像素

如何更改RGBA图像的单个像素?

在图像中随机更改像素值程序——matlab

更改 Konva.js 中的图像渲染

iOS - 如何在不调整大小和重新定位按钮视图的情况下更改按钮图像