carico un file .png trasparente in un oggetto UII.Ottieni BoundingBox di un'immagine trasparente?
Come calcolare la vera casella di delimitazione. Per esempio. se l'immagine reale è più piccola delle dimensioni .png.
Grazie per l'aiuto
carico un file .png trasparente in un oggetto UII.Ottieni BoundingBox di un'immagine trasparente?
Come calcolare la vera casella di delimitazione. Per esempio. se l'immagine reale è più piccola delle dimensioni .png.
Grazie per l'aiuto
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!");
}
Se si desidera che l'immagine da ridimensionare alle dimensioni della visualizzazione dell'immagine è possibile chiamare
[myImageView sizeToFit];
Supponendo "scatola di un'immagine di delimitazione" è semplicemente un rettangolo nell'immagine, specificato in coordinate pixel.
si desidera che il rettangolo di image
che contiene tutti i pixel con un alfa maggiore di threshold
(che equivale a dire che tutti i pixel che non sono in questo rettangolo hanno un alfa inferiore threshold
). Dopodiché puoi trasformare questo rettangolo in coordinate dello schermo (o qualunque cosa tu voglia).
L'algoritmo di base è di iniziare con un rettangolo contenente l'intera immagine, quindi ridurre il rettangolo orizzontalmente, quindi verticalmente (o verticalmente poi orizzontalmente).
Non so Objective-C, così ho messo il codice in puro C (alcune funzioni sono solo per rendere il codice più chiaro):
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;
}
Ora che avete le coordinate del rettangolo di selezione casella in pixel nell'immagine, dovresti essere in grado di trasformarla in coordinate del dispositivo.
C'è un possibile (anche se non comune) problema. 'x' è' unsigned' in 'shrinkHorizontally', ma stai eseguendo il ciclo con' for (x = img-> width - 1; x> = 0; x -) 'per restringere a destra. Simile per 'y' in' shrinkVertically'. Non ci sarà un comportamento indefinito poiché 'getPixelAlpha' controlla i limiti, ma se la soglia è troppo alta (rispetto all'immagine), si fermerà a ciclo indefinito. Inoltre, potresti velocizzare la ricerca non riconsiderando i pixel già elaborati (anche se le prestazioni di big-O non cambieranno). – jerry
Vuoi dire, la dimensione dell'immagine è (0,0) o (w, 0) o (0, h)? – Synxis
Bene, questo è un altro problema se 'Image's può avere una dimensione essere' 0'. Ciò che intendevo, tuttavia, è se non ci fosse un pixel il cui canale alfa fosse maggiore o uguale a 'threshold'. Dì "threshold = 0xFF" ma tutti i pixel hanno 'getPixelAlpha (img, x, y) <= 0xFE' (come ho detto, non comune). Quindi 'lineAlphaMax> = threshold' non sarà mai vero, quindi non uscirai mai dal ciclo esterno. Invece, il ciclo funzionerà come previsto fino a quando l'iteratore del ciclo 'x -' gira quando 'x' è' 0' (per 'shrinkHorizontally'). Questo farà sì che 'x' si sposti su' UINT_MAX', che è '> = 0'. Il ciclo funzionerà per sempre. – jerry
Lasciatemi riformulare: "Come trovo il rettangolo più piccolo in un'immagine parzialmente trasparente che contiene tutti i pixel con un valore alfa sopra una certa soglia?". E 'questo che intendevi? –
Hai una risposta da http://stackoverflow.com/questions/6521987/crop-uiimage-to-alpha e la risposta di user404709 funziona per me. –