YUV422P、YV16、NV16、NV61格式转换成RGB24

YUV422有打包格式(Packed),一如前文所述。同时还有平面格式(Planar),即Y、U、V是分开存储的,每个分量占一块地方,其中Y为width*height,而U、V合占width*height,该种格式每个像素占16比特。根据U、V的顺序,分出2种格式,U前V后即YUV422P,也叫I422,V前U后,叫YV16(YV表示Y后面跟着V,16表示16bit)。另外,还有一种变态的半平面格式(Semi-planar),即Y单独占一块地方,但其后U、V又紧挨着排在一起,根据U、V的顺序,又有2种,U前V后叫NV16,在国内好像很多人叫它为YUV422SP格式;V前U后叫NV61。不过这种格式似乎不太受VLC欢迎(具体可去看看VLC的wiki)。

先给出YUV422平面格式的转换函数,如下:

[cpp]  view plain  copy
  1. /** 
  2. 内存分布 
  3.                     w 
  4.             +--------------------+ 
  5.             |Y0Y1Y2Y3...         | 
  6.             |...                 |   h 
  7.             |...                 | 
  8.             |                    | 
  9.             +--------------------+ 
  10.             |U0U1      | 
  11.             |...       |   h 
  12.             |...       | 
  13.             |          | 
  14.             +----------+ 
  15.             |V0V1      | 
  16.             |...       |  h 
  17.             |...       | 
  18.             |          | 
  19.             +----------+ 
  20.                 w/2 
  21. */  
  22. void yuv422p_to_rgb24(YUV_TYPE type, unsigned char* yuv422p, unsigned char* rgb, int width, int height)  
  23. {  
  24.     int y, cb, cr;  
  25.     int r, g, b;  
  26.     int i = 0;  
  27.     unsigned char* p_y;  
  28.     unsigned char* p_u;  
  29.     unsigned char* p_v;  
  30.     unsigned char* p_rgb;  
  31.   
  32.     p_y = yuv422p;  
  33.     p_u = p_y + width * height;  
  34.     p_v = p_u + width * height / 2;  
  35.   
  36.     if (type == FMT_YV16)  
  37.     {  
  38.         p_v = p_y + width * height;  
  39.         p_u = p_u + width * height / 2;  
  40.     }  
  41.     p_rgb = rgb;  
  42.   
  43.     init_yuv422p_table();  
  44.   
  45.     for (i = 0; i < width * height / 2; i++)  
  46.     {  
  47.         y  = p_y[0];  
  48.         cb = p_u[0];  
  49.         cr = p_v[0];  
  50.   
  51.         r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value  
  52.         b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value  
  53.         g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value  
  54.   
  55.         // 此处可调整RGB排序,BMP图片排序为BGR  
  56.         // 默认排序为:RGB  
  57.         p_rgb[0] = r;  
  58.         p_rgb[1] = g;  
  59.         p_rgb[2] = b;  
  60.   
  61.         y  = p_y[1];  
  62.         cb = p_u[0];  
  63.         cr = p_v[0];  
  64.         r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value  
  65.         b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value  
  66.         g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value  
  67.   
  68.         p_rgb[3] = r;  
  69.         p_rgb[4] = g;  
  70.         p_rgb[5] = b;  
  71.   
  72.         p_y += 2;  
  73.         p_u += 1;  
  74.         p_v += 1;  
  75.         p_rgb += 6;  
  76.     }  
  77. }  

接着给出NV16、NV61转换成RGB的函数,如下:

