Android2.2源代碼中關於生成圖片縮略圖的一個bug

現象:在sdcard上存放一個特殊分辨率的JPEG圖片,比如1x10000。然後使用android自帶的圖庫應用程序去瀏覽該圖片。使用圖庫瀏覽圖片,會先生成縮略圖供用戶瀏覽。此時,圖庫應用程序會異常退出,如果可以看其log,會發現dalvik分配內存時發生內存溢出。但是如果你使用別的圖片查看工具,不去生成縮略圖,直接打開該圖片,則不會發生異常。

分析:經過分析,發現google在做縮略圖時,有一處錯誤。Google設定所有縮略圖的分辨率都是96x96。以此爲目標,然後根據原始圖片的分辨率和目標圖片來計算縮放因子。相關函數在文件ThumbnailUtils.java中,其路徑爲:

/framework/base/media/java/android/media/ThumbnailUtils.java

函數具體定義爲:

    /**

     * Creates a centered bitmap of the desired size.

     *

     * @param source original bitmap source

     * @param width targeted width

     * @param height targeted height

     * @param options options used during thumbnail extraction

     */

    public static Bitmap extractThumbnail(

            Bitmap source, int width, int height, int options) {

        if (source == null) {

            return null;

        }

 

        float scale;

        if (source.getWidth() < source.getHeight()) {

            scale = width / (float) source.getWidth();

        } else {

            scale = height / (float) source.getHeight();

        }

 

        Matrix matrix = new Matrix();

        matrix.setScale(scale, scale);

        Bitmap thumbnail = transform(matrix, source, width, height,

                OPTIONS_SCALE_UP | options);

        return thumbnail;

    }

如果原始圖片的分辨率爲1600x1200,計算出來的scale爲:

scale = 96 / 1200 = 0.08

所需要的memory大小爲:1600*0.08 * 1200*0.08 * 2 = 24Kbyte

如果原始圖片的分辨率爲1x10000,計算出來的scale爲:

Scale = 96 / 1 = 96

所需要的memory大小爲:1*96 * 10000*96 * 2 = 175Mbyte,

而其本身所需要的空間爲:1 * 10000 * 2 = 19Kbyte。

Dalvik爲每個進程設置了允許申請的memory大小,默認爲16M。175M的memory需要是任何系統都不能滿足的。

總結:google在處理scale時,應該是隻考慮了大圖像縮小的情況,而沒有考慮小圖象放大的情況,特別是寬需要放大,而高需要縮小(或相反)。爲了不讓圖庫應用程序異常退出,可以在這裏做一些限制,當其所需memory過大時,可以不去生成縮略圖。

發佈了53 篇原創文章 · 獲贊 23 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章