组合BG为JPEG的图像会导致意外结果

为什么组合BG为JPEG的图像会导致意外结果?

这是我在2个图像的覆盖中无法正常工作的答案的后续行动。 在那里发布的源(使用在内存中创建的BG图像)看起来像这样:

  • BG图像位于左侧。
  • FG图像(具有透明度的PNG)位于中间。
  • 合并后的图像位于右侧。

到现在为止还挺好。 但是那个问这个问题的人评论说,如果BG是JPEG,那就失败了。 认为他们错了,我改变了我的例子,将BG图像编码为JPEG。 现在,如果我使用BufferedImage.TYPE_INT_ARGBBufferedImage.TYPE_INT_RGB作为最终图像,我得到他们所指的:

TYPE_INT_ARGB

使用支持透明度的最终图像组合图像

TYPE_INT_RGB

使用不支持透明度的最终图像组合图像

我期望结果与至少其中一个的结果相同(更多的是ARGB变体)。

 import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.URL; import javax.imageio.ImageIO; class CombineImages { public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { try { URL urlImage1 = new URL("http://i.stack.imgur.com/T5uTa.png"); // Load the FG image Image fgImage = ImageIO.read(urlImage1); int w = fgImage.getWidth(null); int h = fgImage.getHeight(null); // Create a non-trasparent BG image BufferedImage bgImageTemp = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bgImageTemp, "jpg", baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); BufferedImage bgImageJpeg = ImageIO.read(bais); int result = JOptionPane.showConfirmDialog( null, "Use a final image with transparency?", "Transparency", JOptionPane.YES_NO_OPTION); int type = (result==JOptionPane.OK_OPTION ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); // Create the final image BufferedImage finalImage = new BufferedImage(w,h,type); Graphics2D g = finalImage.createGraphics(); g.drawImage(bgImageJpeg, w, h, null); g.drawImage(fgImage, w, h, null); g.dispose(); JPanel gui = new JPanel(new GridLayout(1,0,5,5)); gui.add(new JLabel(new ImageIcon(bgImageJpeg))); gui.add(new JLabel(new ImageIcon(fgImage))); gui.add(new JLabel(new ImageIcon(finalImage))); JOptionPane.showMessageDialog(null, gui); } catch (Exception e) { e.printStackTrace(); } } }; SwingUtilities.invokeLater(r); } } 

看起来这是由于一个错字。

在您引用的答案中 ,形成组合图像的代码是

 Graphics2D g = finalImage.createGraphics(); g.drawImage(bgImage, 0, 0, null); g.drawImage(fgImage, 0, 0, null); 

但在这个问题上,它被改为,

 Graphics2D g = finalImage.createGraphics(); g.drawImage(bgImageJpeg, w, h, null); g.drawImage(fgImage, w, h, null); 

后者开始在“左上角”绘制,这恰好是图像的右下角,所以没有真正绘制出来的。 然而,前者按预期绘制了整个图像。

gui.repaint();

自从你在构造joptionpane时有效地绘制了面板和组件之后尝试了一下,但是,即使这样,因为构造线程匹配的可见性调用不会成立,你应该在joptionpane调用之后在绘制覆盖方法中调用g.drawImage。

它无法绘制屏幕上尚未存在的内容,但是对于调用存在容差,因为它理论上存在于一组足够用于该方法的对象。