NV16和BGR相互转换C++实现

一、NV16格式

Y分量单独存放,UV分量交错存放(先U后V),2个Y共用1个UV,总长度为W×H×2。通道数为2,平均每个像素占16位,故称NV16格式。

Y Y Y Y
Y Y Y Y
U V U V
U V U V

二、NV16转BGR

static void NV16_2_BGR(const cv::Mat &yuv_image, unsigned char *buffer) {
  int bgr_image_width = yuv_image.cols;
  int bgr_image_height = yuv_image.rows / 2;
  cv::Mat bgr_image = cv::Mat(bgr_image_height, bgr_image_width, CV_8UC3);

  int length_y = bgr_image_width * bgr_image_height;
  int length_uv = length_y >> 1;
  unsigned char *pt_yuv_y = yuv_image.data;
  unsigned char *pt_yuv_uv = yuv_image.data + length_y;

  for (int h = 0; h < bgr_image_height; ++h)
  {
    cv::Vec3b *pt_bgr_image_line = bgr_image.ptr<cv::Vec3b>(h);
    unsigned char *pt_yuv_y_line = pt_yuv_y + h * bgr_image_width;
    unsigned char *pt_yuv_uv_line = pt_yuv_uv + h * bgr_image_width;
    for (int w = 0; w < bgr_image_width; ++w)
    {
      unsigned char y, u, v;
      int b, g, r;
      y = pt_yuv_y_line[w];
      if (w%2 == 0)
      {
        u = pt_yuv_uv_line[w];
        v = pt_yuv_uv_line[w+1];
      }
      if (w%2 == 1)
      {
        u = pt_yuv_uv_line[w-1];
        v = pt_yuv_uv_line[w];
      }

			r = y + ((360 * (v - 128) + 128) >> 8);
			g = y - (((88 * (u - 128) + 184 * (v - 128)) - 128) >> 8);
			b = y + ((455 * (u - 128) + 128) >> 8);

			if (b < 0)
				b = 0;
			if (b > 255)
				b = 255;
			if (g < 0)
				g = 0;
			if (g > 255)
				g = 255;
			if (r < 0)
				r = 0;
			if (r > 255)
				r = 255;

      pt_bgr_image_line[w][0] = b;
      pt_bgr_image_line[w][1] = g;
      pt_bgr_image_line[w][2] = r;
    }
  }

  int length = bgr_image_width*bgr_image_height*3;
  memcpy(buffer, bgr_image.data, length);
}

三、BGR转NV16

static void BGR_2_NV16(const cv::Mat &bgr_image, unsigned char *buffer) {
  int bgr_image_width = bgr_image.cols;
  int bgr_image_height = bgr_image.rows;

  int length_y = bgr_image_width * bgr_image_height;
  int length_uv = length_y >> 1;
  unsigned char *pt_yuv_y = buffer;
  unsigned char *pt_yuv_uv = buffer + length_y;

  for (int h = 0; h < bgr_image_height; ++h)
  {
    const cv::Vec3b *pt_bgr_image_line = bgr_image.ptr<cv::Vec3b>(h);
    unsigned char *pt_yuv_y_line = pt_yuv_y + h * bgr_image_width;
    unsigned char *pt_yuv_uv_line = pt_yuv_uv + h * bgr_image_width;
    for (int w = 0; w < bgr_image_width; ++w)
    {
      unsigned char b, g, r;
      int y, u, v;
      b = pt_bgr_image_line[w][0];
      g = pt_bgr_image_line[w][1];
      r = pt_bgr_image_line[w][2];
      y = (77 * r + 150 * g + 29 * b + 128) >> 8;
      if (y < 0)
        y = 0;
      if (y > 255)
        y = 255;
      pt_yuv_y_line[w] = y;

      if (w%2 == 0)
      {
        u = ((-44 * r - 87 * g + 131 * b + 128) >> 8) + 128;
        v = ((131 * r - 110 * g - 21 * b + 128) >> 8) + 128;
        if (u < 0)
          u = 0;
        if (u > 255)
          u = 255;
        if (v < 0)
          v = 0;
        if (v > 255)
          v = 255;
        pt_yuv_uv_line[w] = u;
        pt_yuv_uv_line[w+1] = v;
      }

    }
  }
}

YUV格式详解参见:YUV 格式详解,只看这一篇就够了(转)

你可能感兴趣的:(c++,开发语言)