/**************************************************************** * * Copyright: (c) Copyright Motorola Inc. 1998 * * Date: April 24, 1998 * * Function: RGB2YCbCr() * * Description: Converts from Gamma Corrected RGB to the * YCbCr Color Space. RGB is generally used * by monitors and represents the Red, Green, * and Blue components of a color. YCbCr is * used for transmission and storage. Y represents * the luminence, with Cb representing the blue * color difference, and Cr representing the red * color difference. * * The formulae for converting to YCbCr based on * ITU-CCITT 601-2 are: * (1) Y = [( 8432 R + 16425 G + 3176 B)/32768] + 16 * (2) Cb = [(-4818 R - 9527 G + 14345 B)/32768] + 128 * (3) Cr = [(14345 R - 12045 G - 2300 B)/32768] + 128 * * Inputs: RGB_ptr : pointer to RGB interleaved char data * ( R0G0B0R1B1C1R2G2B2.... ). * * RGB_size: The number of bytes of RGB data to be * converted to YCbCr format. It is assumed * the number is divisble by 16*3 otherwise * special case code must be employed for the * boundaries. It should be noted Digital TV * signals fit this constraint ( NTSC: 720 x 480; * PAL: 720 x 526 ), as does Video conferencing * ( 352 x 288 ), Video telephony ( 176 x 144 ), * and Digital HDTV ( 1920 x 1152 ) and the * formats described in the H.263 standard. * * Outputs: YCC_ptr : pointer to YCbCr data, organized as * 16 bytes Y, 16 bytes Cb, 16 bytes Cr. * It is assumed that a 128-bit aligned * array of the appropriate size has been * pre-allocated. * **************************************************************/ void RGB2YCbCr(vector unsigned char *RGB_ptr, int RGB_size, vector unsigned char *YCC_ptr) { vector signed short r0, r1, r2, g0, g1, g2, b0, b1, b2, c0, c16, c128; vector unsigned char z0, tc0, tc1, tc2, tc3; vector signed short tr0, tr1, tg0, tg1, tb0, tb1; vector signed short t0, t1, t2, t3, t4, t5; int i; /* Permutation vector is used to extract the interleaved RGB. */ vector unsigned char vPerm1 = (vector unsigned char)( 0, 3, 6, 9, 12, 15, 18, 21, /* R0..R7 */ 1, 4, 7, 10, 13, 16, 19, 22 /* G0..G7 */); vector unsigned char vPerm2 = (vector unsigned char)( 2, 5, 8, 11, 14, 17, 20, 23, /* B0..B7 */ 0, 0, 0, 0, 0, 0, 0, 0 /* dont care */); vector unsigned char vPerm3 = (vector unsigned char)( 8, 11, 14, 17, 20, 23, 26, 29, /* R8..R15 */ 9, 12, 15, 18, 21, 24, 27, 30 /* G8..G15 */); vector unsigned char vPerm4 = (vector unsigned char)(10, 13, 16, 19, 22, 25, 28, 31, /* B8..B15 */ 0, 0, 0, 0, 0, 0, 0, 0 /* dont care */); /* Load the equation constants. */ vector signed short vConst1 = (vector signed short)( 8432, 16425, 3176, -4818, -9527, 14345, 0, 0 ); vector signed short vConst2 = (vector signed short)( 14345, -12045, -2300, 16, 128, 0, 0, 0 ); r0 = vec_splat( vConst1, 0 ); /* 8432 */ g0 = vec_splat( vConst1, 1 ); /* 16425 */ b0 = vec_splat( vConst1, 2 ); /* 3176 */ r1 = vec_splat( vConst1, 3 ); /* -4818 */ g1 = vec_splat( vConst1, 4 ); /* -9527 */ b1 = vec_splat( vConst1, 5 ); /* 14345 */ r2 = vec_splat( vConst2, 0 ); /* 14345 */ g2 = vec_splat( vConst2, 1 ); /*-12045 */ b2 = vec_splat( vConst2, 2 ); /* -2300 */ c16 = vec_splat( vConst2, 3 ); /* 16 */ c128 = vec_splat( vConst2, 4 ); /* 128 */ c0 = (vector signed short) (0); /* 0 */ z0 = (vector unsigned char) (0); /* 0 */ for ( i = 0; i < (RGB_size/sizeof(vector unsigned char)); i+=3 ) { /* Load the 3 RGB input vectors and seperate into red, green and blue from the interleaved format. */ tc0 = vec_perm( RGB_ptr[i], RGB_ptr[i+1], vPerm1 ); /* R0..R7 G0..G7 */ tc1 = vec_perm( RGB_ptr[i], RGB_ptr[i+1], vPerm2 ); /* B0..B7 */ tc2 = vec_perm( RGB_ptr[i+1], RGB_ptr[i+2], vPerm3 ); /* R8..R15 G8..G15 */ tc3 = vec_perm( RGB_ptr[i+1], RGB_ptr[i+2], vPerm4 ); /* B8..B15 */ /* Unpack to 16 bit arithmatic for converstion. */ tr0 = vec_unpack2sh( z0, tc0 ); /* tr0 = R0 .. R7 */ tg0 = vec_unpack2sl( z0, tc0 ); /* tg0 = G0 .. G7 */ tb0 = vec_unpack2sh( z0, tc1 ); /* tb0 = B0 .. B7 */ tr1 = vec_unpack2sh( z0, tc2 ); /* tr0 = R8 .. R15 */ tg1 = vec_unpack2sl( z0, tc2 ); /* tg0 = G8 .. G15 */ tb1 = vec_unpack2sh( z0, tc3 ); /* tb0 = B8 .. B15 */ /* Convert the first three input vectors. Note that only the top 17 bits of the 32 bit product are stored. This is the same as doing the divide by 32768. */ t0 = vec_mradds( tr0, r0, c0 ); /* (R0 .. R7) * 8432 */ t1 = vec_mradds( tr0, r1, c0 ); /* (R0 .. R7) * -4818 */ t2 = vec_mradds( tr0, r2, c0 ); /* (R0 .. R7) * 14345 */ t0 = vec_mradds( tg0, g0, t0 ); /* += (G0 .. G7) * 16425 */ t1 = vec_mradds( tg0, g1, t1 ); /* += (G0 .. G7) * -9527 */ t2 = vec_mradds( tg0, g2, t2 ); /* += (G0 .. G7) * -12045 */ t0 = vec_mradds( tb0, b0, t0 ); /* += (B0 .. B7) * 3176 */ t1 = vec_mradds( tb0, b1, t1 ); /* += (B0 .. B7) * 14345 */ t2 = vec_mradds( tb0, b2, t2 ); /* += (B0 .. B7) * -2300 */ /* Convert the next three input vectors. */ t3 = vec_mradds( tr1, r0, c0 ); /* (R8 .. R15) * 8432 */ t4 = vec_mradds( tr1, r1, c0 ); /* (R8 .. R15) * -4818 */ t5 = vec_mradds( tr1, r2, c0 ); /* (R8 .. R15) * 14345 */ t3 = vec_mradds( tg1, g0, t3 ); /* += (G8 .. G15) * 16425 */ t4 = vec_mradds( tg1, g1, t4 ); /* += (G8 .. G15) * -9527 */ t5 = vec_mradds( tg1, g2, t5 ); /* += (G8 .. G15) * -12045 */ t3 = vec_mradds( tb1, b0, t3 ); /* += (B8 .. B15) * 3176 */ t4 = vec_mradds( tb1, b1, t4 ); /* += (B8 .. B15) * 14345 */ t5 = vec_mradds( tb1, b2, t5 ); /* += (B8 .. B15) * -2300 */ /* Add the constants. */ t0 = vec_adds( t0, c16 ); t3 = vec_adds( t3, c16 ); t1 = vec_adds( t1, c128 ); t4 = vec_adds( t4, c128 ); t2 = vec_adds( t2, c128 ); t5 = vec_adds( t5, c128 ); /* Pack the results, and store them. */ YCC_ptr[i] = vec_packsu( t0, t3 ); /* Y0 .. Y15 */ YCC_ptr[i+1] = vec_packsu( t1, t4 ); /* Cb0 .. Cb15 */ YCC_ptr[i+2] = vec_packsu( t2, t5 ); /* Cr0 .. Cr15 */ } }