开发者

How to cut a Shape out of BitmapData?

开发者 https://www.devze.com 2023-01-28 19:39 出处:网络
I have a filled Shape, and a BitmapData that is the same width and height as the Shape\'s bounding box.

I have a filled Shape, and a BitmapData that is the same width and height as the Shape's bounding box.

I need to cut the Shape from the BitmapData (basically draw the BitmapData onto the shape...) [like so: http://imgur.com/uwE5F.png]

I use the rather hackish method of:

        public static function cutPoly(img:BitmapData, s:Shape, bounds:Bounds):BitmapData {
        var temp:BitmapData = new BitmapData(bounds.width, bounds.height, true);
        Main.inst.stageQuality("low"); //hack to kill anti-aliasing
        temp.draw(s,new Matrix());
        Main.inst.stageQuality("high"); // end hack

        //0xFF00FF00 is the color of the shape
        makeColTrans(temp,0xFF00FF00); //makes the color transparent :P
        //return temp;
        img.draw(temp);
        //img.draw(temp);
  开发者_高级运维      temp.dispose();
        makeColTrans(img, 0xFFFFFFFF);
        return img;
    }

I was wondering if there is a better method...one that isn't just a hack.


It can also be considered hack but you can add the bitmap and the (drawn) shape in a container sprite, mask the bitmap with the shape and draw the resulting image again. The only benefit you'd gain would be using the runtime's native drawing algorithms and that is only the case if your makeColTrans scans the whole bitmap pixel by pixel.

edited for code sample:

    public static function cutPoly(sourceBitmapData:BitmapData, maskShape:Shape, bounds:Rectangle):BitmapData {
        // you might not need this, supplying just the sourceBitmap to finalBitmapData.draw(), it should be tested though.
        var sourceBitmapContainer:Sprite = new Sprite();
        sourceBitmapContainer.addChild(sourceBitmap);
        sourceBitmapContainer.addChild(maskShape);

        var sourceBitmap:Bitmap = new Bitmap(sourceBitmapData);
        maskShape.x = bounds.x;
        maskShape.y = bounds.y;
        sourceBitmap.mask = maskShape;

        var finalBitmapData:BitmapData = new BitmapData(bounds.width, bounds.height, true, 0x00ffffff);
        // or var finalBitmapData:Bitmap = new BitmapData(maskShape.width, maskShape.height); not too sure about the contents of the bounds...
        finalBitmapData.draw(sourceBitmapContainer);

        return finalBitmapData;
    }


the second argument of the draw() method takes a transform matrix - you can specify offsets, rotation, skew, etc here. then use that bitmapdata object as the source of beginBitmapFill on the shape.


Is the colour around the shape consistent? If so, you could find the first instance of that coloured pixel and floodFill() the bitmapdata with 0x00000000 from that coordinate, and then draw the result to a new transparent bitmapdata.

edit

Here's another example using thresholds. It's far from perfect, but it does get you part of the way there. In this case, the class "Tile" is just the image you provided in your question with a linkage ID.

import flash.display.BitmapData;
import flash.geom.Point;
import flash.display.Bitmap;

var sample : Tile = new Tile();

var alphaBitmap : BitmapData = new BitmapData ( sample.width, sample.height, true, 0x00000000 );
    alphaBitmap .draw ( sample );
    alphaBitmap.threshold( alphaBitmap, alphaBitmap.rect, new Point(), "<", 0xFFEFEFEF, 0xFFFFFFFF, 0xFFFFFFFF );
    alphaBitmap.threshold( alphaBitmap, alphaBitmap.rect, new Point(), "!=", 0xFFFFFFFF, 0x00000000 );

    addChild ( new Bitmap ( alphaBitmap ) );

var source : Tile = new Tile();
var output : BitmapData = new BitmapData ( sample.width, sample.height, true, 0x00000000 );
    output.copyPixels( source, source.rect, new Point(), alphaBitmap );

var outputBitmap : Bitmap = new Bitmap ( output );
    outputBitmap.x = outputBitmap.width;

addChild ( outputBitmap );


If you're looking to do this "cookie-cut" algorithm mostly just out of BitmapData objects, consider this:

var bmp:BitmapData = pSourceBmp.clone();
var alphaBmp:BitmapData = new BitmapData(shape.width, shape.height, true, 0);

alphaBmp.draw( shape );

var alphaOrigin:Point = new Point();
var pasteOrigin:Point = new Point();

bmp.copyPixels( bmp, bmp.rect, pasteOrigin, alphaBmp, alphaOrigin, true);

NOTE: This code is not tested.

I've used something like this in a Blitting engine for "cookie-cutting" purpose, and it worked beautifully to extract shapes out of any given vector graphics. Interesting alternative to Masks.

0

精彩评论

暂无评论...
验证码 换一张
取 消