Android 图片压缩

来源:互联网 发布:广州市云润大数据 编辑:程序博客网 时间:2024/06/15 19:32

一 前言

        在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩);质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手机拍照都能达到3M左右了,尺寸压缩一般可用于生成缩略图。
两种方法都实装在了我的项目中,结果却发现在质量压缩的模块中,本来1.9M的图片压缩后反而变成3M多了,很是奇怪,再做了进一步调查终于知道原因了。下面这个博客说的比较清晰:
android图片压缩总结:
           总结来看,图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,所谓的质量压缩,它其实只能实现对file的影响,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是被压缩过的,但是中间的bitmap并没有被压缩(或者说几乎没有被压缩,我不确定),因为bigmap在内存中的大小是按像素计算的,也就是width * height,对于质量压缩,并不会改变图片的像素,所以就算质量被压缩了,但是bitmap在内存的占有率还是没变小,但你做成file时,它确实变小了;而尺寸压缩由于是减小了图片的像素,所以它直接对bitmap产生了影响,当然最终的file也是相对的变小了

二 压缩方式

1 质量压缩
public static void compressQuality(Bitmap bmp , File saveFile , int scale){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//压缩后的数据保存到baos中
bmp.compress(Bitmap.CompressFormat.JPEG, scale, baos);
FileOutputStream os = null;
try {
os = new FileOutputStream(saveFile);
os.write(baos.toByteArray());
os.flush();
os.close();
baos.close();
} catch (FileNotFoundException e) {
LogUtil.logErrorMessage(TAG,e.getMessage());
} catch (IOException e) {
LogUtil.logErrorMessage(TAG,e.getMessage());
}finally {
try {
if (null != os){
os.close();
}
baos.close();
} catch (IOException e) {
LogUtil.logErrorMessage(TAG,e.getMessage());
}

}
}
说明:第一个参数为需要压缩的bitmap图片对象,第二个参数为压缩后图片保存的位置,第三个参数scale压缩比例,其值0-100,100为不压缩,值越小压缩也严重。
2 尺寸压缩
public static void compressSize(Bitmap bmp , File saveFile, int scale){
//压缩Bitmap到对应尺寸
Bitmap compressBitmap = Bitmap.createBitmap(bmp.getWidth() / scale, bmp.getHeight() / scale,Bitmap.Config.ARGB_8888);
// 原图的裁剪区域
Rect srcRect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
//压缩后的区域
Rect compressRect = new Rect(0, 0, bmp.getWidth() / scale, bmp.getHeight() / scale);
//创建画布,用来绘制图片
Canvas canvas = new Canvas();
canvas.setBitmap(compressBitmap);
canvas.drawBitmap(bmp,srcRect,compressRect,null);
//压缩后的数据保存到baos中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
compressBitmap.compress(Bitmap.CompressFormat.JPEG,100,baos);
FileOutputStream os = null;
try {
os = new FileOutputStream(saveFile);
os.write(baos.toByteArray());
os.flush();
os.close();
baos.close();
} catch (FileNotFoundException e) {
LogUtil.logErrorMessage(TAG,e.getMessage());
} catch (IOException e) {
LogUtil.logErrorMessage(TAG,e.getMessage());
}finally {
try {
if (null != os){
os.close();
}
baos.close();
} catch (IOException e) {
LogUtil.logErrorMessage(TAG,e.getMessage());
}

}
//释放内存回收资料
compressBitmap.recycle();
System.gc();

}
       说明:第一个参数为需要压缩的bitmap图片对象,第二个参数为压缩后图片保存的位置,第三个参数scale尺寸压缩倍数,值越大压缩也严重;从上述代码也可以看出尺寸压缩针对的对象是bitmap,对原先的图片Bitmap对象进行尺寸缩减,相应的图片的大小、像素也就减小了。
设置图片的采样率,降低图片像素
public static void compressBitmap(String filePath, File file , int inSampleSize){
// 数值越高,图片像素越低
BitmapFactory.Options options = new BitmapFactory.Options();
//采样率
options.inSampleSize = inSampleSize;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, 100 ,baos);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
说明:参数一 图片的位置;参数二压缩后图片保存的位置;参数三采样率数值越高,图片像素越低

三 JNI调用libjpeg库压缩

JNI静态调用 bitherlibjni.c 中的方法来实现压缩,首先要添加os库到lib中,在app的build添加如下代码:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
再者,在工具类中添加声明libjpeg库:
static {
System.loadLibrary("jpegbither");
System.loadLibrary("bitherjni");
}
再者添加native方法:
private static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes,
boolean optimize);
参数说明如下:
* @param bit 需要压缩的Bitmap对象
* @param w 图片宽度
* @param h 图片高度
* @param quality 压缩质量0-100
* @param fileNameBytes 压缩后要保存的文件地址
* @param optimize 是否采用哈弗曼表数据计算 品质相差5-10倍
然后就可以调用该方法了。
具体示例参考:https://gitee.com/lzbgit/JpegbitherLibTest
工具类封装点击查看NativeUtil。

四 ThumbnailUtils系统工具类视频缩略图

1 Bitmap createVideoThumbnail(String filePath, int kind)

创建一张视频的缩略图。如果视频已损坏或者格式不支持可能返回null。

filePath:视频文件路径

kind:文件种类,可以是 MINI_KIND 或 MICRO_KIND

Bitmap extractThumbnail(Bitmap source, int width, int height, int options)

创建所需尺寸居中缩放的位图。

source: 需要被创造缩略图的源位图对象

width: 生成目标的宽度

height: 生成目标的高度

options:在缩略图抽取时提供的选项

 Bitmap extractThumbnail(Bitmap source, int width, int height)   

创建所需尺寸居中缩放的位图。
source: 需要被创造缩略图的源位图对象
width: 生成目标的宽度
height: 生成目标的高度

参考:
http://www.jianshu.com/p/e9e1db845c21
http://blog.csdn.net/jdsjlzx/article/details/44228935

原创粉丝点击