3 回答
TA贡献1806条经验 获得超5个赞
好的,我找到了一个不错的选择,我认为它应该适用于任何类型的位图解码。
不仅如此,它还允许您使用所需的任何样本大小(而不只是2的幂)进行缩减。如果您付出更多努力,甚至可以使用分数而不是整数进行缩小。
下面的代码适用于res文件夹中的图像,但是对于任何类型的位图解码都可以轻松完成:
private Bitmap downscaleBitmapUsingDensities(final int sampleSize,final int imageResId)
{
final Options bitmapOptions=new Options();
bitmapOptions.inDensity=sampleSize;
bitmapOptions.inTargetDensity=1;
final Bitmap scaledBitmap=BitmapFactory.decodeResource(getResources(),imageResId,bitmapOptions);
scaledBitmap.setDensity(Bitmap.DENSITY_NONE);
return scaledBitmap;
}
我已经测试过了,它显示了降采样的图像就好了。在下面的图像中,我显示了原始图像,并使用inSampleSize方法和我的方法缩小了图像的尺寸。
很难看到差异,但是使用密度的像素实际上并不仅仅是跳过像素,而是将所有像素都考虑在内。它可能会慢一些,但它更精确,并且使用了更好的插值法。
在此处输入图片说明
与使用inSampleSize相比,唯一的缺点似乎是速度,它在inSampleSize上更好,因为inSampleSize会跳过像素,并且因为密度方法会对跳过的像素进行额外的计算。
但是,我认为android以某种相同的速度运行这两种方法。
我认为这两种方法的比较类似于最近邻降采样与双线性插值降采样之间的比较。
编辑:与Google相比,我发现了这里显示的方法的一个缺点。在此过程中使用的内存可能很高,我认为这取决于图像本身。这意味着您仅应在您认为合理的情况下使用它。
编辑:对于那些希望克服内存问题的人,我已经制定了合并的解决方案(包括Google的解决方案和我的解决方案)。它不是完美的,但是比我以前做的要好,因为它在下采样期间不会使用原始位图所需的内存。相反,它将使用Google解决方案中使用的内存。
这是代码:
// as much as possible, use google's way to downsample:
bitmapOptions.inSampleSize = 1;
bitmapOptions.inDensity = 1;
bitmapOptions.inTargetDensity = 1;
while (bitmapOptions.inSampleSize * 2 <= inSampleSize)
bitmapOptions.inSampleSize *= 2;
// if google's way to downsample isn't enough, do some more :
if (bitmapOptions.inSampleSize != inSampleSize)
{
// downsample by bitmapOptions.inSampleSize/originalSampleSize .
bitmapOptions.inTargetDensity = bitmapOptions.inSampleSize;
bitmapOptions.inDensity = inSampleSize;
}
else if(sampleSize==1)
{
bitmapOptions.inTargetDensity=preferHeight ? reqHeight : reqWidth;
bitmapOptions.inDensity=preferHeight ? height : width;
}
因此,简而言之,两种方法的优缺点:
Google的方式(使用inSampleSize)在解码期间使用较少的内存,并且速度更快。但是,它有时会导致一些图形失真,并且仅支持下采样到2的幂次,因此结果位图可能会花费比您想要的更多的值(例如,x1 / 4的大小而不是x1 / 7的大小)。
我的方法(使用密度)更加精确,可以提供更高质量的图像,并且在结果位图上使用的内存更少。但是,它在解码期间可能会占用大量内存(取决于输入),并且速度稍慢。
编辑:另一项改进,因为我发现在某些情况下输出图像与所需的尺寸限制不符,并且您不希望使用Google的方式对太多像素进行下采样:
final int newWidth = width / bitmapOptions.inSampleSize, newHeight = height / bitmapOptions.inSampleSize;
if (newWidth > reqWidth || newHeight > reqHeight) {
if (newWidth * reqHeight > newHeight * reqWidth) {
// prefer width, as the width ratio is larger
bitmapOptions.inTargetDensity = reqWidth;
bitmapOptions.inDensity = newWidth;
} else {
// prefer height
bitmapOptions.inTargetDensity = reqHeight;
bitmapOptions.inDensity = newHeight;
}
}
因此,例如,从2448x3264图像降采样到1200x1200,它将变为900x1200
- 3 回答
- 0 关注
- 2738 浏览
添加回答
举报