IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android保存yuv工具类 -> 正文阅读

[移动开发]android保存yuv工具类

假设图像尺寸是width * height

原索引srcIndex:初始为0

目的索引destIndex:初始为0,指向目的字节数组

(1)将Y通道保存到字节数组

for (loop : height) {?????? // 循环height

?????? 拷贝width字节数据

?????? 偏移行距:srcIndex += rowStride

?????? 偏移宽度:destIndex += width

}

(2)将U通道保存到字节数组

外层循环height/2

内层循环width/2

package com.camera.camera2testbed;

import android.graphics.ImageFormat;
import android.media.Image;
import java.nio.ByteBuffer;

public class YuvUtil {
    public static final int YUV420P = 0;
    public static final int YUV420SP = 1;
    public static final int NV21 = 2;

    public  static byte[] yuvBytes = null;
    private static byte uBytes[] = null;
    private static byte vBytes[] = null;

    public static boolean getBytesFromImageAsType(Image image, int type, boolean black_white) {
        if (null == image) {
            return false;
        }
        // 获取源数据,如果是YUV格式的数据planes.length = 3
        // plane[i]里面的实际数据可能存在byte[].length <= capacity (缓冲区总大小)
        final Image.Plane[] planes = image.getPlanes();
        if (planes.length != 3) {
            return false;
        }
        // 数据有效宽度,一般的,图片width <= rowStride,这也是导致byte[].length <= capacity的原因
        // 所以只取width部分
        int width = image.getWidth();
        int height = image.getHeight();
        //此处用来装填最终的YUV数据,需要1.5倍的图片大小,因为Y U V 比例为 4:1:1
        if (null == yuvBytes) {
            yuvBytes = new byte[width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8];
        }
        // 临时存储uv数据的
        if (null == uBytes) {
            uBytes = new byte[width * height / 4];
        }
        if (null == vBytes) {
            vBytes = new byte[width * height / 4];
        }
        if ((null == yuvBytes) || (null == uBytes) || (null == vBytes)) {
            return false;
        }
        // 源数组的装填到的位置
        int srcIndex = 0;
        // 目标数组的装填到的位置
        int dstIndex = 0;
        int uIndex = 0;
        int vIndex = 0;
        int pixelsStride = 0, rowStride = 0;
        for (int planeNo = 0;planeNo < planes.length;planeNo++) {
            pixelsStride = planes[planeNo].getPixelStride();
            rowStride = planes[planeNo].getRowStride();
            ByteBuffer buffer = planes[planeNo].getBuffer();
            byte[] bytes = new byte[buffer.capacity()];
            if (null == bytes) {
                return false;
            }
            buffer.get(bytes);
            srcIndex = 0;
            switch (planeNo) {
                case 0:
                    for (int i = 0; i < height; i++) {
                        System.arraycopy(bytes, srcIndex, yuvBytes, dstIndex, width);
                        srcIndex += rowStride;
                        dstIndex += width;
                    }
                    break;
                case 1:
                    for (int i = 0; i < height / 2; i++) {
                        for (int j = 0; j < width / 2; j++) {
                            uBytes[uIndex++] = bytes[srcIndex];
                            srcIndex += pixelsStride;
                        }
                        if (2 == pixelsStride) {
                            srcIndex += rowStride - width;
                        } else if (1 == pixelsStride) {
                            srcIndex += rowStride - width / 2;
                        }
                        else {
                            return false;
                        }
                    }
                    break;
                case 2:
                    for (int i = 0; i < height / 2; i++) {
                        for (int j = 0; j < width / 2; j++) {
                            vBytes[vIndex++] = bytes[srcIndex];
                            srcIndex += pixelsStride;
                        }
                        if (2 == pixelsStride) {
                            srcIndex += rowStride - width;
                        } else if (1 == pixelsStride) {
                            srcIndex += rowStride - width / 2;
                        }
                        else {
                            return false;
                        }
                    }
                    break;
            }
        }
        final byte char_128 = (byte) 128;
        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:
                if (true == black_white) {
                    for (int i = 0; i < vBytes.length; i++) {
                        yuvBytes[dstIndex++] = char_128;
                        yuvBytes[dstIndex++] = char_128;
                    }
                }
                else {
                    for (int i = 0; i < vBytes.length; i++) {
                        yuvBytes[dstIndex++] = uBytes[i];
                        yuvBytes[dstIndex++] = vBytes[i];
                    }
                }
                break;
            case NV21:
                if (true == black_white) {
                    for (int i = 0; i < vBytes.length; i++) {
                        yuvBytes[dstIndex++] = char_128;
                        yuvBytes[dstIndex++] = char_128;
                    }
                }
                else {
                    for (int i = 0; i < vBytes.length; i++) {
                        yuvBytes[dstIndex++] = vBytes[i];
                        yuvBytes[dstIndex++] = uBytes[i];
                    }
                }
                break;
            default:
                return false;
        }
        return true;
    }
}

github:android_demo/Camera2TestBed at main · wangzhicheng2013/android_demo · GitHub

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:34:46  更:2022-07-17 16:36:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 3:35:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码