【问题标题】:Why does documentation sample divide by 2 to calculate inSampleSize for Bitmap loading?为什么文档样本除以 2 来计算位图加载的 inSampleSize?
【发布时间】:2014-04-15 14:45:20
【问题描述】:

在 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的照片,所以我需要把它缩小一点。

我调用了文档中提供的静态辅助方法:

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

单步执行此代码,halfHeight 将是 1216,halfWidth 将是 2160,如果该值除以 inSampleSize 仍大于请求的维度,则 inSampleSize 只会不是 1。

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

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

【问题讨论】:

    标签: android graphics opengl-es bitmap


    【解决方案1】:

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

    【讨论】:

      【解决方案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;
      }
      

      这不会使高度和宽度都大于 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 是一个相当大的跳跃;您最终可能会得到一个略高于您正在寻找的大小一半的位图,然后必须按比例放大。我只是在学习如何使用图像并且完全是在猜测,但这不会比缩小几乎是所需尺寸两倍的图像更糟糕吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-11
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        • 2012-03-15
        • 1970-01-01
        相关资源
        最近更新 更多