RGB<---->YUV转换

192 篇文章 ¥19.90 ¥99.00
本文介绍了RGB与YUV颜色编码之间的转换,YUV主要用于电视系统和模拟视频,允许黑白电视与彩色电视兼容,并节省频宽。提供了一段C/C++代码实现RGB到YUV420的转换,以及从YUV420反向转换回RGB的代码,包括读取BMP文件、转换和写入BMP文件的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。

      并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽

1、RGB---->YUV转换

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. // BmptoYuv420.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. // 说明:下面的代码用C\C++执行都可以,用C的时候请把#include<iostream> 删除。  
  7. //        代码的详细说明视频即将推出,请时刻关注我的Blog: http://hexun.com/ctfysj  
  8. //   
  9. // RGB to YUV420 原代码:  RGB2YUV.CPP文件  
  10.   
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include <string.h>  
  14. #include <iostream>   
  15.   
  16. //转换矩阵  
  17. #define MY(a,b,c) (( a*  0.2989  + b*  0.5866  + c*  0.1145))  
  18. #define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c*  0.5000 + 128))  
  19. #define MV(a,b,c) (( a*  0.5000  + b*(-0.4184) + c*(-0.0816) + 128))  
  20. //大小判断  
  21. #define DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c)))  
  22. #define DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c)))  
  23. #define DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c)))  
  24. //只处理352*288文件  
  25. #define WIDTH /*352*/320  
  26. #define HEIGHT /*288*/240  
  27.   
  28. //读BMP  
  29. void ReadBmp(unsigned char *RGB,FILE *fp);  
  30.   
  31. //转换函数  
  32. void Convert(unsigned char *RGB, unsigned char *YUV);  
  33.   
  34. //入口  
  35. int main()  
  36. {  
  37.     int i=1;  
  38.     char file[255];  
  39.     FILE *fp;  
  40.     FILE *fp2;  
  41.     unsigned char *YUV = NULL;  
  42.     unsigned char *RGB = NULL;  
  43.     unsigned int imgSize = WIDTH*HEIGHT;  
  44.   
  45.     if((fp2 = fopen("test.cif", "wb")) == NULL)//生成文件名  
  46.     {  
  47.         return 0;  
  48.     }  
  49.   
  50.     RGB = (unsigned char*)malloc(imgSize*6);  
  51.     YUV = (unsigned char*)malloc(imgSize + (imgSize>>1));  
  52.      
  53.     for(i=1; i<2; i++)  
  54.     {  
  55.         sprintf(file, "test.bmp", i);//读取文件  
  56.         if((fp = fopen(file, "rb")) == NULL)  
  57.           continue;  
  58.   
  59.         printf("打开文件%s\n", file);  
  60.         ReadBmp(RGB, fp);  
  61.         Convert(RGB, YUV);  
  62.         fwrite(YUV, 1, imgSize+(imgSize>>1), fp2);//写入文件  
  63.         fclose(fp);  
  64.     }  
  65.   
  66.     fclose(fp2);  
  67.     if(RGB)  
  68.         free(RGB);  
  69.   
  70.     if(YUV)  
  71.         free(YUV);  
  72.   
  73.     printf("完成\n");  
  74.     system("pause");  
  75.     return 1;  
  76. }  
  77.   
  78. //读BMP  
  79. void ReadBmp(unsigned char *RGB,FILE *fp)  
  80. {  
  81.     int i,j;  
  82.     unsigned char temp;  
  83.   
  84.     fseek(fp,54, SEEK_SET);  
  85.   
  86.     fread(RGB+WIDTH*HEIGHT*3, 1, WIDTH*HEIGHT*3, fp);//读取  
  87.     for(i=HEIGHT-1,j=0; i>=0; i--,j++)//调整顺序  
  88.     {  
  89.         memcpy(RGB+j*WIDTH*3,RGB+WIDTH*HEIGHT*3+i*WIDTH*3,WIDTH*3);  
  90.     }  
  91.       
  92.     //顺序调整  
  93.     for(i=0; (unsigned int)i < WIDTH*HEIGHT*3; i+=3)  
  94.     {  
  95.         temp = RGB[i];  
  96.         RGB[i] = RGB[i+2];  
  97.         RGB[i+2] = temp;  
  98.     }  
  99. }  
  100.   
  101. void Convert(unsigned char *RGB, unsigned char *YUV)  
  102. {  
  103.     //变量声明  
  104.     unsigned int i,x,y,j;  
  105.     unsigned char *Y = NULL;  
  106.     unsigned char *U = NULL;  
  107.     unsigned char *V = NULL;  
  108.       
  109.     Y = YUV;  
  110.     U = YUV + WIDTH*HEIGHT;  
  111.     V = U + ((WIDTH*HEIGHT)>>2);  
  112.   
  113.     for(y=0; y < HEIGHT; y++)  
  114.         for(x=0; x < WIDTH; x++)  
  115.         {  
  116.             j = y*WIDTH + x;  
  117.             i = j*3;  
  118.             Y[j] = (unsigned char)(DY(RGB[i], RGB[i+1], RGB[i+2]));  
  119.   
  120.             if(x%2 == 1 && y%2 == 1)  
  121.             {  
  122.                 j = (WIDTH>>1) * (y>>1) + (x>>1);  
  123.                 //上面i仍有效  
  124.                 U[j] = (unsigned char)  
  125.                        ((DU(RGB[i  ], RGB[i+1], RGB[i+2]) +   
  126.                          DU(RGB[i-3], RGB[i-2], RGB[i-1]) +  
  127.                          DU(RGB[i  -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3]) +  
  128.                          DU(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);  
  129.   
  130.                 V[j] = (unsigned char)  
  131.                        ((DV(RGB[i  ], RGB[i+1], RGB[i+2]) +   
  132.                          DV(RGB[i-3], RGB[i-2], RGB[i-1]) +  
  133.                          DV(RGB[i  -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3]) +  
  134.                          DV(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);  
  135.             }  
  136.   
  137.         }  
  138. }  

说明:生成一个YUV格式的文件,此处取名为:test.cif

 

2、YUV---->RGB转换(把test.cif转换成bmp图片)

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. // YuvtoRgb.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. //   
  7. // int main(int argc, char* argv[])  
  8. // {  
  9. //  return 0;  
  10. // }  
  11.   
  12. #include <stdio.h>  
  13. #include <stdlib.h>  
  14. #include <iostream>  
  15. #define WIDTH /*352*/320  
  16. #define HEIGHT /*288*/240  
  17. //转换矩阵  
  18. double YuvToRgb[3][3] = {1,       0,  1.4022,  
  19.                          1,    -0.3456, -0.7145,  
  20.                          1,   1.771,       0};  
  21.   
  22. //根据RGB三分量写BMP,不必关注  
  23. int WriteBmp(int width, int height, unsigned char *R,unsigned char *G,unsigned char *B, char *BmpFileName);  
  24.   
  25. //转换函数  
  26. int Convert(char *file, int width, int height, int n)  
  27. {  
  28.     //变量声明  
  29.     int i = 0;  
  30.     int temp = 0;  
  31.     int x = 0;  
  32.     int y = 0;  
  33.     int fReadSize = 0;  
  34.     int ImgSize = width*height;  
  35.     FILE *fp = NULL;  
  36.     unsigned char* yuv = NULL;  
  37.     unsigned char* rgb = NULL;  
  38.     unsigned char* cTemp[6];  
  39.     char BmpFileName[256];  
  40.   
  41.     //申请空间  
  42.     int FrameSize = ImgSize + (ImgSize >> 1);  
  43.     yuv = (unsigned char *)malloc(FrameSize);  
  44.     rgb = (unsigned char *)malloc(ImgSize*3);  
  45.     //读取指定文件中的指定帧  
  46.     if((fp = fopen(file, "rb")) == NULL)  
  47.         return 0;  
  48.     fseek(fp, FrameSize*(n-1), SEEK_CUR);  
  49.     fReadSize = fread(yuv, 1, FrameSize, fp);  
  50.     fclose(fp);  
  51.     if(fReadSize < FrameSize)  
  52.         return 0;  
  53.     //转换指定帧  如果你不是处理文件 主要看这里  
  54.     cTemp[0] = yuv;                        //y分量地址  
  55.     cTemp[1] = yuv + ImgSize;            //u分量地址  
  56.     cTemp[2] = cTemp[1] + (ImgSize>>2);    //v分量地址  
  57.     cTemp[3] = rgb;                        //r分量地址  
  58.     cTemp[4] = rgb + ImgSize;            //g分量地址  
  59.     cTemp[5] = cTemp[4] + ImgSize;        //b分量地址  
  60.     for(y=0; y < height; y++)  
  61.         for(x=0; x < width; x++)  
  62.         {  
  63.             //r分量  
  64.             temp = cTemp[0][y*width+x] + (cTemp[2][(y/2)*(width/2)+x/2]-128) * YuvToRgb[0][2];  
  65.             cTemp[3][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 : temp);  
  66.             //g分量  
  67.             temp = cTemp[0][y*width+x] + (cTemp[1][(y/2)*(width/2)+x/2]-128) * YuvToRgb[1][1]  
  68.                                        + (cTemp[2][(y/2)*(width/2)+x/2]-128) * YuvToRgb[1][2];  
  69.             cTemp[4][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 : temp);  
  70.             //b分量  
  71.             temp = cTemp[0][y*width+x] + (cTemp[1][(y/2)*(width/2)+x/2]-128) * YuvToRgb[2][1];  
  72.             cTemp[5][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 : temp);  
  73.         }  
  74.   
  75.     //写到BMP文件中  
  76.     sprintf(BmpFileName, "test.bmp", file, n);  
  77.     WriteBmp(width, height, cTemp[3], cTemp[4], cTemp[5], BmpFileName);  
  78.   
  79.     free(yuv);  
  80.     free(rgb);  
  81.     return n;  
  82. }  
  83. //入口 没啥东西  
  84. void main()  
  85. {  
  86.     int i=1;  
  87. //    for( i=0; i<260; i++)  
  88.         Convert("test.cif", WIDTH, HEIGHT, i);//调用上面的Convert,获取文件的第i帧  
  89. }  
  90.   
  91. //写BMP  不必关注  
  92. int WriteBmp(int width, int height, unsigned char *R,unsigned char *G,unsigned char *B, char *BmpFileName)  
  93. {  
  94.     int x=0;  
  95.     int y=0;  
  96.     int i=0;  
  97.     int j=0;  
  98.     FILE *fp;  
  99.     unsigned char *WRGB;  
  100.     unsigned char *WRGB_Start;  
  101.     int yu = width*3%4;  
  102.     int BytePerLine = 0;  
  103.   
  104.     yu = yu!=0 ? 4-yu : yu;  
  105.     BytePerLine = width*3+yu;  
  106.   
  107.     if((fp = fopen(BmpFileName, "wb")) == NULL)  
  108.         return 0;  
  109.     WRGB = (unsigned char*)malloc(BytePerLine*height+54);  
  110.     memset(WRGB, 0, BytePerLine*height+54);  
  111.       
  112.     //BMP头  
  113.     WRGB[0] = 'B';  
  114.     WRGB[1] = 'M';  
  115.     *((unsigned int*)(WRGB+2)) = BytePerLine*height+54;  
  116.     *((unsigned int*)(WRGB+10)) = 54;  
  117.     *((unsigned int*)(WRGB+14)) = 40;  
  118.     *((unsigned int*)(WRGB+18)) = width;  
  119.     *((unsigned int*)(WRGB+22)) = height;  
  120.     *((unsigned short*)(WRGB+26)) = 1;  
  121.     *((unsigned short*)(WRGB+28)) = 24;  
  122.     *((unsigned short*)(WRGB+34)) = BytePerLine*height;  
  123.   
  124.     WRGB_Start = WRGB + 54;  
  125.   
  126.     for(y=height-1,j=0; y >= 0; y--,j++)  
  127.     {  
  128.         for(x=0,i=0; x<width; x++)  
  129.         {  
  130.             WRGB_Start[y*BytePerLine+i++] = B[j*width+x];  
  131.             WRGB_Start[y*BytePerLine+i++] = G[j*width+x];  
  132.             WRGB_Start[y*BytePerLine+i++] = R[j*width+x];  
  133.         }  
  134.     }  
  135.   
  136.     fwrite(WRGB, 1, BytePerLine*height+54, fp);  
  137.     free(WRGB);  
  138.     fclose(fp);  
  139.     return 1;  
  140. }  




http://blog.youkuaiyun.com/liulina603/article/details/18863665
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值