Android開發(fā)實現(xiàn)圖片大小與質量壓縮及保存
Android中圖片有四種屬性
ALPHA_8:每個像素占用1byte內存
ARGB_4444:每個像素占用2byte內存
ARGB_8888:每個像素占用4byte內存 (默認)
RGB_565:每個像素占用2byte內存
Android默認的顏色模式為ARGB_8888,這個顏色模式色彩最細膩,顯示質量最高。但同樣的,占用的內存也最大。所以在對圖片效果不是特別高的情況下使用RGB_565(565沒有透明度屬性)
Android目前常用圖片格式
有png,jpeg和webp
png:無損壓縮圖片格式,支持Alpha通道,Android切圖素材多采用該格式
jpeg:有損壓縮圖片格式,不支持背景透明,適用于照片等色彩豐富的(大圖壓縮,不適合logo)
webp:是一種同時提供了有損壓縮和無損壓縮的圖片格式,派生自視頻編碼格式VP8,從谷歌官網(wǎng)來看,無損webp平均比png小26%,有損的webp平均比jpeg小25%~34%,無損webp支持Alpha通道,有損webp在一定的條件下同樣支持,有損webp在Android4.0(API 14)之后支持,無損和透明在Android4.3(API18)之后支持
使用
大小壓縮
private Bitmap getimage(String srcPath) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); //開始讀入圖片,此時把options.inJustDecodeBounds 設回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此時返回bm為空 newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //現(xiàn)在主流手機比較多是800*480分辨率,所以高和寬我們設置為 float hh = 800f;//這里設置高度為800f float ww = 480f;//這里設置寬度為480f //縮放比。由于是固定比例縮放,只用高或者寬其中一個數(shù)據(jù)進行計算即可 int be = 1;//be=1表示不縮放 if (w > h && w > ww) {//如果寬度大的話根據(jù)寬度固定大小縮放 be = (int) (newOpts.outWidth / ww); } else if (w < h && h > hh) {//如果高度高的話根據(jù)寬度固定大小縮放 be = (int) (newOpts.outHeight / hh); } if (be <= 0) be = 1; newOpts.inSampleSize = be;//設置縮放比例 //重新讀入圖片,注意此時已經(jīng)把options.inJustDecodeBounds 設回false了 bitmap = BitmapFactory.decodeFile(srcPath, newOpts); return compressImage(bitmap);//壓縮好比例大小后再進行質量壓縮 }
質量壓縮
注意:
第二次壓縮之前都要先清空 baos.reset(); 再進行壓縮
image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
有時候我們采用質量壓縮沒有效果,有可能是每次壓縮的質量過小,所以我們可以嘗試修改壓縮質量(quality)是10;
quality壓縮機提示,0-100。0表示壓縮小尺寸,100意味著最大質量的壓縮。一些格式,如無損的PNG,將忽略質量設定;
private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos); int options = 90; int length = baos.toByteArray().length / 1024; if (length>5000){ //重置baos即清空baos baos.reset(); //質量壓縮方法,這里100表示不壓縮,把壓縮后的數(shù)據(jù)存放到baos中 image.compress(Bitmap.CompressFormat.JPEG, 10, baos); }else if (length>4000){ baos.reset(); image.compress(Bitmap.CompressFormat.JPEG, 20, baos); }else if (length>3000){ baos.reset(); image.compress(Bitmap.CompressFormat.JPEG, 50, baos); }else if (length>2000){ baos.reset(); image.compress(Bitmap.CompressFormat.JPEG, 70, baos); } //循環(huán)判斷如果壓縮后圖片是否大于1M,大于繼續(xù)壓縮 while (baos.toByteArray().length / 1024>1024) { //重置baos即清空baos baos.reset(); //這里壓縮options%,把壓縮后的數(shù)據(jù)存放到baos中 image.compress(Bitmap.CompressFormat.JPEG, options, baos); //每次都減少10 options -= 10; } //把壓縮后的數(shù)據(jù)baos存放到ByteArrayInputStream中 ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); //把ByteArrayInputStream數(shù)據(jù)生成圖片 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null); return bitmap; }
混合方式壓縮
private Bitmap comp(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos); if( baos.toByteArray().length / 1024>1024) {//判斷如果圖片大于1M,進行壓縮避免在生成圖片(BitmapFactory.decodeStream)時溢出 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//這里壓縮50%,把壓縮后的數(shù)據(jù)存放到baos中 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); BitmapFactory.Options newOpts = new BitmapFactory.Options(); //開始讀入圖片,此時把options.inJustDecodeBounds 設回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //現(xiàn)在主流手機比較多是800*480分辨率,所以高和寬我們設置為 float hh = 800f;//這里設置高度為800f float ww = 480f;//這里設置寬度為480f //縮放比。由于是固定比例縮放,只用高或者寬其中一個數(shù)據(jù)進行計算即可 int be = 1;//be=1表示不縮放 if (w > h && w > ww) {//如果寬度大的話根據(jù)寬度固定大小縮放 be = (int) (newOpts.outWidth / ww); } else if (w < h && h > hh) {//如果高度高的話根據(jù)寬度固定大小縮放 be = (int) (newOpts.outHeight / hh); } if (be <= 0) be = 1; newOpts.inSampleSize = be;//設置縮放比例 //重新讀入圖片,注意此時已經(jīng)把options.inJustDecodeBounds 設回false了 isBm = new ByteArrayInputStream(baos.toByteArray()); bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); return compressImage(bitmap);//壓縮好比例大小后再進行質量壓縮 }
采樣率壓縮
采樣率壓縮是通過設置BitmapFactory.Options.inSampleSize,來減小圖片的分辨率,進而減小圖片所占用的磁盤空間和內存大小。
設置的inSampleSize會導致壓縮的圖片的寬高都為1/inSampleSize,整體大小變?yōu)樵紙D片的inSampleSize平方分之一,當然,這些有些注意點:
- 1、inSampleSize小于等于1會按照1處理
- 2、inSampleSize只能設置為2的平方,不是2的平方則最終會減小到最近的2的平方數(shù),如設置7會按4進行壓縮,設置15會按8進行壓縮。
/** * * @param inSampleSize 可以根據(jù)需求計算出合理的inSampleSize */ public static void compress(int inSampleSize) { File sdFile = Environment.getExternalStorageDirectory(); File originFile = new File(sdFile, "originImg.jpg"); BitmapFactory.Options options = new BitmapFactory.Options(); //設置此參數(shù)是僅僅讀取圖片的寬高到options中,不會將整張圖片讀到內存中,防止oom options.inJustDecodeBounds = true; Bitmap emptyBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options); options.inJustDecodeBounds = false; options.inSampleSize = inSampleSize; Bitmap resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options); ByteArrayOutputStream bos = new ByteArrayOutputStream(); resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); try { FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg")); fos.write(bos.toByteArray()); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
圖片保存到本地
/** * 保存bitmap到本地 * @param context the context * @param mBitmap the m bitmap * @return string */ public static String saveBitmap(Context context, Bitmap mBitmap) { String savePath; File filePic; try { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { savePath = SD_PATH; } else { savePath = context.getApplicationContext().getFilesDir().getAbsolutePath() + IN_PATH; } filePic = new File(savePath + DateTimeHelper.format(new Date(), "yyyyMMddHHmmss") + ".jpg"); Log.d("LUO", "圖片地址====" + filePic); if (!filePic.exists()) { filePic.getParentFile().mkdirs(); filePic.createNewFile(); } FileOutputStream fos = new FileOutputStream(filePic); //不壓縮,保存本地 mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); return null; } return filePic.getAbsolutePath(); }
以上就是Android開發(fā)實現(xiàn)圖片大小與質量壓縮及保存的詳細內容,更多關于Android開發(fā)圖片大小質量壓縮保存的資料請關注腳本之家其它相關文章!
相關文章
Android使用KeyStore對數(shù)據(jù)進行加密的示例代碼
這篇文章主要介紹了Android使用KeyStore對數(shù)據(jù)進行加密的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01Android開發(fā)基礎之創(chuàng)建啟動界面Splash Screen的方法
這篇文章主要介紹了Android開發(fā)基礎之創(chuàng)建啟動界面Splash Screen的方法,以實例形式較為詳細的分析了Android定制啟動界面的布局及功能實現(xiàn)相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10Android列表組件ListView使用詳解之動態(tài)加載或修改列表數(shù)據(jù)
今天小編就為大家分享一篇關于Android列表組件ListView使用詳解之動態(tài)加載或修改列表數(shù)據(jù),小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03android自定義toast(widget開發(fā))示例
這篇文章主要介紹了android自定義toast(widget開發(fā))示例,需要的朋友可以參考下2014-03-03使用android studio開發(fā)工具編譯GBK轉換三方庫iconv的方法
這篇文章主要介紹了使用android studio開發(fā)工具編譯GBK轉換三方庫iconv的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06android ViewPager實現(xiàn)自動無限輪播和下方向導圓點
本篇文章主要介紹了android ViewPager實現(xiàn)自動輪播和下方向導圓點,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02利用Jetpack?Compose實現(xiàn)繪制五角星效果
這篇文章主要為大家介紹了Jetpack?Compose如何使用自定義操作符實現(xiàn)繪制五角星效果,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-04-04