博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android camera2 回调imagereader 从Image拿到YUV数据转化成RGB,生成bitmap并保存
阅读量:6194 次
发布时间:2019-06-21

本文共 7710 字,大约阅读时间需要 25 分钟。

ImageUtil.java
import android.graphics.ImageFormat;import android.media.Image;import android.os.Build;import android.support.annotation.RequiresApi;import android.util.Log;import java.nio.ByteBuffer;public class ImageUtil {        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, int type) {            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;                int pixelsStride, 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) {                    case YUV420P:                        System.arraycopy(uBytes, 0, yuvBytes, dstIndex, uBytes.length);                        System.arraycopy(vBytes, 0, yuvBytes, dstIndex + uBytes.length, vBytes.length);                        break;                    case YUV420SP:                        for (int i = 0; i < vBytes.length; i++) {                            yuvBytes[dstIndex++] = uBytes[i];                            yuvBytes[dstIndex++] = vBytes[i];                        }                        break;                    case NV21:                        for (int i = 0; i < vBytes.length; i++) {                            yuvBytes[dstIndex++] = vBytes[i];                            yuvBytes[dstIndex++] = uBytes[i];                        }                        break;                }                return yuvBytes;            } catch (final Exception e) {                if (image != null) {                    image.close();                }                Log.i(TAG, e.toString());            }            return null;        }    /***     * YUV420 转化成 RGB     */    public static int[] decodeYUV420SP(byte[] yuv420sp, int width, int height)    {        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);            }        }        return rgb;    }}

回调OnImageReader

private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {        @Override        public void onImageAvailable(ImageReader reader) {            Image image = reader.acquireLatestImage();            int imageWidth = image.getWidth();            int imageHeight = image.getHeight();            byte[] data68 = ImageUtil.getBytesFromImageAsType(image,2);            if(time==5) {               int rgb[] = ImageUtil.decodeYUV420SP(data68, imageWidth, imageHeight);                Bitmap bitmap2 = Bitmap.createBitmap(rgb, 0, imageWidth,                        imageWidth, imageHeight,                        android.graphics.Bitmap.Config.ARGB_8888);                try {                    File newFile = new File(Environment.getExternalStorageDirectory(), "345.png");                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));                    bitmap2.compress(Bitmap.CompressFormat.PNG, 100, bos);                    bos.flush();                    bos.close();                    bitmap2.recycle();                } catch (Exception e) {                }            }//            Message msg = Message.obtain();//            msg.obj = bitmap2;//            msg.what = 003;//            runHandler.sendMessage(msg);            image.close();        }    };

 

转载于:https://www.cnblogs.com/Jackie-zhang/p/10084947.html

你可能感兴趣的文章
ASP.NET MVC中检测浏览器版本并提示下载更新
查看>>
firdac支持的序列和还原格式
查看>>
Online, Cheap -- and Elite
查看>>
python datetime笔记
查看>>
exceptions.IOError: decoder jpeg not available
查看>>
【中文分词系列】 4. 基于双向LSTM的seq2seq字标注
查看>>
正则指引
查看>>
一些专业术语的总结
查看>>
条件变脸pthread_cond_signal丢失问题
查看>>
必须掌握的8个dos命令
查看>>
libcurl多线程超时设置不安全
查看>>
WinINet function(1)
查看>>
【转】Deep Learning(深度学习)学习笔记整理系列之(二)
查看>>
代码质量与上线压力
查看>>
系统时间不对 导至不能正常上网
查看>>
Binlog中最容易踩到的坑
查看>>
摄像头说明
查看>>
php 使用 ffmpeg 转换视频,截图,并生成缩略图
查看>>
jQuery EasyUI API 中文文档 - 加载器
查看>>
addedbytes.com 制作的速查表欣赏
查看>>