How to narrow a Rectangle within a Sprite to exclude transparent pixels?
I have a Sprite
that contains opaque objects surrounded by transparent pixels. I also have a Rectangle
that represents a part of the Sprite
that I want to render using BitmapData.draw()
.
The problem is that the Rectangle
that I obtained also contains transparent parts. How can I narrow the Rectangle
to only include the opaque parts and ignore the transparent surroundings?
kapep's answer is just what I want to do, but the problem is that the source is a Sprite开发者_如何学C
, not a BitmapData
object, and I don't have getColorBoundsRect()
on a Sprite
.
You can use getColorBoundsRect
for this.
var mask:uint = 0xFF000000; // ignore rgb, use alpha only
var transparent = 0x00000000;
var rect:Rectangle = imageBitmapData.getColorBoundsRect(mask, transparent, false);
To operate with the pixels of the sprite, it needs to be drawn to a BitmapData
first (use BitmapData.draw
). Then after getting a smaller rectangle with getColorBoundsRect
, create a new BitmapData with the dimensions of that rectangle. The last step is to use copyPixels, to copy the area of the rectangle from first image to the new one.
var imageBitmapData:BitmapData = new BitmapData(image.width, image.height, true, 0);
imageBitmapData.draw(image);
// var rect = ... as above
var resultBitmapData:BitmapData = new BitmapData(rect.width, rect.height, true, 0);
resultBitmapData.copyPixels(imageBitmapData, rect, new Point(0,0));
I find your question a tad confusing, but if I do understand correctly, here's what you should do:
First, use BitmapData.draw()
to take the "picture" of the Sprite, placing it in your new BitmapData
instance. Then, you need to find the boundaries of the transparent area. Do this separately for each edge. Starting at each edge, look at pixels on a regular interval (e.g. every 10 pixels) and see if they're all transparent. If they are, move in towards the center by a certain number of pixels and repeat. Here's some example code (not tested!):
// Bitmap data already exists
var bmd:BitmapData; // content already exists
var isTransparent:Function = function(bmd:BitmapData, x:uint, y:uint):Boolean
{
var pixelValue:uint = bmd.getPixel32(0, 0);
var alphaValue:uint = pixelValue >> 24 & 0xFF;
return (alphaValue == 0);
};
// Look at right edge
var curX:uint = bmd.width-1;
var interval:uint = 10;
var iterations:uint = Math.ceil(bmd.height / interval);
var transparentX:uint = curX + 1;
var stillTransparent:Boolean = true;
while (stillTransparent)
{
for (var i:uint=0; i<iterations; i++)
{
var curY:int = i * interval;
if (!isTransparent(bmd, curX, curY))
{
stillTransparent = false;
break;
}
}
// If stillTransparent==true, this entire column was transparent.
// Get ready for next loop by moving in [interval] pixels
if (stillTransparent)
{
transparentX = curX
curX -= interval; // check needed if may be completely transparent
}
}
// transparentX now represents the last known x value on
// the right edge where everything was still transparent.
Finally, take the x
and y
results of the transparency boundary tests and use them to create a Rectangle
and use BitmapData.draw
to only copy the relevant non-transparent portion into a new BitmapData
instance.
精彩评论