首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >android - calculateInSampleSize,当Math.round > height时,为什么reqHeight要处理height( height /height)?

android - calculateInSampleSize,当Math.round > height时,为什么reqHeight要处理height( height /height)?
EN

Stack Overflow用户
提问于 2012-12-04 12:37:27
回答 5查看 5.9K关注 0票数 10

我正在看'developer.android.com‘来缩小我的位图文件,我发现了一件我不理解的事情。所以我很感谢你给我一点帮助。

这是一个来自developer.android.com的snippet

代码语言:javascript
复制
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) {
    if (width > height) {
      inSampleSize = Math.round((float)height / (float)reqHeight);
    } else {
      inSampleSize = Math.round((float)width / (float)reqWidth);
    }
  }
  return inSampleSize;
}

在if语句中,当“if(width > height)”时,为什么要计算“(ReqHeight)height/ (float)reqHeight”?

例如,width=600、height=800、reqWidth=100、reqHeight=100。

在这种情况下,inSampleSize将为6,计算的维度为width=100、height=133。高度仍然高于reqHeight。

所以,有没有人能给我解释一下?对于复杂的解释,我很抱歉,但我希望有人给我一个想法。:)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-12-04 16:34:11

我所能说的是他们的逻辑看起来是错误的:(不管怎么说,这个方法相当简单,所以用正确的条件重新实现它应该不是什么大问题!)我的意思是,当你看一看decodeSampledBitmapFromResource,它只想减少位图,使其适合所需的边界,所以这肯定是一个错误。

编辑::这看起来更糟糕,因为对我来说,它在某些情况下不起作用。假设你的宽度为200,高度为600。将最大界限设置为width = 100和height = 500。您有height > width,但是如果您希望它们都适合返回结果,inSampleSize必须是200/100,而不是600/500。所以基本上,如果你重新实现这个方法,我会这样做:

代码语言:javascript
复制
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 stretch_width = Math.round((float)width / (float)reqWidth);
    int stretch_height = Math.round((float)height / (float)reqHeight);

    if (stretch_width <= stretch_height) 
        return stretch_height;
    else 
        return stretch_width;
}

但是看起来他们的代码有太多的问题,我不相信我正确地理解了它的要点!

票数 4
EN

Stack Overflow用户

发布于 2015-03-08 21:49:19

上面问题中的代码严重过时。如BitmapFactory.Options reference (自2013年3月8日起)中所述,inSampleSize将向下舍入到最接近的2的幂。

如果设置为大于1的值,则请求解码器对原始图像进行二次采样,返回较小的图像以节省内存。采样大小是对应于解码位图中的单个像素的任一维度的像素数。例如,inSampleSize == 4返回的图像的宽度/高度是原始图像的1/4,像素数量是原始图像的1/16。任何值<= 1都被视为1。注意:解码器使用基于2的幂的最终值,任何其他值都将向下舍入到最接近的2的幂。

2013年3月8日的BitmapFactory.Options reference

因此计算inSampleSize正确代码应该是Loading Large Bitmaps

代码语言:javascript
复制
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;
}

但是,上面的代码可以进行额外的优化。因为halfWidthhalfHeight已经被2整除,而循环可以被重写以返回大于或等于请求大小界限的图像

代码语言:javascript
复制
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }

图像大小的800x800 pix的原始代码,必须适合100x100 pix将返回inSampleSize的4 ->返回的图像将是200x200 pix,和修改的代码将返回inSampleSize的8 ->返回的图像将是100x100 pix。

注意:使用inSampleSizeBitmapFactory.decodeXXX方法对图像进行下采样的主要功能是在加载比显示所需大得多的图像时保留内存。这些方法与上面的代码结合在一起,总是会给出最小的图像(按2的幂缩放),它大于(或等于)请求的边界,而不是适合该边界的图像。

票数 4
EN

Stack Overflow用户

发布于 2013-03-15 07:40:02

嗯,在伸缩方面遇到了很多问题之后,我想我有了自己的答案:

使用http://developer.android.com/training/displaying-bitmaps/load-bitmap.html中的“高效加载大型位图”,我想发布一些我的结果(下面的原始代码):

代码语言:javascript
复制
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);

我目前正在使用1280x752分辨率的Galaxy-Tab7.7,在横向模式下。想象一个具有以下规格的Image:

1920 x 1200 ..会发生什么呢?

heighRatio = 1920/1280 = 1.5和widthRatio = 1200/752 = 1.59

这两个数字都四舍五入到2,所以如果我理解正确的话,图像将按因子2缩小。这将导致图像为1920/2 = 960 * 600,低于我要求的1280 * 752分辨率。

我解决了这个问题,用一层一层地替换掉了圆形:

代码语言:javascript
复制
// Calculate ratios of height and width to requested height and width
final int heightRatio = (int)Math.floor((float) height / (float) reqHeight);
final int widthRatio = (int)Math.floor((float) width / (float) reqWidth);

这实际上防止了我的一些图像被过多地缩小。我目前仍在研究参数inSampleSize,看看是否可以使用"fractions“。目前,大小不超过1280x752 (*2) = 2560*1504的所有图像将不会被缩放()。我正在编写的imageView是图像的详细视图,所以现在应该不是太大的问题。

我将中代码的修改版本与以下代码结合使用:

代码语言:javascript
复制
returnview.setAdjustViewBounds(true);

这将防止图像比我的屏幕更大,从而得到一个混乱的边界框。如果您设置了实际图像的背景色,就可以看到它。此外,有了现在修复的代码,我可以实现一些onClick处理程序来检测用户是否在我的图像外部单击以关闭图像。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13696166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档