2009-11-05 10 views
6

Necesito tomar una imagen JPG a todo color y reasignar sus colores a una paleta indexada. La paleta consistirá en colores específicos poblados de una base de datos. Necesito asignar cada color de la imagen a su valor "más cercano" en el índice. Estoy seguro de que existen diferentes algoritmos para comparar y calcular el valor "más cercano". En busca de bibliotecas de códigos administrados C#, .NET solamente.Convertir de 32-BPP a 8-BPP indexado (C#)

(Se usará en un proceso en el que tengamos aproximadamente 120 colores de botones, y queremos asignar cualquier imagen a esos 120 colores para hacer un collage).

+0

+1, buena pregunta! –

Respuesta

2

Este proceso se llama Quantization. Como cada color representa 3 valores compactos, deberá usar Octrees para resolver este problema.

Echa un vistazo a este article con código de ejemplo.

El artículo se centra en obtener la última paleta para la imagen, pero su proceso sería inverso para la segunda parte, solo reducirá los colores más utilizados que están cerca de la paleta dada.

+0

¿El framework .NET ha incorporado bibliotecas de cuantificación? –

+0

No tengo conocimiento de .NET (soy un chico de Linux), y estoy acostumbrado a hacer cosas yo mismo (TM). Lo siento, no puedo brindar más información. – LiraNuna

0

Tuve que hacer esto en un gran proyecto .NET. No hay nada en el marco para ello, pero este artículo me llevó rápidamente a una solución: http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/6103.aspx

+0

Su enlace está muerto. –

+0

Parece que acaban de eliminar el '.' en su nombre. Esto funciona: http://codebetter.com/brendantompkins/2004/01/26/use-gdi-to-save-crystal-clear-gif-images-with-net/ – Nestor

0

La palabra JPEG debe hacer sonar las alarmas. Es muy probable que las imágenes ya estén en un espacio de color altamente cuantificado, y el remuestreo adicional potencialmente introducirá un aliasing. Si puede, trabaje con imágenes sin comprimir para reducir este efecto.

La respuesta a su pregunta es sí, puede guardar las imágenes en un formato alternativo, pero no estoy seguro si la funcionalidad nativa es adecuada para lo que parece un requisito bastante complejo. Si puede definir la paleta de colores de la colección de imágenes, es probable que mejore la calidad de la salida.

La entrada de blog ya mencionada titulada Usar 'GDI + para guardar imágenes GIF transparentes con .NET' contiene referencias útiles al código.

3

Nada lo ayudará con GDI. Parece que las imágenes indexadas son una tecnología demasiado atrasada para que Microsoft se preocupe. Todo lo que puede hacer es leer y escribir archivos de imágenes indexadas.

por lo general hay dos pasos cuando los colores de cuantificación en una imagen:
1) Encontrar la mejor gama de colores para la imagen (color de cuantificación)
2) en el mapa los solors de origen a la paleta encontrado (Asignación de color)

Por lo que entiendo, ya tiene la paleta en la base de datos, eso significa que la parte más difícil se ha hecho por usted. Todo lo que necesita hacer es asignar los colores de 24 bits a los colores de paleta proporcionados. Si no tiene la paleta inicial, tendrá que calcularla usted mismo usando un algoritmo de cuantificación: los octrees o Median Cut son los más conocidos. Median Cut da mejores resultados pero es más lento y más difícil de implementar y afinar.

Para asignar los colores, el algoritmo más simple en su caso es calcular la distancia desde el color de origen a todos los colores de la paleta y elegir el más cercano.

float ColorDistanceSquared(Color c1, Color c2) 
{ 
    float deltaR = c2.R - c1.R; 
    float deltaG = c2.G - c1.G; 
    float deltaB = c2.B - c1.B; 
    return deltaR*deltaR + deltaG*deltaG + deltaB*deltaB; 
} 

También puede ponderar los canales de modo que el azul tiene menos peso, no ir demasiado al agua con él, de lo que dará resultados horribles, específicamente 30/59/11 no funcionará en absoluto:

float ColorDistanceSquared(Color c1, Color c2) 
{ 
    float deltaR = (c2.R - c1.R) * 3; 
    float deltaG = (c2.G - c1.G) * 3; 
    float deltaB = (c2.B - c1.B) * 2; 
    return deltaR*deltaR + deltaG*deltaG + deltaB*deltaB; 
} 

Llama esa cosa para todos los colores de fuente y paleta y busca el valor Mín. Si almacena en caché los resultados a medida que avanza en un mapa, esto será muy rápido.

Además, el color de la fuente rara vez se ajustará a un color de paleta suficiente para no crear bandas y áreas planas y la pérdida de detalles en su imagen. Para evitar eso, puedes usar el dithering. El algoritmo más simple y el que ofrece los mejores resultados es el Difuminado de difusión de errores.

Una vez que haya mapeado sus colores, tendrá que bloquear manualmente un mapa de bits y escribir los índices allí, ya que .Net no le permitirá escribir en una imagen indexada.