Java 高分辨率二维低分辨率图像

Java 高分辨率二维低分辨率图像,java,swing,jframe,image-resizing,Java,Swing,Jframe,Image Resizing,我正在使用XBR4x算法的程序将旧2D游戏中的.gif图像从32x32放大到48x48 具体程序如下: 手动将所有图像重命名为.jpeg,因为程序无法打开.gif 调整图像大小后,程序将其保存为.bmp 再次手动将图像重命名为.gif 问题是: 当在绘画中查看图像时,它们看起来非常好,当在我的RGB BuffereImage中绘制时,它们突然都有一个白色/灰色~1px边框,而不是背景色,图像直接相邻放置。因为我有一个完整的马赛克的图像,白色的边界是不可能的 图32x32: 放大后的图像48x48

我正在使用XBR4x算法的程序将旧2D游戏中的.gif图像从32x32放大到48x48

具体程序如下:

  • 手动将所有图像重命名为.jpeg,因为程序无法打开.gif
  • 调整图像大小后,程序将其保存为.bmp
  • 再次手动将图像重命名为.gif
  • 问题是:

    当在绘画中查看图像时,它们看起来非常好,当在我的RGB BuffereImage中绘制时,它们突然都有一个白色/灰色~1px边框,而不是背景色,图像直接相邻放置。因为我有一个完整的马赛克的图像,白色的边界是不可能的

    图32x32:

    放大后的图像48x48:

    带有白色边框的4幅地球图像的Ingame屏幕截图:

    问题是:


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

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

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

    边界是由所述工具执行的缩放过程的结果。考虑这个演示,显示基于问题的缩放图像和使用. 请注意,如果您选择使用自己的缩放方法,请查看更多优化的解决方案

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

    导入java.awt.Graphics;
    导入java.awt.GraphicsEnvironment;
    导入java.awt.Image;
    导入java.awt.Transparency;
    导入java.awt.image.buffereImage;
    导入java.net.URL;
    导入javax.imageio.imageio;
    导入javax.swing.ImageIcon;
    导入javax.swing.JLabel;
    导入javax.swing.JOptionPane;
    导入javax.swing.JPanel;
    公营班级测验量表{
    公共静态void main(字符串[]args){
    试一试{
    BuffereImage original=ImageIO.read(新URL(
    "http://i.stack.imgur.com/rY2i8.gif"));
    图像缩放=原始.getScaledInstance(48,48,,
    图像。比例\面积\平均值);
    BuffereImage ScaleDP=ImageIO.read(新URL(
    "http://i.stack.imgur.com/Argxi.png"));
    BuffereImage tilesOP=buildTiles(缩放贴图,3,3);
    BuffereImage tiles=buildTiles(按比例,3,3);
    JPanel面板=新的JPanel();
    添加(新JLabel(新图像图标(tilesOP));
    添加(新JLabel(新图像图标(瓷砖));
    JOptionPane.showMessageDialog(空,面板,
    “平铺:OP vs getScaledInstance”,
    JOptionPane.INFORMATION(信息和消息);
    }捕获(例外e){
    showMessageDialog(null,例如getMessage(),“失败”,
    JOptionPane.ERROR\u消息);
    e、 printStackTrace();
    }
    }
    静态缓冲区图像构建分幅(图像分幅、整数行、整数列){
    int-width=tile.getWidth(null);
    int height=tile.getHeight(null);
    BuffereImage dest=图形环境
    .getLocalGraphicsEnvironment()
    .getDefaultScreenDevice()
    .getDefaultConfiguration()
    .createCompatibleImage(宽*行,高*列,
    透明(半透明);
    Graphics g=dest.getGraphics();
    对于(int row=0;row
    我给Hawkynt发了电子邮件,Hawkynt是该工具的开发人员,错误似乎不在工具中,而是在微软的实现中,他解决了这个问题(实际上,甚至更大的工具,如Multiple Image Resizer.NET,都有这个问题)。这是他对他的计划所说的:

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

    之后,我使用了GDI+中的重采样命令,该命令实现了Microsoft版本的双三次调整大小算法。 这种实现是有缺陷的,因此它在300px以下的图像的左侧和上方产生一个像素


    我只需将调整大小的图像比所需的大一个像素,并将其向左和向上移动一个像素,这样白色边框就不再可见,目标图像就有了预期的尺寸。”

    要更快地获得更好的帮助,请发布一篇文章,你是重命名图像还是转换图像?如果你在问题中附上了调整大小前后的样本图像,那也很好。综上所述,问题最有可能是因为像xBr或hqx这样的算法只能放大x2、x3等,而不能放大x1、5。因此,该程序似乎对图像进行了一些预调整,从而产生了那些白色边框。为什么不使用图形“编辑器”(如Gimp(大,但免费)来调整图像的大小呢?因为Gimp和其他类似的程序只有丑陋且非常基本的放大算法。我所知道的最好的是,可惜还没有公开。虽然xBR离它很近,所以我想使用它。原始图像没有Alpha通道,但我只看到了输出图像