2010-03-23 54 views
7

我加載一個透明的PNG到UIImage。獲取透明圖像的BoundingBox?

如何計算真實的邊界框。例如。如果真實圖像小於.png尺寸。

感謝您的幫助

+5

讓我改述一下:「如何在部分透明的圖像中找到最小的矩形,其中包含alpha值高於某個閾值的所有像素?」。這是你的意思嗎? – 2010-03-23 16:24:41

+1

從http://stackoverflow.com/questions/6521987/crop-uiimage-to-alpha得到了答案,user404709的答案適用於我。 – 2012-03-19 04:45:06

回答

0
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]; 
8

假設「邊界圖像框」是一個簡單的矩形在圖像中,在像素座標中指定。

你想要的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

有可能(雖然不常見)的問題。 'x'在'shrinkHorizo​​ntally'中是'unsigned',但是你正在用'for(x = img-> width - 1; x> = 0; x - )'循環以從右邊縮小。類似於'shrinkVertically'中的'y'。由於getPixelAlpha檢查邊界,所以不會有未定義的行爲,但是如果閾值太高(與圖像相比),它將無限循環。此外,通過不重新考慮已處理的像素(儘管大O性能不會改變),您可以加快搜索速度。 – jerry 2013-03-26 21:02:54

+0

你的意思是,圖像的大小是(0,0)還是(w,0)或(0,h)? – Synxis 2013-03-27 08:46:38

+0

那麼,如果'Image'允許維數爲'0',那是另一個問題。然而,我的意思是,如果沒有像素的alpha通道大於或等於'threshold'。說'threshold = 0xFF',但所有像素都有'getPixelAlpha(img,x,y)<= 0xFE'(正如我所說的,不常見)。然後'lineAlphaMax> = threshold'永遠不會是真的,所以你永遠不會從外部循環中'破壞'。相反,循環將按預期運行,直到循環迭代器'x - '在'x'爲'0'時運行('shrinkHorizo​​ntally')。這會導致'x'換行到'UINT_MAX',它是'> = 0'。循環將永遠運行。 – jerry 2013-03-27 14:30:51