编写彩色空间转换程序:YUVtoRGB
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                编写彩色空间转换程序:YUVtoRGB
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.                        
                                Y=+0.299R+0.587G+0.114B
 U0=0.564(B-Y)=?0.1684R?0.3316G+0.5B
 V0=0.713(R-Y)=+0.5R?0.4187G?0.0813B
所以
 B-Y=U0/0.564 B=Y+1.773U0
 R-Y=V0/0.713 R=Y+1.403V0
 G=(Y-(0.299R+0.114B))/0.587 G=Y-0.714V0-0.344U0
U=U0+128
 V=V0+128
所以
 B=Y+1.773U-226.944
 R=Y+1.403V-179.584
 G=Y-0.714V-0.344U+135.424
yuv2rgb.cpp:
#include "stdlib.h" #include "yuv2rgb.h" #include <stdio.h>static float R_V01403[256],B_U01773[256], G_U_0344[256],G_V_0714[256];int YUV2RGB(int x_dim, int y_dim, void* bmp, void* rgb_out) {static int init_done = 0;long i, j, size;unsigned char* y, * u, * v;unsigned char* r, * g, * b;size = x_dim * y_dim;if (init_done == 0){InitLookupTable();init_done = 1;}// allocate memoryy = (unsigned char*)bmp;b = (unsigned char*)rgb_out;// convert RGB to YUVfor (j = 0; j < y_dim; j++){for (i = 0; i < x_dim; i++) {g = b + 1;r = b + 2;u = y + x_dim * y_dim - (i + 1) / 2 - (j + 1)/2 * x_dim/2;v = y + x_dim * y_dim + x_dim / 2 * y_dim / 2 - (i + 1) / 2 - (j + 1)/2 * x_dim/2;int rr, gg, bb;rr= (int)(*y + R_V01403[*v]); //-179.584gg=(int)(*y + G_U_0344[*u] + G_V_0714[*v]);//+ 135.424bb=(int)(*y + B_U01773[*u]);//- 226.944*r = rr;//(unsigned char)(*y + R_V01403[*v] ); //-179.584*g = gg;// (unsigned char)(*y + G_U_0344[*u] + G_V_0714[*v]);//+ 135.424*b = bb;//(unsigned char)(*y + B_U01773[*u] );//- 226.944y++;b+=3;}}return 0; }void InitLookupTable() {int i;for (i = 0; i < 256; i++) R_V01403[i] = (float)1.403 * (i-128);for (i = 0; i < 256; i++) B_U01773[i] = (float)1.773 * (i-128);for (i = 0; i < 256; i++) G_U_0344[i] = (float)-0.344 * (i-128);for (i = 0; i < 256; i++) G_V_0714[i] = (float)-0.714 * (i-128); }main.cpp:
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include "yuv2rgb.h" #pragma warning(disable:4996) #define u_int8_t unsigned __int8 #define u_int unsigned __int32 #define u_int32_t unsigned __int32 #define FALSE false #define TRUE trueint main(int argc, char** argv) {/* variables controlable from command line */u_int frameWidth = 352; /* --width=<uint> */u_int frameHeight = 240; /* --height=<uint> */bool flip = TRUE; /* --flip */unsigned int i;/* internal variables */char* rgbFileName = NULL;char* yuvFileName = NULL;FILE* rgbFile = NULL;FILE* yuvFile = NULL;u_int8_t* yuvBuf = NULL;u_int8_t* rgbBuf = NULL;u_int32_t videoFramesWritten = 0;/* begin process command line *//* point to the specified file names */yuvFileName = argv[1];rgbFileName = argv[2];frameWidth = atoi(argv[3]);frameHeight = atoi(argv[4]);/* open the RGB file */yuvFile = fopen(yuvFileName, "rb");if (yuvFile == NULL){printf("cannot find yuv file\n");exit(1);}else{printf("The input yuv file is %s\n", yuvFileName);}/* open the RAW file */rgbFile = fopen(rgbFileName, "wb");if (rgbFile == NULL){printf("cannot find rgb file\n");exit(1);}else{printf("The output rgb file is %s\n", rgbFileName);}/* get an input buffer for a frame */yuvBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 1.5);/* get the output buffers for a frame */rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight*3);if (yuvBuf == NULL || rgbBuf == NULL){printf("no enough memory\n");exit(1);}while (fread(yuvBuf, 1, frameWidth * frameHeight * 1.5, yuvFile)){if (YUV2RGB(frameWidth, frameHeight, yuvBuf, rgbBuf)){printf("error");return 0;}for (i = 0; i < frameWidth * frameHeight*3; i++){if (rgbBuf[i] < 0) rgbBuf[i] = 0;if (rgbBuf[i] > 255) rgbBuf[i] = 255;} /*for (i = 0; i < frameWidth * frameHeight / 4; i++){if (uBuf[i] < 16) uBuf[i] = 16;if (uBuf[i] > 240) uBuf[i] = 240;if (vBuf[i] < 16) vBuf[i] = 16;if (vBuf[i] > 240) vBuf[i] = 240;}fwrite(bBuf, 1, frameWidth * frameHeight, yuvFile);fwrite(gBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);fwrite(rBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);*/fwrite(rgbBuf, 1, frameWidth*frameHeight*3, rgbFile);printf("\r...%d", ++videoFramesWritten);}printf("\n%u %ux%u video frames written\n",videoFramesWritten, frameWidth, frameHeight);/* cleanup */fclose(rgbFile);fclose(yuvFile);return(0); }yuv2rgb.h
#pragma once int YUV2RGB(int x_dim, int y_dim, void* bmp, void* rgb_out);void InitLookupTable();圖片出現(xiàn)以下錯誤:
 
