3

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

我尝试了许多选项,包括将所有涉及的显示对象设置为 cacheAsBitmap=true、使用 copyPixels 而不是绘制、模糊滤镜与渐变填充……所有这些都无济于事。

下面的课程说明了我的问题。我已经包含了一个可以正常工作但没有羽化边缘的solid() 方法、一个gradient() 方法和一个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);
        }

    }

}
4

6 回答 6

2

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

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

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

除非您分别处理 alpha 通道和 rgb 通道,否则您无能为力。但是,您还必须自己完成所有合成,这不是一项简单的任务,并且可能会大大降低您的应用程序的速度。

于 2012-06-25T12:45:17.930 回答
1

我很惊讶BlurFilter没有奏效。过去我很幸运。可能值得玩一下Flex Filter Explorer以查看设置是否需要调整。

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

于 2011-03-06T01:43:48.823 回答
0

如果画笔颜色是纯色的,您也可以尝试使用 Glow filter,通过精确的设置可以实现

于 2011-03-07T14:10:03.587 回答
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);
于 2011-03-07T17:24:46.327 回答
0

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

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

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

另外,尝试更改 PixelSnapping。始终重视 PixelSnapping。从来没有,但我猜你已经尝试过了。

于 2011-03-08T16:57:30.823 回答
0

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

brush.cacheAsBitmap = true;

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

于 2012-05-31T00:36:21.363 回答