为什么文档示例在位图加载时要将inSampleSize除以2来计算?

5
在Android培训文档中,有一篇关于有效加载大型位图的文章,其中讨论了在加载图像时计算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,因此我需要将其缩小一点。
我调用了文档中提供的静态帮助方法:
options.inSampleSize = BitmapUtils.calculateInSampleSize(options, maxTextureSize, maxTextureSize);

逐步执行此代码时,`halfHeight` 将为 1216,`halfWidth` 将为 2160,只有当该值除以 `inSampleSize` 仍大于所请求的尺寸时,`inSampleSize` 才会不为 1。
运行此设置时,`inSampleSize` 被设置为 1,这根本不会缩小图像,并且 OpenGL 抛出了异常,因为它比 `GL_MAX_TEXTURE_SIZE` 还要大。
我的问题是,为什么我们要在这里除以2?我不关心我的图像是否适合所请求的尺寸的一半,我想要整个图像适合。保持增加 `inSampleSize` 直到 `(halfHeight / inSampleSize) > reqHeight` 和 `(halfWidth / inSampleSize) > reqWidth` 不再成立,难道不更有意义吗?
2个回答

2

我之前对该方法的意图有所误解。我以为我们要找到一个inSampleSize来解码Bitmap以适应请求的尺寸内部。但现在我明白了,该方法的目的是返回一个值来解码一个Bitmap,使其尽可能接近但不小于请求的尺寸。


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的倍数是相当大的跳跃;你可能会得到一个略微超过你要求的大小的位图,然后不得不放大。我正在学习如何使用图像,并且完全是在推测,但是比起缩小几乎是所需大小两倍的图像,那不会看起来更糟糕吗?

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