Предполагая, что "ограничивающий прямоугольник изображения" - это просто прямоугольник на изображении, указанный в пиксельных координатах.
Требуется прямоугольник 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;
}
Теперь, когда у вас есть координаты ограничительной рамки в пикселях на вашем изображении, вы сможете преобразовать ее в координаты устройства.