轉換公式:
Y = Kr * R + (1 - Kr - Kb) * G + Kb * B
Cb = 0.5 * (B - Y) / (1 - Kb)
Cr = 0.5 * (R - Y) / (1 - Kr)
其中:
Kr=0.299 , Kb=0.114
Y = 0.299 * R + 0.587 * G + 0.114 * B
Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + 128
Cr = 0.5 * R - 0.418687589 * G - 0.081312411 * B + 128
#define SCALEBITS 16 /* speediest right-shift on some machines */
#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))#define R_Y_OFF 0 /* offset to R => Y section */
#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
#define R_CB_OFF (3*(MAXJSAMPLE+1))
#define G_CB_OFF (4*(MAXJSAMPLE+1))
#define B_CB_OFF (5*(MAXJSAMPLE+1))
#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
#define G_CR_OFF (6*(MAXJSAMPLE+1))
#define B_CR_OFF (7*(MAXJSAMPLE+1))
#define TABLE_SIZE (8*(MAXJSAMPLE+1))#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
#define RGB_GREEN 1 /* Offset of Green */
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
初始化查找表:for (i = 0; i <= MAXJSAMPLE; i++) {
rgb2ycc_tab[i+R_Y_OFF] = FIX(0.299) * i;
rgb2ycc_tab[i+G_Y_OFF] = FIX(0.587) * i;
rgb2ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
rgb2ycc_tab[i+R_CB_OFF] = (-FIX(0.168735892)) * i;
rgb2ycc_tab[i+G_CB_OFF] = (-FIX(0.331264108)) * i;
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
* This ensures that the maximum output will round to MAXJSAMPLE
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
*/
rgb2ycc_tab[i+B_CB_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1;
/* B=>Cb and R=>Cr tables are the same
rgb2ycc_tab[i+R_CR_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1;
*/
rgb2ycc_tab[i+G_CR_OFF] = (-FIX(0.418687589)) * i;
rgb2ycc_tab[i+B_CR_OFF] = (-FIX(0.081312411)) * i;
}
轉換一行數據
inptr = *input_buf++;
outptr0 = output_buf[0][output_row];
outptr1 = output_buf[1][output_row];
outptr2 = output_buf[2][output_row];
output_row++;
for (col = 0; col < num_cols; col++) {
r = GETJSAMPLE(inptr[RGB_RED]);
g = GETJSAMPLE(inptr[RGB_GREEN]);
b = GETJSAMPLE(inptr[RGB_BLUE]);
/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
* must be too; we do not need an explicit range-limiting operation.
* Hence the value being shifted is never negative, and we don't
* need the general RIGHT_SHIFT macro.
*/
/* Y */
outptr0[col] = (JSAMPLE)
((rgb2ycc_tab[r+R_Y_OFF] + rgb2ycc_tab[g+G_Y_OFF] + rgb2ycc_tab[b+B_Y_OFF])
>> SCALEBITS);
/* Cb */
outptr1[col] = (JSAMPLE)
((rgb2ycc_tab[r+R_CB_OFF] + rgb2ycc_tab[g+G_CB_OFF] + rgb2ycc_tab[b+B_CB_OFF])
>> SCALEBITS);
/* Cr */
outptr2[col] = (JSAMPLE)
((rgb2ycc_tab[r+R_CR_OFF] + rgb2ycc_tab[g+G_CR_OFF] + rgb2ycc_tab[b+B_CR_OFF])
>> SCALEBITS);
inptr += RGB_PIXELSIZE;
}