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