博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
音视频编解码---YUV BMP RBG大端方式存储/小端方式读取 转换公式(线性量化)
阅读量:3920 次
发布时间:2019-05-23

本文共 4974 字,大约阅读时间需要 16 分钟。

RGB和YUV概念

RGB方式:(必定是Packet形式存放数据)

  ①RGB565
  ②RGB888(真彩色)
  ③ARBG=RGB+A透明度
本质:只记录R、G、B三基色各自的亮度
优势:方便数字化表达,广泛用于数字化彩色显示器,计算机编程等领域。
劣势:和传统的灰度图兼容不好,表达颜色的效率不高

YUV格式

YUV即YCbCr(色彩空间)//源自2个标准,但几乎相同

  Y表示亮度,U和V表示色度。只有Y就是黑白图像,再加上UV就是彩色图像了。//VU=128
优势:让彩色系统和传统黑白系统很好的兼容。
  
  
YUV 格式:
  【YUV】①【默认】打包(packed)格式 [YUV]+[YUV]… 三分量同平面
  【YUVp】②平面(planar)格式。使用三个数组分开存放 三个分量分别处于三个平面
    ①P(planar)      [Y]+[U]+[V]
    在这里插入图片描述
    ②SP(Semi-Planar)  [Y]+[U+V]   //semi半独立式
    在这里插入图片描述

YUV分类:

1、444  Y:U:V=4:4:4		完全取样2、422  Y:U:V=4:2:2		2:1的水平取样,垂直完全采样。3、420 	Y:U:V=4:1:1		2:1的水平取样,垂直2:1采样。	UV互相援引,即每一行4:2:0和4:0:2交替出现4、411	Y:U:V=4:1:1 	4:1的水平取样,垂直完全采样
YUV420P的4种分类:1、是否semir 2、UV先后顺序
YU12/I420: 	YYYYYYYY UU VV    =>YUV420PYV12: 		YYYYYYYY VV UU    =>YUV420PNV12: 		YYYYYYYY UVUV     =>YUV420SPNV21: 		YYYYYYYY VUVU     =>YUV420SP//P planer 表示数据存放再不同palner//S semir  表示UV一起or独自存放
YUV422
YUYV/YUY2YVYUUYVY

2、YUV和RGB的关系及转换

相互转换:用数学方法互相换算,是个典型的浮点运算过程。

YUV转灰度图:UV=128

rgb->BMP(文件头+信息头+像素数据)
按照小端存储顺序RRGB=0x00bbggrr调整然后写入像素数据
2种像素格式的转换公式(线性量化与否)

RGB常用颜色:

其中:  #808080 Gray 灰色 即R=G=B=128
根据换算公式:
  Y = 0.299R+0.587G+0.114B
  U = -0.169R-0.331G+0.5B+128
  V = 0.5R-0.419G-0.081B+128
  ↓↓↓
  由灰度图像R=G=B可知:Y=R=G=B, U=128, V=128.
  
故YUV420P去颜色(变成灰度图)//UV颜色→设置为128
memset(pic+wh,128,wh/2);//把后面部分的1/3像素’UV’数据转换成灰度色

3、YUV和RBG的转换

3.1 YUV和RGB的转换关系

未量化: Y/U/V ~(0-255)

1.小数形式,未量化R = Y + 1.4075 * (V-128);  G = Y - 0.3455 * (U-128) - 0.7169*(V-128);  B = Y + 1.779 * (U-128);  Y = 0.299*R + 0.587*G + 0.114*B;U = (B-Y)/1.772;    V = (R-Y)/1.402;       (U~(-128-127))或写为:Y =  0.299*R + 0.587*G + 0.114*B;U = -0.169*R - 0.331*G + 0.5  *B ;V =  0.5  *R - 0.419*G - 0.081*B;2.整数形式(减少计算量)未量化R= Y + ((360 * (V - 128))>>8) ; G= Y - (( ( 88 * (U - 128)  + 184 * (V - 128)) )>>8) ; B= Y +((455 * (U - 128))>>8) ;Y = (77*R + 150*G + 29*B)>>8;U = ((-44*R  - 87*G  + 131*B)>>8) + 128;V = ((131*R - 110*G - 21*B)>>8) + 128 ;

量化就是让通过线性变换让Y 或 U 或V 处于一定的范围内, 比如让Y (0,255) 变到 Y’ (16,235) 就这样来实行: Y’ = Y*[(235-16)/255] +16

量化后的公式( Y~(16,235) U/V ~(16,240) ) 量化

1.小数形式yuv --> rgbR = 1.164*Y + 1.596 * V - 222.9G = 1.164*Y - 0.392 * U - 0.823 * V+ 135.6B = 1.164*Y + 2.017 * U- 276.8 rgb --> yuv Y = 0.257*R' + 0.504*G' + 0.098*B' + 16U = -0.148*R' - 0.291*G' + 0.439*B' + 128V = 0.439*R' - 0.368*G' - 0.071*B' + 1282.整数的形式(减小计算量)   ( Y~(16,235)  U/V ~(16,240)  )yuv --> rgbR = (298*Y + 411 * V - 57344)>>8G = (298*Y - 101* U - 211* V+ 34739)>>8B = (298*Y + 519* U- 71117)>>8rgb --> yuv Y= (  66*R + 129*G +  25*B)>>8 +  16 U= ( -38*R -  74*G + 112*B)>>8 + 128V= ( 112*R -  94*G -  18*B)>>8 + 128

