Android2.2源代码中关于生成图片缩略图的一个bug

当尝试用Android2.2的图库应用打开1x10000分辨率的JPEG图片时,由于缩略图生成过程中错误地计算了缩放比例,导致内存溢出。分析指出,Google在`ThumbnailUtils.java`中计算缩放因子时只考虑了大图缩小的情况,未处理小图放大可能导致的过大内存需求。这会导致Dalvik内存分配失败,使图库应用崩溃。解决方案是限制缩略图生成时的内存消耗,避免在需要大量内存时生成缩略图。
摘要由CSDN通过智能技术生成

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值