一 前言
在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩;质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手机拍照都能达到3M左右了,尺寸压缩一般可用于生成缩略图。
两种方法都实装在了我的项目中,结果却发现在质量压缩的模块中,本来1.9M的图片压缩后反而变成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对象进行尺寸缩减,相应的图片的大小、像素也就减小了。
3
设置图片的采样率,降低图片像素
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库压缩
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倍
1 Bitmap createVideoThumbnail(String filePath, int kind)
创建一张视频的缩略图。如果视频已损坏或者格式不支持可能返回null。
filePath:视频文件路径
kind:文件种类,可以是 MINI_KIND 或 MICRO_KIND
2 Bitmap extractThumbnail(Bitmap source, int width, int height, int options)
创建所需尺寸居中缩放的位图。
source: 需要被创造缩略图的源位图对象
width: 生成目标的宽度
height: 生成目标的高度
options:在缩略图抽取时提供的选项
3
Bitmap extractThumbnail(Bitmap source, int width, int height)
创建所需尺寸居中缩放的位图。
source: 需要被创造缩略图的源位图对象
width: 生成目标的宽度
height: 生成目标的高度