cargo un .png transparente en un UIImage.Obtener BoundingBox de una imagen transparente?
Cómo calculo el cuadro delimitador real. P.ej. si la imagen real es más pequeña que las dimensiones .png.
Gracias por ayudar a
cargo un .png transparente en un UIImage.Obtener BoundingBox de una imagen transparente?
Cómo calculo el cuadro delimitador real. P.ej. si la imagen real es más pequeña que las dimensiones .png.
Gracias por ayudar a
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!");
}
Si desea que la imagen para cambiar el tamaño al tamaño de la vista de la imagen se puede llamar
[myImageView sizeToFit];
Asumiendo "cuadro de una imagen de delimitación" es simplemente un rectángulo en la imagen, especificada en coordenadas de píxel.
desea que el rectángulo de image
que contiene todos los píxeles con un alfa mayor que threshold
(que es equivalente a decir que todos los píxeles que no están en este rectángulo tienen un alfa menor que threshold
). Después de eso, puedes transformar este rectángulo en coordenadas de pantalla (o lo que quieras).
El algoritmo básico es comenzar con un rectángulo que contenga toda la imagen, luego encoger el rectángulo horizontalmente, luego verticalmente (o verticalmente y luego horizontalmente).
No sé Objective-C, por lo que poner el código en C puro (algunas funciones son sólo para hacer el código más claro):
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;
}
Ahora que tiene las coordenadas de la delimitación cuadro en píxel en su imagen, debería poder transformarlo en las coordenadas del dispositivo.
Hay un problema posible (aunque poco común). 'x' está' unsigned' en 'shrinkHorizontally', sin embargo, está bucleando con' for (x = img-> width - 1; x> = 0; x -) 'para contraer desde la derecha. Similar para 'y' en' shrinkVertically'. No habrá un comportamiento indefinido ya que 'getPixelAlpha' verifica los límites, pero si el umbral es demasiado alto (en comparación con la imagen), se repetirá indefinidamente. Además, podría acelerar un poco la búsqueda al no reconsiderar los píxeles ya procesados (aunque el rendimiento del gran O no cambiará). – jerry
¿Quiere decir que el tamaño de la imagen es (0,0) o (w, 0) o (0, h)? – Synxis
Bueno, ese es otro problema si 'Image's se permite tener una dimensión sea' 0'. Lo que quise decir, sin embargo, es si no había un píxel cuyo canal alfa fuera mayor o igual que 'umbral'. Diga 'threshold = 0xFF' pero todos los píxeles tienen' getPixelAlpha (img, x, y) <= 0xFE' (como dije, poco común). Entonces 'lineAlphaMax> = threshold' nunca será verdadero, por lo que nunca' saldrá 'del bucle externo. En cambio, el bucle se ejecutará como se espera hasta que el iterador de bucle 'x -' se ejecute cuando 'x' sea' 0' (para 'shrinkHorizontally'). Esto hará que 'x' se ajuste a' UINT_MAX', que es '> = 0'. El ciclo se ejecutará para siempre. – jerry
Permítanme reformular: "¿Cómo puedo encontrar el rectángulo más pequeño en una imagen parcialmente transparente que contiene todos los píxeles con un valor alfa por encima de un cierto umbral?". ¿Es eso lo que querías decir? –
Obtuve una respuesta de http://stackoverflow.com/questions/6521987/crop-uiimage-to-alpha y la respuesta del usuario404709 me funciona. –