高分辨率2D低分辨率图像

时间:2012-07-30 15:52:52

标签: java swing jframe image-resizing

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

确切的程序:

  1. 手动将所有图片重命名为.jpeg,因为该程序无法打开.gif
  2. 调整图像大小,程序将其保存为.bmp
  3. 再次手动将图像重命名为.gif。
  4. 问题:

    在查看Paint中的图像时,它们看起来非常好,当我在RGB BufferedImage中绘制时,它们突然都有一个白色/灰色~1px边框,而不是背景颜色,图像直接放在彼此旁边。由于我对这些图像进行了整体拼接,因此白色边框是不可取的。

    图片32x32:enter image description here

    升级后的图像48x48:enter image description here

    以4个具有白色边框的地球图像的屏幕截图:enter image description here

    问题:

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

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

请注意,如果您选择使用自己的缩放方法,请查看The Perils of Image.getScaledInstance()以获取更多优化解决方案。

enter image description here

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我通过电子邮件发送了该工具的开发人员Hawkynt,似乎错误不在工具中,而是在Microsofts实现中并且他修复了它(实际上甚至更大的工具,如Multiple Image Resizer .NET都有问题)。这就是他对他的计划所说的话:

“当您手动输入宽度和/或高度时,图像会根据所选算法调整大小,一切都很顺利。

之后我使用了GDI +的resample命令,该命令实现了Microsoft版本的bicubic resize算法。 这种实现方式存在缺陷,因此它在左侧和上侧生成一个像素,用于300px以下的图像。

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