开发者

How to narrow a Rectangle within a Sprite to exclude transparent pixels?

开发者 https://www.devze.com 2023-04-10 18:15 出处:网络
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().

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.

0

精彩评论

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

关注公众号