Получить BoundingBox прозрачного изображения? - PullRequest
7 голосов
/ 23 марта 2010

я загружаю прозрачный .png в UIImage.

Как вычислить настоящий ограничивающий прямоугольник. Например. если реальное изображение меньше, чем .png-размеры.

Спасибо за помощь

Ответы [ 2 ]

8 голосов
/ 18 марта 2012

Предполагая, что "ограничивающий прямоугольник изображения" - это просто прямоугольник на изображении, указанный в пиксельных координатах.

Требуется прямоугольник image, который содержит все пиксели с альфа-каналом, превышающим threshold (эквивалентно сказать, что все пиксели, не входящие в этот прямоугольник, имеют альфа-канал ниже threshold). После этого вы можете преобразовать этот прямоугольник в экранную координату (или как хотите).

Основной алгоритм состоит в том, чтобы начать с прямоугольника, содержащего все изображение, затем уменьшить прямоугольник по горизонтали, затем по вертикали (или по вертикали, а затем по горизонтали).

Я не знаю Objective-C, поэтому я поместил код на чистый C (некоторые функции просто делают код более понятным):

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;
}

Теперь, когда у вас есть координаты ограничительной рамки в пикселях на вашем изображении, вы сможете преобразовать ее в координаты устройства.

0 голосов
/ 23 марта 2010
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!");
}

Если вы хотите изменить размер изображения до размера изображения, вы можете позвонить

[myImageView sizeToFit];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...