位图缩放销毁质量

7
我已经制作了一个适用于Android Wear的表盘。
但问题在于图像缩放。当我调整它们的大小时,背景、标记和小工具的图像质量会降低。

例如,我将480x480的背景图像置于drawable-nodpi文件夹中(我也尝试了其他dpi),并进行以下缩放:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = true;
Bitmap bgImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.ticks_1, options);
bgImage = Bitmap.createScaledBitmap(bgImage , width, height, false);

以下是图片:

背景 输入图像描述

这是我在手表上看到的:

屏幕截图

我在调整大小方面做错了什么吗?

4个回答

10

我在这里找到了一个解决方案(链接),它非常有效。
这是缩放图像的代码部分:

public Bitmap getResizedBitmap(Bitmap bitmap, int newWidth, int newHeight) {
        Bitmap resizedBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

        float scaleX = newWidth / (float) bitmap.getWidth();
        float scaleY = newHeight / (float) bitmap.getHeight();
        float pivotX = 0;
        float pivotY = 0;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);

        Canvas canvas = new Canvas(resizedBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));

        return resizedBitmap;
    }

不错。+1。很想看看应用了这段代码后最终的手表屏幕是什么样子 :) - IAmGroot
那只是一个测试图像。我正在开发一个拥有更多功能和外观的手表表盘。那个带圆圈的蓝色图像就像顶部的那一个,没有任何失真和像素化。 - filipst
当你完成最终版本后,请将链接发送给我们 :) - IAmGroot
这是应用程序的链接 https://play.google.com/store/apps/details?id=com.tppm.watch.faces.android.wear - filipst
这很酷!营销图片中有一个错别字。对结果印象深刻。 - IAmGroot
显示剩余2条评论

2
以下是对下面代码的一些评论。你解码的选项部分没有起到任何作用,因为没有设置样本大小。所以可以删除它。
// BitmapFactory.Options options = new BitmapFactory.Options();
// options.inScaled = true;
// Bitmap bgImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.ticks_1, options);
Bitmap bgImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.ticks_1);
bgImage = Bitmap.createScaledBitmap(bgImage , width, height, false);

我认为你的图像失真问题实际上是由于图像本身。当你将其缩小到75%时,它无法在保持图像完全相同的情况下进行调整大小。这些带子非常细,任何微小的偏差都会导致外观不同。
我建议尝试使用更厚的环来测试图像是否失真,即使只是作为快速测试或永久解决方案。
更新:
要在所有分辨率下保持图像清晰,请研究矢量图像。这些图像在所有分辨率下都是像素完美的,并且可以呈现出极好的图形效果。特别是,因为你正在使用基本形状,所以应该很容易实现。
如果你正在调整位图的大小,你可以期望图像模糊,因为图像被重新绘制。如果必须使用位图,请在不同dpi文件夹中包含多个分辨率,以便Android选择最佳匹配进行调整大小。

我有一张只有一个黑色圆圈的图片,但是我再次得到了低质量的结果。我不明白其他人是如何在他们的图片中添加大量图形来制作面部表情的。 - filipst
@filipst 请看编辑。如果您想要高质量,应该使用基本形状几何的矢量图像。我认为您的问题是关于图像由于缺乏质量而失真,而不是锐度。这里有一些信息 - IAmGroot
我会尝试一下。但是你认为像这样的手表,例如是通过编程绘制的吗? https://play.google.com/store/apps/details?id=com.denite.watchface.blackmetal - filipst
@filipst 看起来更像是9 patch和drawables。此外,需要正确的DPI图像。我不会将矢量图像称为程序化。虽然指定了绘制方式的坐标,但它更加灵活多样。 - IAmGroot

1
改变
bgImage = Bitmap.createScaledBitmap(bgImage , width, height, false);

bgImage = Bitmap.createScaledBitmap(bgImage , width, height, true);

这将应用简单的双线性插值。结果将是一个有点模糊的图像,因为圆圈非常细,但会使用更多信息来创建缩放图像。结果图像也将具有一些莫尔纹理,但比您示例图片中的扭曲要少。如果您在Photoshop中使用双三次滤波器缩小图像,您将获得最佳结果,但即使如此,使用矢量图形也将优于任何像Doomsknight建议的基于位图的努力。

-1

以上已接受的剪切位图,请尝试我的答案

  public Bitmap getResizedBitmap(Bitmap bitmap, int newWidth, int newHeight) {
             Bitmap scaledBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());

    float scaleX = newWidth / (float) bitmap.getWidth();
    float scaleY = newHeight / (float) bitmap.getHeight();
    float pivotX = 0;
    float pivotY = 0;

    Matrix scaleMatrix = new Matrix();
    scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);

    Canvas canvas = new Canvas(resizedBitmap);
    canvas.setMatrix(scaleMatrix);
    canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));

    return resizedBitmap;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接