为什么画质下降了?
Why quality of the picture decreased?
我在屏幕上显示图片:
Bitmap bitmap = decodeSampledBitmapFromResource(data, 100, 100);
decodeSampledBitmapFromResource() 方法如下所示:
public static Bitmap decodeSampledBitmapFromResource(String path,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
使用Matrix将图片旋转90度后,图片质量下降:
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap bitmap = decodeSampledBitmapFromResource(data, 100, 100);
bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
为什么显示的图片质量下降?以及如何以正常质量制作它?
旋转前的图片:
旋转后的图片:
看起来您几乎是直接从 documentation 中提取代码,这很好,但您需要了解该代码的作用。以此代码为例:
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;
}
我猜这与您的 calculateInSampleSize()
方法相同。此方法计算应用于缩放图像以最佳匹配给定尺寸的除数。
在您的例子中,您为宽度和高度提供了 100px
。这意味着如果起始图像是 680 x 600 像素,您的 inSampleSize
将是 2,因此生成的图像将是 340 x 300 像素,这是质量损失。如果您不需要显示完整分辨率,这有助于减小图像尺寸,但在您的情况下,您似乎确实需要使用原始图像尺寸以您需要的分辨率显示它。
这并不意味着您应该放弃计算inSampleSize
,它只是意味着您应该提供一个与您的[=17=更匹配的所需宽度和高度]尺寸。
int requiredWidth = imageView.getMeasuredWidth();
int requiredHeight = imageView.getMeasureHeight();
Note: this will not work if the ImageView
width and/or height is
set to wrap_content
, as the width and height will not be measured until a
source image is provided.
在你的情况下,我也会在你计算 inSampleSize
时交换所需的宽度和高度,因为你正在将图像旋转 90°:
options.inSampleSize = calculateInSampleSize(options, requiredHeight, requiredWidth);
最后,请确保您的 ImageView.ScaleType
而不是 设置为 FIT_XY
,因为这会扭曲图像,导致质量下降。其他缩放类型也可以 增加 图像的大小,使其超出原始尺寸,这也会导致感知到的质量下降。
最后,如果您的应用程序显示大量图片,我建议您使用图片加载库来为您加载图片。这些库将处理缩放图像以适应 ImageView
,并且大多数也支持 wrap_content
。 Glide, Picasso and Fresco 是一些很好的例子。
我在屏幕上显示图片:
Bitmap bitmap = decodeSampledBitmapFromResource(data, 100, 100);
decodeSampledBitmapFromResource() 方法如下所示:
public static Bitmap decodeSampledBitmapFromResource(String path,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
使用Matrix将图片旋转90度后,图片质量下降:
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap bitmap = decodeSampledBitmapFromResource(data, 100, 100);
bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
为什么显示的图片质量下降?以及如何以正常质量制作它?
旋转前的图片:
旋转后的图片:
看起来您几乎是直接从 documentation 中提取代码,这很好,但您需要了解该代码的作用。以此代码为例:
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;
}
我猜这与您的 calculateInSampleSize()
方法相同。此方法计算应用于缩放图像以最佳匹配给定尺寸的除数。
在您的例子中,您为宽度和高度提供了 100px
。这意味着如果起始图像是 680 x 600 像素,您的 inSampleSize
将是 2,因此生成的图像将是 340 x 300 像素,这是质量损失。如果您不需要显示完整分辨率,这有助于减小图像尺寸,但在您的情况下,您似乎确实需要使用原始图像尺寸以您需要的分辨率显示它。
这并不意味着您应该放弃计算inSampleSize
,它只是意味着您应该提供一个与您的[=17=更匹配的所需宽度和高度]尺寸。
int requiredWidth = imageView.getMeasuredWidth();
int requiredHeight = imageView.getMeasureHeight();
Note: this will not work if the
ImageView
width and/or height is set towrap_content
, as the width and height will not be measured until a source image is provided.
在你的情况下,我也会在你计算 inSampleSize
时交换所需的宽度和高度,因为你正在将图像旋转 90°:
options.inSampleSize = calculateInSampleSize(options, requiredHeight, requiredWidth);
最后,请确保您的 ImageView.ScaleType
而不是 设置为 FIT_XY
,因为这会扭曲图像,导致质量下降。其他缩放类型也可以 增加 图像的大小,使其超出原始尺寸,这也会导致感知到的质量下降。
最后,如果您的应用程序显示大量图片,我建议您使用图片加载库来为您加载图片。这些库将处理缩放图像以适应 ImageView
,并且大多数也支持 wrap_content
。 Glide, Picasso and Fresco 是一些很好的例子。