【问题标题】:AS3 - bitmapData edge alpha transparency problemAS3 - bitmapData 边缘 alpha 透明度问题
【发布时间】:2012-10-21 01:37:03
【问题描述】:

我正在 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);
        }

    }

}

【问题讨论】:

    标签: flash actionscript-3 draw bitmapdata


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这是个好主意,但也有一些不规则形状的画笔很难同心地创建。似乎在绘制到位图时任何模糊的形状都会受到这些小瑕疵的影响
      【解决方案3】:

      如果笔刷颜色是纯色的,你也可以尝试使用 Glow 滤镜,通过精确的设置可以实现

      【讨论】:

        【解决方案4】:

        我相信这更多是 enterframe 的问题,而不是您的逻辑问题。我注意到,如果将 enter_frame 处理程序更改为 mouse_move 处理程序,效果会好得多。使用 enter_frame 的问题是你一遍又一遍地绘制同一个项目——它自然有它自己的工件——所以在大约 600 次绘制之后,它会开始显示这些工件。我认为最好使用 mouse_move。

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

        这对我很有效:

        stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
        

        【讨论】:

        • 监听鼠标移动也有同样的问题,只是不太明显。在我的实际代码中,我在最后一个鼠标点和当前点之间进行插值,以便间隔正确间隔。但无论间距如何,伪影始终存在,只是程度较小。
        • 我看到了你的问题——这个人太糟糕了。看起来 Flash 真的把你搞砸了——看起来模糊过滤器很烂/和/或预乘 alpha? ....尝试将您的模糊质量更改为 1 - 这似乎减少了很多伪影....但我认为最终,您将不得不创建自己的着色器 ...
        【解决方案5】:

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

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

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

        另外,尝试将 PixelSnapping.ALWAYS 值更改为 PixelSnapping。NEVER,但我猜你已经尝试过了。

        【讨论】:

        • brushMap 仅在 onMove2 copyPixels() 调用中使用。由于它的 ARGB,0x00ffffff 和 0x0 几乎相同。无论如何,这与手头的问题没有区别。 pixelSnapping 也没有运气,我已经尝试了所有设置......真的希望我能找到一个简单的解决方案
        【解决方案6】:

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

        brush.cacheAsBitmap = true;
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-18
          • 2023-02-20
          • 2014-03-23
          • 1970-01-01
          • 2010-12-21
          • 2018-05-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多