WEB开发网
开发学院软件开发VC RGB与YUV图像视频格式的相互转换 阅读

RGB与YUV图像视频格式的相互转换

 2007-08-29 21:35:09 来源:WEB开发网   
核心提示: 在整个视频行业中,定义了很多 YUV 格式,RGB与YUV图像视频格式的相互转换(3),我以UYVY格式标准来说明,4:2:2 格式UYVY每像素占16 位,您可以执行本文附带的程序 (功能菜单->转换并写入YUV两场) 查看转换过程,RGB转UYVY公式如下:公式:(RGB =&g

在整个视频行业中,定义了很多 YUV 格式,我以UYVY格式标准来说明,4:2:2 格式UYVY每像素占16 位,UYVY字节顺序如下图:

RGB与YUV图像视频格式的相互转换

(图3 UYVY字节顺序)

其中第一个字节为U0,每二个字节为Y0,依次排列如下:

[U0,Y0,U1,Y1] [U1,Y2,V1,Y3] [U2,Y4,V2,Y5] ……

经过仔细分析,我们要实现RGB转YUV格式的话,一个像素的RGB占用三个节,而UYVY每像素占用两个字节,我演示直接把UYVY字节信息保存到*.pal格式中(这是我自己写来测试用的^_^),*.pal格式中,先保存上场像素,接着保存下场像素,如果是720x576的一张图像转换为YUV格式并保存的话,文件大小应该是829,440字节(720*576*2)。您可以执行本文附带的程序 (功能菜单->转换并写入YUV两场) 查看转换过程。

RGB转UYVY公式如下:

公式:(RGB => YCbCr)

Y = 0.257R′ + 0.504G′ + 0.098B′ + 16

Cb = -0.148R′ - 0.291G′ + 0.439B′ + 128

Cr = 0.439R′ - 0.368G′ - 0.071B′ + 128

代码实现:

// RGB转换为YUV
void CRGB2YUVView::RGB2YUV(byte *pRGB, byte *pYUV)
{
  byte r,g,b;
  r = *pRGB; pRGB++;
  g = *pRGB; pRGB++;
  b = *pRGB;
  
  *pYUV = static_cast<byte>(0.257*r + 0.504*g + 0.098*b + 16);  pYUV++;  // y
  *pYUV = static_cast<byte>(-0.148*r - 0.291*g + 0.439*b + 128); pYUV++;  // u
  *pYUV = static_cast<byte>(0.439*r - 0.368*g - 0.071*b + 128);       // v
}
像素转换实现:// 转换RGB
void CRGB2YUVView::OnConvertPAL()
{
  CDC *pDC = GetDC();
  CRect rect;
  CBrush brush(RGB(128,128,128));
  GetClientRect(&rect);
  pDC->FillRect(&rect, &brush);
  // PAL 720x576 : 中国的电视标准为PAL制  
  int CurrentXRes = 720;
  int CurrentYRes = 576;
  int size    = CurrentXRes * CurrentYRes;
  
  // 分配内存
  byte *Video_Field0 = (byte*)malloc(CurrentXRes*CurrentYRes);
  byte *Video_Field1 = (byte*)malloc(CurrentXRes*CurrentYRes);
  
  // 保存内存指针
  byte *Video_Field0_ = Video_Field0;
  byte *Video_Field1_ = Video_Field1;
  byte yuv_y0, yuv_u0, yuv_v0, yuv_v1; // {y0, u0, v0, v1};
  byte bufRGB[3]; // 临时保存{R,G,B}
  byte bufYUV[3]; // 临时保存{Y,U,V}
  // 初始化数组空间
  ZeroMemory(bufRGB, sizeof(byte)*3);
  ZeroMemory(bufYUV, sizeof(byte)*3);
  // 初始化内存
  ZeroMemory(Video_Field0, CurrentXRes*CurrentYRes);
  ZeroMemory(Video_Field1, CurrentXRes*CurrentYRes);
  
  // BMP 位图操作
  BITMAPFILEHEADER bmfh;
  BITMAPINFOHEADER bmih;
  char strFileName[MAX_PATH]="720bmp.bmp";
  CFile* f;
  f = new CFile();
  f->Open(strFileName, CFile::modeRead);
  f->SeekToBegin();
  f->Read(&bmfh, sizeof(bmfh));
  f->Read(&bmih, sizeof(bmih));
  // 分配图片像素内存
  RGBTRIPLE *rgb;
  rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];
  f->SeekToBegin();
  f->Seek(54,CFile::begin); // BMP 54个字节之后的是位像素数据
  f->Read(rgb, bmih.biWidth * bmih.biHeight * 3);   // 这里只读24位RGB(r,g,b)图像
  
  // 上场 (1,3,5,7...行)
  for (int i = bmih.biHeight-1; i>=0; i--) {
    for (int j = 0; j<bmih.biWidth; j++) {
      if(!(i%2)==0)
      {
        bufRGB[0] = rgb[i*bmih.biWidth+j].rgbtRed;  //  R
        bufRGB[1] = rgb[i*bmih.biWidth+j].rgbtGreen; // G
        bufRGB[2] = rgb[i*bmih.biWidth+j].rgbtBlue; // B
        // RGB转换为YUV
        RGB2YUV(bufRGB,bufYUV);
        yuv_y0 = bufYUV[0];  // y
        yuv_u0 = bufYUV[1];  // u
        yuv_v0 = bufYUV[2];  // v
        
        for (int k=0; k<1000; k++) ; //延时
        // 视图中显示
        pDC->SetPixel(j, (bmih.biHeight-1)-i, RGB(bufRGB[0], bufRGB[1], bufRGB[2]));
        
        // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5]
        // 每像素点两个字节,[内]为四个字节
        if ((j%2)==0)
        {
          *Video_Field0 = yuv_u0; 
          Video_Field0++;
          yuv_v1 = yuv_v0;  // v保存起来供下一字节使用
        }
        else
        {
          *Video_Field0 = yuv_v1; 
          Video_Field0++;
        }
        *Video_Field0 = yuv_y0;   
        Video_Field0++;
      }// end if i%2
    }
  }
  // 下场 (2,4,6,8...行)
  for (int i_ = bmih.biHeight-1; i_>=0; i_--) {
    for (int j_ = 0; j_<bmih.biWidth; j_++) {
      if((i_%2)==0)
      {
        bufRGB[0] = rgb[i_*bmih.biWidth+j_].rgbtRed;  //  R
        bufRGB[1] = rgb[i_*bmih.biWidth+j_].rgbtGreen; // G
        bufRGB[2] = rgb[i_*bmih.biWidth+j_].rgbtBlue; // B
        // RGB转换为YUV
        RGB2YUV(bufRGB,bufYUV);
        yuv_y0 = bufYUV[0];  // y
        yuv_u0 = bufYUV[1];  // u
        yuv_v0 = bufYUV[2];  // v
        for (int k=0; k<1000; k++) ; //延时
        // 视图中显示
        pDC->SetPixel(j_, (bmih.biHeight-1)-i_, RGB(bufRGB[0], bufRGB[1], bufRGB[2]));
        // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5]
        // 每像素点两个字节,[内]为四个字节
        if ((j_%2)==0)
        {
          *Video_Field1 = yuv_u0; 
          Video_Field1++;
          yuv_v1 = yuv_v0;  // v保存起来供下一字节使用
        }
        else
        {
          *Video_Field1 = yuv_v1; 
          Video_Field1++;
        }
        *Video_Field1 = yuv_y0;   
        Video_Field1++;
      }
    }
  }
  // 关闭BMP位图文件
  f->Close();
  WriteYUV(Video_Field0_, Video_Field1_, size);
  
  // 释放内存
  free( Video_Field0_ );
  free( Video_Field1_ );
  delete f;
  delete rgb;
}

YUV转RGB

上一页  1 2 3 4  下一页

Tags:RGB YUV 图像

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接