Android實(shí)現(xiàn)圖片壓縮示例代碼
核心思想是通過BitmapFactory.Options來縮放圖片,主要是用到了它的inSampleSize參數(shù)(采樣率)
當(dāng)inSampleSize為1的時(shí)候,采樣后的圖片大小為圖片的原始大??;
當(dāng)inSampleSize為2的時(shí)候,采樣后的圖片的寬和高是原來的1/2,也就是說,它的像素點(diǎn)是原來的1/4,占的內(nèi)存自然就是原來的1/4了。以此類推。
當(dāng)inSampleSize小于1的時(shí)候,效果和等于1的時(shí)候是一樣的。
壓縮流程如下:
1.BitmapFactory.Options 的inJustDecodeBounds參數(shù)設(shè)置為true(這個(gè)時(shí)候BitmapFactory只是解析圖片的原始寬高,并不會(huì)去加載圖片)。
2.從BitmapFactory.Options 中取出圖片的原始寬高,outWidth,outHeight。
3.根據(jù)自己的需要設(shè)置合適的采樣率。
4.BitmapFactory.Options 的inJustDecodeBounds參數(shù)設(shè)置為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); }
接下來結(jié)合一個(gè)小demo來實(shí)現(xiàn)一個(gè)完整的流程
先把圖片壓縮類封裝起來
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); } }
最后記得獲取網(wǎng)絡(luò)權(quán)限
運(yùn)行的結(jié)果:
壓縮前后的bitmap大小對(duì)比
壓縮前后的bitmap大小對(duì)比
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Studio輕松構(gòu)建自定義模板的步驟記錄
這篇文章主要給大家介紹了關(guān)于Android Studio輕松構(gòu)建自定義模板的相關(guān)資料,文中通過示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10Android OKHttp框架的分發(fā)器與攔截器源碼刨析
okhttp是一個(gè)第三方類庫,用于android中請(qǐng)求網(wǎng)絡(luò)。這是一個(gè)開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架,由移動(dòng)支付Square公司貢獻(xiàn)(該公司還貢獻(xiàn)了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient2022-11-11三行Android代碼實(shí)現(xiàn)白天夜間模式流暢切換
這篇文章主要為大家分享了三行Android代碼實(shí)現(xiàn)白天夜間模式流暢切換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Android中使用BitmapShader類來制作各種圖片的圓角
這篇文章主要介紹了Android中使用BitmapShader類來制作各種圖片的圓角的方法,文中隨教程講解帶出的例子可以輕松控制圖片圓形的變換,很好很強(qiáng)大,需要的朋友可以參考下2016-04-04Android實(shí)現(xiàn)歌詞漸變色和進(jìn)度的效果
這篇文章主要介紹了Android實(shí)現(xiàn)歌詞漸變色和進(jìn)度的效果的相關(guān)資料,需要的朋友可以參考下2016-03-03Android中SharedPreference詳解及簡單實(shí)例
這篇文章主要介紹了 Android中SharedPreference詳解及簡單實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09Android ListView 子控件onClick正確獲取position的方法
這篇文章主要介紹了Android ListView 子控件onClick正確獲取position的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-01-01