Android中图片压缩方案详细讲解.docx

上传人:b****3 文档编号:5209565 上传时间:2022-12-14 格式:DOCX 页数:21 大小:22.79KB
下载 相关 举报
Android中图片压缩方案详细讲解.docx_第1页
第1页 / 共21页
Android中图片压缩方案详细讲解.docx_第2页
第2页 / 共21页
Android中图片压缩方案详细讲解.docx_第3页
第3页 / 共21页
Android中图片压缩方案详细讲解.docx_第4页
第4页 / 共21页
Android中图片压缩方案详细讲解.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

Android中图片压缩方案详细讲解.docx

《Android中图片压缩方案详细讲解.docx》由会员分享,可在线阅读,更多相关《Android中图片压缩方案详细讲解.docx(21页珍藏版)》请在冰豆网上搜索。

Android中图片压缩方案详细讲解.docx

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(whh){//如果高度高的话根据宽度固定大小缩放

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(bitWidthimageHeight){

//如果图片高度比宽度大,以高度为基准

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1