YuvImage源码分析以及使用
一、什么是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
上一篇: JavaScript动态加载效果
下一篇: 日志系列--账单日志的统计分析
推荐阅读
-
AsyncTask的使用以及源码分析
-
YuvImage源码分析以及使用
-
(八)JobSchedule 的使用以及源码分析
-
解决jenkins产生的日志过大以及一些衍生问题 博客分类: 开源分析系统使用Linux jenkins
-
模拟死锁以及使用jstack命令分析查找死锁原因
-
SharedPreferences的使用和源码分析
-
流程图+源码深入分析:缓存穿透和击穿问题出现原理以及可落地的解决方案
-
java使用websocket,并且获取HttpSession 源码分析(推荐)
-
SQL Server扩展事件的使用ring_buffer target时“丢失”事件的原因分析以及ring_buffer target潜在的问题
-
SQL Server扩展事件的使用ring_buffer target时“丢失”事件的原因分析以及ring_buffer target潜在的问题