Combining images where BG is JPEG produces unexpected results

Why does combining images where BG is JPEG produce unexpected results?

This is a continuation of my answer in Image Overlay 2 not working properly . The source hosted there (using the BG image created in memory) is as follows:

ZTyPM.png

  • The BG image is on the left.
  • The FG image (PNG with transparency) is in the middle.
  • Combined image on the right.

So far so good. But then the person who asked the question noted that if BG was JPEG, he failed. Thinking they were wrong, I changed my example to encode a BG image in JPEG format. Now, if I use BufferedImage.TYPE_INT_ARGB or BufferedImage.TYPE_INT_RGB for the final image, I get what they were talking about:

TYPE_INT_ARGB

Combined image using a final image that supports transparency

TYPE_INT_RGB

Combined image using a final image that does not support transparency

I expected the result to be the same as the original, at least for one of them (moreover, the ARGB variant).

 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); } } 
+6
source share
2 answers

This seems to be due to a typo.

In response, the link to the code that generated the combined image was

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

But in this matter he was changed to

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

The latter begins to draw on the "upper left corner" , which, it turns out, is located in the lower right corner of the image, so nothing has been done. The first, however, paints all the images as expected.

+3
source

gui.repaint ();

Try this after you have effectively drawn the panel and components when building the joptionpane, but even when the stream construction matching the call to visibility does not contain the truth, you should call g.drawImage in the override color method after calling joptionpane.

He cannot draw something that does not yet exist on the screen, however, there is call tolerance because he theoretically exists as a set of objects sufficient for this method.

0
source

Source: https://habr.com/ru/post/950103/


All Articles