国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android圖片壓縮(質(zhì)量壓縮和尺寸壓縮)

2019-12-12 03:58:49
字體:
供稿:網(wǎng)友

在網(wǎng)上調(diào)查了圖片壓縮的方法并實(shí)裝后,大致上可以認(rèn)為有兩類壓縮:質(zhì)量壓縮(不改變圖片的尺寸)和尺寸壓縮(相當(dāng)于是像素上的壓縮);質(zhì)量壓縮一般可用于上傳大圖前的處理,這樣就可以節(jié)省一定的流量,畢竟現(xiàn)在的手機(jī)拍照都能達(dá)到3M左右了,尺寸壓縮一般可用于生成縮略圖。

兩種方法都實(shí)裝在了我的項(xiàng)目中,結(jié)果卻發(fā)現(xiàn)在質(zhì)量壓縮的模塊中,本來1.9M的圖片壓縮后反而變成3M多了,很是奇怪,再做了進(jìn)一步調(diào)查終于知道原因了。下面這個(gè)博客說的比較清晰:

android圖片壓縮總結(jié)

總 結(jié)來看,圖片有三種存在形式:硬盤上時(shí)是file,網(wǎng)絡(luò)傳輸時(shí)是stream,內(nèi)存中是stream或bitmap,所謂的質(zhì)量壓縮,它其實(shí)只能實(shí)現(xiàn)對(duì) file的影響,你可以把一個(gè)file轉(zhuǎn)成bitmap再轉(zhuǎn)成file,或者直接將一個(gè)bitmap轉(zhuǎn)成file時(shí),這個(gè)最終的file是被壓縮過的,但 是中間的bitmap并沒有被壓縮(或者說幾乎沒有被壓縮,我不確定),因?yàn)閎igmap在內(nèi)存中的大小是按像素計(jì)算的,也就是width * height,對(duì)于質(zhì)量壓縮,并不會(huì)改變圖片的像素,所以就算質(zhì)量被壓縮了,但是bitmap在內(nèi)存的占有率還是沒變小,但你做成file時(shí),它確實(shí)變小 了;

而尺寸壓縮由于是減小了圖片的像素,所以它直接對(duì)bitmap產(chǎn)生了影響,當(dāng)然最終的file也是相對(duì)的變小了;

最后把自己總結(jié)的工具類貼出來:

