it-swarm.com.de

Finden der dominanten Farbe eines Bildes in einem @ @ drawable-Android

Sie können verstehen, warum ich versuche, die dominante Farbe in einem Bild zu finden, wenn Sie Windows 7 verwenden. Wenn Sie mit der Maus über ein Programm in der Taskleiste fahren, ändert sich der Hintergrund dieses bestimmten Programms basierend auf der dominantesten Farbe des Symbols. Ich habe diese Technik auch in anderen Programmen bemerkt, kann mich aber nicht an sie erinnern.

Ich kann mir vorstellen, dass dies in einer Reihe von UI-Techniken hilfreich ist, die ich zum Entwickeln einer Anwendung verwende, und ich habe mich gefragt, wie das Ermitteln der gebräuchlichsten Farbe von einer Android-Ressource aus möglich wäre.

36
styler1972

In Android 5.0 Lollipop wurde eine Klasse hinzugefügt, um nützliche Farben aus einer Bitmap zu extrahieren. Die in Android.support.v7.graphics gefundene Palette class kann die folgenden Farben extrahieren:

  • Beschwingt
  • Lebendige Dunkelheit
  • Lebendiges Licht
  • Gedämpft
  • Gedämpftes Dunkel
  • Gedämpftes Licht

Diese Android-Schulungsseite enthält alle Details, die Sie zur Verwendung der Klasse benötigen (ich habe es selbst in Android Studio ausprobiert und war sehr unkompliziert): http://developer.Android.com/training/material/drawables.html#ColorExtract

Zitieren:

Die Android Support Library r21 und höher enthält die Palette Klasse, mit der Sie auffällige Farben aus einem Bild extrahieren können. Zu extrahieren Sie diese Farben, übergeben Sie ein Bitmap-Objekt an Palette.generate () statische Methode im Hintergrund-Thread, in den Sie Ihre Bilder laden. Ob Sie können diesen Thread nicht verwenden. Rufen Sie die Palette.generateAsync () - Methode und .__ auf. Geben Sie stattdessen einen Listener an. *

Sie können die hervorstechenden Farben mit dem Getter aus dem Bild abrufen Methoden in der Palette-Klasse, z. B. Palette.getVibrantColor.

Um die Palette-Klasse in Ihrem Projekt zu verwenden, fügen Sie den folgenden Gradle .__ hinzu. Abhängigkeit von Ihrem App-Modul:

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

* Wenn Sie generateAsync () verwenden müssen, gehen Sie folgendermaßen vor:

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

BEARBEITEN: Da bei der Frage nach dem Extrahieren von Farben aus einer anzeigbaren Ressource gefragt wird, müssen Sie zunächst das Zeichenobjekt in eine Bitmap konvertieren, um die beschriebene Methode zu verwenden. Glücklicherweise ist das mit BitmapFactory ganz einfach:

Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
                                       R.drawable.icon_resource);`
60
Tony Wickham

Es gibt auch eine andere Lösung, sie ist näherungsweise. Wenn Sie jedoch keine lange Verzögerung bei der Suche nach Farbe wünschen, kann dies die Aufgabe erfüllen.

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;
}
25
Pdroid

Diese Klasse durchläuft eine Bitmap und gibt die dominanteste Farbe zurück. Gerne können Sie den Code bei Bedarf bereinigen.

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";
    }
}

um das Hex zu erhalten, rufen Sie einfach returnColour(); auf.

7

Ich habe meine eigenen Methoden geschrieben, um dominante Farben zu erhalten:

Methode 1 (Meine Technik)

  1. Reduzieren Sie auf ARGB_4444 Farbraum
  2. Berechnen Sie das maximale Vorkommen einzelner RGB-Elemente und erhalten Sie drei unterschiedliche Maximalwerte
  3. Maximalwerte zu dominanten RGB-Farben kombinieren

    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;
     }
    

Methode 2 (alte Technik)

  1. Reduzieren Sie auf ARGB_4444 Farbraum
  2. Berechnen Sie das Vorkommen jeder Farbe und ermitteln Sie die maximale Farbe als dominante Farbe

    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;
    }
    
4
Mohsen Afshin

Durchlaufen Sie alle Farbdaten des Pixels und mitteln Sie die Farbwerte. Ignorieren Sie alles, was eine Graustufe oder eine Transparenz ist. Ich glaube, das ist das, was Microsoft in Windows 7 auf der Grundlage eines kürzlich veröffentlichten Blogposts tut.

edit
Der Blogeintrag: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/12/10/10244432.aspx

Dieser Link, der zeigt, wie Chrome die dominierende Farbe auswählt, kann ebenfalls hilfreich sein. http://www.quora.com/Google-Chrome/How-does-Chrome-pick-the-color-for-the-stripes-on-the-Most-visited-page-thumbnails

2
Bradley Uffner

Um die Dominant/Vibrant/Muted Farbe aus einem Bild zu ermitteln, verwenden Sie Palette :

importieren:

implementation 'androidx.palette:palette:1.0.0'

Verwendung:

    val bitmap = BitmapFactory.decodeResource(resources, R.drawable.image)

    Palette.Builder(bitmap).generate { it?.let {  palette ->
        val dominantColor = palette.getDominantColor(ContextCompat.getColor(context!!, R.color.defaultColor))

        // TODO: use dominant color

    } }
1
Francis

Keine der anderen Antworten hat die Aufgabe für mich erfüllt, und ich habe die Ursache des Problems nicht ausgeschlossen.

Das habe ich am Ende gebraucht:

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;
}
0
rraallvv

Abhängigkeiten hinzufügen

implementation 'androidx.palette:palette:1.0.0'

und..

Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Palette.from(bitmap).generate(palette -> {
    int vibrant = palette.getVibrantColor(0x000000); // <=== color you want
    int vibrantLight = palette.getLightVibrantColor(0x000000);
    int vibrantDark = palette.getDarkVibrantColor(0x000000);
    int muted = palette.getMutedColor(0x000000);
    int mutedLight = palette.getLightMutedColor(0x000000);
    int mutedDark = palette.getDarkMutedColor(0x000000);
});
0
Williaan Lopes