YUV格式入门

关于YUV格式的讲解,网上有很多,主要有以下几种格式:

1)打包(packed)格式.将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel):

MEDIASUBTYPE_YUY2 YUY2格式,以4:2:2方式打包(比较常用的,默认的4:2:2的格式)
MEDIASUBTYPE_YUYV YUYV格式(实际格式与YUY2相同)
MEDIASUBTYPE_YVYU YVYU格式,以4:2:2方式打包
MEDIASUBTYPE_UYVY UYVY格式,以4:2:2方式打包
MEDIASUBTYPE_AYUV              ,带Alpha通道的4:4:4 YUV格式

2)平面(planar)格式。后者使用三个数组分开存放YUV三个分量 

MEDIASUBTYPE_IF09  IF09格式
MEDIASUBTYPE_IYUV  IYUV格式
MEDIASUBTYPE_YV12 YV12格式
MEDIASUBTYPE_YVU9 YVU9格式
 

YUV 采样

YUV 的优点之一是,色度频道的采样率可比 Y 频道低,同时不会明显降低视觉质量。有一种表示法可用来描述 U 和 V 与 Y 的采样频率比例,这个表示法称为 A:B:C 表示法(其实就是Y:U:V):

  • 4:4:4 表示色度频道没有下采样, 每一个Y分量都对应一个UV分量,最简单容易理解。 
srcY = Buf_yuv444;
srcU = srcY + width * height;
srcV = srcU + width * height;
  • 4:2:2 表示 2:1 的水平下采样,没有垂直下采样。相对于4:4:4,就是每隔一列删去一列U(或者V)分量,只保留第0,2,4,6....列的U(V)分量。
srcY = Buf_yuv422;
srcU = srcY + width * height;
srcV = srcU + width/2 * height;
  • 4:2:0 表示 2:1 的水平下采样,2:1 的垂直下采样。相对于4:2:2,再继续每隔一行删去一行U(或者V)分量,只保留第0,2,4,6....行的U(V)分量。
srcY = Buf_yuv420;
srcU = srcY + width * height;
srcV = srcU + width/2 * height/2;
  • 4:1:1 表示 4:1 的水平下采样,没有垂直下采样。对于每个 U 样例或 V 样例,每个扫描行都包含四个 Y 样例。不常见。

YUV444 TO YUV420:(packed)(BYTE)

void YUV444To420(BYTE* yuv444, BYTE* yuv420, DWORD width, DWORD height)
{          
  int ynum=width*height;  
  DWORD i, j, k;

  BYTE *dstY =  yuv420;
  BYTE *dstU = dstY + ynum;
  BYTE *dstV = dstU + ynum / 4;

  BYTE *srcY = yuv444;
  BYTE *srcU = srcY + ynum;
  BYTE *srcV = srcU + ynum;

  k = 0;
  for (i = 0; i < height; i ++){
    for (j = 0; j < width; j ++){
      dstY[k++] = srcY[i * width + j];
    }
  }
  k = 0;
  for(i = 0;i < height;i += 2){
    for(j = 0;j < width; j += 2){
      dstU[k++] = srcU[i * width + j]; 
    }
  }
  k = 0;
  for(i = 0;i < height;i += 2){
    for(j = 0;j < width;j += 2){
      dstV[k++] = srcV[i * width + j];
    }
  } 
}

 YUV422 TO YUV420:(packed) (Int16_t)

void YUV422To420_10bit(int16_t* yuv422, int16_t* yuv420, DWORD width, DWORD height)
{
  int ynum = width*height;
  DWORD i, j, k;

  SHORT *dstY = yuv420;
  SHORT *dstU = dstY + ynum;
  SHORT *dstV = dstU + ynum / 4;

  SHORT *srcY = yuv422;
  SHORT *srcU = srcY + ynum;
  SHORT *srcV = srcU + ynum / 2;

  memcpy(dstY, srcY, ynum * 2);

  k = 0;
  width /= 2;
  for (i = 0; i < height; i += 2){
    for (j = 0; j < width; j += 1){
      dstU[k++] = srcU[i * width + j];
    }
  }
  k = 0;
  for (i = 0; i < height; i += 2){
    for (j = 0; j < width; j += 1){
      dstV[k++] = srcV[i * width + j];
    }
  }
}
 
 
原文地址:https://www.cnblogs.com/liuyalunuli/p/5054947.html