笔者在上篇中写了一个初步的nv21与yuv444互转的代码,这里重新写了一下,提速不少!

    1. void nv21_to_yuv444(String nv21_file, Mat & YUV_img, int height, int width)
    2. {
    3. FILE * fp;
    4. // fopen_s(&fp, nv21_file.c_str(), "rb");
    5. fp = fopen(nv21_file.c_str(), "rb");
    6. // nv21_to_yuv444
    7. int nv21_size = height * width;
    8. int half_nv21_size = nv21_size >> 1;
    9. // int quarter_nv21_size = nv21_size >> 2;
    10. // int half_height = height >> 1;
    11. int half_width = width >> 1;
    12. uchar *Y_block_ptr = (uchar *)malloc(nv21_size * sizeof(uchar));
    13. uchar *vu_block_ptr = (uchar *)malloc(half_nv21_size * sizeof(uchar));
    14. // uchar *v_block_ptr = (uchar *)malloc(quarter_nv21_size * sizeof(uchar));
    15. // uchar *u_block_ptr = (uchar *)malloc(quarter_nv21_size * sizeof(uchar));
    16. fread(Y_block_ptr, sizeof(uchar), nv21_size, fp);
    17. fseek(fp, nv21_size, SEEK_SET);
    18. fread(vu_block_ptr, sizeof(uchar), half_nv21_size, fp);
    19. // uchar * V_block_ptr = (uchar *)malloc(nv21_size * sizeof(uchar));
    20. // uchar * U_block_ptr = (uchar *)malloc(nv21_size * sizeof(uchar));
    21. // Mat Y_img(height, width, CV_8UC1, Y_block_ptr);
    22. Vec3b * YUV_img_ptr = (Vec3b *)YUV_img.data;
    23. for (int i = 0; i < half_nv21_size;)
    24. {
    25. for (int j = 0; j < half_width; ++j)
    26. {
    27. uchar v_val = *vu_block_ptr++;
    28. uchar u_val = *vu_block_ptr++;
    29. // method_1
    30. /*
    31. Vec3b & yuv_img_pixel_1 = *YUV_img_ptr;
    32. Vec3b & yuv_img_pixel_3 = *(YUV_img_ptr + width);
    33. Vec3b & yuv_img_pixel_2 = *(++YUV_img_ptr);
    34. Vec3b & yuv_img_pixel_4 = *(YUV_img_ptr + width);
    35. YUV_img_ptr++;
    36. // Y, U, V
    37. yuv_img_pixel_1 = Vec3b(*Y_block_ptr, u_val, v_val);
    38. yuv_img_pixel_3 = Vec3b(*(Y_block_ptr + width), u_val, v_val);
    39. yuv_img_pixel_2 = Vec3b(*(++Y_block_ptr), u_val, v_val);
    40. yuv_img_pixel_4 = Vec3b(*(Y_block_ptr + width), u_val, v_val);
    41. Y_block_ptr++;
    42. */
    43. #if 0
    44. // method_2: slow
    45. *YUV_img_ptr = Vec3b(*Y_block_ptr, u_val, v_val);
    46. *(YUV_img_ptr + width) = Vec3b(*(Y_block_ptr + width), u_val, v_val);
    47. ++YUV_img_ptr;
    48. ++Y_block_ptr;
    49. *(YUV_img_ptr) = Vec3b(*Y_block_ptr, u_val, v_val);
    50. *(YUV_img_ptr + width) = Vec3b(*(Y_block_ptr + width), u_val, v_val);
    51. ++YUV_img_ptr;
    52. ++Y_block_ptr;
    53. #else
    54. // method_3: fast
    55. Vec3b & yuv_img_pixel_1 = *YUV_img_ptr;
    56. Vec3b & yuv_img_pixel_3 = *(YUV_img_ptr + width);
    57. Vec3b & yuv_img_pixel_2 = *(++YUV_img_ptr);
    58. Vec3b & yuv_img_pixel_4 = *(YUV_img_ptr + width);
    59. ++YUV_img_ptr;
    60. // Y, U, V
    61. yuv_img_pixel_1[0] = *Y_block_ptr;
    62. yuv_img_pixel_3[0] = *(Y_block_ptr + width);
    63. yuv_img_pixel_2[0] = *(++Y_block_ptr);
    64. yuv_img_pixel_4[0] = *(Y_block_ptr + width);
    65. ++Y_block_ptr;
    66. yuv_img_pixel_1[1] = u_val;
    67. yuv_img_pixel_3[1] = u_val;
    68. yuv_img_pixel_2[1] = u_val;
    69. yuv_img_pixel_4[1] = u_val;
    70. yuv_img_pixel_1[2] = v_val;
    71. yuv_img_pixel_3[2] = v_val;
    72. yuv_img_pixel_2[2] = v_val;
    73. yuv_img_pixel_4[2] = v_val;
    74. #endif
    75. i += 2;
    76. }
    77. YUV_img_ptr += width;
    78. Y_block_ptr += width;
    79. }
    80. }
    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;
    }