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过大时,可以不去生成缩略图。

你可能感兴趣的:(android,Google,null,工具,float,Matrix)