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/

YUV422是一种颜色编码格式,它有多种存储方式。其中一种是打包格式(Packed),即Y、U、V三个分量连续存储在一起,每个像素占16比特。另一种是平面格式(Planar),即Y、U、V分别存储在不同的内存块中,其中Y占据width*height的空间,而U和V合并占据width*height的空间。根据U、V的顺序,可以分为两种格式,U前V后的是YUV422P,也叫I422,V前U后的是YV16。还有一种变态的半平面格式(Semi-planar),即Y单独占一块内存,而U和V紧挨着排在一起,根据U、V的顺序,又有两种格式,U前V后的是NV16,V前U后的是NV61。\[1\] 要将YUV422转换RGB格式,可以使用OpenCV库中的函数。首先,读取YUV格式的文件或模拟从设备获取YUV数据流。然后,使用相应的函数将YUV数据转换为Mat格式的RGB图像。最后,将Mat类型的图像显示在QLabel控件上。可以在MainWindow的.cpp文件中添加一个函数来实现将Mat类型图像显示在QLabel控件上的功能。该函数首先对图像进行处理,将其转换为适合显示的格式,然后将其转换为QPixmap对象,并将其设置为QLabel控件的图像。\[2\]\[3\] #### 引用[.reference_title] - *1* [YUV格式学习:YUV422PYV16NV16NV61格式转换RGB24](https://blog.csdn.net/subfate/article/details/47304945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [YUV422转RGB并显示于Qlabel](https://blog.csdn.net/xiaohuolong1827/article/details/123646367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值