一般的视频采集设备输出的数据都是YUV格式,
1.什么是YUV
YUV是一种图像编码方式 ,其中Y表示明亮度(Luminance、Luma),也就是灰阶值。
U、V 表示色度(Chrominance 或 Chroma),描述的是色调和饱和度。
2.为什么要用YUV格式
相比大家熟悉的RGB编码方式,YUV格式将图片的亮度和色度信息分开存储。为什么做?有什么好处呢?
由于人眼的视网膜杆细胞多于视网膜锥细胞,其中视网膜杆细胞的作用就是识别亮度,视网膜锥细胞的作用就是识别色度,所以人眼对亮度比较敏感,而对色度没那么敏感。利用这个特性,我们在采样的时候可以尽量保留亮度信息(Y),适当减少色度信息(UV),人眼也很难辨别出来。因此相比RGB编码方式,YUV能节省不少存储空间。
YUV格式运用十分广泛,从电视机到各种视频采集和显示设备,都是用的YUV格式。
3.YUV采样格式
YUV 图像的主流采样方式有如下三种:
- YUV 4:4:4
- YUV 4:2:2
- YUV 4:2:0
YUV 4:4:4 每个像素都采样一个Y、U、V分量,占用 3 个字节。
YUV 4:2:2 每个像素采样一个Y分量,两个像素共用一个UV分量,整体算下来每个像素点占用2个字节。
YUV 4:2:0 每个像素采样一个Y分量, 4个像素共用一个UV分量,整体算下来每个像素点占用1.5个字节。
4.YUV存储
YUV420P是基于 planar 平面模式进行存储,先存储所有的 Y 分量,然后存储所有的 U 分量,最后存储所有的 V 分量。
YUV420SP 先存储所有的 Y 分量,然后 UV 交替存储
5.YUV操作
<center><font color=gray size=2>原图</font></center>
1)提取Y分量
public static byte[] splitY(byte[] yuv420p, int w, int h) {
int frame = w * h;
byte[] y = new byte[frame];
System.arraycopy(yuv420p, 0, y, 0, y.length);
return y;
}
2)提取U分量
public static byte[] splitU(byte[] yuv420p, int w, int h) {
int frame = w * h;
byte[] u = new byte[frame / 4];
System.arraycopy(yuv420p, frame, u, 0, u.length);
return u;
}
3)提取V分量
public static byte[] splitV(byte[] yuv420p, int w, int h) {
int frame = w * h;
byte[] v = new byte[frame / 4];
System.arraycopy(yuv420p, frame + frame / 4, v, 0, v.length);
return v;
}
4)图片亮度减半
public static void halfLuminance(byte[] yuv420p, int w, int h) {
int frame = w * h;
for (int i = 0; i < frame; i++) {
int luminance = NumberUtils.byteToInt(yuv420p[i]);
yuv420p[i] = NumberUtils.intToByte(luminance / 2);
}
}
项目地址:
Gitee:https://gitee.com/huaisu2020/Android-Live
Github:https://github.com/xh2009cn/Android-Live