2015-09-26 153 views
8

給定帶有alpha通道(透明度)的圖像我想刪除圖像邊界和實際圖像之間的空白區域。 這應該在背景任務或加載屏幕中完成,並且具有可接受的運行時間以不削弱用戶體驗。如何刪除Android中圖像的空白區域?

enter image description here

我怎樣才能實現這個結果?

回答

17

我很難找到最佳實踐或甚至建議來解決我的問題。基於this anwer by JannGabriel,他們通過縮小圖像大小來裁剪圖像的右下角,我設法進一步去除了頂部和左側的空白區域,並且通常可以縮短加工時間。結果很好,我目前在我的項目中使用它。 我對Android編程相當陌生,歡迎對此方法提出任何建議。

public static Bitmap TrimBitmap(Bitmap bmp) { 
    int imgHeight = bmp.getHeight(); 
    int imgWidth = bmp.getWidth(); 


    //TRIM WIDTH - LEFT 
    int startWidth = 0; 
    for(int x = 0; x < imgWidth; x++) { 
     if (startWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 


    //TRIM WIDTH - RIGHT 
    int endWidth = 0; 
    for(int x = imgWidth - 1; x >= 0; x--) { 
     if (endWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - TOP 
    int startHeight = 0; 
    for(int y = 0; y < imgHeight; y++) { 
     if (startHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - BOTTOM 
    int endHeight = 0; 
    for(int y = imgHeight - 1; y >= 0; y--) { 
     if (endHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 


    return Bitmap.createBitmap(
      bmp, 
      startWidth, 
      startHeight, 
      endWidth - startWidth, 
      endHeight - startHeight 
    ); 

} 

說明: 對於圖像的每一側,一個FOR循環運行,以檢查是否像素不包含透明的顏色,返回第一非透明像素有用座標。這是通過使用作爲基礎的座標來完成的,該座標與要修剪的維度相反:找到y,爲每個y掃描x。

要檢查其中的垂直頂部空格結束,它運行下列步驟:

  1. 起動是從頂行(Y = 0)
  2. 檢查所有的行的列(X從0到圖像寬度)
  3. 如果找到不透明的像素,請打破循環並保存y座標。否則繼續。
  4. 在列的結尾處,轉到下一行(y + 1)並開始檢查列重複。如果已經找到一個不透明的像素,請打破它。

對其他維度使用了類似的方法,只是改變了掃描的方向。

一旦獲得圖像第一個有用像素的4個座標,將調用Bitmap.createBitmap方法,將原始位圖作爲基準圖像,並將有用像素座標調整爲調整大小的左上角和右下角限制。

注意1:有用的是要注意座標0,0等於左上角。注意2:Bitmap.createBitmap中的結束寬度和高度被新的起始相對座標減少,否則新圖像將錯誤地向右下方推動邊界。像這樣:你有一個圖像100x100px,所以結束座標100,100。將開始座標更改爲50,50將使精化矩形的結束座標達到150,150(100原始座標+修改後的起始點的50),將其推到原始圖像邊界之外。爲了避免這種情況,新的結束座標由新的起始座標減少(100 + 50新起始座標 - 50個新起始座標調整)

注意3:在原始答案中,檢查給定的所有像素方向使用座標的相同尺寸進行查找,返回最先進的有用像素。檢查相反的尺寸並停止在第一個有用像素處增加性能。

+1

您的示例代碼將修剪至少一個像素,即使圖像沒有透明列或行。最好使用'http:// stackoverflow.com/a/886979/1043882'中描述的方式,而不是'if(startWidth == 0)'和其他類似的語句。 – hasanghaforian

+0

'startWidth'和'startHeight'最初不應設置爲0,因爲如果您的圖像頂部和左側沒有空白空間,則for循環將運行至結束。所以你會浪費等於'2 *寬*高'的計算時間。我認爲將它們設置爲「-1」更好。 – Ruslan