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

2023-05-16


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android camera2 回调imagereader 从Image拿到YUV数据转化成RGB,生成bitmap并保存 的相关文章

随机推荐

  • iOS 什么是函数式编程

    前言 xff1a 当前只做理解性的常规背书 xff0c 根据不断深入学习会不断丰富解读内容 xff0c 欢迎评论提意见 函数式编程 xff1a Functional Programming 1 基本解释 xff1a 函数式编程 是一种思维模
  • MVC笔记 MVC注意事项及优化

    一 学习MVC注意事项 1 了解不同的项目类型 从ASP NET 2 0开始 xff0c vs针对网站开发区分了两种项目类型 xff0c 一种是 39 项目 39 xff08 Website Project xff09 另一种是 39 网址
  • 微软:新Windows设备需要默认支持TPM 2.0安全功能

    在Windows 10系统中微软已经做出大量调整来提升安全性能 xff0c 而现在微软进一步提升运行最新操作系统设备的安全等级 自今年夏天开始 xff0c 微软表示需要所有Windows 10设备都默认支持TPM 2 0 可信任安全平台模组
  • 令牌桶算法限流

    限流 限流是对某一时间窗口内的请求数进行限制 xff0c 保持系统的可用性和稳定性 xff0c 防止因流量暴增而导致的系统运行缓慢或宕机 常用的限流算法有令牌桶和和漏桶 xff0c 而Google开源项目Guava中的RateLimiter
  • 关机一直显示正在关闭服务器,电脑关机后,显示正在关机,但等半天也关不了 怎么办...

    电脑关机后 xff0c 显示正在关机 xff0c 但等半天也关不了 怎么办以下文字资料是由 历史新知网www lishixinzhi com 小编为大家搜集整理后发布的内容 xff0c 让我们赶快一起来看一下吧 xff01 电脑关机后 xf
  • 一只老鸟嵌入式工程师的血泪史!

    作为一名在嵌入式行业摸爬滚打许久的老鸟 xff0c 回想自己的经历之路 xff0c 那么漫长可又仿佛近在眼前 随着学生的日益增多 xff0c 偶尔之间 xff0c 会想起自己曾经的一个经历 此文仅献给那些刚刚踏上硬件之路和还在徘徊的同学们
  • 程序员的“菜鸟心态综合症”

    第3章 程序员的 菜鸟心态综合症 清华大学出版社 Java程序员 xff0c 上班那点事儿 作者 xff1a 钟声 第3章部分节选 人的一生会遇到很多挫折 xff0c 尤其是我们刚刚参加工作初期的年轻人 这个人生阶段往往会出现各种各样的处世
  • sc.textFile("file:///home/spark/data.txt") Input path does not exist解决方法——submit 加参数 --master local...

    use this val data 61 sc textFile 34 home spark data txt 34 this should work and set master as local Input path does not
  • mongodb查询数据库中某个字段中的值包含某个字符串的方法

    正则表达式最能解决 xff1a 例如 xff1a db getCollection 39 news 39 find 39 content 39 120 77 215 34 9999 这里主要是注意正则表达式要写对 xff0c 该转义的注意转
  • MATLAB 求两个矩阵的 欧氏距离

    欧式距离定义 xff1a 欧式距离公式有如下几种表示方法 xff1a MATLAB 求两个矩阵的 欧氏距离 xff1a 如果定义两个矩阵分别为a b 则定义c 61 a b 2 所求距离d 61 sqrt sum c
  • Vmware虚拟机磁盘空间不足

    Vmware虚拟机清理磁盘空间 遇到一个问题就是虚拟机中的磁盘空间越来越小 xff0c 即使把文件删除以后 xff0c 磁盘空间还是无法释放 这主要是vmware中的缓存没有清除 在使用vmware虚拟机的时候 xff0c 经常会在主机和虚
  • 技术面试感觉什么都会,面试官一问回答不上来怎么办?

    又到了一年金三银四 xff0c 回想到很多年前我刚参加工作时的面试经历 xff0c 那时都是呆呆地等着面试官问问题 xff0c 被问到一些自己并不熟悉的问题时要不就是思考半天也切不中要点 xff0c 要不就只能无奈地回答并不清楚了 其实不管
  • 强化学习遭遇瓶颈!分层RL将成为突破的希望

    本文作者是法国里尔大学Inria SequeL团队的博士生 xff0c Yannis Flet Berliac xff0c 他在本文中对分层强化学习 xff08 HRL xff09 的研究进行了总结 xff0c 文章首先回顾了强化学习 xf
  • 如何免费下载百度文库文章的三种方法

    百度文库中的资源很丰富 xff0c 但那里的文章不能复制 xff0c 而且有的要下载币 给 大家总结下免费下载复制百度文库的三种方法 第一种 利用百度快照 我们在百度文库中找到自己想要的文章后 xff0c 直接把那篇文章的地址复制 xff0
  • 434个H5游戏源码

    各种类型HTML5游戏 xff0c 界面和JS均可供项目参考 下面是下载地址 转载于 https blog 51cto com 12130120 2374590
  • iOS 左右滑动 手势 响应方法

    1 64 property nonatomic strong UISwipeGestureRecognizer leftSwipeGestureRecognizer 64 property nonatomic strong UISwipeG
  • 一道c语言编程题

    一道c语言编程题 将一个5 5的矩阵中最大的元素放在中心 xff0c 四个角分别放四个最小的元素 xff08 顺序从左到右 xff0c 从上到下顺序依次从小到大存放 xff09 xff0c 写一函数实现之 xff0c 用main函数调用 i
  • print(1,2,3,sep=':')的输出结果是?

    print 1 2 3 sep 61 39 39 1 2 3 第一个参数 要打印的值 第二个参数sep表示要打印多个值时 各值的分割方式 默认空格 第三个参数end表示结尾的方式 默认 n 转载于 https www cnblogs com
  • S3. Android 消息推送

    概要 消息推送 转载于 https www cnblogs com zlxyt p 11133181 html
  • Android camera2 回调imagereader 从Image拿到YUV数据转化成RGB,生成bitmap并保存

    ImageUtil java import android graphics ImageFormat import android media Image import android os Build import android sup