2010-02-02 75 views
12

我正在開發一個Android應用程序,顯示從Flickr下載的照片。我獲得從一個字節數組,而這又是從相關的Flickr URL讀取的位圖對象時,如下所示:Android:BitmapFactory.decodeByteArray給出像素化位圖

BitmapFactory.Options opt = new BitmapFactory.Options(); 
opt.inDither = true; 
opt.inPreferredConfig = Bitmap.Config.ARGB_8888; 
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt); 

我然後繪製位圖上在視圖對象的的onDraw方法的帆布:

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); 
canvas.drawBitmap(bitmap, 0, 0, paint); 

問題是生成的圖片是像素化的,我找不出原因;我嘗試了許多選擇和繪畫對象的變體,但沒有運氣。

Bad image, see pixelation in top left corner http://homepages.inf.ed.ac.uk/s0677975/bad.jpg

Good picture, this is the expected result http://homepages.inf.ed.ac.uk/s0677975/good.jpg

看看例如:在我的應用程序中顯示的圖片,並在原來的URL的圖像之間的差大致由以下證明在左上角的雲層中查看區別。

請注意,從項目資源加載並以類似方式繪製的JPEG圖片顯示得很好,即沒有像素化。

任何人都可以告訴我爲什麼會發生這種情況嗎?

稍微詳細一點,從Flickr獲取字節數組如下:這是基於代碼從羅曼蓋伊照片媒體應用:

InputStream in = new BufferedInputStream(url.openStream(), IO_BUFFER_SIZE); 
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE); 
copy(in, out); 
out.flush(); 
final byte[] data = dataStream.toByteArray(); 

PS:我也貼在android.developer谷歌集團這個問題的一個變種。


非常感謝您的建議 - 現在我真的很困惑!我照你的建議做了,發現直接從下載的字節數組得到的圖像確實是像素化的。但是,這是從完全相同的URL下載的,在我的計算機上訪問時,它不是像素化的。以下是相應的Flickr網址:

http://farm3.static.flickr.com/2678/4315351421_54e8cdb8e5.jpg

更奇怪的是,當我在模擬器,而不是我的電話(一部HTC英雄)上運行相同的應用程序,也沒有像素。

這究竟如何呢?

下面是我用從一個URL加載一個位圖的代碼 - 它是基於羅曼蓋伊照片媒體應用程序,它採用了威爾的建議寫的原始字節數組到文件:

Bitmap loadPhotoBitmap(URL url) { 
    Bitmap bitmap = null; 
     InputStream in = null; 
     BufferedOutputStream out = null; 

     try { 

      FileOutputStream fos = new FileOutputStream("/sdcard/photo-tmp.jpg"); 
      BufferedOutputStream bfs = new BufferedOutputStream(fos); 

      in = new BufferedInputStream(url.openStream(), 
        IO_BUFFER_SIZE); 

      final ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 
      out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE); 
      copy(in, out);      
      out.flush(); 
      final byte[] data = dataStream.toByteArray(); 

      bfs.write(data, 0, data.length); 
      bfs.flush(); 

      BitmapFactory.Options opt = new BitmapFactory.Options(); 
      bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt); 

     } catch (IOException e) { 
      android.util.Log.e(LOG_TAG, "Could not load photo: " + this, e); 
     } finally { 
      closeStream(in); 
      closeStream(out) 
      closeStream(bfs); 
     } 

     return bitmap; 
    } 

private static void copy(InputStream in, OutputStream out) throws IOException { 
    byte[] b = new byte[IO_BUFFER_SIZE]; 
    int read; 
    while ((read = in.read(b)) != -1) { 
     out.write(b, 0, read); 
    } 
} 

private static void closeStream(Closeable stream) { 
    if (stream != null) { 
     try { 
      stream.close(); 
     } catch (IOException e) { 
      android.util.Log.e(LOG_TAG, "Could not close stream", e); 
     } 
    } 
} 

我在這裏瘋了嗎? Best, Michael。

+0

我冒昧地將圖像內聯,因爲這通常會使問題更好,更易於閱讀。 – unwind

+1

你有沒有找到解決這個問題的方法?我已經嘗試了這些建議,但沒有運氣。這是超級討厭。 – blork

+0

作爲腳註,不要忘了JPEG在android環境中不是無損的。儘管它得到了支持,但對PNG的支持令人沮喪。 – user836725

回答

3

將從URL中提取的原始字節寫入/sdcard/tmp.jpg,然後在PC上查看。

JPEG圖像以8x8(或16x16)塊壓縮。如你所描述的,「像素化」實際上就是在這些圖塊中,這表明「壞」圖像是比其他圖像更加積極壓縮的JPEG圖像。

因此,我預計實際的問題是所下載的圖像是非常低質量的版本,例如,一個用於縮略圖/預覽用例。

+0

我也懷疑這一點,但「壞」圖像的實際文件大小比「好」圖像大18%*大。怪事。 – unwind

+0

這證明什麼都沒有:) – Will

4

好的,我終於明白了:看起來我的移動網絡會進行圖像壓縮以節省帶寬。

因此,從我的手機下載的圖片質量低於從我的計算機下載的相同圖片。

這對我的應用程序來說是一件壞事,但我不認爲我能做些什麼。嘆。

再次感謝您的輸入!

Best, Michael。

+0

它也可能是由HTTP頭提示 - Facebook本身可能會爲手機提供低質量的圖像。發送之前編輯標題 - 基本上,全部刪除它們! – Will

+1

您可以嘗試將http標頭設置爲Accept-Encoding gzip。不確定,但它可能會繞過網絡圖像壓縮。請參閱http://stackoverflow.com/questions/1573391/android-http-communication-should-use-accept-encoding-gzip –

+0

您是否試圖通過在瀏覽器中下載圖像來確認這一點?我有同樣的問題,但如果我在網頁瀏覽器中打開圖像,我會得到一張不合格的圖像。所以必須有一種方法來獲得正確的圖像。 – Janusz

1

某些版本的Android在Bitmap類中存在一個bug,並在某些操作時將Bitmap轉換爲RGB_565。這將表現在與您圖片上的相似的工件中。這也將解釋藍天的結合。 另外,請記住,Android加載時甚至在編譯資源文件時,會嘗試通過將它們轉換爲rgb_565來「優化」圖像。看看: http://android.nakatome.net/2010/04/bitmap-basics.html