笔者在上篇中写了一个初步的nv21与yuv444互转的代码,这里重新写了一下,提速不少!
void nv21_to_yuv444(String nv21_file, Mat & YUV_img, int height, int width){FILE * fp;// fopen_s(&fp, nv21_file.c_str(), "rb");fp = fopen(nv21_file.c_str(), "rb");// nv21_to_yuv444int nv21_size = height * width;int half_nv21_size = nv21_size >> 1;// int quarter_nv21_size = nv21_size >> 2;// int half_height = height >> 1;int half_width = width >> 1;uchar *Y_block_ptr = (uchar *)malloc(nv21_size * sizeof(uchar));uchar *vu_block_ptr = (uchar *)malloc(half_nv21_size * sizeof(uchar));// uchar *v_block_ptr = (uchar *)malloc(quarter_nv21_size * sizeof(uchar));// uchar *u_block_ptr = (uchar *)malloc(quarter_nv21_size * sizeof(uchar));fread(Y_block_ptr, sizeof(uchar), nv21_size, fp);fseek(fp, nv21_size, SEEK_SET);fread(vu_block_ptr, sizeof(uchar), half_nv21_size, fp);// uchar * V_block_ptr = (uchar *)malloc(nv21_size * sizeof(uchar));// uchar * U_block_ptr = (uchar *)malloc(nv21_size * sizeof(uchar));// Mat Y_img(height, width, CV_8UC1, Y_block_ptr);Vec3b * YUV_img_ptr = (Vec3b *)YUV_img.data;for (int i = 0; i < half_nv21_size;){for (int j = 0; j < half_width; ++j){uchar v_val = *vu_block_ptr++;uchar u_val = *vu_block_ptr++;// method_1/*Vec3b & yuv_img_pixel_1 = *YUV_img_ptr;Vec3b & yuv_img_pixel_3 = *(YUV_img_ptr + width);Vec3b & yuv_img_pixel_2 = *(++YUV_img_ptr);Vec3b & yuv_img_pixel_4 = *(YUV_img_ptr + width);YUV_img_ptr++;// Y, U, Vyuv_img_pixel_1 = Vec3b(*Y_block_ptr, u_val, v_val);yuv_img_pixel_3 = Vec3b(*(Y_block_ptr + width), u_val, v_val);yuv_img_pixel_2 = Vec3b(*(++Y_block_ptr), u_val, v_val);yuv_img_pixel_4 = Vec3b(*(Y_block_ptr + width), u_val, v_val);Y_block_ptr++;*/#if 0// method_2: slow*YUV_img_ptr = Vec3b(*Y_block_ptr, u_val, v_val);*(YUV_img_ptr + width) = Vec3b(*(Y_block_ptr + width), u_val, v_val);++YUV_img_ptr;++Y_block_ptr;*(YUV_img_ptr) = Vec3b(*Y_block_ptr, u_val, v_val);*(YUV_img_ptr + width) = Vec3b(*(Y_block_ptr + width), u_val, v_val);++YUV_img_ptr;++Y_block_ptr;#else// method_3: fastVec3b & yuv_img_pixel_1 = *YUV_img_ptr;Vec3b & yuv_img_pixel_3 = *(YUV_img_ptr + width);Vec3b & yuv_img_pixel_2 = *(++YUV_img_ptr);Vec3b & yuv_img_pixel_4 = *(YUV_img_ptr + width);++YUV_img_ptr;// Y, U, Vyuv_img_pixel_1[0] = *Y_block_ptr;yuv_img_pixel_3[0] = *(Y_block_ptr + width);yuv_img_pixel_2[0] = *(++Y_block_ptr);yuv_img_pixel_4[0] = *(Y_block_ptr + width);++Y_block_ptr;yuv_img_pixel_1[1] = u_val;yuv_img_pixel_3[1] = u_val;yuv_img_pixel_2[1] = u_val;yuv_img_pixel_4[1] = u_val;yuv_img_pixel_1[2] = v_val;yuv_img_pixel_3[2] = v_val;yuv_img_pixel_2[2] = v_val;yuv_img_pixel_4[2] = v_val;#endifi += 2;}YUV_img_ptr += width;Y_block_ptr += width;}}
Mat yuv444_to_nv21(Mat & YUV_srcImg, int height, int width)
{
int size = height * width;
int quarter_size = size >> 2;
int half_height = height >> 1;
int half_width = width >> 1;
Mat nv21_img(height + half_height, width, CV_8UC1);
uchar *y_nv21_img_ptr = nv21_img.data;
uchar *vu_nv21_img_ptr = nv21_img.data + size;
Vec3b * YUV_srcImg_ptr = (Vec3b *)YUV_srcImg.data;
for (int i = 0; i < size; ++i)
{
Vec3b & YUV_srcImg_pixel = *YUV_srcImg_ptr++;
*y_nv21_img_ptr++ = YUV_srcImg_pixel[0];
}
YUV_srcImg_ptr = (Vec3b *)YUV_srcImg.data;
for (int i = 0; i < half_height; ++i) {
for (int j = 0; j < half_width; ++j)
{
Vec3b & YUV_srcImg_pixel = *YUV_srcImg_ptr++;
*vu_nv21_img_ptr++ = YUV_srcImg_pixel[2];
*vu_nv21_img_ptr++ = YUV_srcImg_pixel[1];
YUV_srcImg_ptr++;
}
YUV_srcImg_ptr += width;
}
return nv21_img;
}
