最近在看android camera源码,在DngCreator.java 文件中看到YUV420_888转换成RGB代码,摘抄下来方便使用。代码路径:Android/sdk/platforms/android-35/android.jar!/android/hardware/camera2/DngCreator.class
1. 将YUV420_888先转换成YUV的格式。
/**
* Generate a direct RGB {@link ByteBuffer} from a YUV420_888 {@link Image}.
*/
private static ByteBuffer convertToRGB(Image yuvImage) {
// TODO: Optimize this with renderscript intrinsic.
int width = yuvImage.getWidth();
int height = yuvImage.getHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(BYTES_PER_RGB_PIX * width * height);
Image.Plane yPlane = yuvImage.getPlanes()[0];
Image.Plane uPlane = yuvImage.getPlanes()[1];
Image.Plane vPlane = yuvImage.getPlanes()[2];
ByteBuffer yBuf = yPlane.getBuffer();
ByteBuffer uBuf = uPlane.getBuffer();
ByteBuffer vBuf = vPlane.getBuffer();
yBuf.rewind();
uBuf.rewind();
vBuf.rewind();
int yRowStride = yPlane.getRowStride();
int vRowStride = vPlane.getRowStride();
int uRowStride = uPlane.getRowStride();
int yPixStride = yPlane.getPixelStride();
int vPixStride = vPlane.getPixelStride();
int uPixStride = uPlane.getPixelStride();
byte[] yuvPixel = { 0, 0, 0 };
byte[] yFullRow = new byte[yPixStride * (width - 1) + 1];
byte[] uFullRow = new byte[uPixStride * (width / 2 - 1) + 1];
byte[] vFullRow = new byte[vPixStride * (width / 2 - 1) + 1];
byte[] finalRow = new byte[BYTES_PER_RGB_PIX * width];
for (int i = 0; i < height; i++) {
int halfH = i / 2;
yBuf.position(yRowStride * i);
yBuf.get(yFullRow);
uBuf.position(uRowStride * halfH);
uBuf.get(uFullRow);
vBuf.position(vRowStride * halfH);
vBuf.get(vFullRow);
for (int j = 0; j < width; j++) {
int halfW = j / 2;
yuvPixel[0] = yFullRow[yPixStride * j];
yuvPixel[1] = uFullRow[uPixStride * halfW];
yuvPixel[2] = vFullRow[vPixStride * halfW];
yuvToRgb(yuvPixel, j * BYTES_PER_RGB_PIX, /*out*/finalRow);
}
buf.put(finalRow);
}
yBuf.rewind();
uBuf.rewind();
vBuf.rewind();
buf.rewind();
return buf;
}
2.将YUV 转换成为RGB。
/**
* Convert a single YUV pixel to RGB.
*/
private static void yuvToRgb(byte[] yuvData, int outOffset, /*out*/byte[] rgbOut) {
final int COLOR_MAX = 255;
float y = yuvData[0] & 0xFF; // Y channel
float cb = yuvData[1] & 0xFF; // U channel
float cr = yuvData[2] & 0xFF; // V channel
// convert YUV -> RGB (from JFIF's "Conversion to and from RGB" section)
float r = y + 1.402f * (cr - 128);
float g = y - 0.34414f * (cb - 128) - 0.71414f * (cr - 128);
float b = y + 1.772f * (cb - 128);
// clamp to [0,255]
rgbOut[outOffset] = (byte) Math.max(0, Math.min(COLOR_MAX, r));
rgbOut[outOffset + 1] = (byte) Math.max(0, Math.min(COLOR_MAX, g));
rgbOut[outOffset + 2] = (byte) Math.max(0, Math.min(COLOR_MAX, b));
}