android – calculateInSampleSize,为什么Math.round在width> height时处理height(height / reqHeight)?

我正在寻找'developer.android.com'来缩小我的位图文件,我发现有一件事我不明白。 所以我感谢你给我一点帮助。

这是一个来自developer.android.com的片段

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)”为什么要计算“(float)height /(float)reqHeight”?

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

在这种情况下,inSampleSize将是6,计算的维度是宽度= 100,高度= 133。 身高仍然高于reqHeight ..

那么,有谁能解释一下吗? 对不起复杂的解释,但我希望有人给我一个想法。 🙂

Solutions Collecting From Web of "android – calculateInSampleSize,为什么Math.round在width> height时处理height(height / reqHeight)?"

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

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

 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; } 

但是,这看起来像他们的代码太多的问题,我相信我正确地理解它的重点!

那么,在与扩展东西有很多问题后,我想我有我自己的答案:

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html使用“高效载入大位图”我想发布我的一些结果&#xFF08; 原始代码如下 ):

 // 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); 

我目前正在使用1280 x 752分辨率横向模式下的Galaxy-Tab 7.7。 想象一下具有以下规格的图像:

1920 x 1200 ..会发生什么?

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

两个数字都会变成2,所以如果我理解了所有的东西,那么这个图片将被缩小2倍。 这将导致图像为1920/2 = 960 * 600 ,这是我所需的分辨率为1280 * 752

我解决了这个问题:

 // 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是否使用“分数”是一个选项。 目前所有图像尺寸最大为1280×752(* 2)= 2560 * 1504的尺寸都不会缩放。 我写的imageView是图像的详细视图,所以它现在不应该是太多的问题。

我使用代码的修改版本与以下内容一起使用:

 returnview.setAdjustViewBounds(true); 

这将防止图像大于我的屏幕,得到一个混乱的边界框。 如果您将颜色背景设置为实际图像,您可以看到它。 此外,使用现在固定的代码,我可以实现一些onClick处理程序来检测用户是否单击我的图像以外closures图像。

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

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

BitmapFactory.Options参考 2013年3月8日

所以正确的代码来计算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; } 

但是上面的代码可以额外优化。 由于halfWidthhalfHeight已经被2除,而loop可以被重写成返回的图像大于或等于请求的大小范围。

  while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } 

原始代码的图像尺寸800x800像素必须适合100x100像素将返回inSampleSize 4 – >返回的图像将是200x200像素和修改后的代码将返回inSampleSize 8 – >返回的图像将是100x100像素。

注意:使用inSampleSizeBitmapFactory.decodeXXX方法下采样图像的主要function是在加载比显示所需的图像大得多的图像时保留内存。 这些方法结合上面的代码将总是给你最大的图像(2的幂),是大于(或相等)所要求的范围,而不是适合在这个范围内的图像。

我发现他们的逻辑

 if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float)height / (float)reqHeight); } else { inSampleSize = Math.round((float)width / (float)reqWidth); } } 

令人困惑。 我会采取一个更简单的方法。 我的逻辑是如果图像是水平图像而忽略所需的高度,则将图像放在宽度上,如果图像是垂直图像则忽略所需的宽度,将图像放大到高度。

 if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float) width / (float) reqWidth); } else { inSampleSize = Math.round((float) height / (float) reqHeight); } } 

他们的逻辑不仅被认为是错误的。 在图像中你需要的东西不是缩小,直到一个参数小于所需的值,如果它被分成了一半,但确保没有维度大于2048.在这之上,很多时候你可以“渲染纹理或显示图像。 如果你有一个像是4000×1300的图像,你说你至less需要768.如果没有低于这个值,它实际上不能切割1300。 所以它什么也不做,退出。 尝试加载失败的4000幅图像。

 public static int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) { int height = options.outHeight; int width = options.outWidth; int inSampleSize = 1; while (height > maxHeight || width > maxWidth) { height /= 2; width /= 2; inSampleSize *= 2; } return inSampleSize; }