我试图无损压缩图像,为了利用规律性,我想将图像从RGB转换为Y'CbCr。 (RGB和Y'CbCr的确切细节在这里并不重要; RGB数据由三个字节组成,我有三个字节来存储结果。)
转换过程本身非常简单,但有一个问题:虽然转换在数学上是可逆的,但实际上会出现舍入误差。当然,这些错误很小,几乎无法察觉,但它确实意味着该过程不再是无损的。
我的问题是:是否存在转换,将三个八位整数(表示红色,绿色和蓝色分量)转换为另外三个八位整数(表示类似于Y'CbCr的颜色空间,其中两个组件发生变化仅略微相对于位置,或者至少小于RGB颜色空间),并且可以在不丢失信息的情况下进行反转?
答案 0 :(得分:15)
<强> YCoCg24 强>
这是一个我称之为“YCoCg24”的颜色转换,它将三个八位整数(表示红色,绿色和蓝色分量)转换为另外三个八位(带符号)整数(表示类似于Y'CbCr的颜色空间) ),并且是双射的(因此可以在不丢失信息的情况下反转):
G R B Y Cg Co
| | | | | |
| |->-(-1)->(+) (+)<-(-/2)<-| |
| | | | | |
| (+)<-(/2)-<-| |->-(+1)->(+) |
| | | | | |
|->-(-1)->(+) | | (+)<-(-/2)<-|
| | | | | |
(+)<-(/2)-<-| | | |->-(+1)->(+)
| | | | | |
Y Cg Co G R B
forward transformation reverse transformation
或伪代码:
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 )
一些示例颜色:
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色彩空间
另一种颜色转换,将三个八位整数转换为另外三个八位整数。
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 )
一些示例颜色:
color R G B G CbCr
white 0xFFFFFF 0xFF0000
light grey 0xEFEFEF 0xEF0000
dark grey 0x111111 0x110000
black 0x000000 0x000000
<强>评论强>
似乎有不少lossless color space transforms。 Henrique S. Malvar等人提到了几种无损色彩空间变换。 "Lifting-based reversible color transformations for image compression"; 在JPEG XR中有无损色彩空间转换; 几个“lossless JPEG”提案中使用的原始可逆颜色变换(ORCT); G,R-G,B-G色空间; 等等 Malvar等人似乎对24位RGB像素的26位YCoCg-R表示感到非常兴奋。
但是,几乎所有这些都需要超过24位才能存储转换后的像素颜色。
我在YCoCg24中使用的“lifting”技术类似于Malvar等人的技术,以及JPEG XR中的无损色彩空间转换。
因为加法是可逆的(并且加法模0x100是双射的),从(a,b)到(x,y)的任何变换可以由以下Feistel network产生,可逆和双射:
a b
| |
|->-F->-(+)
| |
(+)-<-G-<-|
| |
x y
其中(+)表示8位加法(模0x100),b x y都是8位值,F和G表示任意函数。
<强>详情
为什么只有3个字节来存储结果? 这听起来像是适得其反的premature optimization。 如果您的目标是在合理的时间内将图像无损压缩为尽可能小的压缩文件,那么中间阶段的大小就无关紧要了。 它甚至可能适得其反 - “较大”的中间表示(如可逆颜色变换或26位YCoCg-R)可能导致最终压缩文件大小小于“较小”中间表示(如RGB或YCoCg24)。
编辑: Oopsies。 “(x)mod 0x100”或“(x)&amp; 0xff”中的任何一个给出完全相同的结果 - 我想要的结果。 但不知何故,我把它们混在一起产生了一些不起作用的东西。
答案 1 :(得分:2)