在转换的过程中需要注意: U,V相较于Y的数据比例

3.2 RGB转YUV

unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char  max_val){
if(x>max_val) return max_val; else if(x
> 8) + 16 ; u = (unsigned char)( ( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128 ; v = (unsigned char)( ( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128 ; *(ptrY++) = clip_value(y,0,255); if (j%2==0&&i%2 ==0) *(ptrU++) =clip_value(u,0,255); else {
if (i%2==0) *(ptrV++) =clip_value(v,0,255);} } } return true;}

3.3 YUYV转RGB24

#define Y0	0#define U	1#define Y1	2#define	V	3 #define R	0#define G	1#define	B	2 int yuv422_rgb24(unsigned char *yuv_buf, unsigned char *rgb_buf, unsigned int width, unsigned int height){
int yuvdata[4]; int rgbdata[3]; unsigned char *rgb_temp; unsigned int i, j; rgb_temp = rgb_buf; for (i = 0; i < height * 2; i++) {
for (j = 0; j < width; j+= 4) {
/* get Y0 U Y1 V */ yuvdata[Y0] = *(yuv_buf + i * width + j + 0); yuvdata[U] = *(yuv_buf + i * width + j + 1); yuvdata[Y1] = *(yuv_buf + i * width + j + 2); yuvdata[V] = *(yuv_buf + i * width + j + 3); /* the first pixel */ rgbdata[R] = yuvdata[Y0] + (yuvdata[V] - 128) + (((yuvdata[V] - 128) * 104 ) >> 8); rgbdata[G] = yuvdata[Y0] - (((yuvdata[U] - 128) * 89) >> 8) - (((yuvdata[V] - 128) * 183) >> 8); rgbdata[B] = yuvdata[Y0] + (yuvdata[U] - 128) + (((yuvdata[U] - 128) * 199) >> 8); if (rgbdata[R] > 255) rgbdata[R] = 255; if (rgbdata[R] < 0) rgbdata[R] = 0; if (rgbdata[G] > 255) rgbdata[G] = 255; if (rgbdata[G] < 0) rgbdata[G] = 0; if (rgbdata[B] > 255) rgbdata[B] = 255; if (rgbdata[B] < 0) rgbdata[B] = 0; *(rgb_temp++) = rgbdata[R] ; *(rgb_temp++) = rgbdata[G]; *(rgb_temp++) = rgbdata[B]; /* the second pix */ rgbdata[R] = yuvdata[Y1] + (yuvdata[V] - 128) + (((yuvdata[V] - 128) * 104 ) >> 8); rgbdata[G] = yuvdata[Y1] - (((yuvdata[U] - 128) * 89) >> 8) - (((yuvdata[V] - 128) * 183) >> 8); rgbdata[B] = yuvdata[Y1] + (yuvdata[U] - 128) + (((yuvdata[U] - 128) * 199) >> 8); if (rgbdata[R] > 255) rgbdata[R] = 255; if (rgbdata[R] < 0) rgbdata[R] = 0; if (rgbdata[G] > 255) rgbdata[G] = 255; if (rgbdata[G] < 0) rgbdata[G] = 0; if (rgbdata[B] > 255) rgbdata[B] = 255; if (rgbdata[B] < 0) rgbdata[B] = 0; *(rgb_temp++) = rgbdata[R]; *(rgb_temp++) = rgbdata[G]; *(rgb_temp++) = rgbdata[B]; } } return 0;}

转载地址:http://oyhrn.baihongyu.com/

你可能感兴趣的文章
剑指 Offer 25. 合并两个排序的链表
查看>>
剑指 Offer 26. 树的子结构
查看>>
剑指 Offer 27. 二叉树的镜像
查看>>
剑指 Offer 28. 对称的二叉树
查看>>
剑指 Offer 29. 顺时针打印矩阵
查看>>
剑指 Offer 30. 包含min函数的栈
查看>>
剑指 Offer 31. 栈的压入、弹出序列
查看>>
剑指 Offer 32 - I. 从上到下打印二叉树
查看>>
剑指 Offer 32 - III. 从上到下打印二叉树 III
查看>>
剑指 Offer 33. 二叉搜索树的后序遍历序列
查看>>
模式18.桥接模式-java
查看>>
剑指 Offer 34. 二叉树中和为某一值的路径
查看>>
剑指 Offer 35. 复杂链表的复制
查看>>
剑指 Offer 36. 二叉搜索树与双向链表
查看>>
剑指 Offer 38. 字符串的排列
查看>>
剑指 Offer 40. 最小的k个数
查看>>
剑指 Offer 41. 数据流中的中位数
查看>>
模式19.命令模式-Java
查看>>
模式20.职责链模式-Java
查看>>
剑指 Offer 45. 把数组排成最小的数
查看>>