1

Can't use 100% real code, sorry. A lot of side-functions in other classes, some of them isn't mine.

I'm making a visual novel - just remark about my project, for better undestanding.

I have a JFrame with card layout of JPanels. gameMainPanel are one of them. My target - make a shot of non-visible at shoting moment panel. On one panel is my game drawing, on another I'm making game-savefile with screenshot of moment in game - so game panel isn't visible at that moment. It's working OK, but when I use an animated GIF on my game panel - it's not screenshoting, but every other GUI components do.

I'm loading and resizing an animated GIF with code like this:

ImageIcon imageIcon = new ImageIcon(Engine.getPathString("/resource/character/" + name));
imageIcon.setImage(imageIcon.getImage().getScaledInstance(resizeX, resizeY, Image.SCALE_DEFAULT));
GameWindow.gameCharacterCenter.setIcon(imageIcon); //gameCharacterCenter is a simple JLabel on game panel

Engine.getPathString is a little wrapper, just returns a string with full path to file. Engine.getPathString("/example/dummy.txt") will return something like "C:/Java projects/Folder with that project/example/dummy.txt", regarding full correct path of course.

In one moment I need to make a shot of my game panel, I'm making it like this:

screenshot = new File(String.valueOf(Engine.getPathFile("/saves/" + name + ".jpeg")));
BufferedImage bufImage = new BufferedImage(GameWindow.gameMainPanel.getSize().width, GameWindow.gameMainPanel.getSize().height, BufferedImage.TYPE_INT_RGB);
GameWindow.gameMainPanel.paint(bufImage.createGraphics());
try {
    screenshot.createNewFile();
    ImageIO.write(bufImage, "jpeg", screenshot);
} catch (Exception ex) {
}

And that code is correctly screenshoting my gameMainPanel, with all it's childs - game menu, characters, labels with text... But not the characters if they are animated GIFs. When I'm loading with exact same code a simple *.jpg or *.png - it's capping OK.

Why are JLabel with animated GIF in it isn't visible when I'm painting it parent, but when it's JPG in it - it's paint to BufferedImage as normal?

Can't provide full code of project, sorry. English not my native, so - also - sorry for that too.

Made with PrintScreen button:

https://i.stack.imgur.com/n6EcE.jpg

Made with ingame methods:

https://i.stack.imgur.com/zKlgn.jpg

camickr
  • 321,443
  • 19
  • 166
  • 288
Lemis
  • 15
  • 6
  • 1
    A [mcve] would certainly help here. That said, painting of Swing components is highly optimized, so you may want to try using the [print](https://docs.oracle.com/javase/8/docs/api/javax/swing/JComponent.html#print-java.awt.Graphics-) method instead of paint. – VGR Mar 12 '17 at 04:26
  • Tried a print method instead of paint - same result. Sorry, will add MCV example (in form of self-explanatory program) a bit later, can't do it just right now. – Lemis Mar 12 '17 at 04:29
  • For that MCVE suggested by @VGR, consider using hot linked images from [this Q&A](http://stackoverflow.com/q/19209650/418556). Also try using the `Robot` to get a screen capture of the component of interest. – Andrew Thompson Mar 12 '17 at 04:41
  • 1
    Because it's not realised in the screen yet, it's "possible" that the gif won't be painted (because of the overheads and plumbing of the paint engine). One "possible" solution would be to use ImageIO to load the gif instead of ImageIcon, only do this for the snapshot as it will only load the first frame – MadProgrammer Mar 12 '17 at 04:57
  • MadProgrammer, sounds good! I think I'll use that little cheat for now, it's not hard for processing time and user can't see that cheat when doing a save and autoscreenshot. Sorry, can't mark a comments as an answer. – Lemis Mar 12 '17 at 15:05

1 Answers1

1

So, I put together a quick test, basically, I took a PNG image a animated gif image, I used ImageIO to load both and attempted to save the resulting panel and then I used ImageIcon to load the image and save it

My inputs...

PNG Image

PNG Image

GIF Image

Gif Image

The "code"

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }

                    BufferedImage png = ImageIO.read(...));
                    BufferedImage gif = ImageIO.read(...);
                    ImageIcon gifImg = new ImageIcon(...);

                    TestPane pngPane = new TestPane(png);
                    TestPane gifPane = new TestPane(gif);
                    TestPane imgPane = new TestPane(gifImg.getImage());

                    save(pngPane, "PNGTest.png");
                    save(gifPane, "gifTest.png");
                    save(imgPane, "imgGifTest.png");

                } catch (IOException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public void save(JPanel pane, String to) throws IOException {
        pane.setSize(pane.getPreferredSize());
        BufferedImage img = new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = img.createGraphics();
        pane.printAll(g2d);
        g2d.dispose();

        ImageIO.write(img, "png", new File(to));
    }

    public class TestPane extends JPanel {

        private Image img;

        public TestPane(Image img) {
            this.img = img;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(img.getWidth(this), img.getHeight(this));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(img, 0, 0, this);
            g2d.dispose();
        }

    }

}

The Results...

PNG Image via ImageIO

PNG Image via <code>ImageIO</code>

GIF Image via ImageIO

GIF Image via <code>ImageIO</code>

GIF Image via ImageIcon

GIF Image via <code>ImageIcon</code>

I don't want to get into the hows and whys of it all, needless to say, ImageIcon does use a background thread to load the image and relies on the ImageObserver support of the component to get it repainted as it's state changes, this is how it gets the animated GIF to update on the screen, so, one might surmise that we're just missing that update notification.

I've not tested it, but you could use a MediaTracker to monitor the ImageIcon's state and wait till it's loaded, but given the simplicity of using ImageIO I'd question whether it's worth it or not.

Cavert

You will need to use ImageIcon if you want the animated gif to play on a live component! So you can only use this "cheat" when generating the preview!

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • You made a great work! But I'm making a shot not when image a loading, but about 1-5-10 second after that, so I don't think what 'MediaTracker' can help me with that. Or you mean use it in somewhere in the middle of screenshot creation, not for "it's loaded, we can start now"? And what's with "Cavert" part? My gifs are working on screen, they are wisible and animated. – Lemis Mar 12 '17 at 15:03
  • Sorry, misreaded all of it. Your answer is correct, It's just me. I'll use that cheat. Marks your answer. – Lemis Mar 12 '17 at 15:09