import javaioByteArrayInputStream; import javaioByteArrayOutputStream; import javaioFile; import javaioFileNotFoundException; import javaioFileOutputStream; import javaioIOException;  import androidgraphicsBitmap; import androidgraphicsBitmapConfig; import androidgraphicsBitmapFactory;  /**  * Image compress factory class  *  * @author  *  */ public class ImageFactory {    /**    * Get bitmap from specified image path    *    * @param imgPath    * @return    */   public Bitmap getBitmap(String imgPath) {     // Get bitmap through image path     BitmapFactoryOptions newOpts = new BitmapFactoryOptions();     newOptsinJustDecodeBounds = false;     newOptsinPurgeable = true;     newOptsinInputShareable = true;     // Do not compress     newOptsinSampleSize = 1;     newOptsinPreferredConfig = ConfigRGB_565;     return BitmapFactorydecodeFile(imgPath, newOpts);   }      /**    * Store bitmap into specified image path    *    * @param bitmap    * @param outPath    * @throws FileNotFoundException    */   public void storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException {     FileOutputStream os = new FileOutputStream(outPath);     bitmapcompress(BitmapCompressFormatJPEG, 100, os);   }      /**    * Compress image by pixel, this will modify image width/height    * Used to get thumbnail    *    * @param imgPath image path    * @param pixelW target pixel of width    * @param pixelH target pixel of height    * @return    */   public Bitmap ratio(String imgPath, float pixelW, float pixelH) {     BitmapFactoryOptions newOpts = new BitmapFactoryOptions();      // 開始讀入圖片,此時(shí)把optionsinJustDecodeBounds 設(shè)回true,即只讀邊不讀內(nèi)容     newOptsinJustDecodeBounds = true;     newOptsinPreferredConfig = ConfigRGB_565;     // Get bitmap info, but notice that bitmap is null now      Bitmap bitmap = BitmapFactorydecodeFile(imgPath,newOpts);           newOptsinJustDecodeBounds = false;      int w = newOptsoutWidth;      int h = newOptsoutHeight;      // 想要縮放的目標(biāo)尺寸     float hh = pixelH;// 設(shè)置高度為240f時(shí),可以明顯看到圖片縮小了     float ww = pixelW;// 設(shè)置寬度為120f,可以明顯看到圖片縮小了     // 縮放比。由于是固定比例縮放,只用高或者寬其中一個(gè)數(shù)據(jù)進(jìn)行計(jì)算即可      int be = 1;//be=1表示不縮放      if (w > h && w > ww) {//如果寬度大的話根據(jù)寬度固定大小縮放        be = (int) (newOptsoutWidth / ww);      } else if (w < h && h > hh) {//如果高度高的話根據(jù)寬度固定大小縮放        be = (int) (newOptsoutHeight / hh);      }      if (be <= 0) be = 1;      newOptsinSampleSize = be;//設(shè)置縮放比例     // 開始?jí)嚎s圖片,注意此時(shí)已經(jīng)把optionsinJustDecodeBounds 設(shè)回false了     bitmap = BitmapFactorydecodeFile(imgPath, newOpts);     // 壓縮好比例大小后再進(jìn)行質(zhì)量壓縮 //    return compress(bitmap, maxSize); // 這里再進(jìn)行質(zhì)量壓縮的意義不大,反而耗資源,刪除     return bitmap;   }      /**    * Compress image by size, this will modify image width/height    * Used to get thumbnail    *    * @param image    * @param pixelW target pixel of width    * @param pixelH target pixel of height    * @return    */   public Bitmap ratio(Bitmap image, float pixelW, float pixelH) {     ByteArrayOutputStream os = new ByteArrayOutputStream();     imagecompress(BitmapCompressFormatJPEG, 100, os);     if( ostoByteArray()length / 1024>1024) {//判斷如果圖片大于1M,進(jìn)行壓縮避免在生成圖片(BitmapFactorydecodeStream)時(shí)溢出         osreset();//重置baos即清空baos        imagecompress(BitmapCompressFormatJPEG, 50, os);//這里壓縮50%,把壓縮后的數(shù)據(jù)存放到baos中      }      ByteArrayInputStream is = new ByteArrayInputStream(ostoByteArray());      BitmapFactoryOptions newOpts = new BitmapFactoryOptions();      //開始讀入圖片,此時(shí)把optionsinJustDecodeBounds 設(shè)回true了      newOptsinJustDecodeBounds = true;     newOptsinPreferredConfig = ConfigRGB_565;     Bitmap bitmap = BitmapFactorydecodeStream(is, null, newOpts);      newOptsinJustDecodeBounds = false;      int w = newOptsoutWidth;      int h = newOptsoutHeight;      float hh = pixelH;// 設(shè)置高度為240f時(shí),可以明顯看到圖片縮小了     float ww = pixelW;// 設(shè)置寬度為120f,可以明顯看到圖片縮小了     //縮放比。由于是固定比例縮放,只用高或者寬其中一個(gè)數(shù)據(jù)進(jìn)行計(jì)算即可      int be = 1;//be=1表示不縮放      if (w > h && w > ww) {//如果寬度大的話根據(jù)寬度固定大小縮放        be = (int) (newOptsoutWidth / ww);      } else if (w < h && h > hh) {//如果高度高的話根據(jù)寬度固定大小縮放        be = (int) (newOptsoutHeight / hh);      }      if (be <= 0) be = 1;      newOptsinSampleSize = be;//設(shè)置縮放比例      //重新讀入圖片,注意此時(shí)已經(jīng)把optionsinJustDecodeBounds 設(shè)回false了      is = new ByteArrayInputStream(ostoByteArray());      bitmap = BitmapFactorydecodeStream(is, null, newOpts);     //壓縮好比例大小后再進(jìn)行質(zhì)量壓縮 //   return compress(bitmap, maxSize); // 這里再進(jìn)行質(zhì)量壓縮的意義不大,反而耗資源,刪除     return bitmap;   }      /**    * Compress by quality, and generate image to the path specified    *    * @param image    * @param outPath    * @param maxSize target will be compressed to be smaller than this size(kb)    * @throws IOException    */   public void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException {     ByteArrayOutputStream os = new ByteArrayOutputStream();     // scale     int options = 100;     // Store the bitmap into output stream(no compress)     imagecompress(BitmapCompressFormatJPEG, options, os);      // Compress by loop     while ( ostoByteArray()length / 1024 > maxSize) {       // Clean up os       osreset();       // interval 10       options -= 10;       imagecompress(BitmapCompressFormatJPEG, options, os);     }          // Generate compressed image file     FileOutputStream fos = new FileOutputStream(outPath);      foswrite(ostoByteArray());      fosflush();      fosclose();    }      /**    * Compress by quality, and generate image to the path specified    *    * @param imgPath    * @param outPath    * @param maxSize target will be compressed to be smaller than this size(kb)    * @param needsDelete Whether delete original file after compress    * @throws IOException    */   public void compressAndGenImage(String imgPath, String outPath, int maxSize, boolean needsDelete) throws IOException {     compressAndGenImage(getBitmap(imgPath), outPath, maxSize);          // Delete original file     if (needsDelete) {       File file = new File (imgPath);       if (fileexists()) {         filedelete();       }     }   }      /**    * Ratio and generate thumb to the path specified    *    * @param image    * @param outPath    * @param pixelW target pixel of width    * @param pixelH target pixel of height    * @throws FileNotFoundException    */   public void ratioAndGenThumb(Bitmap image, String outPath, float pixelW, float pixelH) throws FileNotFoundException {     Bitmap bitmap = ratio(image, pixelW, pixelH);     storeImage( bitmap, outPath);   }      /**    * Ratio and generate thumb to the path specified    *    * @param image    * @param outPath    * @param pixelW target pixel of width    * @param pixelH target pixel of height    * @param needsDelete Whether delete original file after compress    * @throws FileNotFoundException    */   public void ratioAndGenThumb(String imgPath, String outPath, float pixelW, float pixelH, boolean needsDelete) throws FileNotFoundException {     Bitmap bitmap = ratio(imgPath, pixelW, pixelH);     storeImage( bitmap, outPath);          // Delete original file         if (needsDelete) {           File file = new File (imgPath);           if (fileexists()) {             filedelete();           }         }   }    } 

android圖片壓縮總結(jié)

一.圖片的存在形式

1.文件形式(即以二進(jìn)制形式存在于硬盤上)

2.流的形式(即以二進(jìn)制形式存在于內(nèi)存中)

3.Bitmap形式

這三種形式的區(qū)別: 文件形式和流的形式對(duì)圖片體積大小并沒有影響,也就是說,如果你手機(jī)SD卡上的如果是100K,那 么通過流的形式讀到內(nèi)存中,也一定是占100K的內(nèi)存,注意是流的形式,不是Bitmap的形式,當(dāng)圖片以Bitmap的形式存在時(shí),其占用的內(nèi)存會(huì)瞬間 變大, 我試過500K文件形式的圖片加載到內(nèi)存,以Bitmap形式存在時(shí),占用內(nèi)存將近10M,當(dāng)然這個(gè)增大的倍數(shù)并不是固定的

檢測(cè)圖片三種形式大小的方法:

文件形式: file.length()

流的形式: 講圖片文件讀到內(nèi)存輸入流中,看它的byte數(shù)

Bitmap: bitmap.getByteCount()

二.常見的壓縮方式

1. 將圖片保存到本地時(shí)進(jìn)行壓縮, 即將圖片從Bitmap形式變?yōu)镕ile形式時(shí)進(jìn)行壓縮,

特點(diǎn)是:  File形式的圖片確實(shí)被壓縮了, 但是當(dāng)你重新讀取壓縮后的file為 Bitmap是,它占用的內(nèi)存并沒有改變  

方法說明: 該方法是壓縮圖片的質(zhì)量, 注意它不會(huì)減少圖片的像素,比方說, 你的圖片是300K的, 1280*700像素的, 經(jīng)過該方法壓縮后, File形式的圖片是在100以下, 以方便上傳服務(wù)器, 但是你BitmapFactory.decodeFile到內(nèi)存中,變成Bitmap時(shí),它的像素仍然是1280*700, 計(jì)算圖片像素的方法是 bitmap.getWidth()和bitmap.getHeight(), 圖片是由像素組成的, 每個(gè)像素又包含什么呢? 熟悉PS的人知道, 圖片是有色相,明度和飽和度構(gòu)成的.

public static void compressBmpToFile(Bitmap bmp,File file){     ByteArrayOutputStream baos = new ByteArrayOutputStream();     int options = 80;//個(gè)人喜歡從80開始,     bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);     while (baos.toByteArray().length / 1024 > 100) {        baos.reset();       options -= 10;       bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);     }     try {       FileOutputStream fos = new FileOutputStream(file);       fos.write(baos.toByteArray());       fos.flush();       fos.close();     } catch (Exception e) {       e.printStackTrace();     }   } 

該方法的官方文檔也解釋說, 它會(huì)讓圖片重新構(gòu)造, 但是有可能圖像的位深(即色深)和每個(gè)像素的透明度會(huì)變化,JPEG onlysupports opaque(不透明), 也就是說以jpeg格式壓縮后, 原來圖片中透明的元素將消失.所以這種格式很可能造成失真

既然它是改變了圖片的顯示質(zhì)量, 達(dá)到了對(duì)File形式的圖片進(jìn)行壓縮, 圖片的像素沒有改變的話, 那重新讀取經(jīng)過壓縮的file為Bitmap時(shí), 它占用的內(nèi)存并不會(huì)少.(不相信的可以試試)

因?yàn)? bitmap.getByteCount() 是計(jì)算它的像素所占用的內(nèi)存, 請(qǐng)看官方解釋: Returns the number of bytes used to store this bitmap's pixels.

2.   將圖片從本地讀到內(nèi)存時(shí),進(jìn)行壓縮 ,即圖片從File形式變?yōu)锽itmap形式

