2011-12-12 15 views
26

Windows 7を使用している場合、イメージ内で支配的な色を見つけようとしている理由を理解できます。タスクバーのプログラム上にマウスを置くと、その特定のプログラムは、アイコン内の最も支配的な色に基づいて変化する。私はこの技術が他のプログラムでも使われていることに気付きましたが、私の頭の上から覚えていません。Android @drawableで画像の支配的な色を見つける

これは、私がアプリケーションを開発するために使用しているいくつかのUIテクニックに役立つことがわかりました。私は、最も一般的な色を見つけることがAndroid drawableリソースからどのように達成されるのだろうかと思いました。

+0

新しいAPIは、ビットマップから目立つ色を抽出できますロリポップを加えました。詳細については、[私の答えは以下を参照](http://stackoverflow.com/a/28145358/1956632)を参照してください。上記のPaletteクラスはsupport7ライブラリに入っているので、古いバージョンのAndroidでも動作するはずです。 –

+0

アンドロイドv7パレットサポートライブラリは、私たちのためにそれを行います。誰でもデモを探しています。http://code2concept.blogspot.in/2015/10/android-support-v7-palette-demo.html – nitesh

答えて

48

を見つけることは、クラスはビットマップから有用な色を抽出助けるために添加しました。 android.support.v7にあるPaletteクラス。

  • 鮮やかな
  • 鮮やかなダーク
  • が鮮やかなライトが
  • ミュート
  • ミュートダーク
  • ミュートライト

このAndroidのトレーニングページが与える:グラフィックスは、次の色を抽出することができますあなたがクラスを使用するために必要なすべての詳細(私はAndroid Studioでそれを試しましたそれは)非常に簡単だった:http://developer.android.com/training/material/drawables.html#ColorExtract

を引用すると:

のAndroidサポートライブラリR21と上記は、あなたがイメージから目立つ色を抽出することができますPalette クラスが含まれています。 にこれらの色を抽出するには、画像をロードするバックグラウンドスレッドのPalette.generate() 静的メソッドにBitmapオブジェクトを渡します。あなたがそのスレッドを使用することはできません 場合は、Palette.generateAsync()メソッドを呼び出し、 代わりにリスナーを提供します。*

あなたはこのような、パレットクラスのゲッター メソッドを使用して画像から目立つ色を取得することができますPalette.getVibrantColorとして

は、アプリケーションのモジュールに次のGradle 依存関係を追加し、プロジェクト内のパレットクラスを使用するには、次の

dependencies { 
    ... 
    compile 'com.android.support:palette-v7:21.0.+' 
} 

*あなたがgenerateAsync()を使用する必要がある場合は、ここに方法は次のとおりです。

Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() { 
    public void onGenerated(Palette palette) { 
     // Do something with colors... 
    } 
}); 

EDIT: ドローイング可能なリソースから色を抽出する方法が質問されているので、先ほど説明した手法を使用するには、まずドロアブルをビットマップに変換する必要があります。幸いにも、それはBitmapFactory使用して非常に簡単です。また、別の解決策がある

