1.Color space conversion
光是公式偶就找到至少三種,但是其中的差異並不清楚.
R = 1.164 * (Y-16) + + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
R = Y + 1.370705 (V-128)
G = Y - 0.698001 (V-128) - 0.337633 (U-128)
B = Y + 1.732446 (U-128)
R = Y + 1.4075 * (V-128)
G = Y – 0.3455 * (U –128) – 0.7169 * (V –128)
B = Y + 1.779 * (U – 128)
根據http://www.fourcc.org/indexyuv.htm
第三種"似乎"才是正確的.
由以上公式可看出都需要作浮點運算,而偶的target platform剛好沒有FPU.
直接運算將會是場災難.
2.選擇公式一作轉換.
YUV is 8 bits data. RGB format is RGB565
R = 1.164 * (Y-16) + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
***Set variables***
YY = 1.164 * (Y-16)
RV = 1.596 * (V-128)
GU = 0.391 * (U-128)
GV = 0.813 * (V-128)
BU = 2.018 * (U-128)
So we got
R = YY + RV
G = YY - GU - GV
B = YY + BU
***Remove floating point by left shift 15***
YY = (YY << 15) = 38142(y-16)
RV = (RV << 15) = 52298(V-128)
GU = (GU << 15) = 12813(U-128)
GV = (GV << 15) = 26641(V-128)
BU = (BU << 15) = 66126(U-128)
Right shift R,G,B to get result
R = (YY + RV) >> 15
G = (YY - GU - GV) >> 15
B = (YY + BU) >> 15
***Create yuv coefficient tables***
由於YUV為8bits,以上的公式只需要5 * 2^8的表格即可.
int yy[256];
for(i=0;i<256;i++)
yy[i] = 38142(i-16)
...
...
***Handle RGB565***
B G R
|-----|------|-----| 16bits
5 6 5
So
R = R >> 3
G = (G & 0xFC) << 3
B = B << 8
***Create RGB result tables***
According to cacluation we know
481 >= R >= -223
432 >= G >= -172
534 >= B >= -277
We'd like RGB value from 0 to 255, so create tables to map the final value.
Also consider RGB 565 into the tables .
unsigned short rt[481+223];
diffcoef = (double) 481 / 256; /*Ignore value less than zero*/
for(i=0;i<704;i++) {
if((i + min) < 0)
rt[i] = 0; /*Ignore value less than zero by setting it to zero*/
else
rt[i] = (unsigned short)(i / diffcoef);
rt[i] >>= 3; /*Handle RGB565*/
}
...
...
Finally we got
RGB565 = bt[((yy[y]+bu[u]) >> 15) - 277] |
gt[((yy[y]+gv[v]+gu[u]) >> 15) -172] |
rt[((yy[y]+rv[v]) >> 15) - 223]
***Reference***
http://realchecko.blogspot.com/2009/02/yuv420-rgb565.html
http://rgbbones.googlepages.com/yuv2rgb
http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
http://multimedia.cx/yuv-3d-rgb.txt
***Example code***
#define precision 32768
typedef struct _ColorSpaceConversion {
int yy[256];
int rv[256];
int gu[256], gv[256];
int bu[256];
unsigned short *_rt, *_gt, *_bt;
unsigned short *rt, *gt, *bt;
} ColorSpaceConversion;
static ColorSpaceConversion csc;
/*
R = 1.164 * (Y-16) + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
*/
static const int cy = 38142; //(int)(1.164 * precision);
static const int crv = 52298; //(int)(1.596 * precision);
static const int cgu = 12813; //(int)(0.391 * precision);
static const int cgv = 26641; //(int)(0.813 * precision);
static const int cbu = 66126; //(int)(2.018 * precision);
void ColorSpaceConversion_Init()
{
int y, u, v;
for(y=0;y<256;y++)
csc.yy[y] = cy * (y - 16);
for(v=0;v<256;v++)
csc.rv[v] = crv * (v - 128);
for(u=0;u<256;u++)
csc.gu[u] = -cgu * (u - 128);
for(v=0;v<256;v++)
csc.gv[v] = -cgv * (v - 128);
for(u=0;u<256;u++)
csc.bu[u] = cbu * (u - 128);
/*
R : [ 481, -223 ] -> (481 + 223) / 256 = 2.75
G : [ 432, -172 ] -> (432 + 172) / 256 = 2.359375
B : [ 534, -277 ] -> (534 + 277) / 256 = 3.16796857
*/
int i;
int max, min, interval;
double diffcoef;
max = (csc.yy[255] + csc.rv[255]) >> 15;
min = (csc.yy[0] + csc.rv[0]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("R : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._rt = malloc(interval * sizeof(unsigned short));
csc.rt = csc._rt - min;
for(i=0;i
// csc._rt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._rt[i] = 0;
else
csc._rt[i] = (unsigned short)((i+min) / diffcoef);
csc._rt[i] >>= 3;
}
/**/
max = (csc.yy[255] + csc.gu[0] + csc.gv[0]) >> 15;
min = (csc.yy[0] + csc.gu[255] + csc.gv[255]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("G : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._gt = malloc(interval * sizeof(unsigned short));
csc.gt = csc._gt - min;
for(i=0;i
// csc._gt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._gt[i] = 0;
else
csc._gt[i] = (unsigned short)((i+min) / diffcoef);
csc._gt[i] &= 0xfc;
csc._gt[i] <<= 3;
}
/**/
max = (csc.yy[255] + csc.bu[255]) >> 15;
min = (csc.yy[0] + csc.bu[0]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("B : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._bt = malloc(interval * sizeof(unsigned short));
csc.bt = csc._bt - min;
for(i=0;i
// csc._bt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._bt[i] = 0;
else
csc._bt[i] = (unsigned short)((i+min) / diffcoef);
csc._bt[i] &= 0xf8;
csc._bt[i] <<= 8;
}
}
void ColorSpaceConversion_Deinit()
{
free(csc.rt);
free(csc.gt);
free(csc.bt);
}
沒有留言:
張貼留言