【问题标题】:Bad PNG rendering (low color depth) in Java SwingJava Swing 中的错误 PNG 渲染(低颜色深度)
【发布时间】:2013-01-04 01:50:37
【问题描述】:

我目前正在使用 Swing 在 Java 中设计吃豆人。我有使用以下语句在屏幕上绘制的 PNG 图像。

wall = new ImageIcon(GamePanel.class.getResource("wall.png")).getImage();
g2d.drawImage(wall, x, y, this);

我遇到的问题是它似乎渲染了实际文件的非常低的颜色深度再现。看起来它确实保留了透明度(灰色背景是 Panel bg 颜色),但它失去了颜色深度。

实际图像是这样的: 运行时是这样的:

有人有解决办法吗?谢谢!

【问题讨论】:

    标签: java image swing png


    【解决方案1】:

    第二张图片中似乎有问题。在黑色 BG 上看到它,它看起来非常不同 - 没有“光环”。

    import java.awt.*;
    import java.net.URL;
    import javax.swing.*;
    
    public class TestYellowDotImage {
    
        public static JLabel getColoredLabel(Icon icon, Color color) {
            JLabel label = new JLabel(icon);
            label.setBackground(color);
            label.setOpaque(true);
    
            return label;
        }
    
        public static void main(String[] args) throws Exception {
            URL url = new URL("http://i.stack.imgur.com/1EZVZ.png");
            final Icon icon = new ImageIcon(url);
            Runnable r = new Runnable() {
    
                @Override
                public void run() {
                    JPanel gui = new JPanel(new GridLayout(0, 4));
    
                    gui.add(new JLabel(icon));
                    gui.add(getColoredLabel(icon, Color.BLACK));
                    gui.add(getColoredLabel(icon, Color.WHITE));
                    gui.add(getColoredLabel(icon, Color.RED));
    
                    JOptionPane.showMessageDialog(null, gui);
                }
            };
            // Swing GUIs should be created and updated on the EDT
            // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
            SwingUtilities.invokeLater(r);
        }
    }
    

    【讨论】:

    • 尝试使用ImageIO 而不是ImageIcon 加载图像。 ImageIO 在加载期间阻塞,ImageIcon 异步加载。
    • IIUC,ImageIcon(url) 表示“图像将被预加载……”在内部,它使用loadImage(),即“加载图像,仅在图像加载时返回。”
    • @trashgod 呵呵。好吧,我唯一的反对意见是它有时会默默地失败(尽管这里显然不是这种情况)。
    • 啊,我没看到;谢谢。仔细观察,至少有一个实现使用 System.out.println() 处理 InterruptedException
    【解决方案2】:

    g2d上试试这个设置:-

        Map<RenderingHints.Key, Object> map = new HashMap<RenderingHints.Key, Object>();
        map.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        RenderingHints renderHints = new RenderingHints(map);
        g2d.setRenderingHints(renderHints);
    

    【讨论】:

      【解决方案3】:

      使用Grid,您可以将鼠标悬停在像素上以查看 alpha 分量如何在图标边缘滚落。

      public Grid(String name) {
          this.setBackground(new Color(0xFFFFFFC0));
          Icon icon = null;
          try {
              icon = new ImageIcon(new URL("http://i.stack.imgur.com/1EZVZ.png"));
          } catch (MalformedURLException e) {
              e.printStackTrace(System.err);
          }
          ...
      }
      

      IconTest 显示了图标如何以不同的 alpha 和默认的AlphaComposite.SRC_OVER 规则呈现。

      /*** @see https://stackoverflow.com/a/14432025/230513 */
      public class IconTest {
      
          private static final int N = 8;
          private static final Random r = new Random();
      
          public static void main(String[] args) throws MalformedURLException {
              final URL url = new URL("http://i.stack.imgur.com/1EZVZ.png");
              final Icon icon = new ImageIcon(url);
              EventQueue.invokeLater(new Runnable() {
      
                  @Override
                  public void run() {
                      JFrame f = new JFrame("IconTest");
                      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                      JPanel p = new JPanel(new GridLayout(N, N));
                      for (int i = 0; i < N * N; i++) {
                          final JLabel label = new JLabel(icon);
                          label.setOpaque(true);
                          label.setBackground(new Color(0, 0, 255, i));
                          p.add(label);
                      }
                      f.add(p);
                      f.pack();
                      f.setLocationRelativeTo(null);
                      f.setVisible(true);
                  }
              });
          }
      }
      

      【讨论】:

      • 当我在我的机器上运行此代码时,我得到了相同的结果。所以它一定是我以前的代码。我会把它的全部发布出来。
      【解决方案4】:

      解决了。在paint() 方法中使用了repaint()。删除它,它可以工作。

      感谢大家的帮助。

      【讨论】:

      • “已解决。” 恭喜!很高兴你把事情解决了。 :)
      • @user1305850:对不起,如果我坚持的话。 :-) 你的问题中变暗的图像让我想起了重复应用默认AlphaComposite.SRC_OVER 规则的结果,所以你的回答似乎是合理的。 OTOH,你接受别人的回答得两分!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 1970-01-01
      • 2022-12-30
      • 1970-01-01
      相关资源
      最近更新 更多