YUV是一种亮度信号Y和色度信号U、V是分离的色彩空间,它主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。 YUV格式分为两种类型:Packed类型和Planar类型。
1、Packed类型:是将YUV分量存在在同一个数组中,每个像素点的Y、U、V是连续交错存储的;
2、Planar类型:是将YUV分量分别存放到三个独立的数组中,且先连续存储所有像素点的Y,紧接着存储所有像素点的U,最后是所有像素点的V。
一、将NV21转Yuv420p
// YYYYYYYY VUVU --> YYYYYYYY UVUV
// 将NV21转换为Yuv420sp
public static byte[] nv21ToYuv420sp(byte[] src, int width, int height) {
int yLength = width * height;
int uLength = yLength / 4;
int vLength = yLength / 4;
int frameSize = yLength + uLength + vLength;
byte[] yuv420sp = new byte[frameSize];
// Y分量
System.arraycopy(src, 0, yuv420sp, 0, yLength);
for (int i = 0; i < yLength/4; i++) {
// U分量
yuv420sp[yLength + 2 * i] = src[yLength + 2*i+1];
// V分量
yuv420sp[yLength + 2*i+1] = src[yLength + 2*i];
}
return yuv420sp;
}
二、将YUV420SemiPlanner转换为NV21
// YYYYYYYY UVUV(yuv420sp)--> YYYYYYYY VUVU(nv21)
// 将YUV420SemiPlanner转换为NV21
public static byte[] yuv420spToNV21(byte[] src, int width, int height) {
int yLength = width * height;
int uLength = yLength / 4;
int vLength = yLength / 4;
int frameSize = yLength + uLength + vLength;
byte[] nv21 = new byte[frameSize];
// Y分量
System.arraycopy(src, 0, nv21, 0, yLength);
for (int i = 0; i < yLength/4; i++) {
// U分量
nv21[yLength + 2*i +1] = src[yLength+2*i];
// V分量
nv21[yLength + 2*i] = src[yLength + 2*i + 1];
}
return nv21;
}
三、将YUV420Planner(I420)转换为NV21
// YYYYYYYY UU VV --> YYYYYYYY VUVU
// 将YUV420Planner(I420)转换为NV21
public static byte[] yuv420pToNV21(byte[] src, int width, int height) {
int yLength = width * height;
int uLength = yLength / 4;
int vLength = yLength / 4;
int frameSize = yLength + uLength + vLength;
byte[] nv21 = new byte[frameSize];
System.arraycopy(src, 0, nv21, 0, yLength); // Y分量
for (int i = 0; i < yLength / 4; i++) {
// U分量
nv21[yLength + 2*i + 1] = src[yLength + i];
// V分量
nv21[yLength + 2*i] = src[yLength + uLength + i];
}
return nv21;
}
四、将nv21转换为yuv420p(I420)
// YYYYYYYY VUVU ---> YYYYYYYY UU VV
//
public static byte[] nv21ToYuv420p(byte[] src, int width, int height) {
int yLength = width * height;
int uLength = yLength / 4;
int vLength = yLength / 4;
int frameSize = yLength + uLength + vLength;
byte[] yuv420p = new byte[frameSize];
// Y分量
System.arraycopy(src, 0, yuv420p, 0, yLength);
for (int i = 0; i < yLength/4; i++) {
// U分量
yuv420p[yLength + i] = src[yLength + 2*i + 1];
// V分量
yuv420p[yLength + uLength + i] = src[yLength + 2*i];
}
return yuv420p;
}
五、将YV12转换为NV21
// YYYYYYYY VV UU --> YYYYYYYY VUVU
// 将YV12转换为NV21
public static byte[] yv12ToNV21(byte[] src, int width, int height) {
int yLength = width * height;
int uLength = yLength / 4;
int vLength = yLength / 4;
int frameSize = yLength + uLength + vLength;
byte[] nv21 = new byte[frameSize];
System.arraycopy(src, 0, nv21, 0, yLength); // Y分量
for (int i = 0; i < yLength / 4; i++) {
// U分量
nv21[yLength + 2*i + 1] = src[yLength + vLength + i];
// V分量
nv21[yLength + 2*i] = src[yLength + i];
}
return nv21;
}
五种数据互相转换。
-END