无损RGB到Y’CbCr转换

前端之家收集整理的这篇文章主要介绍了无损RGB到Y’CbCr转换前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图无损压缩图像,为了利用规律性,我想将图像从RGB转换为Y’CbCr. (RGB和Y’CbCr的确切细节在这里并不重要; RGB数据由三个字节组成,我有三个字节来存储结果.)

转换过程本身非常简单,但有一个问题:虽然转换在数学上是可逆的,但实际上会出现舍入误差.当然,这些错误很小,几乎无法察觉,但它确实意味着该过程不再是无损的.

我的问题是:是否存在转换,将三个八位整数(表示红色,绿色和蓝色分量)转换为另外三个八位整数(表示类似于Y’CbCr的颜色空间,其中两个分量仅稍微改变相对于位置,或至少小于RGB颜色空间),并且可以在不丢失信息的情况下反转?

解决方法

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,Co ):
    (green,temp) = reverse_lift( Y,Cg )
    (red,blue)   = reverse_lift( temp,Co)
    return( red,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,blue ):
    Cb = (blue - green) mod 0x100
    Cr = (red  - green) mod 0x100
    return( green,Cb,Cr)

function GCbCr_to_RGB( Y,Co ):
    blue = (Cb + green) mod 0x100
    red  = (Cr + green) mod 0x100
    return( red,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,B-G色空间;
等等
Malvar等人似乎对24位RGB像素的26位YCoCg-R表示感到非常兴奋.

然而,几乎所有这些都需要超过24位来存储变换后的像素颜色.

我在YCoCg24中使用的“lifting”技术类似于Malvar等人的技术,以及JPEG XR中的无损色彩空间变换.

因为加法是可逆的(并且加法模0x100是双射的),所以可以由以下Feistel network产生的从(a,b)到(x,y)的任何变换是可逆的和双射的:

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)& 0xff”中的任何一个给出完全相同的结果 – 我想要的结果.但不知怎的,我把它们混在一起产生了一些不起作用的东西.

猜你在找的CSS相关文章