核心思想是通过bitmapfactory.options来缩放图片,主要是用到了它的insamplesize参数(采样率)
当insamplesize为1的时候,采样后的图片大小为图片的原始大小;
当insamplesize为2的时候,采样后的图片的宽和高是原来的1/2,也就是说,它的像素点是原来的1/4,占的内存自然就是原来的1/4了。以此类推。
当insamplesize小于1的时候,效果和等于1的时候是一样的。
压缩流程如下:
1.bitmapfactory.options 的injustdecodebounds参数设置为true(这个时候bitmapfactory只是解析图片的原始宽高,并不会去加载图片)。
2.从bitmapfactory.options 中取出图片的原始宽高,outwidth,outheight。
3.根据自己的需要设置合适的采样率。
4.bitmapfactory.options 的injustdecodebounds参数设置为false,然后就可以加载图片了。
下面我们看代码:
public bitmap decodesampledbitmapfrombytes(byte[] bytes,int reqwidth,int reqheight){ final bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; bitmapfactory.decodebytearray(bytes,0,bytes.length,options); options.insamplesize = calculateinsamplesize(options,reqwidth,reqheight); options.injustdecodebounds = false; return bitmapfactory.decodebytearray(bytes,0,bytes.length,options); } public int calculateinsamplesize(bitmapfactory.options options,int reqwidth,int reqheight){ if(reqwidth == 0 || reqheight == 0){ return 1; } final int width = options.outwidth; final int height = options.outheight; int insamplesize = 1; if( width > reqwidth || height > reqheight){ final int halfwidth = width / 2; final int halfheight = height / 2; while ((halfwidth / insamplesize) >= reqwidth && (halfheight / insamplesize) >= reqheight){ insamplesize *=2; } } return insamplesize; }
如此一来,就完成了一张图片的压缩。另外,bitmapfactory还有其它的decode方法,我们也可以仿照上面的来写。
public bitmap decodesampledbitmapfromresource(resources res,int resid,int reqwidth,int reqheight){ final bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; bitmapfactory.decoderesource(res,resid,options); options.insamplesize = calculateinsamplesize(options,reqwidth,reqheight); options.injustdecodebounds = false; return bitmapfactory.decoderesource(res,resid,options); }
public bitmap decodesampledbitmapfromdescrptor(filedescriptor fd,int reqwidth,int reqheight){ final bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; bitmapfactory.decodefiledescriptor(fd,null,options); options.insamplesize = calculateinsamplesize(options,reqwidth,reqheight); options.injustdecodebounds = false; return bitmapfactory.decodefiledescriptor(fd,null,options); }
接下来结合一个小demo来实现一个完整的流程
先把图片压缩类封装起来
public class imageresizer { private static final string tag = "imageresizer"; public imageresizer(){} public bitmap decodesampledbitmapfromresource(resources res,int resid,int reqwidth,int reqheight){ final bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; bitmapfactory.decoderesource(res,resid,options); options.insamplesize = calculateinsamplesize(options,reqwidth,reqheight); options.injustdecodebounds = false; return bitmapfactory.decoderesource(res,resid,options); } public bitmap decodesampledbitmapfrombytes(byte[] bytes,int reqwidth,int reqheight){ final bitmapfactory.options options = new bitmapfactory.options(); bitmap a = bitmapfactory.decodebytearray(bytes,0,bytes.length,options); log.d(tag, "before bitmap : " + a.getrowbytes() * a.getheight()); options.injustdecodebounds = true; bitmapfactory.decodebytearray(bytes,0,bytes.length,options); options.insamplesize = calculateinsamplesize(options,reqwidth,reqheight); options.injustdecodebounds = false; bitmap b = bitmapfactory.decodebytearray(bytes,0,bytes.length,options); log.d(tag, "after bitmap : " + b.getrowbytes() * b.getheight()); return b; } public bitmap decodesampledbitmapfromdescrptor(filedescriptor fd,int reqwidth,int reqheight){ final bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; bitmapfactory.decodefiledescriptor(fd,null,options); options.insamplesize = calculateinsamplesize(options,reqwidth,reqheight); options.injustdecodebounds = false; return bitmapfactory.decodefiledescriptor(fd,null,options); } public int calculateinsamplesize(bitmapfactory.options options,int reqwidth,int reqheight){ if(reqwidth == 0 || reqheight == 0){ return 1; } final int width = options.outwidth; final int height = options.outheight; int insamplesize = 1; if( width > reqwidth || height > reqheight){ final int halfwidth = width / 2; final int halfheight = height / 2; while ((halfwidth / insamplesize) >= reqwidth && (halfheight / insamplesize) >= reqheight){ insamplesize *=2; } } return insamplesize; } }
然后就可以拿来用了:
activity_main2.xml
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main2" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context="com.example.yuan.test.main2activity"> <imageview android:id="@+id/main2iv" android:layout_width="200dp" android:layout_height="200dp" /> </relativelayout>
main2activity.java
public class main2activity extends appcompatactivity { private imageview iv; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main2); initview(); testhttp(iv); } private void testhttp(final imageview iv) { new thread(new runnable() { @override public void run() { string urlstring = "https://static.pexels.com/photos/295818/pexels-photo-295818.jpeg"; httpurlconnection urlconnection = null; inputstream in = null; bytearrayoutputstream outstream = null; try { url url = new url(urlstring); urlconnection = (httpurlconnection) url.openconnection(); in = urlconnection.getinputstream(); byte[] buffer = new byte[1024]; int len; outstream = new bytearrayoutputstream(); while ((len = in.read(buffer)) != -1){ outstream.write(buffer,0,len); } final byte[] data = outstream.tobytearray(); runonuithread(new runnable() { @override public void run() { //在主线程加载ui iv.setimagebitmap(new imageresizer().decodesampledbitmapfrombytes(data,200,200)); } }); } catch (ioexception e) { e.printstacktrace(); }finally { try { if(urlconnection !=null){ urlconnection.disconnect(); } if(in != null){ in.close(); } if(outstream != null){ outstream.close(); } } catch (ioexception e) { e.printstacktrace(); } } } }).start(); } private void initview() { iv = (imageview) findviewbyid(r.id.main2iv); } }
最后记得获取网络权限
运行的结果:
压缩前后的bitmap大小对比
压缩前后的bitmap大小对比
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。
如对本文有疑问, 点击进行留言回复!!
Android studio开发小型对话机器人app(实例代码)
Android通过Java sdk的方式接入OpenCv的方法
Android 通过cmake的方式接入opencv的方法步骤
Android Studio finish()方法的使用与解决app点击“返回”(直接退出)
Android 进度条 ProgressBar的实现代码(隐藏、出现、加载进度)
网友评论