2009-11-05 5 views
6

Ich muss ein Vollfarb-JPG-Bild und neu zuordnen seine Farben auf eine indizierte Palette. Die Palette besteht aus bestimmten Farben, die aus einer Datenbank stammen. Ich muss jede Farbe des Bildes dem "nächsten" Wert im Index zuordnen. Ich bin mir sicher, dass es verschiedene Algorithmen gibt, um den "nächsten" Wert zu vergleichen und zu berechnen. Suchen Sie nur nach C#, .NET-verwalteten Codebibliotheken.Convert von 32-BPP zu 8-BPP Indexed (C#)

(Es wird in einem Prozess verwendet, wo wir 120 oder so bestimmte Farben von Tasten haben, und wir wollen jedes Bild zu diesen 120 Farben zuordnen, um eine Collage zu machen).

+0

+1, nette Frage! –

Antwort

2

Dieser Prozess heißt Quantization. Da jede Farbe 3 gepackte Werte darstellt, müssen Sie Octrees verwenden, um dieses Problem zu lösen.

Überprüfen Sie diese article mit Beispielcode.

Der Artikel konzentriert sich auf die ultimative Palette für das Bild, aber Ihr Prozess wäre es umgekehrt für den zweiten Teil, reduzieren Sie nur die am häufigsten verwendeten Farben, die in der Nähe der angegebenen Palette sind.

+0

Also hat das .NET-Framework in Quantisierung Bibliotheken eingebaut? –

+0

Ich habe keine Kenntnisse von .NET (ich bin ein Linux-Typ), und ich bin es gewohnt, Sachen selbst (TM) zu tun. Entschuldigung, ich kann keine weiteren Informationen liefern. – LiraNuna

0

Ich musste dies in einem großen .NET-Projekt tun. Es gibt nichts im Rahmen dafür, aber dieser Artikel führte mich schnell zu einer Lösung: http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/6103.aspx

+0

Ihr Link ist tot. –

+0

Sieht so aus, als hätten sie nur das '.' in seinem Namen. Das funktioniert: http://codebetter.com/bregantompkins/2004/01/26/use-gdi-to-save-crystal-clear-gif-images-with-net/ – Nestor

0

Das JPEG-Wort sollte Alarmglocken läuten. Die Bilder befinden sich sehr wahrscheinlich bereits in einem stark quantisierten Farbraum und weiteres Resampling wird möglicherweise Aliasing einführen. Wenn Sie können, arbeiten Sie mit unkomprimierten Bildern, um diesen Effekt zu reduzieren.

Die Antwort auf Ihre Frage ist ja - Sie können die Bilder in einem alternativen Format speichern - aber ich bin mir nicht sicher, ob die native Funktionalität für das, was wie eine ziemlich komplexe Anforderung klingt, angemessen ist. Wenn Sie die Farbpalette aus der Sammlung von Bildern definieren können, verbessern Sie wahrscheinlich die Qualität der Ausgabe.

Der bereits erwähnte Blog-Eintrag mit dem Titel 'GDI + zum Speichern von kristallklaren GIF-Bildern mit .NET' enthält nützliche Verweise auf Code.

3

Nichts wird Ihnen mit GDI helfen. Es scheint, indexierte Bilder sind zu rückständig eine Technologie für Microsoft zu kümmern. Sie können nur indizierte Bilddateien lesen und schreiben.

Es gibt in der Regel zwei Schritt, wenn die Quantisierung Farben in einem Bild:
1) Finden Sie die besten Palette für das Bild (Farbquantisierung)
2) Ordnen Sie die Quelle solors auf die gefundene Palette (Color Mapping)

Von dem, was ich verstehe, haben Sie bereits die Palette in der Datenbank, dh der schwierigste Teil wurde für Sie erledigt. Alles, was Sie tun müssen, ist, die 24-Bit-Farben den bereitgestellten Palettenfarben zuzuordnen. Wenn Sie nicht über die Startpalette verfügen, müssen Sie sie mit einem Quantisierungsalgorithmus berechnen: Am bekanntesten sind Octrees oder Median Cut. Median Cut liefert bessere Ergebnisse, ist jedoch langsamer und schwieriger zu implementieren und fein abzustimmen.

Um die Farben zuzuordnen, ist der einfachste Algorithmus in Ihrem Fall, den Abstand von Ihrer Quellfarbe zu allen Palettenfarben zu berechnen und den nächsten auszuwählen.

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

Sie können ponderate auch die Kanäle, so dass blaue weniger Gewicht hat, gehen Sie nicht zu über Bord mit ihm, sonst wird es schrecklich Ergebnisse geben, speziell 30/59/11 wird nicht funktionieren:

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

Nennen Sie dieses Ding für alle Quell- und Palettenfarben und finden Sie die Min. Wenn Sie Ihre Ergebnisse auf einer Karte zwischenspeichern, wird das sehr schnell gehen.

Außerdem passt die Quellfarbe selten zu einer Palettenfarbe, die nicht zu Streifenbildung und Unebenheiten sowie zum Verlust von Details in Ihrem Bild führt. Um dies zu vermeiden, können Sie Dithering verwenden. Der einfachste Algorithmus, der die besten Ergebnisse liefert, ist das Error Diffusion Dithering.

Sobald Sie Ihre Farben zugeordnet haben, müssen Sie ein Bitmap manuell sperren und die Indizes darin schreiben, da .Net Ihnen nicht erlaubt, auf ein indiziertes Bild zu schreiben.