android图片压缩的三种方式
為了避免oom的出現,幾乎每個應用都會對大圖進行壓縮,我現在手頭做的產品就有很多地方用到,以前封裝工具類的時候,都是在網上找東找西,然后拼拼湊湊,有效果就行了,一直用的迷迷糊糊,這幾天工作比較閑,正好系統的總結梳理一下圖片壓縮方式:
圖片壓縮現在常見的有三種方式:
1、等比壓縮,等比壓縮是保持原圖長寬比例的壓縮,只是圖片變小,展示的還是原圖的所有內容(區別于第二種通過Matrix壓縮,可以選取圖片的一部分,類似于上傳頭像時,讓你在圖上選一塊zoom的形式)。等比壓縮用的的主要是BitmapFactory.Options,通過options縮放比例的設置,來生成縮略圖:
/** * @param path 圖片路徑 * @param targetSize 縮放后期待的長邊(圖片長和寬大的那一個邊)的長度 * @param targetW 期待的縮放后寬度 * @param targetH 期待的縮放后高度 * @return */ public static Bitmap equalRatioScale(String path,int targetW,int targetH){ // 獲取option BitmapFactory.Options options = new BitmapFactory.Options(); // inJustDecodeBounds設置為true,這樣使用該option decode出來的Bitmap是null, // 只是把長寬存放到option中 options.inJustDecodeBounds = true; // 此時bitmap為null Bitmap bitmap = BitmapFactory.decodeFile(path, options); int inSampleSize = 1; // 1是不縮放 // 計算寬高縮放比例 int inSampleSizeW = options.outWidth / targetW; int inSampleSizeH = options.outHeight / targetH; // 最終取大的那個為縮放比例,這樣才能適配,例如寬縮放3倍才能適配屏幕,而 // 高不縮放就可以,那樣的話如果按高縮放,寬在屏幕內就顯示不下了 if (inSampleSizeW > inSampleSizeH) { inSampleSize = inSampleSizeW; }else { inSampleSize = inSampleSizeH; } // 設置縮放比例 options.inSampleSize = inSampleSize; // 一定要記得將inJustDecodeBounds設為false,否則Bitmap為null options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(path, options); return bitmap; }2、通過Matrix進行更加靈活的縮放:這種方式主要是通過構建縮放矩陣和Bitmap.createBitmap方法來實現靈活縮放,寬和高縮放的比例可以不一致,而且通過Bitmap.createBitmap方法創建出來的是新的位圖,這個位圖可以是選取原圖的一部分,而不是對原圖進行整體縮放!類似于上傳頭像時,讓你在原圖上扣下來一塊的效果,控制非常靈活。
/** * @param path 原圖路徑 * @param offsetX 截取開始點在X軸偏移量 * @param offsetY 截取開始點在Y軸偏移量 * @param targetW 截取多寬(像素) * @param targetH 截取多高(像素) * @return */ public static Bitmap matrixScale(String path,int offsetX,int offsetY,int targetW,int targetH){ // 構建原始位圖 Bitmap bitmap = BitmapFactory.decodeFile(path); // 獲取原始寬高 int width = bitmap.getWidth(); int height = bitmap.getHeight(); // 計算寬高縮放比例,targetW,targetH即期待縮放完成后位圖的寬高 float scaleW = (float)targetW / width; float scaleH = (float)targetH / height; // 將縮放比例放進矩陣 Matrix matrix = new Matrix(); matrix.postScale(scaleW, scaleH); // 這個方法作用非常多,詳細解釋一下各個參數的意義! // bitmap:原始位圖 // 第二到第五個參數,即截取原圖哪一部分構建新位圖, // offsetX和offsetY代表在X軸和Y軸上的像素偏移量,即從哪個位置開始截取 // width和height代表截取多少個像素,但是要注意,offsetX+width應該小于等于原圖的寬度 // offsetY+height小于等于原圖高度,要不然會報錯,因為截到原圖外面去了 // 像下面這樣填寫,就代表截取整個原圖, // Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false); // 如果填寫100,100,200,200,就代表 // 從原圖左上角往右和下各偏移100像素,然后往后和往下各截取200構建新位圖 // matrix:縮放矩陣 // 最后一個參數表示如果矩陣里面還存放了過濾條件,是否按條件過濾(如果matrix里面只放了平移數據),最后一個參數設置成什么都不會生效 bitmap = Bitmap.createBitmap(bitmap, offsetX, offsetY, width, height, matrix, false); return bitmap; }3、無損壓縮,無損壓縮是說圖片大小和清晰度看上去和原圖沒有什么差別,但是確實size縮小了,這里縮小的原理是犧牲了分辨率等其他直觀看不到的東西,看起來和原圖一樣,但是一放大就立馬失真了,不會和原圖一樣放大很多才會逐漸變得不清晰。無損壓縮后的圖片像素并不會減少,而Bitmap占用內存的定義就是像素點占的內存,所以以Bitmap的方式加載到內存中時,和壓縮前占用的內存是同樣大的,原來會oom的圖片,質量壓縮后同樣會oom;但是,質量壓縮后將流輸出到文件中,文件的size會大幅度減小,所以質量壓縮特別適合在Android端進行圖片上傳的時候進行圖片壓縮,既能保持上傳后的清晰度,又能減小size。另外質量壓縮不是可以無限縮小的,降低到一定程度,就算把quality設置的再小,size也不會再降低了。另外這種方式最好返回保存壓縮后的圖片保存的文件路徑,而不要直接返回Bitmap,示例就懶得改了。
<pre name="code" class="java">/** * @param path 圖片路徑 * @param quality 質量 0-100,100表示原圖 * @return */ public static Bitmap losslessScale(String path,int quality){ Bitmap bitmap = BitmapFactory.decodeFile(path); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(CompressFormat.JPEG, quality, baos); Log.e("哈哈","原始大小:" + baos.toByteArray().length); // 因為質量壓縮不是可以無限縮小的,所以一張高質量的圖片,再怎么壓縮, // 最終size可能還是大于你指定的size,造成異常 // 所以不建議循環壓縮,而是指定quality,進行一次壓縮就可以了 // while (baos.toByteArray().length / 1024 > maxSize) { // quality -= 10; // baos.reset(); // bitmap.compress(CompressFormat.JPEG, quality, baos); // Log.e("哈哈","過程中大小為:" // + baos.toByteArray().length); // } bitmap.compress(CompressFormat.JPEG, quality, baos); Log.e("哈哈","最終大小" + baos.toByteArray().length); Bitmap compressedBitmap = BitmapFactory.decodeByteArray( baos.toByteArray(), 0, baos.toByteArray().length); return compressedBitmap; }一張圖片處理過程,建議先進行等比壓縮或者Matrix壓縮后,再進行質量壓縮,這樣組合使用,不管是生成縮略圖還是圖片上傳,效果都不錯
總結
以上是生活随笔為你收集整理的android图片压缩的三种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL自动备份数据到另一台电脑
- 下一篇: 电容的电抗|X|,总阻抗|Z|和等效电阻