Ruu*_*uud 9 rgb lossless-compression color-space
我试图无损压缩图像,为了利用规律性,我想将图像从RGB转换为Y'CbCr.(我和RGB和Y'CbCr的含义的确切细节在这里并不重要; RGB数据由三个字节组成,我有三个字节来存储结果.)
转换过程本身非常简单,但有一个问题:尽管转换在数学上是可逆的,但实际上会出现舍入误差.当然,这些错误很小,几乎无法察觉,但它确实意味着该过程不再是无损的.
我的问题是:是否存在转换,将三个八位整数(表示红色,绿色和蓝色分量)转换为另外三个八位整数(表示类似于Y'CbCr的颜色空间,其中两个组件仅稍微改变相对于位置,或至少小于RGB颜色空间),并且可以在不丢失信息的情况下进行反转?
Dav*_*ary 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
Run Code Online (Sandbox Code Playgroud)
或者在伪代码中:
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 )
Run Code Online (Sandbox Code Playgroud)
一些示例颜色:
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
Run Code Online (Sandbox Code Playgroud)
G,RG,BG色彩空间
另一种颜色转换,将三个八位整数转换为另外三个八位整数.
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 )
Run Code Online (Sandbox Code Playgroud)
一些示例颜色:
color R G B G CbCr
white 0xFFFFFF 0xFF0000
light grey 0xEFEFEF 0xEF0000
dark grey 0x111111 0x110000
black 0x000000 0x000000
Run Code Online (Sandbox Code Playgroud)
评论
似乎有很多无损色彩空间转换.Henrique S. Malvar等人提到了几种无损色彩空间变换."用于图像压缩的基于提升的可逆颜色变换" ; JPEG XR中有无损色彩空间转换; 几个" 无损JPEG "提案中使用的原始可逆颜色变换(ORCT); G,RG,BG色彩空间; Malvar等人似乎对24位RGB像素的26位YCoCg-R表示感到非常兴奋.
然而,几乎所有这些都需要超过24位来存储变换后的像素颜色.
我在YCoCg24中使用的" 提升 "技术类似于Malvar等人的技术,以及JPEG XR中的无损色彩空间转换.
因为加法是可逆的(并且加法模0x100是双射的),所以可以由以下Feistel网络产生的从(a,b)到(x,y)的任何变换是可逆的和双射的:
a b
| |
|->-F->-(+)
| |
(+)-<-G-<-|
| |
x y
Run Code Online (Sandbox Code Playgroud)
其中(+)表示8位加法(模0x100),abxy都是8位值,F和G表示任意函数.
细节
为什么只有3个字节来存储结果?这听起来像是一种适得其反的过早优化.如果您的目标是在合理的时间内将图像无损压缩为尽可能小的压缩文件,那么中间阶段的大小就无关紧要了.它甚至可能适得其反 - "较大"的中间表示(如可逆颜色变换或26位YCoCg-R)可能导致最终压缩文件大小小于"较小"中间表示(如RGB或YCoCg24).
编辑:Oopsies."(x)mod 0x100"或"(x)&0xff"中的任何一个给出完全相同的结果 - 我想要的结果.但不知怎的,我把它们混在一起产生了一些不起作用的东西.
| 归档时间: |
|
| 查看次数: |
6177 次 |
| 最近记录: |