Bitmap icon = BitmapFactory.decodeResource(context.getResources(), 
             R.drawable.icon_resource);` 
+0

パレットクラスの抽出色を試したい場合は、Playストアで自分のアプリをチェックアウトしてください:https://play.google.com/store/apps/details?id=com.tonyw.sampleapps.palettecolorextraction GitHubでソースコードを見つけることができます:https://github.com/tony-w/PaletteColorExtraction –

+2

優れた答え。これにより、利用可能なライブラリとメソッドのほとんどが冗長化されます。 – Baz

+0

私はすべてを説明することが最善であると思います。それはもっと明確になります。 –

2

すべてのピクセルの色データをループして平均すると、グレーまたは透明の陰影は無視されます。私はそれが最近のブログ記事に基づいてWindows 7でMicrosoftがやっていることだと思う。

編集
ブログ記事を:http://blogs.msdn.com/b/oldnewthing/archive/2011/12/06/10244432.aspx

クロムが支配的な色を選ぶ方法を示すこのリンクも役に立つかもしれません。 http://www.quora.com/Google-Chrome/How-does-Chrome-pick-the-color-for-the-stripes-on-the-Most-visited-page-thumbnails

+0

API関数があることを期待していましたどこか深いところに埋もれている。これは良い情報です – styler1972

+2

私は単純なハックを見つけました:1x1ビットマップとしてコピーし、色を取得してください:http://aerilys.fr/blog/?p = 1341 – radley

7

このクラスは、ビットマップを反復処理し、最も支配的な色を返します。 必要に応じてコードを自由に整理してください。

public class ImageColour { 

String colour; 


public ImageColour(Bitmap image) throws Exception { 

    int height = image.getHeight(); 
    int width = image.getWidth(); 

    Map m = new HashMap(); 

     for(int i=0; i < width ; i++){ 

      for(int j=0; j < height ; j++){ 

       int rgb = image.getPixel(i, j); 
       int[] rgbArr = getRGBArr(rgb);     

       if (!isGray(rgbArr)) { 

         Integer counter = (Integer) m.get(rgb); 
         if (counter == null) 
          counter = 0; 
         counter++;         
         m.put(rgb, counter);  

       }     
      } 
     }   

     String colourHex = getMostCommonColour(m); 
    } 



    public static String getMostCommonColour(Map map) { 

     List list = new LinkedList(map.entrySet()); 
     Collections.sort(list, new Comparator() { 
       public int compare(Object o1, Object o2) { 

       return ((Comparable) ((Map.Entry) (o1)).getValue()) 
        .compareTo(((Map.Entry) (o2)).getValue()); 

       } 

     });  

     Map.Entry me = (Map.Entry)list.get(list.size()-1); 
     int[] rgb= getRGBArr((Integer)me.getKey()); 

     return Integer.toHexString(rgb[0])+" "+Integer.toHexString(rgb[1])+" "+Integer.toHexString(rgb[2]);   
    }  


    public static int[] getRGBArr(int pixel) { 

     int red = (pixel >> 16) & 0xff; 
     int green = (pixel >> 8) & 0xff; 
     int blue = (pixel) & 0xff; 

     return new int[]{red,green,blue}; 

    } 

    public static boolean isGray(int[] rgbArr) { 

     int rgDiff = rgbArr[0] - rgbArr[1]; 
     int rbDiff = rgbArr[0] - rgbArr[2]; 

     int tolerance = 10; 

     if (rgDiff > tolerance || rgDiff < -tolerance) 
      if (rbDiff > tolerance || rbDiff < -tolerance) { 

       return false; 

      }     

     return true; 
    } 


public String returnColour() { 

    if (colour.length() == 6) { 
     return colour.replaceAll("\\s", ""); 
    } else { 
     return "ffffff"; 
    } 
} 

進を取得するには、単に returnColour();

+0

このアプローチを使用して誰でも公差変数で遊ぶことをお勧めします。設定した値に応じて、アルゴリズムは高速または低速で実行されます。 –

3

を呼び出して、私は支配的な色を得るために、私自身の方法を書いた:

方法1(マイ技術)

  1. ARGB_4444に削減色空間
  2. Comp UTE最大個々のRGB要素の発生及び3つの独特の最大値を求める
  3. 支配的なRGB色に最大値を結合

    public int getDominantColor1(Bitmap bitmap) { 
    
    if (bitmap == null) 
        throw new NullPointerException(); 
    
    int width = bitmap.getWidth(); 
    int height = bitmap.getHeight(); 
    int size = width * height; 
    int pixels[] = new int[size]; 
    
    Bitmap bitmap2 = bitmap.copy(Bitmap.Config.ARGB_4444, false); 
    
    bitmap2.getPixels(pixels, 0, width, 0, 0, width, height); 
    
    final List<HashMap<Integer, Integer>> colorMap = new ArrayList<HashMap<Integer, Integer>>(); 
    colorMap.add(new HashMap<Integer, Integer>()); 
    colorMap.add(new HashMap<Integer, Integer>()); 
    colorMap.add(new HashMap<Integer, Integer>()); 
    
    int color = 0; 
    int r = 0; 
    int g = 0; 
    int b = 0; 
    Integer rC, gC, bC; 
    for (int i = 0; i < pixels.length; i++) { 
        color = pixels[i]; 
    
        r = Color.red(color); 
        g = Color.green(color); 
        b = Color.blue(color); 
    
        rC = colorMap.get(0).get(r); 
        if (rC == null) 
         rC = 0; 
        colorMap.get(0).put(r, ++rC); 
    
        gC = colorMap.get(1).get(g); 
        if (gC == null) 
         gC = 0; 
        colorMap.get(1).put(g, ++gC); 
    
        bC = colorMap.get(2).get(b); 
        if (bC == null) 
         bC = 0; 
        colorMap.get(2).put(b, ++bC); 
    } 
    
    int[] rgb = new int[3]; 
    for (int i = 0; i < 3; i++) { 
        int max = 0; 
        int val = 0; 
        for (Map.Entry<Integer, Integer> entry : colorMap.get(i).entrySet()) { 
         if (entry.getValue() > max) { 
          max = entry.getValue(); 
          val = entry.getKey(); 
         } 
        } 
        rgb[i] = val; 
    } 
    
    int dominantColor = Color.rgb(rgb[0], rgb[1], rgb[2]); 
    
    return dominantColor; 
    } 
    

方法2(旧技術)

  1. 減らし〜ARGB_4444色空間
  2. 各色の発生及び最大のもののような支配的な色のAndroid 5.0ロリポップで

    public int getDominantColor2(Bitmap bitmap) { 
    if (bitmap == null) 
        throw new NullPointerException(); 
    
    int width = bitmap.getWidth(); 
    int height = bitmap.getHeight(); 
    int size = width * height; 
    int pixels[] = new int[size]; 
    
    Bitmap bitmap2 = bitmap.copy(Bitmap.Config.ARGB_4444, false); 
    
    bitmap2.getPixels(pixels, 0, width, 0, 0, width, height); 
    
    HashMap<Integer, Integer> colorMap = new HashMap<Integer, Integer>(); 
    
    int color = 0; 
    Integer count = 0; 
    for (int i = 0; i < pixels.length; i++) { 
        color = pixels[i]; 
        count = colorMap.get(color); 
        if (count == null) 
         count = 0; 
        colorMap.put(color, ++count); 
    } 
    
    int dominantColor = 0; 
    int max = 0; 
    for (Map.Entry<Integer, Integer> entry : colorMap.entrySet()) { 
        if (entry.getValue() > max) { 
         max = entry.getValue(); 
         dominantColor = entry.getKey(); 
        } 
    } 
    return dominantColor; 
    } 
    
+0

質問:bitmap2とは何ですか?元のビットマップからコピーした後は使用していないようです。 –

20

、それはより多くの近似だが、あなたは色を検索するための長い遅延を持たせたくない場合は、それが仕事をすることができます。

public static int getDominantColor(Bitmap bitmap) { 
    Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, 1, 1, true); 
    final int color = newBitmap.getPixel(0, 0); 
    newBitmap.recycle(); 
    return color; 
} 
+0

これは非常に有用な答えです。私はループメソッドを使用していたが、それはUIが不規則になっていた。今はとてもスムーズです。 –

+0

コードに構文エラーがあります。 –

+0

サポート:palette-v7:25.0.0では、これはもはやカスタムメソッドを必要とせず、単にpalette.getDominantSwatch()を使用します。 –

0

他の回答は私の仕事であり、問​​題の原因を除外しませんでした。

これは私が使用して終了するものである:

public static int getDominantColor(Bitmap bitmap) { 
    if (bitmap == null) { 
     return Color.TRANSPARENT; 
    } 
    int width = bitmap.getWidth(); 
    int height = bitmap.getHeight(); 
    int size = width * height; 
    int pixels[] = new int[size]; 
    //Bitmap bitmap2 = bitmap.copy(Bitmap.Config.ARGB_4444, false); 
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height); 
    int color; 
    int r = 0; 
    int g = 0; 
    int b = 0; 
    int a; 
    int count = 0; 
    for (int i = 0; i < pixels.length; i++) { 
     color = pixels[i]; 
     a = Color.alpha(color); 
     if (a > 0) { 
      r += Color.red(color); 
      g += Color.green(color); 
      b += Color.blue(color); 
      count++; 
     } 
    } 
    r /= count; 
    g /= count; 
    b /= count; 
    r = (r << 16) & 0x00FF0000; 
    g = (g << 8) & 0x0000FF00; 
    b = b & 0x000000FF; 
    color = 0xFF000000 | r | g | b; 
    return color; 
} 
関連する問題