从输入流中调整位图大小

5

我正在尝试从InputStream中调整一张图片的大小,所以我使用了Strange out of memory issue while loading an image to a Bitmap object中的代码,但我不知道为什么这段代码总是返回没有图像的Drawable。

这个代码可以正常工作:

private Drawable decodeFile(InputStream f){
    try {
        InputStream in2 = new BufferedInputStream(f);
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=2;
        return new BitmapDrawable(BitmapFactory.decodeStream(in2, null, o2));
    } catch (Exception e) {
        return null;
    }
}

这个不起作用:

private Drawable decodeFile(InputStream f){
    try {
        InputStream in1 = new BufferedInputStream(f);
        InputStream in2 = new BufferedInputStream(f);
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(in1,null,o);

        //The new size we want to scale to
        final int IMAGE_MAX_SIZE=90;

        //Find the correct scale value. It should be the power of 2.
        int scale = 2;
        if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
            scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / 
               (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inJustDecodeBounds = false;
        o2.inSampleSize=scale;
        return new BitmapDrawable(BitmapFactory.decodeStream(in2, null, o2));
    } catch (Exception e) {
        return null;
    }
}

为什么一个选项会影响另一个选项?如果我使用两个不同的InputStream和Options,这是如何可能的?

2个回答

8
实际上,你有两个不同的 "BufferedInputStream",但它们在内部使用唯一的 "InputStream" 对象,因为 "BufferedInputStream" 只是 "InputStream" 的一个包装器。
因此,你不能仅仅在相同的流上调用两次 "BitmapFactory.decodeStream" 方法,这肯定会失败,因为第二次解码不会从流的开头开始。如果支持重置流,则需要重置流或重新打开它。

我理解你的问题,但是我从HttpURLConnection接收到这个流,我该怎么办? - kavain
你说得对,我没有两个InputStreams,就像你说的那样,我学会了如何复制InputStream,在这里:https://dev59.com/iW025IYBdhLWcg3wkW8F 非常感谢。 - kavain
2
你意识到你正在调整Bitmap以改善内存,对吧?但是那个链接会让你将整个Bitmap的备份字节数组保存两次...我只会重新打开FileInputStream或你正在使用的任何其他东西。 - HandlerExploit
@andrei-mankevich 这样的InputStream(不支持mark/reset)可以被简单地包装成BufferedInputStream。 - Sachin Gupta

1

这是我的代码,它运行良好,希望能对您有所帮助。

//Decode image size
    BitmapFactory.Options optionsIn = new BitmapFactory.Options();
    optionsIn.inJustDecodeBounds = true; // the trick is HERE, avoiding memory leaks
    BitmapFactory.decodeFile(filePath, optionsIn);

    BitmapFactory.Options optionsOut = new BitmapFactory.Options();
    int requiredWidth = ECameraConfig.getEntryById(Preferences.I_CAMERA_IMAGE_RESOLUTION.get()).getyAxe();
    float bitmapWidth = optionsIn.outWidth;
    int scale = Math.round(bitmapWidth / requiredWidth);
    optionsOut.inSampleSize = scale;
    optionsOut.inPurgeable = true;//avoiding memory leaks
    return BitmapFactory.decodeFile(filePath, optionsOut);

我相信你不需要两个InputStream。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接