Android中图片压缩方案详细讲解.docx
- 文档编号:7361549
- 上传时间:2023-05-11
- 格式:DOCX
- 页数:21
- 大小:22.79KB
Android中图片压缩方案详细讲解.docx
《Android中图片压缩方案详细讲解.docx》由会员分享,可在线阅读,更多相关《Android中图片压缩方案详细讲解.docx(21页珍藏版)》请在冰点文库上搜索。
Android中图片压缩方案详细讲解
Android中图片压缩方案详解
1、质量压缩法
设置bitmapoptions属性,降低图片的质量,像素不会减少
第一个参数为需要压缩的bitmap图片对象,第二个参数为压缩后图片保存的位置
设置options属性0-100,来实现压缩。
privateBitmapcompressImage(Bitmapimage){
ByteArrayOutputStreambaos=newByteArrayOutputStream();
press(Bitmap.CompressFormat.JPEG,100,baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
intoptions=100;
while(baos.toByteArray().length/1024>100){//循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
press(Bitmap.CompressFormat.JPEG,options,baos);//这里压缩options%,把压缩后的数据存放到baos中
options-=10;//每次都减少10
}
ByteArrayInputStreamisBm=newByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmapbitmap=BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream数据生成图片
returnbitmap;
}
质量压缩不会减少图片的像素。
它是在保持像素不变的前提下改变图片的位深及透明度等,来达到压缩图片的目的。
进过它压缩的图片文件大小会有改变,但是导入成bitmap后占得存是不变的。
因为要保持像素不变,所以它就无法无限压缩,到达一个值之后就不会继续变小了。
显然这个方法并不适用于缩略图,其实也不适用于想通过压缩图片减少存的适用,仅仅适用于想在保证图片质量的同时减少文件大小的情况而已。
2、采样率压缩法
privateBitmapgetimage(StringsrcPath){
BitmapFactory.OptionsnewOpts=newBitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds设回true了
newOpts.inJustDecodeBounds=true;
Bitmapbitmap=BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空
newOpts.inJustDecodeBounds=false;
intw=newOpts.outWidth;
inth=newOpts.outHeight;
//现在主流手机比较多是1280*720分辨率,所以高和宽我们设置为
floathh=1280f;//这里设置高度为1280f
floatww=720f;//这里设置宽度为720f
//缩放比。
由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
intbe=1;//be=1表示不缩放
if(w>h&&w>ww){//如果宽度大的话根据宽度固定大小缩放
be=(int)(newOpts.outWidth/ww);
}elseif(w
be=(int)(newOpts.outHeight/hh);
}
if(be<=0)
be=1;
newOpts.inSampleSize=be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds设回false了
bitmap=BitmapFactory.decodeFile(srcPath,newOpts);
returncompressImage(bitmap);//压缩好比例大小后再进行质量压缩
}
这个方法的好处是大大的缩小了存的使用,在读存储器上的图片时,如果不需要高清的效果,可以先只读取图片的边,通过宽和高设定好取样率后再加载图片,这样就不会过多的占用存。
3、缩放法
通过缩放图片像素来减少图片占用存大小。
+方式一
publicstaticvoidcompressBitmapToFile(Bitmapbmp,Filefile){
//尺寸压缩倍数,值越大,图片尺寸越小
intratio=2;
//压缩Bitmap到对应尺寸
Bitmapresult=Bitmap.createBitmap(bmp.getWidth()/ratio,bmp.getHeight()/ratio,Config.ARGB_8888);
Canvascanvas=newCanvas(result);
Rectrect=newRect(0,0,bmp.getWidth()/ratio,bmp.getHeight()/ratio);
canvas.drawBitmap(bmp,null,rect,null);
ByteArrayOutputStreambaos=newByteArrayOutputStream();
//把压缩后的数据存放到baos中
press(Bitmap.CompressFormat.JPEG,100,baos);
try{
FileOutputStreamfos=newFileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
}catch(Exceptione){
e.printStackTrace();
}
}
方式二
ByteArrayOutputStreamout=newByteArrayOutputStream();
press(Bitmap.CompressFormat.JPEG,85,out);
floatzoom=(float)Math.sqrt(size*1024/(float)out.toByteArray().length);
Matrixmatrix=newMatrix();
matrix.setScale(zoom,zoom);
Bitmapresult=Bitmap.createBitmap(image,0,0,image.getWidth(),image.getHeight(),matrix,true);
out.reset();
press(Bitmap.CompressFormat.JPEG,85,out);
while(out.toByteArray().length>size*1024){
System.out.println(out.toByteArray().length);
matrix.setScale(0.9f,0.9f);
result=Bitmap.createBitmap(result,0,0,result.getWidth(),result.getHeight(),matrix,true);
out.reset();
press(Bitmap.CompressFormat.JPEG,85,out);
}
缩放法其实很简单,设定好matrix,在createBitmap就可以了。
但是我们并不知道缩放比例,而是要求了图片的最终大小。
直接用大小的比例来做的话肯定是有问题的,用大小比例的开方来做会比较接近,但是还是有差距。
但是只要再做一下微调应该就可以了,微调的话就是修改过的图片大小比最终大小还大的话,就进行0.8的压缩再比较,循环直到大小合适。
这样就能得到合适大小的图片,而且也能比较保证质量。
4、JNI调用libjpeg库压缩
JNI静态调用bitherlibjni.c中的方法来实现压缩Java_net_bither_util_NativeUtil_compressBitmap
net_bither_util为包名,NativeUtil为类名,compressBitmap为native方法名,我们只需要调用saveBitmap()方法就可以,bmp需要压缩的Bitmap对象,quality压缩质量0-100,fileName压缩后要保存的文件地址,optimize是否采用哈弗曼表数据计算品质相差5-10倍。
jstringJava_net_bither_util_NativeUtil_compressBitmap(JNIEnv*env,
jobjectthiz,jobjectbitmapcolor,intw,inth,intquality,
jbyteArrayfileNameStr,jbooleanoptimize){
AndroidBitmapInfoinfocolor;
BYTE*pixelscolor;
intret;
BYTE*data;
BYTE*tmpdata;
char*fileName=jstrinTostring(env,fileNameStr);
if((ret=AndroidBitmap_getInfo(env,bitmapcolor,&infocolor))<0){
LOGE("AndroidBitmap_getInfo()failed!
error=%d",ret);
return(*env)->NewStringUTF(env,"0");;
}
if((ret=AndroidBitmap_lockPixels(env,bitmapcolor,&pixelscolor))<0){
LOGE("AndroidBitmap_lockPixels()failed!
error=%d",ret);
}
BYTEr,g,b;
data=NULL;
data=malloc(w*h*3);
tmpdata=data;
intj=0,i=0;
intcolor;
for(i=0;i for(j=0;j color=*((int*)pixelscolor); r=((color&0x00FF0000)>>16); g=((color&0x0000FF00)>>8); b=color&0x000000FF; *data=b; *(data+1)=g; *(data+2)=r; data=data+3; pixelscolor+=4; } } AndroidBitmap_unlockPixels(env,bitmapcolor); intresultCode=generateJPEG(tmpdata,w,h,quality,fileName,optimize); free(tmpdata); if(resultCode==0){ jstringresult=(*env)->NewStringUTF(env,error); error=NULL; returnresult; } return(*env)->NewStringUTF(env,"1");//success } 5、质量压缩+采样率压缩+JNI调用libjpeg库压缩结合使用 首先通过尺寸压缩,压缩到手机常用的一个分辨率(1280*960微信好像是压缩到这个分辨率),然后我们要把图片压缩到一定大小以(比如说200k),然后通过循环进行质量压缩来计算options需要设置为多少,最后调用JNI压缩。 +计算缩放比 /** *计算缩放比 *parambitWidth当前图片宽度 *parambitHeight当前图片高度 *returnint缩放比 */ publicstaticintgetRatioSize(intbitWidth,intbitHeight){ //图片最大分辨率 intimageHeight=1280; intimageWidth=960; //缩放比 intratio=1; //缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 if(bitWidth>bitHeight&&bitWidth>imageWidth){ //如果图片宽度比高度大,以宽度为基准 ratio=bitWidth/imageWidth; }elseif(bitWidth //如果图片高度比宽度大,以高度为基准 ratio=bitHeight/imageHeight; } //最小比率为1 if(ratio<=0) ratio=1; returnratio; } 质量压缩+JNI压缩 /** *Description: 通过JNI图片压缩把Bitmap保存到指定目录 *paramcurFilePath *当前图片文件地址 *paramtargetFilePath *要保存的图片文件地址 */ publicstaticvoidcompressBitmap(StringcurFilePath,StringtargetFilePath){ //最大图片大小500KB intmaxSize=500; //根据地址获取bitmap Bitmapresult=getBitmapFromFile(curFilePath); ByteArrayOutputStreambaos=newByteArrayOutputStream(); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 intquality=100; press(Bitmap.CompressFormat.JPEG,quality,baos); //循环判断如果压缩后图片是否大于500kb,大于继续压缩 while(baos.toByteArray().length/1024>maxSize){ //重置baos即清空baos baos.reset(); //每次都减少10 quality-=10; //这里压缩quality,把压缩后的数据存放到baos中 press(Bitmap.CompressFormat.JPEG,quality,baos); } //JNI保存图片到SD卡这个关键 NativeUtil.saveBitmap(result,quality,targetFilePath,true); //释放Bitmap if(! result.isRecycled()){ result.recycle(); } } JNI图片压缩工具类 packagenet.bither.util; importandroid.graphics.Bitmap; importandroid.graphics.Bitmap.Config; importandroid.graphics.BitmapFactory; importandroid.graphics.Canvas; importandroid.graphics.Matrix; importandroid.graphics.Rect; importandroid.media.ExifInterface; importjava.io.ByteArrayOutputStream; importjava.io.File; importjava.io.FileInputStream; importjava.io.FileNotFoundException; importjava.io.IOException; /** *JNI图片压缩工具类 * *DescriptionTODO *Packagenet.bither.util *ClassNativeUtil */ publicclassNativeUtil{ privatestaticintDEFAULT_QUALITY=95; /** *Description: JNI基本压缩 *parambit *bitmap对象 *paramfileName *指定保存目录名 *paramoptimize *是否采用哈弗曼表数据计算品质相差5-10倍 */ publicstaticvoidcompressBitmap(Bitmapbit,StringfileName,booleanoptimize){ saveBitmap(bit,DEFAULT_QUALITY,fileName,optimize); } /** *Description: 通过JNI图片压缩把Bitmap保存到指定目录 *paramimage *bitmap对象 *paramfilePath *要保存的指定目录 */ publicstaticvoidcompressBitmap(Bitmapimage,StringfilePath){ //最大图片大小150KB intmaxSize=150; //获取尺寸压缩倍数 intratio=NativeUtil.getRatioSize(image.getWidth(),image.getHeight()); //压缩Bitmap到对应尺寸 Bitmapresult=Bitmap.createBitmap(image.getWidth()/ratio,image.getHeight()/ratio,Config.ARGB_8888); Canvascanvas=newCanvas(result); Rectrect=newRect(0,0,image.getWidth()/ratio,image.getHeight()/ratio); canvas.drawBitmap(image,null,rect,null); ByteArrayOutputStreambaos=newByteArrayOutputStream(); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 intoptions=100; press(Bitmap.CompressFormat.JPEG,options,baos); //循环判断如果压缩后图片是否大于100kb,大于继续压缩 while(baos.toByteArray().length/1024>maxSize){ //重置baos即清空baos baos.reset(); //每次都减少10 options-=10; //这里压缩options%,把压缩后的数据存放到baos中 press(Bitmap.CompressFormat.JPEG,options,baos); } //JNI保存图片到SD卡这个关键 NativeUtil.saveBitmap(result,options,filePath,true); //释放Bitmap if(! result.isRecycled()){ result.recycle(); } } /** *Description: 通过JNI图片压缩把Bitmap保存到指定目录 *paramcurFilePath *当前图片文件地址 *paramtargetFilePath *要保存的图片文件地址 */ publicstaticvoidcompressBitmap(StringcurFilePath,StringtargetFilePath){ //最大图片大小500KB intmaxSize=500; //根据地址获取bitmap Bitmapresult=getBitmapFromFile(curFilePath); ByteArrayOutputStreambaos=newByteArrayOutputStream(); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 intquality=100; press(Bitmap.CompressFormat.JPEG,quality,baos); //循环判断如果压缩后图片是否大于500kb,大于继续压缩 while(baos.toByteArray().length/1024>maxSize){ //重置baos即清空baos baos.reset(); //每次都减少10 quality-=10; //这里压缩quality,把压缩后的数据存放到baos中 press(Bitmap.CompressFormat.JPEG,quality,baos); } //JNI保存图片到SD卡这个关键 NativeUtil.saveBitmap(result,quality,targetFilePath,true); //释放Bitmap if(! resu
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 图片 压缩 方案 详细 讲解