AS3如何检查BitmapData是否为空

发布于 2024-12-03 04:16:35 字数 2726 浏览 0 评论 0原文

我有一个代码可以删除蒙版影片剪辑。 (学分此处) 我想知道如何检查整个影片剪辑是否已被删除。 所以我想我必须检查 BitmapData 是否为空,但我可能大错特错了! 如何检查影片剪辑的每个像素是否已被删除?
当然我下面的例子是错误的,但我认为它必须是这样的。

if (erasableBitmapData = empty)
    { 
    trace("empty")
    }

    var lineSize:Number=40;
    var doDraw:Boolean=false;
    var resumeDrawing:Boolean=false;

    var erasableBitmapData:BitmapData = new BitmapData(700, 500, true, 0xFFFFFFFF);
    var erasableBitmap:Bitmap = new Bitmap(erasableBitmapData);
    erasableBitmap.cacheAsBitmap = true;
    addChild(erasableBitmap);

    maskee.cacheAsBitmap = true;
    maskee.mask = erasableBitmap;

    var eraserClip:Sprite = new Sprite();
    initEraser();
    function initEraser():void {
        eraserClip.graphics.lineStyle(lineSize,0xff0000);
        eraserClip.graphics.moveTo(stage.mouseX,stage.mouseY);
    }

    var drawnBitmapData:BitmapData = new BitmapData(700, 500, true, 0x00000000);
    var drawnBitmap:Bitmap = new Bitmap(drawnBitmapData);

    stage.addEventListener(MouseEvent.MOUSE_MOVE,maskMove);
    stage.addEventListener(MouseEvent.ROLL_OUT, maskOut); 
    stage.addEventListener(MouseEvent.ROLL_OVER,maskOver);
    stage.addEventListener(MouseEvent.MOUSE_DOWN,startDrawing);
    stage.addEventListener(MouseEvent.MOUSE_UP,stopDrawing);

    function startDrawing(e:MouseEvent):void {
        eraserClip.graphics.moveTo(stage.mouseX,stage.mouseY);
        doDraw=true;
    }

    function stopDrawing(e:MouseEvent):void {
        doDraw=false;
        resumeDrawing = false;
    }

    function maskOut(e:Event):void {
        if (doDraw){
            resumeDrawing = true;
        }
    }

    function maskOver(e:MouseEvent):void {
        if (resumeDrawing){
            resumeDrawing = false;
            eraserClip.graphics.moveTo(stage.mouseX,stage.mouseY);
        }
    }

    function maskMove(e:MouseEvent):void {
        if (doDraw && !resumeDrawing){
            eraserClip.graphics.lineTo(stage.mouseX,stage.mouseY);
            drawnBitmapData.fillRect(drawnBitmapData.rect, 0x00000000); 
            drawnBitmapData.draw(eraserClip , new Matrix(), null, BlendMode.NORMAL);
            erasableBitmapData.fillRect(erasableBitmapData.rect, 0xFFFFFFFF);
            erasableBitmapData.draw(drawnBitmap, new Matrix(), null, BlendMode.ERASE);
        }
            e.updateAfterEvent();
    }


    reset_btn.addEventListener(MouseEvent.CLICK,reset);

    function reset(e:Event):void {
        eraserClip.graphics.clear();
        initEraser();
        erasableBitmapData.fillRect(erasableBitmapData.rect, 0xFFFFFFFF);
    }

I have a code to erase a masked movieclip. (credits here)
I would like to know how I can check if the whole movieclip is been erased.
So I thought I had to check if the BitmapData is empty, but I could be terribly wrong!
How can I check if every pixel of the movieclip has been erased?
Of course my example below is wrong, but I think it has to be something like that.

