YUV的存储格式有两大类:packed和planar,还有SemiPlanar。
对于packed的YUV格式,每个像素点的Y,U,V是连续交错存储的。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
i420转YuyvPacked
public static byte[] i420ToYuyv(byte[] i420, int width, int height) {
if (i420 == null || i420.length == 0 || i420.length != width * height * 3 / 2) {
throw new IllegalArgumentException("invalid image params!");
}
byte[] yuyv = new byte[width * height * 2];
int yuyvLineSize = width * 2;
int i420YIndex = 0;
int i420UIndex = width * height;
int i420VIndex = width * height * 5 / 4;
int yuyvLineStart = 0;
for (int i = 0; i < height; i += 2) {
for (int lineOffset = 0; lineOffset < yuyvLineSize; lineOffset += 4) {
byte u = i420[i420UIndex++];
byte v = i420[i420VIndex++];
//偶数行数据赋值
int yuyvOffset = yuyvLineStart + lineOffset;
yuyv[yuyvOffset] = i420[i420YIndex];
yuyv[yuyvOffset + 1] = u;
yuyv[yuyvOffset + 2] = i420[i420YIndex + 1];
yuyv[yuyvOffset + 3] = v;
//奇数行数据赋值
int yuyvNextLineOffset = yuyvLineStart + yuyvLineSize + lineOffset;
yuyv[yuyvNextLineOffset] = i420[i420YIndex + width];
yuyv[yuyvNextLineOffset + 1] = u;
yuyv[yuyvNextLineOffset + 2] = i420[i420YIndex + width + 1];
yuyv[yuyvNextLineOffset + 3] = v;
i420YIndex += 2;
}
i420YIndex += width;
yuyvLineStart += (width << 2);
}
return yuyv;
}
i420转YuyvPlanar
public static byte[] i420ToYuyvPlanar(byte[] i420, int width, int height) {
if (i420 == null || i420.length == 0 || i420.length != width * height * 3 / 2) {
throw new IllegalArgumentException("invalid image params!");
}
byte[] yuyv = new byte[width * height * 2];
int yuyvUIndex = width * height;
int yuyvVIndex = width * height * 3 / 2;
//Y planar
System.arraycopy(i420, 0, yuyv, 0, width * height);
int i420UIndex = width * height;
int i420VIndex = width * height * 5 / 4;
int i420UHeight = height/4;
for(int i = 0; i<i420UHeight; i++) {
// U plannar
System.arraycopy(i420, i420UIndex+i*width, yuyv, yuyvUIndex+i*2*width, width);
System.arraycopy(i420, i420UIndex+i*width, yuyv, yuyvUIndex+(i*2+1)*width, width);
// V plannar
System.arraycopy(i420, i420VIndex+i*width, yuyv, yuyvVIndex+i*2*width, width);
System.arraycopy(i420, i420VIndex+i*width, yuyv, yuyvVIndex+(i*2+1)*width, width);
}
return yuyv;
}