2011-03-31 67 views
4

我需要通過網絡發送從相機拍攝的圖像。該圖片太大,無法創建使用bitmap.compress()所需的位圖;它看起來像Gmail應用程序可以從相機附加圖像,同時保持其大像素大小,但大大減少了文件大小。從相機壓縮位圖

這將不起作用,因爲我getBitmap()將返回一個圖像大到分配,我不想將它取樣到一個較小的大小。

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    getBitmap().compress(Bitmap.CompressFormat.JPEG, 70, baos); 

有關如何在不超過我的總內存的情況下做同樣的任何想法?

更新:

對於任何人回來這個線程我跟着菲爾的答案,並使用Apache的MultiPartEntity獲得輕鬆完成工作。 (它可以爲你處理從磁盤到網絡的流文件)http://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/entity/mime/MultipartEntity.html

+0

是使用相機API抓拍圖片的代碼? – 2011-03-31 02:24:09

+0

不,只是從畫廊拉,但即使是畫廊的應用程序是全尺寸和未壓縮。 – sgarman 2011-03-31 03:11:34

回答

2

由於您沒有定義相當有什麼在網絡上發送「意味着此處,很難給出具體的諮詢。但是,如果你想發送一個無損圖像(或者比已經發生的損失少),我認爲你不會壓縮得更多,因爲JPEG已經壓縮了。它使用有損壓縮,所以如果你增加JPEG壓縮,你會失去細節(雖然可能不是你會注意到的,因爲它基於頻率而不是像素)

如果你只需要通過網絡發送,那麼爲什麼不只是打開一個InputStream,並將數據直接緩存到網絡中?

希望這有助於 - 如果您可以提供更多的細節,我會更新答案。

最良好的祝願,

菲爾Lello

3

在通過網絡發送之前使用壓縮可能是有意義的嗎?發件人方的InflaterInputStream和接收方的DeflaterOutputStream看起來像可行的組合。

附錄 嘗試使用另一種方法:

FileOutputStream fos = new FileOutputStream(file); //intermediate file to store compressed image 
InputStream is=this.getStream(imageUri); //image uri taken from camera 
BitmapFactory.Options options=new BitmapFactory.Options(); 
options.inSampleSize=2; //try to decrease decoded image 
options.inPurgeable=true; //purgeable to disk 
Bitmap bitmap=BitmapFactory.decodeStream(is, null, options); 
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); //compressed bitmap to file 
+0

感謝您的建議,但我實際上想要使用圖像壓縮來壓縮圖像,即Bitmap.CompressFormat.JPEG。我認爲這將處理很多尺寸問題,但我不確定如何在無法首先創建位圖時執行此操作。 – sgarman 2011-03-31 05:29:21

+0

@sgarman看看我的代碼 - 可能會工作 – barmaley 2011-03-31 06:37:06

+0

如果我沒有弄錯,增加inSampleSize會降低圖像分辨率。我希望保持圖像的完整性,就像gmail應用程序在附加照片時一樣。感謝您的持續幫助。 – sgarman 2011-03-31 06:40:43

0

您可以使用圖像即512x384分辨率(微縮略圖)的低版本。檢查this回答如何獲得迷你縮略圖。

縮略圖已經壓縮到80%。

+0

感謝您的回覆,我不想要更小分辨率的圖像,我只需要圖像壓縮的全分辨率。 – sgarman 2011-04-12 07:33:37

+0

實際的圖像分辨率是多少? – Karan 2011-04-12 07:40:40

+0

通常,我正在使用來自圖庫中的照片中的項目。實際分辨率根據相機而在不同設備之間波動。大約2000x1600的圖像通常不可能完全呈現爲位圖。 – sgarman 2011-04-12 07:43:51

0

我認爲你只能在本地代碼中做到這一點,在那裏你可以分配更多的內存。這意味着您需要使用並編譯一個本地庫,例如libjpeg,或者一些完整的包,例如ImageMagick,以支持從各種圖像格式讀取。

有了這個,你根本不會使用Bitmap類進行壓縮。你的本地代碼會照顧讀寫圖像文件。如果你設法編譯庫,你的本地代碼不應該超過幾十行。

除非你知道C並且已經和JNI以及Android NDK一起玩過,這並不容易。尤其是,爲Android編譯第三方庫有時候會非常棘手。

但我相信去本土是唯一的解決方案。

+0

實際上,libjpeg是Android圖像的一部分(無論如何都是在2.2版本的/system/libs/libjpeg.so中),但是JNI包裝並不是。 – 2011-04-15 18:37:24

+0

這是系統的一個私人方面。 libjpeg可以在這裏或不在,它可以被修改或不可以。你不能依靠它。所以唯一的選擇是捆綁自己的libjpeg版本或同等版本。當然,我們可以重新使用Android源代碼附帶的版本和makefiles來簡化編譯。關於Java包裝,如果可用(並且當然有Java jpeg包),它不會解決內存限制問題。我很確定你需要在這裏生活。 – olivierg 2011-04-15 22:08:09