if (erasableBitmapData = empty)
    { 
    trace("empty")
    }

    var lineSize:Number=40;
    var doDraw:Boolean=false;
    var resumeDrawing:Boolean=false;

    var erasableBitmapData:BitmapData = new BitmapData(700, 500, true, 0xFFFFFFFF);
    var erasableBitmap:Bitmap = new Bitmap(erasableBitmapData);
    erasableBitmap.cacheAsBitmap = true;
    addChild(erasableBitmap);

    maskee.cacheAsBitmap = true;
    maskee.mask = erasableBitmap;

    var eraserClip:Sprite = new Sprite();
    initEraser();
    function initEraser():void {
        eraserClip.graphics.lineStyle(lineSize,0xff0000);
        eraserClip.graphics.moveTo(stage.mouseX,stage.mouseY);
    }

    var drawnBitmapData:BitmapData = new BitmapData(700, 500, true, 0x00000000);
    var drawnBitmap:Bitmap = new Bitmap(drawnBitmapData);

    stage.addEventListener(MouseEvent.MOUSE_MOVE,maskMove);
    stage.addEventListener(MouseEvent.ROLL_OUT, maskOut); 
    stage.addEventListener(MouseEvent.ROLL_OVER,maskOver);
    stage.addEventListener(MouseEvent.MOUSE_DOWN,startDrawing);
    stage.addEventListener(MouseEvent.MOUSE_UP,stopDrawing);

    function startDrawing(e:MouseEvent):void {
        eraserClip.graphics.moveTo(stage.mouseX,stage.mouseY);
        doDraw=true;
    }

    function stopDrawing(e:MouseEvent):void {
        doDraw=false;
        resumeDrawing = false;
    }

    function maskOut(e:Event):void {
        if (doDraw){
            resumeDrawing = true;
        }
    }

    function maskOver(e:MouseEvent):void {
        if (resumeDrawing){
            resumeDrawing = false;
            eraserClip.graphics.moveTo(stage.mouseX,stage.mouseY);
        }
    }

    function maskMove(e:MouseEvent):void {
        if (doDraw && !resumeDrawing){
            eraserClip.graphics.lineTo(stage.mouseX,stage.mouseY);
            drawnBitmapData.fillRect(drawnBitmapData.rect, 0x00000000); 
            drawnBitmapData.draw(eraserClip , new Matrix(), null, BlendMode.NORMAL);
            erasableBitmapData.fillRect(erasableBitmapData.rect, 0xFFFFFFFF);
            erasableBitmapData.draw(drawnBitmap, new Matrix(), null, BlendMode.ERASE);
        }
            e.updateAfterEvent();
    }


    reset_btn.addEventListener(MouseEvent.CLICK,reset);

    function reset(e:Event):void {
        eraserClip.graphics.clear();
        initEraser();
        erasableBitmapData.fillRect(erasableBitmapData.rect, 0xFFFFFFFF);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

呆头 2024-12-10 04:16:35

您可以检查是否 getColorBoundsRect 返回一个宽度和高度为 0 的矩形,用于表示您认为“空”的颜色,设置findColor 参数设置为 false。还有其他方法可以做到这一点,但这至少比检查每个像素快很多倍。

findColor 参数的默认值 true 为您提供一个矩形,其中包含 (pixelColor & mask) == emptyColor 为 true 的所有像素。处理 alpha 值时,可以使用 0xFF000000 掩码来忽略像素的 rbg 值并仅检查其 alpha 值。因此,掩码 0xFF000000 和颜色 0xFF000000 将匹配所有完全不透明的像素,而掩码 0xFF000000 和颜色 0x00000000 > 将匹配所有完全透明的像素。正如 meddlingwithfire 所指出的,这在这里不起作用。通过将 findColor 设置为 false,此过程有点相反,以便矩形将包含所有使用空颜色的像素。对于不包含其他颜色的位图,结果将是面积为 0 的矩形。

var maskColor:uint = 0xFF000000;
var emptyColor:uint = 0x00000000;
var bounds:Rectangle = erasableBitmapData.getColorBoundsRect(maskColor, emptyColor, false);
if (bounds.width == 0 && bounds.height == 0){
    trace("empty"); // no visible pixels
}

从技术上讲,黑色透明像素 0x00000000 和红色透明像素 0x00FF0000 之间存在差异 - 但没有明显的差异(两者都是不可见的),因此您应该忽略rgb 值完全正确,就像我在示例中使用该特定掩码所做的那样。

You can check if getColorBoundsRect returns an rectangle with an width and height of 0 for the colour you consider as 'empty', setting the findColor argument to false. There are other ways to do this, but this is at least many times faster than checking every single pixel.

The default value of true for the findColor argument gives you an rectangle that encloses all pixels for those (pixelColor & mask) == emptyColor is true. When dealing with alpha values, a mask of 0xFF000000 can be used to ignore rbg values of a pixel and to only check its alpha value. So the mask 0xFF000000 and the colour 0xFF000000 would match all fully opaque pixels, while the mask 0xFF000000 and the colour 0x00000000 would match all fully transparent pixels. As meddlingwithfire pointed out, this won't do the job here. By setting findColor to false, this process is kind of reversed so that the rectangle will enclose all pixels that are not using the empty colour. For bitmaps containing no other colours, the result will be a rectangle with an area of 0.

var maskColor:uint = 0xFF000000;
var emptyColor:uint = 0x00000000;
var bounds:Rectangle = erasableBitmapData.getColorBoundsRect(maskColor, emptyColor, false);
if (bounds.width == 0 && bounds.height == 0){
    trace("empty"); // no visible pixels
}

Technically there is a difference between a black transparent pixel 0x00000000 and for example a red transparent pixel 0x00FF0000 - but there is no visible difference (both are invisible) so you should ignore the rgb values completely, as I did in the example by using that particular mask.

水中月 2024-12-10 04:16:35

创建基线“空”BitmapData 实例。使用 BitmapData 的比较方法,传入“可能为空”的 BitmapData。您将获得一个新的 BitmapData 引用,其中包含两者之间的像素差异。使用新的 BitmapData 引用,您可以访问直方图方法来获取每个通道的所有计数的列表。如果空 BitmapData 实例和“可能为空”BitmapData 实例完全相同,那么您的直方图通道将具有 BitmapData 中的像素总数作为每个通道的零索引中的计数(因为情况下的 BitmapData 差异)相同的数据将填充 0x00000000 像素)。

