2012-06-16 230 views
49

我有一個URI圖像文件,我想減小其大小以上傳它。初始圖像文件大小取決於移動設備到移動設備(可以是2MB,可以是500KB),但我希望最終大小約爲200KB,以便我可以上傳它。
從我讀,我有(至少)2種選擇:Android - 縮小圖像文件大小

  • 使用BitmapFactory.Options.inSampleSize,子採樣原始圖像,並得到一個更小的圖像;
  • 使用Bitmap.compress來壓縮指定壓縮質量的圖像。

什麼是最好的選擇?


我想在最初調整大小圖像的寬度/高度,直到寬度或高度是1000像素以上(像1024x768或其他),然後用直到文件的大小是200KB以上降低質量壓縮圖象。這裏有一個例子:

int MAX_IMAGE_SIZE = 200 * 1024; // max final file size 
Bitmap bmpPic = BitmapFactory.decodeFile(fileUri.getPath()); 
if ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) { 
    BitmapFactory.Options bmpOptions = new BitmapFactory.Options(); 
    bmpOptions.inSampleSize = 1; 
    while ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) { 
     bmpOptions.inSampleSize++; 
     bmpPic = BitmapFactory.decodeFile(fileUri.getPath(), bmpOptions); 
    } 
    Log.d(TAG, "Resize: " + bmpOptions.inSampleSize); 
} 
int compressQuality = 104; // quality decreasing by 5 every loop. (start from 99) 
int streamLength = MAX_IMAGE_SIZE; 
while (streamLength >= MAX_IMAGE_SIZE) { 
    ByteArrayOutputStream bmpStream = new ByteArrayOutputStream(); 
    compressQuality -= 5; 
    Log.d(TAG, "Quality: " + compressQuality); 
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream); 
    byte[] bmpPicByteArray = bmpStream.toByteArray(); 
    streamLength = bmpPicByteArray.length; 
    Log.d(TAG, "Size: " + streamLength); 
} 
try { 
    FileOutputStream bmpFile = new FileOutputStream(finalPath); 
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpFile); 
    bmpFile.flush(); 
    bmpFile.close(); 
} catch (Exception e) { 
    Log.e(TAG, "Error on saving file"); 
} 

有沒有更好的辦法做到這一點?我應該嘗試繼續使用所有2種方法還是隻使用一種?謝謝

+0

是否源圖像PNG或JPG? –

+0

源圖像是JPG – KitKat

回答

27

使用Bitmap.compress()您只需指定壓縮算法,並通過壓縮操作需要相當多的時間。如果您需要使用大小來減少圖像的內存分配,那麼您就需要使用Bitmap.Options來縮放圖像,首先計算位圖邊界,然後將其解碼爲指定的大小。

我在StackOverflow上找到的最佳示例是this one

+1

我的第一個想法是迭代圖像的縮放(使用'inSampleSize'),直到圖像文件低於MAX_IMAGE_SIZE,但由於我必須將位圖保存到文件中,因此必須使用「位圖」。壓縮()'(或者可能有不同的方法將它保存在文件上?),並將其稱爲100%質量,圖像變得比MAX_IMAGE_SIZE更大,所以我應該迭代Bitmap.compress()質量),直到文件大小<'MAX_IMAGE_SIZE'。也許有更好的解決方案嗎? – KitKat

0

最讓我找到了答案,只是個,我不得不把在一起,以得到工作代碼,這是下面貼

public void compressBitmap(File file, int sampleSize, int quality) { 
     try { 
      BitmapFactory.Options options = new BitmapFactory.Options(); 
      options.inSampleSize = sampleSize; 
      FileInputStream inputStream = new FileInputStream(file); 

      Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, options); 
      inputStream.close(); 

      FileOutputStream outputStream = new FileOutputStream("location to save"); 
      selectedBitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream); 
      outputStream.close(); 
      long lengthInKb = photo.length()/1024; //in kb 
      if (lengthInKb > SIZE_LIMIT) { 
       compressBitmap(file, (sampleSize*2), (quality/4)); 
      } 

      selectedBitmap.recycle(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

2個參數的採樣大小和質量起着重要的作用

的採樣大小用於子樣本的原始圖像,並返回一個較小的圖像,即
SampleSize == 4返回的圖像是原始寬度/高度的1/4。

質量是用來提示壓縮機,輸入範圍在0-100之間。 0意義壓縮爲 小尺寸,100意思壓縮爲最高質量

+0

顯然這不是完整的。變量「照片」甚至沒有在本地聲明。此外,它使用遞歸,不是一個好主意。 – Shroud

+0

@Shroud請隨時編輯並添加丟失的東西, –

+0

@war_Hero:遞歸不是一個好主意.. – Pawan