特點(diǎn): 通過設(shè)置采樣率, 減少圖片的像素, 達(dá)到對(duì)內(nèi)存中的Bitmap進(jìn)行壓縮

先看一個(gè)方法: 該方法是對(duì)內(nèi)存中的Bitmap進(jìn)行質(zhì)量上的壓縮, 由上面的理論可以得出該方法是無效的, 而且也是沒有必要的,因?yàn)槟阋呀?jīng)將它讀到內(nèi)存中了,再壓縮多此一舉, 盡管在獲取系統(tǒng)相冊(cè)圖片時(shí),某些手機(jī)會(huì)直接返回一個(gè)Bitmap,但是這種情況下, 返回的Bitmap都是經(jīng)過壓縮的, 它不可能直接返回一個(gè)原聲的Bitmap形式的圖片, 后果可想而知

方法說明: 該方法就是對(duì)Bitmap形式的圖片進(jìn)行壓縮, 也就是通過設(shè)置采樣率, 減少Bitmap的像素, 從而減少了它所占用的內(nèi)存

private Bitmap compressBmpFromBmp(Bitmap image) {     ByteArrayOutputStream baos = new ByteArrayOutputStream();     int options = 100;     image.compress(Bitmap.CompressFormat.JPEG, 100, baos);     while (baos.toByteArray().length / 1024 > 100) {        baos.reset();       options -= 10;       image.compress(Bitmap.CompressFormat.JPEG, options, baos);     }     ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());     Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);     return bitmap;   } 