也应该相对较快,因为您可以依靠 AS 引擎来查看每个像素,而不必手动调用昂贵的 getPixel() 方法。

使用颜色边界方法可能会导致误报。如果您的位图在左上角和左下位置相同,那么您的颜色边界矩形将包含整个区域,即使中间的所有像素可能完全不同。

Create a baseline "empty" BitmapData instance. Use that BitmapData's compare method, passing in your "potentially empty" BitmapData. You'll get a new BitmapData reference that has the pixel differences between the two. Using that new BitmapData reference, you can access the histogram method to get a list of all the counts for every channel. If the empty BitmapData instance and the "potentially empty" BitmapData instance are exactly the same, then your histogram channel will have the total number of pixels in your BitmapData as the count in the zero index of each channel (since the BitmapData difference in the case of equal data would be filled with 0x00000000 pixels).

Should be relatively quick too, as you can rely on the AS engine to look at each pixel as opposed to having to manually call the expensive getPixel() method.

Using the color bounds approach can lead to false-positives. If your bitmaps are the same in the upper-left and lower-left positions then your color bounds rect will encompass the entire area, even though all of the pixels in-between could be completely different.

寒尘 2024-12-10 04:16:35

BitmapData.compare(BitmapData) 函数返回一个新的 BitmapData,其中包含调用的两个 BitmapData 之间的差异,或者如果 BitmapData >BitmapData 对象是等效的(具有相同的宽度、高度和相同的像素值),该方法返回数字 0。这意味着您可以使用以下代码来检查 DisplayObject 是否包含图形

var eraseableBitmapData:BitmapData = new BitmapData(264,864,true,0xFFFFFFFF);
//initialise the eraseableBitmapData
eraseableBitmapData.draw(someDisplayOject)
//draw your object's bitmap data

var emptyBitmapData:BitmapData = new BitmapData(264,864,true,0xFFFFFFFF);
//create an identical but empty BitmapData object

if( erasableBitmapData.compare ( emptyBitmapData ) == 0 ) {
    trace("empty");//object is completely empty
} else {
    trace("not empty");//object still has stuff in
}

<一href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html#draw%28%29" rel="nofollow">draw() 文档

compare() 文档

The BitmapData.compare(BitmapData) function returns either a new BitmapData containing the difference between the the calling two BitmapDatas, or if the BitmapData objects are equivalent (with the same width, height, and identical pixel values), the method returns the number 0. Meaning you could use the following to check if a DisplayObject contains graphics

var eraseableBitmapData:BitmapData = new BitmapData(264,864,true,0xFFFFFFFF);
//initialise the eraseableBitmapData
eraseableBitmapData.draw(someDisplayOject)
//draw your object's bitmap data

var emptyBitmapData:BitmapData = new BitmapData(264,864,true,0xFFFFFFFF);
//create an identical but empty BitmapData object

if( erasableBitmapData.compare ( emptyBitmapData ) == 0 ) {
    trace("empty");//object is completely empty
} else {
    trace("not empty");//object still has stuff in
}

draw() documentation

compare() documentation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文