为什么文档样本除以2来计算inSampleSize以进行位图加载?

时间:2014-04-15 14:45:20

标签: android graphics opengl-es bitmap

在Android培训文档中,article有效地加载大型位图,讨论计算inSampleSize以在加载图像时对其进行下采样。这是共享的代码示例。

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

对我来说没有意义的是在这里使用halfHeighthalfWidth。让我们来看一个真实世界的例子,这样我就可以表明我的意思了。

我想将用户的照片加载到OpenGL纹理中。我已经查询过发现GL_MAX_TEXTURE_SIZE是4096.用户选择了4320x2432的照片,所以我需要将其缩小一点。

我调用了docs中提供的静态帮助方法:

options.inSampleSize = BitmapUtils.calculateInSampleSize(options, maxTextureSize, maxTextureSize);

单步执行此代码,halfHeight将为1216,halfWidth将为2160,如果该值除以inSampleSize仍然大于请求的维度,则inSampleSize将仅为1以外。

当我运行此设置时,inSampleSize设置为1,它根本不会缩小图像,并且OpenGL会因为大于GL_MAX_TEXTURE_SIZE而抛出拟合。

我的问题是为什么我们在这里除以二?我不在乎我的一半图像是否符合要求的尺寸,我希望整个图像都合适。如果inSampleSize(halfHeight / inSampleSize) > reqHeight一直跟(halfWidth / inSampleSize) > reqWidth碰撞会不会更有意义?

2 个答案:

答案 0 :(得分:2)

这是我对这种方法意图的误解。我以为我们正在寻找一个inSampleSize来解码一个Bitmap以使内部符合要求的尺寸。我现在看到该方法旨在返回一个值来解码一个位图,该位图尽可能接近但不小于所请求的大小。

答案 1 :(得分:1)

奇怪的是,这个问题回答了我的意思。我对方法感到困惑:

// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
        && (halfWidth / inSampleSize) > reqWidth) {
    inSampleSize *= 2;
}

这不会使高度和宽度都大于reqHeight和reqWidth。一旦其中一个小于相关值,循环就会结束。但是,因为该方法使用halfHeight和halfWeight,它有点像在超越标记后退一步......或者测量前面的步骤,而不是...

无论如何,我正在考虑手头的问题并最终得到以下结论:

boolean condition = (height / 2 / inSampleSize) > reqHeight
        && (width / 2 / inSampleSize) > reqWidth;
for (; condition; inSampleSize *= 2) {
}

这样使用for循环是不合适的吗?也许简单地使用会更清楚:

while ((height / 2 / inSampleSize) > reqHeight
        && (width / 2 / inSampleSize) > reqWidth) {
    inSampleSize *= 2;
}

无论如何,我会尝试更好地回答你的实际问题。我认为这种方法旨在最大限度地减少内存使用,而不是提供具有精确所需大小的位图。缩小图像时,因子2是一个相当大的跳跃;你可能最终得到的位图只有你想要的尺寸的一半,然后必须扩大规模。我只是学习如何使用图像并且完全在猜测,但是这看起来比缩小几乎是所需尺寸的两倍的图像更糟糕吗?