[cpp]  view plain  copy
  1. /** 
  2. 内存分布 
  3.                     w 
  4.             +--------------------+ 
  5.             |Y0Y1Y2Y3...         | 
  6.             |...                 |   h 
  7.             |...                 | 
  8.             |                    | 
  9.             +--------------------+ 
  10.             |U0V0U1V1            | 
  11.             |...                 |   h 
  12.             |...                 | 
  13.             |                    | 
  14.             +--------------------+ 
  15.                 w/2 
  16. UV交织为NV16,VU交织为NV61 
  17. 可以与上一函数合并,但方便查看,还是不合并 
  18. */  
  19. void yuv422sp_to_rgb24(YUV_TYPE type, unsigned char* yuv422sp, unsigned char* rgb, int width, int height)  
  20. {  
  21.     int y, cb, cr;  
  22.     int r, g, b;  
  23.     int i = 0;  
  24.     unsigned char* p_y;  
  25.     unsigned char* p_uv;  
  26.     unsigned char* p_rgb;  
  27.   
  28.     p_y = yuv422sp;  
  29.     p_uv = p_y + width * height;    // uv分量在Y后面  
  30.     p_rgb = rgb;  
  31.   
  32.     init_yuv422p_table();  
  33.   
  34.     for (i = 0; i < width * height / 2; i++)  
  35.     {  
  36.         y  = p_y[0];  
  37.         if (type ==  FMT_NV16)  
  38.         {  
  39.             cb = p_uv[0];  
  40.             cr = p_uv[1];    // v紧跟u,在u的下一个位置  
  41.         }  
  42.         if (type == FMT_NV61)  
  43.         {  
  44.             cr = p_uv[0];  
  45.             cb = p_uv[1];    // u紧跟v,在v的下一个位置  
  46.         }  
  47.   
  48.         r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value  
  49.         b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value  
  50.         g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value  
  51.   
  52.         // 此处可调整RGB排序,BMP图片排序为BGR  
  53.         // 默认排序为:RGB  
  54.         p_rgb[0] = r;  
  55.         p_rgb[1] = g;  
  56.         p_rgb[2] = b;  
  57.   
  58.         y  = p_y[1];  
  59.         if (type ==  FMT_NV16)  
  60.         {  
  61.             cb = p_uv[0];  
  62.             cr = p_uv[1];  
  63.         }  
  64.         if (type ==  FMT_NV61)  
  65.         {  
  66.             cr = p_uv[0];  
  67.             cb = p_uv[1];  
  68.         }  
  69.   
  70.         r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value  
  71.         b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value  
  72.         g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value  
  73.   
  74.         p_rgb[3] = r;  
  75.         p_rgb[4] = g;  
  76.         p_rgb[5] = b;  
  77.   
  78.         p_y += 2;  
  79.         p_uv += 2;  
  80.         p_rgb += 6;  
  81.     }  
  82. }  

参考资料:

http://www.fourcc.org/yuv.php

https://wiki.videolan.org/YUV/

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将YUV422格式转换RGB格式,您可以使用FFmpeg库中的函数进行转换。以下是一个使用FFmpeg进行YUV422到RGB转换的示例代码: ```c #include <stdio.h> #include <libavutil/imgutils.h> #include <libswscale/swscale.h> int main() { int width = 640; // 输入图像的宽度 int height = 480; // 输入图像的高度 // 分配输入图像的内存 uint8_t* yuv422Buffer = (uint8_t*)malloc(width * height * 2); // 在这里填充YUV422数据到yuv422Buffer // 分配输出图像的内存 uint8_t* rgbBuffer = (uint8_t*)malloc(width * height * 3); // 创建输入图像的AVFrame AVFrame* yuv422Frame = av_frame_alloc(); yuv422Frame->format = AV_PIX_FMT_YUV422P; yuv422Frame->width = width; yuv422Frame->height = height; av_image_fill_arrays(yuv422Frame->data, yuv422Frame->linesize, yuv422Buffer, AV_PIX_FMT_YUV422P, width, height, 1); // 创建输出图像的AVFrame AVFrame* rgbFrame = av_frame_alloc(); rgbFrame->format = AV_PIX_FMT_RGB24; rgbFrame->width = width; rgbFrame->height = height; av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, rgbBuffer, AV_PIX_FMT_RGB24, width, height, 1); // 创建转换上下文 struct SwsContext* swsContext = sws_getContext(width, height, AV_PIX_FMT_YUV422P, width, height, AV_PIX_FMT_RGB24, 0, NULL, NULL, NULL); // 进行转换 sws_scale(swsContext, yuv422Frame->data, yuv422Frame->linesize, 0, height, rgbFrame->data, rgbFrame->linesize); // 在这里可以使用rgbBuffer中的RGB数据 // 释放资源 free(yuv422Buffer); free(rgbBuffer); av_frame_free(&yuv422Frame); av_frame_free(&rgbFrame); sws_freeContext(swsContext); return 0; } ``` 请注意,此示例假设您已经填充了正确的YUV422数据到yuv422Buffer。您需要根据实际情况修改输入图像的宽度和高度,并在转换后使用rgbBuffer中的RGB数据进行进一步处理。还要确保您已经链接了FFmpeg库并包含所需的头文件。 请参考FFmpeg文档以获得更多关于使用FFmpeg进行图像格式转换的详细信息和选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值