1. The basic principle of color space conversion
1) Color Space conversion formula:
In order to realize the format conversion, we must first clarify the characteristics and the conversion relationship between the format and the target format, which is the core of the programming realization transformation. For the process of RGB to YUV, we have to get the RGB file data, and then through the YUV calculation formula above to do the operation, to get YUV data, so as to achieve the conversion. For YUV to RGB, the YUV data is obtained first, and RGB data is computed by the second set of RGB formulas. In this experiment, the conversion formula is as follows.
Y = 0.298R + 0.612G + 0.117B;
U = -0.168r-0.330g + 0.498B + 128;
V = 0.449r-0.435g-0.083b + 128;
R = Y + 1.4075 (V-128);
G = Y-0.3455 (U-128)-0.7169 (V-128);
B = Y + 1.779 (U-128); Where the UV component is calculated +128 is because the UV component has a negative value, plus 128 just can adjust the range of changes to 0-255. Therefore, in doing YUV to RGB, to pay special attention to the UV component minus 128 in order to substitute to multiply the conversion coefficient.
2) Learn how to store two formats:
RGB Storage: RGB Three components are stored in the order of B, G, R. (4:4:4)
YUV Storage: First save Y and then save the UV component. (4:2:0)
3) Initialize the parameters.
pointers to input and output files: File * rgbfile,file * yuvfile;
Information about the file: Wide framewidth, high frameheight;
Pointer to the space to be opened: unsigned char type, yuv_buf,rgb_buf;
Note: Depending on the features of YUV and RGB storage, there are different methods for RGB and YUV application space. Storage RGB only open a complete space, with a buffer, and YUV three components are stored separately, although in memory is also a one-dimensional data flow, but in order to facilitate the calculation and pointer operation, three components with three buffer, open three block space storage.
2. Analysis of the experimental process
RGB2YUV: First, in the main function, open the RGB file to be converted fopen, read out the data, the data will be written to rgb_buf space, and secondly, into the conversion function, the data of the RGB_BUF Space calculation processing (Y_buffer point to YUV _buf,u_buffer & V_buffer Each open space), Y calculation results are written to Y_buffer (YUV_BUF), the results of UV component calculation exist u_buffer and v_buffer; The UV component in the Uvbuffer is sampled (yuv4:2:0), the result is stored in the target space sub_u_buf,sub_v_buf (exit: U_out,v_out), releasing the space opened in the conversion function ; , go back to the main function and write the results out to the target file to Fwrite, releasing the open space.
Yuv2rgb: First, the main function, open YUV file, read out the data, write the data into the yuv_buf; Secondly, the yuv_buf data is sampled, that is, y does not move, the UV component is deposited into the up_yuv_ Buf Open Space (the UV value of a pixel point is assigned to the corresponding point and the right, bottom, and bottom); Finally, the YUV data in the YUV_BUF,UP_YUV_BUF is computed, the RGB data is restored, the rgb_buf is saved, and the space opened in the conversion function is released . Finally, the result is output to the target file, releasing the open space.
Inspection: The first step, the conversion of RGB material to get YUV1, with the YUV player to see if it is correct, the second step, the resulting YUV1 back to the RGB format, and again the RGB to YUV2, if YUV2 and previously obtained YUV1 exactly the same, then YUV2RGB conversion error Otherwise, the problem should be modified and debugged.
3. Key code and its analysis
1) YUV2RGB Process UV on sample part
In the conversion function to open a space up_yuv_buf, the space size of 2*size just hold the UV component. The PSU1 and PSU2 pointers point to the odd and even two lines in the space of the U component, and Pu points to the position of the U component in the original space. The PSV pointer is the same as U. In a cycle, the use of the pointer to the UV component of the respective parity and two lines are assigned at the same time, then each add 1, re-assignment, to achieve four pixels to take the same value, that is, on the sampling.
for (i = 0; i < Y_DIM/2; i++)
{
psu1 = up_yuv_buf + 2 * i * X_DIM; U even-line pointer
psu2 = UP_YUV_BUF + (2 * i + 1) * X_dim; U odd line pointer
psv1 = up_yuv_buf + size + 2 * i * X_DIM; V even-line pointer
psv2 = up_yuv_buf + size + (2 * i + 1) * X_dim; V Odd line pointer
pu = u_buf + i * X_DIM/2;
PV = v_buf + i * X_DIM/2;
for (j = 0; J < X_dim/2; J + +)
{
*psu1 = *pu; *psu2 = *pu; Odd even line first pixel point assignment, UV at the same time
*psv1 = *PV; *psv2 = *PV;
psu1++; psu2++;
psv1++; psv2++;
*PSU1 = *pu; *PSU2 = *pu; Odd even line second pixel point assignment, UV at the same time
*psv1 = *PV; *psv2 = *PV;
psu1++; psu2++;
psv1++; psv2++;
pu++; pv++;
}
}
1) YUV2RGB Process calculation RGB section
anti-overflow: Three float variables are defined here: TMPR,TMPG,TMPB the computed float RGB values, and then determines if the value is greater than 225, so that it equals 225, if less than 0, so that it equals 0. The variable is then assigned to the position pointed to by the r/g/b pointer. This step is very important, float type 16-bit, unsigned char 8-bit, calculated values in the forced type conversion is likely to overflow, resulting in the image is significantly visible value overflow point, less than 0 is the red point, greater than 255 is the blue point.
for (i = 0; i < Y_dim; i++)
{for
(j=0;j<x_dim;j++)
{
g = b + 1;
R = B + 2;
Tmpr=*y + rgbyuv1402[*v];
Tmpg=*y-rgbyuv0344[*u]-rgbyuv0714[*v];
Tmpb=*y + rgbyuv1772[*u];
To prevent overflow
tmpr=tmpr>255?255: (TMPR<0?0:TMPR);
tmpg=tmpg>255?255: (tmpg<0?0:tmpg);
tmpb=tmpb>255?255: (TMPB<0?0:TMPB);
*r= (unsigned char) tmpr;
*g= (unsigned char) tmpg;
*b= (unsigned char) TMPB;
Y + +;
U + +;
V + +;
B + = 3;
}
}
4. Experimental results and Analysis
(in order to find errors, find a player that can play both RGB and YUV, share: Http://wwww.236.6122.net/uploadFile/2013/vooya.rar)
The result 1:yuv file is gray and has no image. Pixel-point YUV (204,127,127)
Reason: Within the function, give rgb_buffer another space. Rgb_buffer itself has pointed to the exit Rgb_out, has pointed to the main function for the target open space rgb_buf, so there is no need to open space within the function, adding a space code will cause the calculated values are given to the back of the space, so that can not write to the real target space. Since the target space is empty, the RGB value is the default value when writing to the file, and is the initial value (204,127,127) when converted back to YUV.
Rgb_buffer = (unsigned char *) rgb_out;
Rgb_buffer = (unsigned char *) malloc (3 * size * sizeof (unsigned char));//has pointed to the function exit, that is, a space, where there is no need to open space, instead of writing data to the specified space
up_yuv_buf = (unsigned char *) malloc (2 * size * sizeof (unsigned char));
The result 2:yuv file is gray and has a blurred image. As well as after the fix is purple, check the RGB file is also purple, there are blurred images.
Reason: At that time on the sampling, to Up_yuv_buf opened the storage of YUV three components of space, and the y was moved, the initial positioning of the pointer in the process of the loop in the cycle, resulting in each row is the first line of the Y component value, so only the first line is the normal result. Enlarge the player twice times find the first line is correct, so OK is the problem of the pointer, check the code is a move error, you can get the image after modification. The image is purple because in the code shown below, I does not subtract 128, but instead writes when the above array is called:
RGBYUV1402[*V-128];
Note: This array is defined only from 0-155, first minus 128 will inevitably have a value less than 0 problems occur, resulting in an image error. The correct practice should subtract 128 from the following function.
void Initlookuptable ()
{
int i;
for (i = 0; i < i++) Rgbyuv1402[i] = (float) (1.402 * (i-128));
for (i = 0; i < i++) Rgbyuv0344[i] = (float) (0.34414 * (i-128));
for (i = 0; i < i++) Rgbyuv0714[i] = (float) (0.71414 * (i-128));
for (i = 0; i < i++) Rgbyuv1772[i] = (float) (1.772 * (i-128));
}
Result three: RGB file has a blue red dot, YUV file on the contrary.
Cause: The computed RGB values are not judged by the above, causing the data to overflow after the coercion type is converted to unsigned char, causing some points on the image to turn red and blue.
for (i = 0; i < Y_dim; i++)
{for
(j=0;j255?255: (TMPR<0?0:TMPR);
tmpg=tmpg>255?255: (tmpg<0?0:tmpg);
tmpb=tmpb>255?255: (TMPB<0?0:TMPB);
*r= (unsigned char) tmpr;
*g= (unsigned char) tmpg;
*b= (unsigned char) TMPB;
Y + +;
U + +;
V + +;
B + = 3;
}
}
Result four: Correct results
(Comfort, warn yourself, check the wrong hard, please write right at once.) )
Also attached are three other YUV file conversion results: We can find that the process of YUV to RGB, the color has changed significantly, the Blue line will be red, red will be blue. This change is quite evident on the red sleeves of the last picture.