再看一個(gè)方法:

  private Bitmap compressImageFromFile(String srcPath) {     BitmapFactory.Options newOpts = new BitmapFactory.Options();     newOpts.inJustDecodeBounds = true;//只讀邊,不讀內(nèi)容     Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);      newOpts.inJustDecodeBounds = false;     int w = newOpts.outWidth;     int h = newOpts.outHeight;     float hh = 800f;//     float ww = 480f;//     int be = 1;     if (w > h && w > ww) {       be = (int) (newOpts.outWidth / ww);     } else if (w < h && h > hh) {       be = (int) (newOpts.outHeight / hh);     }     if (be <= 0)       be = 1;     newOpts.inSampleSize = be;//設(shè)置采樣率          newOpts.inPreferredConfig = Config.ARGB_8888;//該模式是默認(rèn)的,可不設(shè)     newOpts.inPurgeable = true;// 同時(shí)設(shè)置才會(huì)有效     newOpts.inInputShareable = true;//。當(dāng)系統(tǒng)內(nèi)存不夠時(shí)候圖片自動(dòng)被回收          bitmap = BitmapFactory.decodeFile(srcPath, newOpts); //   return compressBmpFromBmp(bitmap);//原來的方法調(diào)用了這個(gè)方法企圖進(jìn)行二次壓縮                   //其實(shí)是無效的,大家盡管嘗試     return bitmap;   } 

分享個(gè)按照?qǐng)D片尺寸壓縮:

public static void compressPicture(String srcPath, String desPath) {     FileOutputStream fos = null;     BitmapFactoryOptions op = new BitmapFactoryOptions();      // 開始讀入圖片,此時(shí)把optionsinJustDecodeBounds 設(shè)回true了     opinJustDecodeBounds = true;     Bitmap bitmap = BitmapFactorydecodeFile(srcPath, op);     opinJustDecodeBounds = false;      // 縮放圖片的尺寸     float w = opoutWidth;     float h = opoutHeight;     float hh = 1024f;//     float ww = 1024f;//     // 最長(zhǎng)寬度或高度1024     float be = 0f;     if (w > h && w > ww) {       be = (float) (w / ww);     } else if (w < h && h > hh) {       be = (float) (h / hh);     }     if (be <= 0) {       be = 0f;     }     opinSampleSize = (int) be;// 設(shè)置縮放比例,這個(gè)數(shù)字越大,圖片大小越小     // 重新讀入圖片,注意此時(shí)已經(jīng)把optionsinJustDecodeBounds 設(shè)回false了     bitmap = BitmapFactorydecodeFile(srcPath, op);     int desWidth = (int) (w / be);     int desHeight = (int) (h / be);     bitmap = BitmapcreateScaledBitmap(bitmap, desWidth, desHeight, true);     try {       fos = new FileOutputStream(desPath);       if (bitmap != null) {         bitmapcompress(BitmapCompressFormatJPEG, 100, fos);       }     } catch (FileNotFoundException e) {       eprintStackTrace();     }   } 

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 松原市| 观塘区| 龙陵县| 张掖市| 鲜城| 克什克腾旗| 罗定市| 绥中县| 星座| 西充县| 南昌县| 宁晋县| 镇康县| 黑山县| 六安市| 砚山县| 革吉县| 阳泉市| 巴彦县| 广南县| 上林县| 延津县| 汝南县| 南昌县| 河北省| 读书| 安宁市| 黎平县| 如东县| 怀柔区| 安塞县| 呼图壁县| 兴仁县| 新沂市| 璧山县| 隆尧县| 游戏| 秦安县| 鲁山县| 三明市| 通河县|