2015-09-26 24 views
8

アルファチャンネル(透明度)を持つ画像が与えられた場合、画像の境界と実際の画像との間の空白を削除したいと思います。 これはバックグラウンドタスクで、またはユーザーエクスペリエンスに支障をきたさないように許容可能な実行時間でローディング画面で実行する必要があります。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 
    ); 

} 

説明:画像の各側に 、ループ用の画素座標有用最初の非透明画素を返す、透明色が含まれてないかどうかをチェックするために実行されます。これは、トリムする次元とは反対の次元を基底として使用して座標を精緻化します。yを見つけるには、yごとにxをスキャンします。

縦長トップ余白端確認するためには、以下のステップを実行する:

  1. 始動が最上行(Y = 0)
  2. チェック行のすべての列(xからです0からimageWidthへ)
  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

イメージに透明な列または行がない場合でも、サンプルコードで少なくとも1つのピクセルがトリミングされます。 'if(startWidth == 0)'や他の同様のステートメントの代わりに、 'http:// stackoverflow.com/a/886979/1043882'に記述されている方法を使う方が良いでしょう。 – hasanghaforian

+0

'startWidth'と' startHeight'は当初は0に設定してはいけません。なぜなら、イメージの上部に空白がなく、左端にはforループが終わりまで実行されるからです。したがって、あなたは '2 * width * height'に等しい計算時間を無駄にします。私はそれらを '-1'に設定する方が良いと思います。 – Ruslan

関連する問題