【问题标题】:BitmapFactory.Options#outWidth returns different size than actual bitmapBitmapFactory.Options#outWidth 返回与实际位图不同的大小
【发布时间】:2013-03-01 22:16:19
【问题描述】:

我正在编写一个自定义类。在实际绘制之前,需要计算一个位图以进行一些预处理和调整大小。位图本身是经过预处理的 9-patch 图像。在构造函数中,有这样的代码:

BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
bmpOptions.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), BITMAP_ID, bmpOptions);
Bitmap bmp = BitmapFactory.decodeResource(getResources(), BITMAP_ID);
        
Log.d(getClass().getSimpleName(), "width: " + bmp.getWidth() + " " + bmpOptions.outWidth + "; height: " + bmp.getHeight() + " " + bmpOptions.outHeight);

运行 Android 3.2.2 的 7 英寸三星 Galaxy Tab 7 上的输出:

宽度:556 556;身高:890 890

运行 Android 4.1 的 10" Motorola Xoom 上的输出:

宽度:556 556;身高:890 890

运行 Android 4.2.2 的 7" Nexus 7 上的输出:

宽度:740 834;高度; 1185 1335

位图的实际尺寸为:

mdpi:558 x 892

hdpi:836 x 1337

位图是经过预处理的 9-patch,这就是为什么尺寸相差 2 个像素的原因。我不明白为什么 Nexus 7 上的 hdpi 资产会产生如此大的不同。

我也尝试过这些配置:

bmpOptions.inScaled = false;

bmpOptions.inTargetDensity = getResources().getDisplayMetrics().densityDpi;

bmpOptions.inTargetDensity = getResources().getDisplayMetrics().densityDpi;
bmpOptions.inDensity = getResources().getDisplayMetrics().densityDpi;

bmpOptions.inTargetDensity = 0;
bmpOptions.inDensity = 0;

我也尝试了相反的方法,为解码的位图创建第二个 BitmapFactory.Options 并告诉它根本不缩放。

所有这些都提供了完全相同的结果。

【问题讨论】:

    标签: android android-image bitmapfactory


    【解决方案1】:

    要使用 inJustDecodeBounds 选项获得实际图像大小,您需要将返回的 outWidthoutHeight 乘以比例系数,即 inTargetDensity/inDensity。 示例代码为:

    public static void getBitmapDims(Resources res, int resId, Holder<Integer> width, Holder<Integer> height)
    {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, opts);
    
        float scale = (float) opts.inTargetDensity / opts.inDensity;
    
        width.value = (int) (opts.outWidth * scale + 0.5f);
        height.value = (int) (opts.outHeight * scale + 0.5f);
    }
    

    【讨论】:

      【解决方案2】:

      前 3 行不影响第 4 行,因为第 4 行不使用它上面的任何变量。也根本没有使用或填充“bmpOptions”。也许您在发布此问题时重命名了变量?

      另外,位图图像文件是否可能位于具有密度限定符(或默认值,如 mdpi)的文件夹中?

      仅当您将文件放入 drawable-nodpi 时,您将始终获得相同数量的宽度和高度像素。

      【讨论】:

      • 我在这里做的是一个测试。基本上,我将同一个位图解码两次。一次只有边界和另一个直道。如果您将inJustBounds 设置为true,理论上(并且根据文档),我应该能够在不使用时间和内存创建它的情况下获得结果位图的大小。但是,如此处所示,情况并非如此。两者互不影响的事实才是重点。
      • 我会看看当我把它放在no-dpi 文件夹中时会发生什么,但我觉得奇怪的是BitmapFactory 在缩放另一个时没有缩放一个。它应该两者都做。
      • 我把图片放到了 nodpi 文件夹中,效果很好。我觉得非常令人不安的是,当inJustBound 的全部目的是在没有完全解码的情况下为您提供图像的尺寸时存在这种不一致。
      • 它没有进行完整的解码。它确实考虑了您将在完整解码中获得的大小,因此您可以在没有任何额外计算的情况下使用它。
      • 对,但这里不是这样。 BitmapFactory 在进行完整解码时自动缩放图像,但在尝试获取边界时不做任何事情。最后,我得到了不同的值没有办法改变这个或改变(我发现),所以我唯一的选择是提供 tvhdpi 资产或将图像放在 nodpi 文件夹中。
      【解决方案3】:

      难道 Nexus 7 的屏幕是 tv dpi 并从 drawable-h dpi 加载位图?但是,outXXXX 值与位图的最终宽度/高度不匹配仍然很奇怪。

      【讨论】:

      • 没关系。它显然以某种方式缩放位图,但我明确告诉它不要这样做,并且位图仍然缩小。同样,BitmapFactory.Options 应该以与真实位图相同的方式解码位图。
      • 您能否更改原始示例 sn-p 中的代码,因为它无法编译(例如,您声明 bmpOptions 但正在使用 maskOptions...),这样我们可以看看确切的代码并找出问题所在。你是对的,行为看起来很奇怪,但它看起来与你的代码在 Nexus 7 上运行时没有 drawable-tvdpi 目录(而是使用 drawable-hdpi)这一事实有关.
      • 我把图片放在 nodpi 文件夹中,它工作。我觉得非常令人不安的是,当 inJustBound 的全部目的是在没有完全解码的情况下为您提供图像的尺寸时,存在这种不一致。根据文档(或至少是暗示),将inJustBounds 设置为true 在图像尺寸方面的作用应该相同。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多