欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

YuvImage源码分析以及使用

程序员文章站 2024-03-24 15:43:40
...

一、什么是YuvImage
YuvImage包含了YUV数据,并且提供了一个将YUV数据压缩成Jpeg数据的方法。
二、 什么时候使用
相机Camera类的PreviewCallback回调中,这个接口回调的是相机的预览图片,是YUV格式的数据,这是,利用YuvImage对象的compressToJpeg方法生成Jpeg格式的图片保存在本地
三、属性说明

//存储的字节数
private final static int WORKING_COMPRESS_STORAGE = 4096;
//YUV格式
private int mFormat;
// 原始的YUV数据
// 注意:多个图像平面的情况下,需要连接成一个单个字节数组
private byte[] mData;
//跨距   stride指在内存中每行像素所占的空间  每个图像平面的行字节数(不太清楚)
private int[] mStrides;
// 图像的高度
private int mHeight
//图像的宽度
private int mWidth

四、 构造方法

/**
     * Construct an YuvImage.
     *
     * @param yuv     The YUV data. In the case of more than one image plane, all the planes must be
     *                concatenated into a single byte array.
     * @param format  The YUV data format as defined in {@link ImageFormat}.
     * @param width   The width of the YuvImage.
     * @param height  The height of the YuvImage.
     * @param strides (Optional) Row bytes of each image plane. If yuv contains padding, the stride
     *                of each image must be provided. If strides is null, the method assumes no
     *                padding and derives the row bytes by format and width itself.
     * @throws IllegalArgumentException if format is not support; width or height <= 0; or yuv is
     *                null.
     */
    public YuvImage(byte[] yuv, int format, int width, int height, int[] strides) {
        if (format != ImageFormat.NV21 &&
                format != ImageFormat.YUY2) {
            throw new IllegalArgumentException(
                    "only support ImageFormat.NV21 " +
                    "and ImageFormat.YUY2 for now");
        }

        if (width <= 0  || height <= 0) {
            throw new IllegalArgumentException(
                    "width and height must large than 0");
        }

        if (yuv == null) {
            throw new IllegalArgumentException("yuv cannot be null");
        }

        if (strides == null) {
            mStrides = calculateStrides(width, format);
        } else {
            mStrides = strides;
        }

        mData = yuv;
        mFormat = format;
        mWidth = width;
        mHeight = height;
    }

1)yuv : YUV数据,多个图像平面的情况下,需要连接成一个单个字节数组

2) format:压缩格式,目前仅支持ImageFormat.NV21与ImageFormat.YUY2两个格式。

3) width:YuvImage的宽度

4) height:YuvImage的宽度

5) strides:(可选)每个图像平面的行字节。 如果YUV数据包含Padding,必须为每一个图像给一定的幅度,如果strides属性为null,该方法假设没有padding,并且根据格式和宽度自身派生行字节。

6) throws : 不合法的格式,宽高小于0,yue为空
五、 压缩方法

/**
     * Compress a rectangle region in the YuvImage to a jpeg.
     * Only ImageFormat.NV21 and ImageFormat.YUY2
     * are supported for now.
     *
     * @param rectangle The rectangle region to be compressed. The medthod checks if rectangle is
     *                  inside the image. Also, the method modifies rectangle if the chroma pixels
     *                  in it are not matched with the luma pixels in it.
     * @param quality   Hint to the compressor, 0-100. 0 meaning compress for
     *                  small size, 100 meaning compress for max quality.
     * @param stream    OutputStream to write the compressed data.
     * @return          True if the compression is successful.
     * @throws IllegalArgumentException if rectangle is invalid; quality is not within [0,
     *                  100]; or stream is null.
     */
    public boolean compressToJpeg(Rect rectangle, int quality, OutputStream stream) {
        Rect wholeImage = new Rect(0, 0, mWidth, mHeight);
        if (!wholeImage.contains(rectangle)) {
            throw new IllegalArgumentException(
                    "rectangle is not inside the image");
        }

        if (quality < 0 || quality > 100) {
            throw new IllegalArgumentException("quality must be 0..100");
        }

        if (stream == null) {
            throw new IllegalArgumentException("stream cannot be null");
        }

        adjustRectangle(rectangle);
        int[] offsets = calculateOffsets(rectangle.left, rectangle.top);

        return nativeCompressToJpeg(mData, mFormat, rectangle.width(),
                rectangle.height(), offsets, mStrides, quality, stream,
                new byte[WORKING_COMPRESS_STORAGE]);
    }

1) rectangle :要压缩的矩形区域

2) quality :压缩范围,0-100,其中,0表示低质量的压缩,100表示高质量的压缩

3) stream :压缩数据
六、YuvImage使用实例
将Camera中YUV数据转为Bitmap并且保存到本地

private boolean saveYUV2Bitmap(byte[] data,String path) {
  
		ByteArrayOutputStream stream = null;
		try {
			YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, WIDTH, HEIGHT,null);
			
			if (yuvImage != null) {
				stream = new ByteArrayOutputStream();
				yuvImage.compressToJpeg(new Rect(0, 0,WIDTH, HEIGHT),picQuality, stream);
				Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());

				File saveFile = new File(path);
				

				FileOutputStream fileOutputStream = new FileOutputStream(saveFile);
				bmp.compress(Bitmap.CompressFormat.JPEG, picQuality, fileOutputStream);
				fileOutputStream.flush();
				fileOutputStream.close();
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		return true;
	}

备注说明:1、WIDTH宽度、HEIGHT高度、picQuality 0到100

相关标签: 音视频