为什么画面质量下降?

时间:2016-07-22 12:27:26

标签: java android android-bitmap

我在屏幕上显示图片:

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

使用矩阵将图片旋转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);

为什么显示图片的质量下降?以及如何使其达到正常质量?

轮换前的图片: enter image description here

轮换后的图片:

enter image description here

1 个答案:

答案 0 :(得分:2)

看起来您几乎是直接从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 600px,则inSampleSize将为2,因此生成的图像将为340 x 300px,这是质量损失。如果您不需要显示全分辨率,这有助于减小图像大小,但在您的情况下,您似乎需要使用原始图像大小以您需要的分辨率显示它。

意味着您应该放弃计算inSampleSize,这只是意味着您应该提供更符合ImageView尺寸的所需宽度和高度。

int requiredWidth = imageView.getMeasuredWidth();
int requiredHeight = imageView.getMeasureHeight();
  

注意:如果ImageView宽度和/或高度为{<1}},则将不会工作   设置为wrap_content,因为直到a才会测量宽度和高度   提供源图像。

在您的情况下,我还会在您计算inSampleSize时交换所需的宽度和高度,因为您将图像旋转90°:

options.inSampleSize = calculateInSampleSize(options, requiredHeight, requiredWidth);

最后,请确保您的ImageView.ScaleType 设置为FIT_XY,因为这会使图像失真,从而导致质量下降。其他比例类型也可以增加图像的大小超出原始尺寸,这也可能导致感知质量下降。

最后,如果您的应用程序显示了大量图像,我建议使用图像加载库为您加载图像。这些库将处理缩放图像以适合ImageView,并且大多数支持wrap_contentGlidePicassoFresco是一些很好的例子。