AS3 - 位图数据边缘Alpha透明度问题

时间:2011-03-05 22:59:31

标签: flash actionscript-3 draw bitmapdata

我正在as3中构建一个绘图应用程序,并且在刷子上有羽毛或模糊边缘的问题。我正在使用bitmapData.draw()绘制画笔,但是当我慢慢画画时,我会看到边缘周围颜色较深的区域。

我尝试了很多选项,包括将所有显示对象设置为cacheAsBitmap = true,使用copyPixels而不是draw,blur filter vs. gradient fill ... 一切都无济于事。

以下课程说明了我的问题。我已经包含一个正常工作但没有羽化边缘的solid()方法,一个渐变()方法和一个filter()方法,它们都显示相同的问题,而且onMove2也使用了copyPixels()并再次出现同样的问题。

我有什么办法可以解决这个问题吗?!我真的不想使用pixelbender着色器这么简单......

package test {
    import flash.display.*;
    import flash.events.*;
    import flash.filters.*;
    import flash.geom.*;

    public class Sucks extends Sprite {

        private var brush:Sprite;
        private var brushMap:BitmapData;
        private var bmd:BitmapData;
        private var radius:Number = 50;
        private var color:uint = 0x990000;


        public function Sucks() {
            brush = new Sprite();
            brushMap = new BitmapData(radius*2, radius*2, true, 0x00ffffff);
            bmd = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x0);
            var bmp:Bitmap = new Bitmap(bmd, PixelSnapping.ALWAYS, true);
            addChild(bmp);

            //solid();         
            gradient();
            //filter();
            brushMap.draw(brush, new Matrix(1, 0, 0, 1, radius, radius));

            stage.addEventListener(Event.ENTER_FRAME, onMove);
        }

        private function solid():void {
            brush.graphics.beginFill(color, 1);
            brush.graphics.drawCircle(0, 0, radius);
            brush.graphics.endFill();
        }

        private function gradient():void {
            var m:Matrix = new Matrix();
            m.createGradientBox(radius*2, radius*2, 0, -radius, -radius);
            brush.graphics.beginGradientFill(GradientType.RADIAL, [color, color], [1, 0], [0, 250], m);
            brush.graphics.drawCircle(0, 0, radius);
            brush.graphics.endFill();
        }

        private function filter():void {
            solid();
            brush.filters = [new BlurFilter(8, 8, 3)];
        }

        private function onMove(e:Event):void {
            var mp:Matrix = new Matrix();
            mp.tx = mouseX;
            mp.ty = mouseY;
            bmd.draw(brush, mp);
            //bmd.applyFilter(bmd, new Rectangle(0, 0, stage.stageWidth, stage.stageHeight), new Point(), new BlurFilter(2, 2, 3));
        }

        private function onMove2(e:Event):void {
            bmd.copyPixels(brushMap, new Rectangle(0, 0, radius*2, radius*2), new Point(mouseX-radius, mouseY-radius), null, null, true);
        }

    }

}

6 个答案:

答案 0 :(得分:2)

你的问题是由Flash使用预乘alpha的事实引起的。通常这不是一个大问题,但如果您的像素值具有非常低的alpha值,那么很明显,当您使用模糊的软羽毛画笔时,这种情况很常见。

预乘会导致像素中的信息丢失 - 当你的alpha值较低时,颜色值会有效地向下舍入,当你在应用程序中慢慢绘制并且相同的像素再次相互绘制时并将再次导致该区域变暗和变暗。

有关预乘法问题的更多详细信息,请查看我的旧帖子:http://www.quasimondo.com/archives/000665.php

除非你分别处理alpha通道和rgb通道,否则你无能为力。但是,你自己也必须自己做所有的合成,这不是一项微不足道的任务,可能会让你的应用程序变得太慢。

答案 1 :(得分:1)

我很惊讶BlurFilter没有用。我过去很幸运。可能值得使用Flex Filter Explorer来查看设置是否需要调整。

您可以尝试的另一件事是绘制几个具有透明度和减小半径的同心圆,以模拟边缘模糊。

答案 2 :(得分:0)

如果画笔颜色是实心颜色,您也可以尝试使用Glow滤镜,并且可以通过精确设置实现

答案 3 :(得分:0)

我认为这对于使用enterframe而言比使用逻辑更具问题。我注意到如果你将enter_frame处理程序更改为mouse_move处理程序,它会更好。使用enter_frame的问题在于你一遍又一遍地绘制相同的项目 - 这自然有它自己的工件 - 所以在600抽取之后,它将开始显示这些工件。我认为使用mouse_move会更好。

如果你必须使用enter_frame,我建议列出enter_frame和mouse_move,并大大降低enter_frames绘制的不透明度。

这对我很有用:

stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);

答案 4 :(得分:0)

我不知道它是否与它有关,但你设置透明度,但你的BitmapData不透明。

brushMap = new BitmapData(radius*2, radius*2, true, 0x00ffffff);

brushMap = new BitmapData(radius*2, radius*2, true, 0);

另外,尝试将PixelSnapping。 ALWAYS 值更改为PixelSnapping。从不,但我想您已尝试过。

答案 5 :(得分:0)

将画笔的cacheAsBitmap属性更改为true。

brush.cacheAsBitmap = true;

精灵将作为位图而不是矢量保存在内存中,因此在绘制时它会更精确地映射像素。