YCoCg24
Aquí es una transformación de color que llamo "YCoCg24" que que convierte tres enteros de ocho bits (que representan los componentes rojo, verde y azul) en tres otros ocho bits (firmado) enteros (que representan un espacio de color similar a Y'CbCr), y es biyectiva (y por lo tanto se puede invertir sin pérdida de información):
G R B Y Cg Co
| | | | | |
| |->-(-1)->(+) (+)<-(-/2)<-| |
| | | | | |
| (+)<-(/2)-<-| |->-(+1)->(+) |
| | | | | |
|->-(-1)->(+) | | (+)<-(-/2)<-|
| | | | | |
(+)<-(/2)-<-| | | |->-(+1)->(+)
| | | | | |
Y Cg Co G R B
forward transformation reverse transformation
o en pseudocódigo:
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)
Algunos colores ejemplo:
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 espacio de color
Otra transformación de color que convierte tres enteros de ocho bits en otros tres enteros de ocho bits.
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)
Algunos colores ejemplo:
color R G B G CbCr
white 0xFFFFFF 0xFF0000
light grey 0xEFEFEF 0xEF0000
dark grey 0x111111 0x110000
black 0x000000 0x000000
comentarios
Parece que hay un buen número lossless color space transforms. Se mencionan varias transformaciones de espacio de color sin pérdidas en Henrique S. Malvar, et al."Lifting-based reversible color transformations for image compression"; existe la transformación del espacio de color sin pérdida en JPEG XR; la transformada de color reversible original (ORCT) utilizada en varias propuestas "lossless JPEG"; G, R-G, B-G espacio de color; etc. Malvar et al parecen muy entusiasmados con la representación de 26 bits de YCoCg-R de un píxel RGB de 24 bits.
Sin embargo, casi todos requieren más de 24 bits para almacenar el color del píxel transformado.
La técnica "lifting" que uso en YCoCg24 es similar a la de Malvar et al y a la transformación de espacio de color sin pérdida en JPEG XR.
Debido adición es reversible (y adición módulo 0x100 es biyectiva), cualquier transformar de (a, b) a (x, y) que puede ser producido por el siguiente Feistel network es reversible y biyectiva:
a b
| |
|->-F->-(+)
| |
(+)-<-G-<-|
| |
x y
donde (+) indica la adición de 8 bits (módulo 0x100), abxy son todos valores de 8 bits, y F y G indican cualquier función arbitraria.
detalles
¿Por qué sólo tiene 3 bytes para almacenar el resultado en? Eso suena como un contraproducente premature optimization. Si su objetivo es comprimir sin pérdidas una imagen en un archivo comprimido lo más pequeño posible en un período de tiempo razonable, entonces el tamaño de las etapas intermedias es irrelevante. Incluso puede ser contraproducente: una representación intermedia "más grande" (como Transformación de color reversible o YCoCg-R de 26 bits) puede dar como resultado un tamaño de archivo comprimido final más pequeño que una representación intermedia "más pequeña" (como RGB o YCoCg24).
EDITAR: Oopsies. Cualquiera de "(x) mod 0x100" o "(x) & 0xff" da exactamente los mismos resultados - los resultados que quería. Pero de alguna manera los mezclé para producir algo que no funcionaría.
Gracias por esta respuesta elaborada. La razón del requisito de 24 bits es práctica. Entiendo que trabajar con una etapa intermedia de 26 bits puede mejorar la relación de compresión (de hecho, hubo múltiples etapas intermedias que aumentaron el tamaño de la transmisión). Sin embargo, el algoritmo que estaba usando opera en bytes individuales, no en bits. Al tratar el flujo de bits como un flujo de bytes, perdería las bonitas propiedades que presenta la transformación del espacio de color. – Ruud
Sí, cada vez que cambio un sistema de una secuencia de bytes a una secuencia de bits, el sistema suele tardar unas 8 veces más en ejecutarse y es mucho más difícil de depurar. Entonces simpatizo con tu deseo de seguir con los flujos de bytes si es posible. –
David, esta es una transformación muy buena. Muchas gracias por brindarlo. Una cosa a tener en cuenta, su reverse_lift debería devolver x e y, no promedio y diff. – MoDJ