1ImageUtil.java 2 3import android.graphics.ImageFormat; 4import android.media.Image; 5import android.os.Build; 6import android.support.annotation.RequiresApi; 7import android.util.Log; 8 9import java.nio.ByteBuffer; 10 11public class ImageUtil { 12 public static final int YUV420P = 0; 13 public static final int YUV420SP = 1; 14 public static final int NV21 = 2; 15 private static final String TAG = "ImageUtil"; 16 17 /*** 18 * 此方法内注释以640*480为例 19 * 未考虑CropRect的 20 */ 21 @RequiresApi(api = Build.VERSION_CODES.KITKAT) 22 public static byte[] getBytesFromImageAsType(Image image, int type) { 23 try { 24 //获取源数据,如果是YUV格式的数据planes.length = 3 25 //plane[i]里面的实际数据可能存在byte[].length <= capacity (缓冲区总大小) 26 final Image.Plane[] planes = image.getPlanes(); 27 28 //数据有效宽度,一般的,图片width <= rowStride,这也是导致byte[].length <= capacity的原因 29 // 所以我们只取width部分 30 int width = image.getWidth(); 31 int height = image.getHeight(); 32 33 //此处用来装填最终的YUV数据,需要1.5倍的图片大小,因为Y U V 比例为 4:1:1 34 byte[] yuvBytes = new byte[width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8]; 35 //目标数组的装填到的位置 36 int dstIndex = 0; 37 38 //临时存储uv数据的 39 byte uBytes[] = new byte[width * height / 4]; 40 byte vBytes[] = new byte[width * height / 4]; 41 int uIndex = 0; 42 int vIndex = 0; 43 44 int pixelsStride, rowStride; 45 for (int i = 0; i < planes.length; i++) { 46 pixelsStride = planes[i].getPixelStride(); 47 rowStride = planes[i].getRowStride(); 48 49 ByteBuffer buffer = planes[i].getBuffer(); 50 51 //如果pixelsStride==2,一般的Y的buffer长度=640*480,UV的长度=640*480/2-1 52 //源数据的索引,y的数据是byte中连续的,u的数据是v向左移以为生成的,两者都是偶数位为有效数据 53 byte[] bytes = new byte[buffer.capacity()]; 54 buffer.get(bytes); 55 56 int srcIndex = 0; 57 if (i == 0) { 58 //直接取出来所有Y的有效区域,也可以存储成一个临时的bytes,到下一步再copy 59 for (int j = 0; j < height; j++) { 60 System.arraycopy(bytes, srcIndex, yuvBytes, dstIndex, width); 61 srcIndex += rowStride; 62 dstIndex += width; 63 } 64 } else if (i == 1) { 65 //根据pixelsStride取相应的数据 66 for (int j = 0; j < height / 2; j++) { 67 for (int k = 0; k < width / 2; k++) { 68 uBytes[uIndex++] = bytes[srcIndex]; 69 srcIndex += pixelsStride; 70 } 71 if (pixelsStride == 2) { 72 srcIndex += rowStride - width; 73 } else if (pixelsStride == 1) { 74 srcIndex += rowStride - width / 2; 75 } 76 } 77 } else if (i == 2) { 78 //根据pixelsStride取相应的数据 79 for (int j = 0; j < height / 2; j++) { 80 for (int k = 0; k < width / 2; k++) { 81 vBytes[vIndex++] = bytes[srcIndex]; 82 srcIndex += pixelsStride; 83 } 84 if (pixelsStride == 2) { 85 srcIndex += rowStride - width; 86 } else if (pixelsStride == 1) { 87 srcIndex += rowStride - width / 2; 88 } 89 } 90 } 91 } 92 93 // image.close(); 94 95 //根据要求的结果类型进行填充 96 switch (type) { 97 case YUV420P: 98 System.arraycopy(uBytes, 0, yuvBytes, dstIndex, uBytes.length); 99 System.arraycopy(vBytes, 0, yuvBytes, dstIndex + uBytes.length, vBytes.length); 100 break; 101 case YUV420SP: 102 for (int i = 0; i < vBytes.length; i++) { 103 yuvBytes[dstIndex++] = uBytes[i]; 104 yuvBytes[dstIndex++] = vBytes[i]; 105 } 106 break; 107 case NV21: 108 for (int i = 0; i < vBytes.length; i++) { 109 yuvBytes[dstIndex++] = vBytes[i]; 110 yuvBytes[dstIndex++] = uBytes[i]; 111 } 112 break; 113 } 114 return yuvBytes; 115 } catch (final Exception e) { 116 if (image != null) { 117 image.close(); 118 } 119 Log.i(TAG, e.toString()); 120 } 121 return null; 122 } 123 124 /*** 125 * YUV420 转化成 RGB 126 */ 127 public static int[] decodeYUV420SP(byte[] yuv420sp, int width, int height) 128 { 129 final int frameSize = width * height; 130 int rgb[] = new int[frameSize]; 131 for (int j = 0, yp = 0; j < height; j++) { 132 int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; 133 for (int i = 0; i < width; i++, yp++) { 134 int y = (0xff & ((int) yuv420sp[yp])) - 16; 135 if (y < 0) 136 y = 0; 137 if ((i & 1) == 0) { 138 v = (0xff & yuv420sp[uvp++]) - 128; 139 u = (0xff & yuv420sp[uvp++]) - 128; 140 } 141 int y1192 = 1192 * y; 142 int r = (y1192 + 1634 * v); 143 int g = (y1192 - 833 * v - 400 * u); 144 int b = (y1192 + 2066 * u); 145 if (r < 0) 146 r = 0; 147 else if (r > 262143) 148 r = 262143; 149 if (g < 0) 150 g = 0; 151 else if (g > 262143) 152 g = 262143; 153 if (b < 0) 154 b = 0; 155 else if (b > 262143) 156 b = 262143; 157 rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) 158 | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 159 } 160 } 161 return rgb; 162 } 163}
回调OnImageReader
1private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { 2 @Override 3 public void onImageAvailable(ImageReader reader) { 4 Image image = reader.acquireLatestImage(); 5 6 int imageWidth = image.getWidth(); 7 int imageHeight = image.getHeight(); 8 9 byte[] data68 = ImageUtil.getBytesFromImageAsType(image,2); 10 11 if(time==5) { 12 int rgb[] = ImageUtil.decodeYUV420SP(data68, imageWidth, imageHeight); 13 Bitmap bitmap2 = Bitmap.createBitmap(rgb, 0, imageWidth, 14 imageWidth, imageHeight, 15 android.graphics.Bitmap.Config.ARGB_8888); 16 try { 17 File newFile = new File(Environment.getExternalStorageDirectory(), "345.png"); 18 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile)); 19 bitmap2.compress(Bitmap.CompressFormat.PNG, 100, bos); 20 bos.flush(); 21 bos.close(); 22 bitmap2.recycle(); 23 } catch (Exception e) { 24 25 } 26 } 27 28// Message msg = Message.obtain(); 29// msg.obj = bitmap2; 30// msg.what = 003; 31// runHandler.sendMessage(msg); 32 33 image.close(); 34 } 35 };