开发者

Get BoundingBox of a transparent Image?

i load a transparent .png into an UIImage.

How to i calculte the real bounding-box. E.g. if the开发者_StackOverflow社区 the real image is smaller than the .png-dimensions.

Thanks for helping


Assuming "bounding box of an image" is simply a rectangle in the image, specified in pixel coordinates.

You want the rectangle of image which contains all pixels with an alpha greater than threshold (it is equivalent to say that all pixels that are not in this rectangle have an alpha lower than threshold). After that you can transform this rectangle in screen coordinate (or whatever you want).

The basic algorithm is to start with a rectangle containing the whole image, then shrink the rectangle horizontally, then vertically (or vertically then horizontally).

I don't know Objective-C, so I put the code in pure C (some functions are just to make the code more clearer):

typedef struct Rectangle
{
    unsigned int x1, y1, x2, y2;
} Rectangle;

typedef struct Image
{
    unsigned int height,width;
    unsigned int* data;
} Image;

unsigned char getPixelAlpha(Image* img, unsigned int x, unsigned int y)
{
    unsigned int pixel = 0; // default = fully transparent

    if(x >= img->width || y >= img->height)
        return pixel; // Consider everything not in the image fully transparent

    pixel = img->data[x + y * img->width];
    return (unsigned char)((pixel & 0xFF000000) >> 24);
}

void shrinkHorizontally(Image* img, unsigned char threshold, Rectangle* rect)
{
    int x, y;

    // Shrink from left
    for(x = 0; x < (int)img->width; x++)
    {
        // Find the maximum alpha of the vertical line at x
        unsigned char lineAlphaMax = 0;
        for(y = 0; y < (int)img->height; y++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the left limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->x1 = x;
            break;
        }
    }


    // Shrink from right
    for(x = img->width - 1; x >= 0; x--)
    {
        // Find the maximum alpha of the vertical line at x
        unsigned char lineAlphaMax = 0;
        for(y = 0; y < (int)img->height; y++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the right limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->x2 = x;
            break;
        }
    }
}

// Almost the same than shrinkHorizontally.
void shrinkVertically(Image* img, unsigned char threshold, Rectangle* rect)
{
    int x, y;

    // Shrink from up
    for(y = 0; y < (int)img->height; y++)
    {
        // Find the maximum alpha of the horizontal line at y
        unsigned char lineAlphaMax = 0;
        for(x = 0; x < (int)img->width; x++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the up limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->y1 = x;
            break;
        }
    }


    // Shrink from bottom
    for(y = img->height- 1; y >= 0; y--)
    {
        // Find the maximum alpha of the horizontal line at y
        unsigned char lineAlphaMax = 0;
        for(x = 0; x < (int)img->width; x++)
        {
            unsigned char alpha = getPixelAlpha(img,x,y);
            if(alpha > lineAlphaMax)
                lineAlphaMax = alpha;
        }

        // If at least on pixel of the line if more opaque than 'threshold'
        // then we found the bottom limit of the rectangle
        if(lineAlphaMax >= threshold)
        {
            rect->y2 = x;
            break;
        }
    }
}

// Find the 'real' bounding box
Rectangle findRealBoundingBox(Image* img, unsigned char threshold)
{
    Rectangle r = { 0, 0, img->width, img->height };
    shrinkHorizontally(img,threshold,&r);
    shrinkVertically(img,threshold,&r);
    return r;
}

Now that you have the coordinates of the bounding box in pixel in your image, you should be able to transform it in device coordinates.


CGRect myImageViewRect = [myImageView frame];
CGSize myImageSize = [[myImageView image]size];

if(myImageSize.width < myImageViewRect.size.width){
   NSLog(@"it's width smaller!");
}
if(myImageSize.height < myImageViewRect.size.height){
   NSLog(@"it's height smaller!");
}

If you want the image to resize to the size of the image view you can call

[myImageView sizeToFit];
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