觀察正確的yuv與rgb大小和獲得的yuv與rgb大小:
正確值:
 
獲得值:
 
?對比可知獲得的u、v值異常偏小,導致rgb圖像錯誤。
 檢驗得偏移量錯誤。
改正偏移量部分:
for (j = 0; j < y_dim; j++){for (i = 0; i < x_dim; i++) {g = b + 1;r = b + 2;u = y + x_dim * y_dim - (i + 1) / 2 - j * 2 * x_dim / 2 + (j + 1) / 2 * x_dim / 2;v = y + x_dim * y_dim + x_dim / 2 * y_dim / 2 - (i + 1) / 2 - j * 2 * x_dim / 2 + (j + 1) / 2 * x_dim / 2;int rr, gg, bb;rr= (int)(*y + R_V01403[*v]); gg=(int)(*y + G_U_0344[*u] + G_V_0714[*v]);bb=(int)(*y + B_U01773[*u]);*r=rr;*g=gg;*b=bb;y++;b+=3;}}改正后結果:
 
 有部分像素值越界。
將值限定在0~255:
rr= (int)(*y + R_V01403[*v]); //-179.584gg=(int)(*y + G_U_0344[*u] + G_V_0714[*v]);//+ 135.424bb=(int)(*y + B_U01773[*u]);//- 226.944if (rr < 0) rr = 0;if (rr > 255) rr = 255;if (gg < 0) gg = 0;if (gg > 255) gg = 255;if (bb < 0) bb = 0;if (bb > 255) bb = 255;*r = rr;*g = gg;*b = bb;改正后圖像:
 
 變換前yuv圖像:
 
該yuv文件為4:2:0格式,u與v的數(shù)量為y的1/4,由總數(shù)1/4的u與v生成r、g、b會帶來一定誤差,同時進行轉換計算時由小數(shù)變?yōu)檎麛?shù)也會產生一定誤差,但只觀察圖像時難以辨別。
總結
以上是生活随笔為你收集整理的编写彩色空间转换程序:YUVtoRGB的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 统计rgb与yuv文件中各分量的熵
- 下一篇: DPCM 压缩系统的实现和分析
