0

我正在使用带有 XBR4x 算法的程序ImageResizer将旧 2D 游戏中的 .gif 图像从 32x32 升级到 48x48。

具体流程:

  1. 手动将所有图像重命名为 .jpeg,因为程序不会打开 .gif
  2. 调整图像大小,程序将它们保存为 .bmp
  3. 再次手动将图像重命名为 .gif。

问题:

在 Paint 中查看图像时,它们看起来非常好,当在我的 RGB BufferedImage 中绘制时,它们突然都有一个不是背景颜色的白色/灰色 ~1px 边框,图像直接相邻放置。因为我有这些图像的完整马赛克,所以白色边框是不行的。

图像 32x32:在此处输入图像描述

放大后的图像 48x48:在此处输入图像描述

其中 4 张带有白色边框的地球图像的游戏截图:在此处输入图像描述

问题:

这些边界是如何产生的?如果无法回答这个问题,是否有更可靠的方法来提升低分辨率游戏图像,使其看起来不那么像素化?

4

4 回答 4

1

我认为这是图像调整大小算法的产物,例如,如果您在 XnView 中查看它们,则在合并之前,边框实际上是可见的,在放大的图像中。解决此问题的最佳方法是使用另一种工具来调整图像大小,该工具允许用户控制此类边界效果,但如果您必须使用此工具,您仍然可以通过构建 3x3 网格来解决该问题原始图像(将是 96x96),将其缩放到 144x144,然后切出中心的 48x48 块。这将消除边界效应。

于 2012-07-30T17:00:08.347 回答
1

边框是由上述工具执行的缩放过程的结果。考虑这个演示,它显示了基于问题的缩放图像和使用Image.getScaledInstance()创建的缩放图像的图块。

请注意,如果您选择保留自己的缩放方法,请查看Image.getScaledInstance() 的风险以获得更优化的解决方案。

在此处输入图像描述

import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class TestImageScale {

    public static void main(String[] args) {
        try {
            BufferedImage original = ImageIO.read(new URL(
                    "http://i.stack.imgur.com/rY2i8.gif"));
            Image scaled = original.getScaledInstance(48, 48,
                    Image.SCALE_AREA_AVERAGING);
            BufferedImage scaledOP = ImageIO.read(new URL(
                    "http://i.stack.imgur.com/Argxi.png"));

            BufferedImage tilesOP = buildTiles(scaledOP, 3, 3);
            BufferedImage tiles = buildTiles(scaled, 3, 3);

            JPanel panel = new JPanel();
            panel.add(new JLabel(new ImageIcon(tilesOP)));
            panel.add(new JLabel(new ImageIcon(tiles)));

            JOptionPane.showMessageDialog(null, panel,
                    "Tiles: OP vs getScaledInstance",
                    JOptionPane.INFORMATION_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
                    JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }

    static BufferedImage buildTiles(Image tile, int rows, int columns) {

        int width = tile.getWidth(null);
        int height = tile.getHeight(null);

        BufferedImage dest = GraphicsEnvironment
                .getLocalGraphicsEnvironment()
                .getDefaultScreenDevice()
                .getDefaultConfiguration()
                .createCompatibleImage(width * rows, height * columns,
                        Transparency.TRANSLUCENT);
        Graphics g = dest.getGraphics();
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < columns; col++) {
                g.drawImage(tile, row * width, col * width, null);
            }
        }

        g.dispose();

        return dest;
    }
}
于 2012-07-31T03:44:21.083 回答
0

只是一个疯狂的猜测:原始图像是否有一个 Alpha 通道(或者你在调整大小时隐式创建一个)?当使用 alpha 调整图像大小时,缩放过程可能会假设图像外部的区域是透明的,并且边框像素也可能变得部分透明。

于 2012-07-30T17:01:14.700 回答
0

我给工具的开发者 Hawkynt 发了电子邮件,似乎错误不在工具中,而是在 Microsoft 的实现中,他修复了它(实际上像 Multiple Image Resizer .NET 这样更大的工具也有问题)。这是他对他的计划所说的:

“当您手动输入宽度和/或高度时,图像会通过所选算法调整大小,一切正常。

之后我使用了来自 GDI+ 的 resample 命令,它实现了 Microsoft 版本的双三次调整大小算法。这个实现是有缺陷的,所以它会在 300 像素以下的图像的左侧和上部生成一个像素。

我通过简单地将调整大小的图像比想要的大一个像素并将其向左并向上移动一个像素来修复它,因此白色边框不再可见,并且目标图像具有他预期的尺寸。”

于 2012-08-01T22:39:54.937 回答