2012-05-12 22 views
7

Ich versuche, ein Bild verlustfrei zu komprimieren, und um Regelmäßigkeiten auszunutzen, möchte ich das Bild von RGB in Y'CbCr konvertieren. (Die genauen Einzelheiten, was ich mit RGB und Y'CbCr meine, sind hier nicht wichtig; die RGB-Daten bestehen aus drei Bytes, und ich habe drei Bytes, um das Ergebnis zu speichern.)Verlustfreie RGB zu Y'CbCr Umwandlung

Der Konvertierungsprozess selbst ist ziemlich einfach Aber es gibt ein Problem: Obwohl die Transformation mathematisch invertierbar ist, wird es in der Praxis Rundungsfehler geben. Natürlich sind diese Fehler klein und praktisch nicht wahrnehmbar, aber es bedeutet, dass der Prozess nicht mehr verlustfrei ist.

Meine Frage ist: ist eine Transformation existiert, das (die roten, grünen und blauen Komponenten) in drei anderen acht-Bit-Integer (die einen Farbraum drei Acht-Bit-Integer konvertiert ähnlich wie Y'CbCr, wo zwei Komponenten ändern sich nur geringfügig in Bezug auf die Position, oder zumindest weniger als in einem RGB-Farbraum), und das kann ohne Informationsverlust invertiert werden?

Antwort

14

YCoCg24

Hier ist eine Farbtransformation I „YCoCg24“ nenne, dass die drei Acht-Bit-Ganzzahl umwandelt (repräsentierte Rot-, Grün- und Blau-Komponenten) in drei andere acht Bit (Vorzeichen) ganze Zahlen (repräsentierte ein Farbraum ähnlich wie Y'CbCr) und bijektiv ist (und daher kann ohne Informationsverlust umgekehrt werden):

G   R   B  Y   Cg   Co 
|   |   |  |   |   | 
|   |->-(-1)->(+) (+)<-(-/2)<-|   | 
|   |   |  |   |   | 
|   (+)<-(/2)-<-|  |->-(+1)->(+)   | 
|   |   |  |   |   | 
|->-(-1)->(+)   |  |   (+)<-(-/2)<-| 
|   |   |  |   |   | 
(+)<-(/2)-<-|   |  |   |->-(+1)->(+) 
|   |   |  |   |   | 
Y   Cg   Co G   R   B 

forward transformation  reverse transformation 

oder in Pseudo-Code:

function forward_lift(x, y): 
    signed int8 diff = (y - x) mod 0x100 
    average = (x + (diff >> 1)) mod 0x100 
    return (average, diff) 

function reverse_lift(average, signed int8 diff): 
    x = (average - (diff >> 1)) mod 0x100 
    y = (x + diff) mod 0x100 
    return (x, y) 

function RGB_to_YCoCg24(red, green, blue): 
    (temp, Co) = forward_lift(red, blue) 
    (Y, Cg) = forward_lift(green, temp) 
    return(Y, Cg, Co) 

function YCoCg24_to_RGB(Y, Cg, Co): 
    (green, temp) = reverse_lift(Y, Cg) 
    (red, blue) = reverse_lift(temp, Co) 
    return(red, green, blue) 

Einige Beispiel-Farben:

color  R G B  Y CoCg24 
white  0xFFFFFF 0xFF0000 
light grey 0xEFEFEF 0xEF0000 
dark grey 0x111111 0x110000 
black  0x000000 0x000000 

red  0xFF0000 0xFF01FF 
lime  0x00FF00 0xFF0001 
blue  0x0000FF 0xFFFFFF 

G, R-G, B-G-Farbraum

Eine andere Farbtransformation, die drei Acht-Bit-Integer in drei anderen acht-Bit-Integer umwandelt.

function RGB_to_GCbCr(red, green, blue): 
    Cb = (blue - green) mod 0x100 
    Cr = (red - green) mod 0x100 
    return(green, Cb, Cr) 

function GCbCr_to_RGB(Y, Cg, Co): 
    blue = (Cb + green) mod 0x100 
    red = (Cr + green) mod 0x100 
    return(red, green, blue) 

Einige Beispiel-Farben:

color  R G B  G CbCr 
white  0xFFFFFF 0xFF0000 
light grey 0xEFEFEF 0xEF0000 
dark grey 0x111111 0x110000 
black  0x000000 0x000000 

Kommentare

Es scheint schon einige lossless color space transforms zu sein. Mehrere verlustfreie Farbraumtransformationen werden in Henrique S. Malvar, et al."Lifting-based reversible color transformations for image compression"; gibt es die verlustfreie Farbraumtransformation in JPEG XR; die ursprüngliche reversible Farbtransformation (ORCT), die in verschiedenen "lossless JPEG" Vorschlägen verwendet wird; G-, R-G-, B-G-Farbraum; usw. Malvar und andere scheinen ziemlich begeistert von der 26-Bit-YCoCg-R-Darstellung eines 24-Bit-RGB-Pixels zu sein.

Fast alle von ihnen erfordern jedoch mehr als 24 Bits, um die umgewandelte Pixelfarbe zu speichern.

Die Technik "lifting", die ich in YCoCg24 verwende, ähnelt der in Malvar et al. Und der verlustfreien Farbraumtransformation in JPEG XR.

Da zusätzlich umkehrbar (und Addition modulo 0x100 bijektiv), jede Transformation von (a, b) zu (x, y), die durch die folgende Feistel network hergestellt werden können, ist reversibel und bijektive:

a  b 
|  | 
|->-F->-(+) 
|  | 
(+)-<-G-<-| 
|  | 
x  y 

wobei (+) eine 8-Bit-Addition (Modulo 0x100), Abxy alle 8-Bit-Werte und F und G eine beliebige Funktion angeben.

Details

Warum haben Sie nur 3 Bytes in das Ergebnis zu speichern? Das klingt nach einem kontraproduktiven premature optimization. Wenn es Ihr Ziel ist, ein Bild in einer möglichst kleinen komprimierten Datei verlustfrei zu komprimieren, ist die Größe der Zwischenstufen irrelevant. Es kann sogar kontraproduktiv sein - eine "größere" Zwischendarstellung (wie Reversible Color Transformation oder der 26-Bit-YCoCg-R) kann in kleinere endgültige komprimierte Dateigröße als eine "kleinere" Zwischendarstellung (wie z RGB oder YCoCg24).

EDIT: Oopsies. Entweder eines von "(x) mod 0x100" oder "(x) & 0xff" geben genau die gleichen Ergebnisse - die Ergebnisse, die ich wollte. Aber irgendwie habe ich sie zusammengewürfelt, um etwas zu produzieren, das nicht funktionieren würde.

+0

Vielen Dank für diese ausführliche Antwort. Der Grund für die 24-Bit-Anforderung ist ein praktischer. Ich verstehe, dass das Arbeiten mit einer 26-Bit-Zwischenstufe das Komprimierungsverhältnis verbessern kann (tatsächlich gab es mehrere Zwischenstufen, die die Größe des Stroms erhöhten). Der Algorithmus, den ich verwendete, arbeitet jedoch auf einzelnen Bytes, nicht auf Bits. Wenn der Bitstrom als Byte-Stream behandelt wird, verliert er die schönen Eigenschaften, die durch die Farbraum-Transformation entstehen. – Ruud

+0

Ja, jedes Mal, wenn ich ein System von einem Byte-Stream in einen Bit-Stream umschalte, dauert das System normalerweise etwa 8 mal so lange und ist viel schwieriger zu debuggen. Ich habe also Verständnis dafür, dass Sie möglichst bei Byte-Streams bleiben wollen. –

+0

David, das ist eine sehr coole Transformation. Vielen Dank für die Bereitstellung. Eine Sache zu beachten, sollte Ihr reverse_lift X und Y, nicht Durchschnitt und Diff zurückgeben. – MoDJ

2

Ich habe von JPEG eine solche Lösung, verwendet finden 2000. Es ist eine reversible Farbtransformation (RCT) genannt, und es wird bei Wikipedia sowie die JPEG site (obwohl die Rundungsmethoden sind nicht konsistent) beschrieben. Die Ergebnisse sind jedoch nicht so gut wie bei der irreversiblen Farbtransformation.

Ich fand auch eine bessere Methode beschrieben in der Veröffentlichung Verbesserte reversible Integer-zu-Integer-Farbtransformationen von Soo-Chang Pei und Jian-Jiun Ding. Die in diesem Dokument beschriebenen Methoden und die von JPEG 2000 verwendete Methode erfordern jedoch zusätzliche Bits zum Speichern des Ergebnisses. Dies bedeutet, dass die transformierten Werte nicht mehr in 24 Bits passen.