android 将Bitmap转YUV420sp(实例)

本文介绍了一种将ARGB像素数据转换为YUV420SP格式的方法,该格式常用于视频编码场景中。文章详细展示了如何通过特定的RGB到YUV转换算法来实现这一过程,并确保了输出格式符合MediaCodec的要求。



/**
     * 将bitmap里得到的argb数据转成yuv420sp格式
     * 这个yuv420sp数据就可以直接传给MediaCodec,通过AvcEncoder间接进行编码
     * @param yuv420sp 用来存放yuv429sp数据
     * @param argb 传入argb数据
     * @param width   图片width
     * @param height 图片height
     */
    public static void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
        final int frameSize = width * height;

        int yIndex = 0;
        int uvIndex = frameSize;

        int a, R, G, B, Y, U, V;
        int index = 0;
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {

                a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
                R = (argb[index] & 0xff0000) >> 16;
                G = (argb[index] & 0xff00) >> 8;
                B = (argb[index] & 0xff) >> 0;

                // well known RGB to YUV algorithm
                Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
                U = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
                V = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;

                // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
                //    meaning for every 4 Y pixels there are 1 V and 1 U.  Note the sampling is every other
                //    pixel AND every other scanline.
                yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
                if (j % 2 == 0 && index % 2 == 0) {
                    yuv420sp[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
                    yuv420sp[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
                }

                index ++;
            }
        }
    }








<think>好的,用户想了解在Android中使用OpenCV将YUV420数据换为Bitmap的方法。我需要先回忆一下相关的知识点,确保步骤正确。 首先,YUV420是一种常见的视频格式,尤其在摄像头和视频流中广泛使用。Android设备获取的图像数据通常也是YUV格式的,而Bitmap使用的是RGB格式,所以需要进行颜色空间换。 接下来,OpenCV是一个强大的计算机视觉库,支持多种图像处理操作。用户可能已经集成了OpenCV库到他们的Android项目中,这一步可能需要确认,但用户的问题集中在换过程,所以暂时假设环境已经配置好。 YUV420有不同的排列方式,比如NV21和NV12,这些是YUV420的变种,区别在于UV分量的排列顺序。用户需要明确他们的YUV数据具体是哪种格式,否则换可能会出错。例如,NV21是YUV420SP的一种,而NV12则是UV和VU的顺序不同。 然后,考虑使用OpenCV的Mat类来处理图像数据。YUV数据需要先换为Mat对象,可能需要根据不同的格式调整构造参数。例如,如果是NV21格式,可能需要使用Imgproc.COLOR_YUV2RGB_NV21作为换代码,而NV12则对应不同的代码。 步骤大致如下:首先将YUV的字节数组换为OpenCV的Mat,然后进行颜色空间换,最后将换后的Mat换为Bitmap。需要注意的是,Mat的尺寸和类型是否正确,例如,YUV420的尺寸可能需要考虑UV分量的子采样,通常高度是原图的1.5倍,或者宽度是原图的1.5倍,具体取决于数据排列。 另外,要确保换后的Mat格式是ARGB_8888,因为AndroidBitmap通常使用这种格式。OpenCV默认的Mat颜色顺序是BGR,所以在换时可能需要调整参数,比如使用COLOR_YUV2RGBA_NV21来得到RGBA格式,再进一步处理。 还有可能遇到的问题是,输入的YUV数据是否正确,包括宽度、高度以及数据长度是否符合预期。例如,YUV420的数据长度应为width * height * 3 / 2字节,如果不符合,换会失败。 最后,需要处理可能的异常,比如捕获错误或检查OpenCV是否正确加载。用户可能在集成OpenCV时遇到问题,但根据问题描述,这里重点在换过程,所以暂时不深入讨论环境配置的问题。 总结起来,关键步骤是:创建正确参数的Mat对象,使用正确的颜色换代码,执行换,然后通过Utils.matToBitmap方法生成Bitmap。用户需要注意YUV的具体格式和尺寸是否正确,否则可能出现颜色错误或崩溃。</think>在Android中将YUV420数据换为Bitmap需通过以下步骤实现,这里以最常见的NV21格式(YUV420SP)为例: --- ### 一、环境准备 1. 添加OpenCV依赖 ```groovy implementation 'org.opencv:opencv-android:4.5.5' ``` 2. 初始化OpenCV库 ```java if (!OpenCVLoader.initDebug()) { OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, context, loaderCallback); } ``` --- ### 二、核心换步骤 #### 1. 创建YUV Mat对象 ```java // 假设图像尺寸为width x height Mat yuvMat = new Mat(height + height/2, width, CvType.CV_8UC1); yuvMat.put(0, 0, yuvData); // yuvData是byte[]格式的原始数据 ``` #### 2. 换为RGB格式 ```java Mat rgbMat = new Mat(); Imgproc.cvtColor(yuvMat, rgbMat, Imgproc.COLOR_YUV2RGBA_NV21); // 注意:NV21使用COLOR_YUV2RGBA_NV21,NV12使用COLOR_YUV2RGBA_NV12 ``` #### 3. 生成Bitmap ```java Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Utils.matToBitmap(rgbMat, bitmap); ``` --- ### 三、完整代码示例 ```java public Bitmap yuv420ToBitmap(byte[] yuvData, int width, int height) { // 创建YUV Mat Mat yuvMat = new Mat(height + height/2, width, CvType.CV_8UC1); yuvMat.put(0, 0, yuvData); // 换为RGB Mat rgbMat = new Mat(); Imgproc.cvtColor(yuvMat, rgbMat, Imgproc.COLOR_YUV2RGBA_NV21); // 生成Bitmap Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Utils.matToBitmap(rgbMat, bitmap); // 释放内存 yuvMat.release(); rgbMat.release(); return bitmap; } ``` --- ### 四、关键注意事项 1. **格式验证**:确保输入数据是YUV420SP(NV21/NV12)YUV420P(I420) 2. **尺寸计算**:YUV数据长度需满足 `width × height × 1.5` 3. **颜色通道顺序**:Android Bitmap默认使用ARGB_8888格式 4. **性能优化**:大尺寸图像建议在子线程处理 --- ### 五、常见问题排查 1. **绿屏/颜色异常**:检查YUV格式参数是否正确 2. **空指针错误**:确认OpenCV库已正确初始化 3. **内存溢出**:及时调用Mat.release()释放资源 如需处理其他YUV格式,可调整换参数: - `COLOR_YUV2RGBA_I420` 对应YUV420P - `COLOR_YUV2RGBA_YV12` 对应YV12格式
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值