Android: Obtener el color dominante de una imagen

El color dominante de una imagen es el que más presencia tiene en ella. Ultimamente se empieza a usar en aplicaciones en las que algunos elementos adquieren el color de fondo de algún elemento importante; por ejemplo en la aplicación Wally (que encabeza esta entrada) lo usan de una forma muy adecuada y que seguramente será la tendencia en las nuevas versiones de Android.

El proceso sería más o menos el siguiente:

  1. Se inician los contadores de rojo, verde y azul a 0.
  2. Se cuentan los pixeles de la imagen.
  3. Se cuenta la cantidad de rojo / verde / azul de cada pixel y se suma al contador.
  4. Cada contador se divide por el numero de pixeles.
  5. El resultado es el color dominante: rgb(contador rojo, verde, azul)

Si alguien lo usa, me gustaría que me enseñase el resultado, porque suele quedar bastante curioso.

La siguiente función además tiene en cuenta el nivel de opacidad de cada pixel.

Esta función supone un esfuerzo importante para el procesador. Utilizarla con cuidado.

public static int getDominantColor(Bitmap bitmap) {
    if (null == bitmap) return Color.TRANSPARENT;

    int redBucket    = 0;
    int greenBucket  = 0;
    int blueBucket   = 0;
    int alphaBucket  = 0;

    boolean hasAlpha = bitmap.hasAlpha();
    int pixelCount   = bitmap.getWidth() * bitmap.getHeight();
    int[] pixels     = new int[pixelCount];

    bitmap.getPixels(
        pixels,
        0,
        bitmap.getWidth(),
        0,
        0,
        bitmap.getWidth(),
        bitmap.getHeight()
    );

    for (int y = 0, h = bitmap.getHeight(); y < h; y++){
        for (int x = 0, w = bitmap.getWidth(); x < w; x++){
            int color   =  pixels[x + y * w];            // x + y * width
            redBucket   += (color >> 16) & 0xFF;         // Color.red
            greenBucket += (color >> 8) & 0xFF;          // Color.greed
            blueBucket  += (color & 0xFF);               // Color.blue
            if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
        }
    }

    return Color.argb(
        (hasAlpha) ? (alphaBucket / pixelCount) : 255,
        redBucket / pixelCount,
        greenBucket / pixelCount,
        blueBucket / pixelCount
    );
}

Comentarios (5)

Holaa :D, ¿este codigo se puede usar libremente?
Lo he utilizado, y creo que funcionará, solo que se me detiene la App, como dice, si fuerza el procesador, veré como lo arreglo.
Hice el esfuerzo en comprender todo el código. La unica duda que me había quedado era que significaba el: & 0xFF . Pero por ahí leí que era la forma hexadecimal int(255).
Es un excelente codigo, muchas gracias por publicarlo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.