Finding the dominant color of an image in an Android @drawable

后端 未结 8 797
情深已故
情深已故 2020-11-28 20:42

You can understand why I\'m trying to find the dominant color in an image if you use Windows 7. When your mouse over a program in the taskbar, the background of that partic

相关标签:
8条回答
  • 2020-11-28 20:55

    There is also an another solution, it's more approximative but if you don't want to have long delay for searching color, it can do the job.

    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 讨论(0)
  • 2020-11-28 21:05

    Add to dependencies

    implementation 'androidx.palette:palette:1.0.0'
    

    and..

     AppCompatImageView imageView = findViewById(R.id.image_view);
    
     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 讨论(0)
  • 2020-11-28 21:14

    None of the other answers did the job for me, and I didn't rule out the cause of the problem.

    This is what I ended up using:

    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 讨论(0)
  • 2020-11-28 21:15

    This class iterates through a Bitmap and returns the most dominate colour. Feel free to clean up the code where necessary.

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

    to get the hex simply call returnColour();

    0 讨论(0)
  • 2020-11-28 21:15

    I wrote my own methods to get dominant color:

    Method 1 (My technique)

    1. Reduce to ARGB_4444 color space
    2. Compute the maximum occurrence of individual RGB elements and obtaining 3 distinctive maximum values
    3. Combining maximum values to dominant RGB color

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

    Method 2 (Old technique)

    1. Reduce to ARGB_4444 color space
    2. Compute the occurrence of each color and finding the maximum one as dominant color

      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 讨论(0)
  • 2020-11-28 21:17

    Loop through all the pixel's color data and average the color values, ignore anything that is a shade of grey or transparent. I believe that is what Microsoft does in Windows 7 based on a recent blog post.

    edit
    The blog post: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/06/10244432.aspx

    This link showing how Chrome picks the dominant color may also be helpful. http://www.quora.com/Google-Chrome/How-does-Chrome-pick-the-color-for-the-stripes-on-the-Most-visited-page-thumbnails

    0 讨论(0)
提交回复
热议问题