android image 转yuv_Android camera2 回调imagereader 从Image拿到YUV数据转化成RGB,生成bitmap并保存...

该博客介绍了如何在Android中,使用Camera2 API和ImageReader从Image对象中获取YUV数据,并将其转换为RGB,进而生成Bitmap并进行保存。文章详细解析了处理YUV数据的步骤,包括对不同格式的理解和转换过程。
摘要由CSDN通过智能技术生成

importandroid.graphics.ImageFormat;importandroid.media.Image;importandroid.os.Build;importandroid.support.annotation.RequiresApi;importandroid.util.Log;importjava.nio.ByteBuffer;public classImageUtil {public static final int YUV420P = 0;public static final int YUV420SP = 1;public static final int NV21 = 2;private static final String TAG = "ImageUtil";/***

* 此方法内注释以640*480为例

* 未考虑CropRect的*/@RequiresApi(api=Build.VERSION_CODES.KITKAT)public static byte[] getBytesFromImageAsType(Image image, inttype) {try{//获取源数据,如果是YUV格式的数据planes.length = 3//plane[i]里面的实际数据可能存在byte[].length <= capacity (缓冲区总大小)

final Image.Plane[] planes =image.getPlanes();//数据有效宽度,一般的,图片width <= rowStride,这也是导致byte[].length <= capacity的原因//所以我们只取width部分

int width =image.getWidth();int height =image.getHeight();//此处用来装填最终的YUV数据,需要1.5倍的图片大小,因为Y U V 比例为 4:1:1

byte[] yuvBytes = new byte[width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8];//目标数组的装填到的位置

int dstIndex = 0;//临时存储uv数据的

byte uBytes[] = new byte[width * height / 4];byte vBytes[] = new byte[width * height / 4];int uIndex = 0;int vIndex = 0;intpixelsStride, rowStride;for (int i = 0; i < planes.length; i++) {

pixelsStride=planes[i].getPixelStride();

rowStride=planes[i].getRowStride();

ByteBuffer buffer=planes[i].getBuffer();//如果pixelsStride==2,一般的Y的buffer长度=640*480,UV的长度=640*480/2-1//源数据的索引,y的数据是byte中连续的,u的数据是v向左移以为生成的,两者都是偶数位为有效数据

byte[] bytes = new byte[buffer.capacity()];

buffer.get(bytes);int srcIndex = 0;if (i == 0) {//直接取出来所有Y的有效区域,也可以存储成一个临时的bytes,到下一步再copy

for (int j = 0; j < height; j++) {

System.arraycopy(bytes, srcIndex, yuvBytes, dstIndex, width);

srcIndex+=rowStride;

dstIndex+=width;

}

}else if (i == 1) {//根据pixelsStride取相应的数据

for (int j = 0; j < height / 2; j++) {for (int k = 0; k < width / 2; k++) {

uBytes[uIndex++] =bytes[srcIndex];

srcIndex+=pixelsStride;

}if (pixelsStride == 2) {

srcIndex+= rowStride -width;

}else if (pixelsStride == 1) {

srcIndex+= rowStride - width / 2;

}

}

}else if (i == 2) {//根据pixelsStride取相应的数据

for (int j = 0; j < height / 2; j++) {for (int k = 0; k < width / 2; k++) {

vBytes[vIndex++] =bytes[srcIndex];

srcIndex+=pixelsStride;

}if (pixelsStride == 2) {

srcIndex+= rowStride -width;

}else if (pixelsStride == 1) {

srcIndex+= rowStride - width / 2;

}

}

}

}

// image.close();//根据要求的结果类型进行填充

switch(type) {caseYUV420P:

System.arraycopy(uBytes,0, yuvBytes, dstIndex, uBytes.length);

System.arraycopy(vBytes,0, yuvBytes, dstIndex +uBytes.length, vBytes.length);break;caseYUV420SP:for (int i = 0; i < vBytes.length; i++) {

yuvBytes[dstIndex++] =uBytes[i];

yuvBytes[dstIndex++] =vBytes[i];

}break;caseNV21:for (int i = 0; i < vBytes.length; i++) {

yuvBytes[dstIndex++] =vBytes[i];

yuvBytes[dstIndex++] =uBytes[i];

}break;

}returnyuvBytes;

}catch (finalException e) {if (image != null) {

image.close();

}

Log.i(TAG, e.toString());

}return null;

}/***

* YUV420 转化成 RGB*/

public static int[] decodeYUV420SP(byte[] yuv420sp, int width, intheight)

{final int frameSize = width *height;int rgb[] = new int[frameSize];for (int j = 0, yp = 0; j < height; j++) {int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;for (int i = 0; i < width; i++, yp++) {int y = (0xff & ((int) yuv420sp[yp])) - 16;if (y < 0)

y= 0;if ((i & 1) == 0) {

v= (0xff & yuv420sp[uvp++]) - 128;

u= (0xff & yuv420sp[uvp++]) - 128;

}int y1192 = 1192 *y;int r = (y1192 + 1634 *v);int g = (y1192 - 833 * v - 400 *u);int b = (y1192 + 2066 *u);if (r < 0)

r= 0;else if (r > 262143)

r= 262143;if (g < 0)

g= 0;else if (g > 262143)

g= 262143;if (b < 0)

b= 0;else if (b > 262143)

b= 262143;

rgb[yp]= 0xff000000 | ((r << 6) & 0xff0000)| ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);

}

}returnrgb;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值