2012-10-09 95 views
9

tengo una aplicación que indexa los 16 mejores colores que aparecen en los videos.¿Cómo convertir un color RGB al color de 8 bits más parecido?

Estoy tratando de escribir otra aplicación que permite al usuario seleccionar un color y luego la aplicación encuentra todos los vídeos que este color aparece en.

El problema es que, ya que sólo índice de 16 colores por vídeo, los usuarios eligen un color RGB. La probabilidad de que este color esté indexado es muy baja, por lo que casi siempre mi aplicación no arroja resultados.

Pensé en una forma en que podría hacer que esto funcione, podría indexar los colores que aparecen en el video y convertirlos al color más cercano de 8 bits.

Luego, cuando un usuario selecciona un color RGB, puedo convertir la opción del usuario al color más cercano a 8 bits.

De esta forma siempre tendría partidos.

El único gran problema que tengo ahora es cómo convertir un color RGB al color de 8 bits más cercano?

+0

¿Qué idioma estás usando? Tal vez alguna biblioteca ya hace el truco. –

+0

Un color de 8 bits podría hacerse de diferentes maneras. Podría ser un índice en una tabla de colores, o un valor RRRGGGBB, etc. ¿Qué tipo de colores de 8 bits estaba buscando usar? – cHao

+0

8 bits no es suficiente para representar un color arbitrario. –

Respuesta

0

¿Está familiarizado con Floyd–Steinberg dithering? Esto se usa para convertir colores de orden superior a colores de orden inferior, p. RGB de 24 bits RGB a 3 bit (8 colores) o restricción de una imagen RGB a 8 bits (256 colores) para una conversión GIF.

Este algoritmo se describe en la página de Wikipedia vinculado.

+0

La idea es convertir un solo color. El difuminado no tiene sentido en esta aplicación. –

4

Lo que necesita hacer es convertir el RGB a un valor de HSB (brillo de saturación del tono). HSB tiene 3 bytes, al igual que RGB, la diferencia es que los valores de HSB se pueden comparar mucho más fácilmente que RGB.

Su siguiente paso es decidir sobre una ponderación de "importancia". Por ejemplo, si lo único que importa es el "color/enfoque", no la saturación o el brillo, entonces se puede tirar a la basura los bytes S y B y sólo tiene que utilizar el byte de color.

Si se tratara de mí y yo se vieron limitados a 8 bits yo usaría 4 bits de información de color (16 colores diferentes), 3 bits de saturación (8 valores diferentes), y 1 bit de información de brillo (claras u oscuras) .

En este artículo se describe cómo hacer HSB en Java:

http://java.sys-con.com/node/43559

El código fuente de este artículo tiene un convertidor de RGB a HSB en Java.

+0

Iría con 2 bits de saturación y 2 bits de brillo yo mismo. –

5

Convertir en la paleta segura para la Web, es necesario convertir el rango de cada uno de los R, G, B 0-255 componentes a 0-5 y combinarlos:

color = (r*6/256)*36 + (g*6/256)*6 + (b*6/256) 
2

Una posibilidad es simplemente escalar su color de 24 bits hacia abajo en un espacio de color de 8 bits. Como cHao menciona, podría usar RRRGGGBB para su número de 8 bits. A continuación, cada componente de color se puede calcular mediante un simple algoritmo de escala, tales como:

byte red = (originalColor.red * 8)/256; 
byte green = (originalColor.green * 8)/256; 
byte blue = (originalColor.blue * 4)/256; 

El 8, 4, y 254 son el número de posibles valores en cada componente de color. En su color original de 24 bits, rojo, verde y azul pueden tener 256 valores posibles, por lo que es el divisor de la ecuación de escala. En el ejemplo de color de 8 bits, el rojo y el verde son cada uno de 3 bits (8 valores posibles) y el azul es de 2 bits (4 valores posibles).

Después de obtener estos tres componentes, se pueden combinar con un poco de aritmética simple desplazamiento de bits:

byte eightBitColor = (red << 5) | (green << 2) | blue; 

A continuación, puede comparar estos colores de 8 bits. Su resolución drásticamente reducida puede ayudarte.

Alternativamente, puede hacer algo como lo sugirió Tyler, y convertir primero a HSB o HSV, y solo comparar tonos (dependiendo de si necesita o no información de brillo y saturación). Dependiendo de su objetivo, esa puede ser una solución más ideal.

Editar: Algoritmo de escala modificado para corregir una deficiencia señalada por Mark Ransom.

+0

Con un rango de color de solo 8 bits, tiene más sentido ignorar los límites de los bits y usar rangos que no sean potencias de 2. Su respuesta tiene 8 posibles rojos, 8 verdes posibles, pero solo 4 azules posibles; más típico es 6,6,6 (como en mi respuesta) o 6,7,6. Además, su escalado está un poco apagado ya que solo una entrada de 255 dará la salida máxima y esos valores estarán subrepresentados. –

+0

Eso es cierto. Realmente solo estaba tratando de explicar el comentario de cHao. He editado mi respuesta para solucionar el problema de escala. –

+0

JSBin: http://jsbin.com/voqacamema/3/ –

0

probar este algoritmo si desea convertir una imagen 24 bpp imagen de 8 bpp a:

for y = 0 to ImageHeight - 1 
    for x = 0 to ImageWidth - 1 
     GetPixel(x,y,red,grn,blu) 
     {read RGB data from 24bpp file} 
     d0 = red^2 + grn^2 + blu^2 
     ColorIndex = 0 
     for cl = 0 to 255 
     GetPaletteData(p_red,p_gre,p_blu) 
     {read RGB data from 8bpp palette} 
     d = (red - p_red)^2 + (grn - p_grn)^2 + (blu - p_blu)^2 
     if d0 >= d then 
      ColorIndex = cl 
      d0 = d 
     end if 
     next cl 
     {use ColorIndex to create your 8bpp file} 
    next x 
    next y 

Antes de este paso, leer más acerca de los archivos 8bpp en Wikipedia u otras fuentes.

¡Buena suerte!

Cuestiones relacionadas