views:

277

answers:

3

Hi,

I'll like to know if there is a way to create a ImageIcon that is the mirror of another ImageIcon.

Searching on Google, I found how to do it by using many AWT libraries.

Is there a way to do it with Swing ? If not, I'm still having troubles with the AWT method :

The ImageIcon I want to mirror is a animated gif (with contain a transparent color) and the AWT method returns a non-transparent (the transparent color is changed to opaque black) and non-animated gif.

Any ideas how to keep the animation and the transparent color?

Here is the AWT code I found (rangerStand being the original ImageIcon) :

 Image reversed = rangerStand.getImage();
 BufferedImage bufferedImage = new BufferedImage(reversed.getWidth(null), reversed.getHeight(null), BufferedImage.TYPE_INT_RGB);
 Graphics gb = bufferedImage.getGraphics();
 gb.drawImage(reversed, 0, 0, null);
 gb.dispose();

 AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
 tx.translate(-reversed.getWidth(null), 0);
 AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
 bufferedImage = op.filter(bufferedImage, null);
 ImageIcon lol = new ImageIcon(bufferedImage);
 this.sprite.setIcon(lol);

Thanks for reading.

A: 

No idea on how to solve the problem with native Swing or AWT - although Java supports GIF89a with transparency and animation. I guess, you have to unpack the GIF89a, mirror the animation images one-by-one and repack. There's at least one library that you could give a try: gif4j light

Andreas_D
+5  A: 

You might want to try and subclassing the ImageIcon class and paint the image reversed. Try this piece of code, it might do the trick (i haven't tried with animated transparent gif but it should work):

EDIT: I slightly changed the code and tested it with an animated gif. It works!

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


/**
 * @author Savvas Dalkitsis
 */
public class Test {

    public static void main(String[] args) {
     JFrame f = new JFrame("Test");
     JLabel l = new JLabel();
     ImageIcon io = new MirrorImageIcon("test.gif");
     l.setIcon(io);
     f.getContentPane().add(l);
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     f.pack();
     f.setVisible(true);
    }

}

@SuppressWarnings("serial")
class MirrorImageIcon extends ImageIcon {

    public MirrorImageIcon(String filename) {
     super(filename);
    }

    @Override
    public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
     Graphics2D g2 = (Graphics2D)g.create();
     g2.translate(getIconWidth(), 0);
     g2.scale(-1, 1);
     super.paintIcon(c, g2, x, y);
    }

}
Savvas Dalkitsis
+1 for the original way to solve this problem
Martijn Courteaux
'ImageIcon lolimg = new MirrorImageIcon("Images/Sprites/Ranger/stand.gif"); JLabel lolabel = new JLabel(lolimg); lolabel.setBounds(16,0, 16, 16); panel.add(lolabel);'panel = getContentPane() of my JApplet. The JLabel is empty. What am I doing wrong ?
Cheshire
hm... i don't really know... try without setting the bounds manually and using a layout manager. Maybe that will work. Did you try my code as-is? Try it using the image "Images/Sprites/Ranger/stand.gif" and if that doesn't work as well something else is wrong...
Savvas Dalkitsis
when you say "panel = getContentPane() " are you assigning the content pane of your panel to your reference "panel"? Because you should be doing it the other way around. try setContentPane(panel)
Savvas Dalkitsis
I just added the class MirrorImageIcon. I can use the image with the normal ImageIcon method. The image doesn't appear with a layout manager either.
Cheshire
No, sorry, my mistake : panel is a JLayeredPane() added to the getContentPane() and I add every of my components to it.
Cheshire
and did my code work on it's own? try copy - paste my code on it's own file and compile it. see if it works.
Savvas Dalkitsis
Ok, got it to work : I was using a Java.net.URL instead of a String for the filename. >.<Thank you very much for your solution.
Cheshire
Btw you can override all the default ImageIcon constructors and simply delegate to them from MirrorImageIcon so you can use the URL as well...
Savvas Dalkitsis
Nice. Didn't think this was applicable to animated gifs.
Thorbjørn Ravn Andersen
A: 

First of all, the image support in Swing is based on AWT, so "doing it with Swing" does not make much sense.

Except for that, you have two problems: Keeping the transparency and keeping the animation. The first issue is simple to solve. With BufferedImage.TYPE_INT_RGB, you are creating a new BufferedImage without an alpha channel (transparency information). If you change the type to BufferedImage.TYPE_INT_ARGB, that issue should be fixed.

The animation bit is quite a bit harder. An Image or a BufferedImage does not really support animation, but using an animated GIF as a source and displaying the Image in a GUI component causes a kind of non-disclosed interaction between the image and the GUI component, causing the animation to be shown. The way you copy the original image to a BufferedImage will probably cause the single frame, which is currently displayed to be copied into the BufferedImage. It's more than two lines of code, but you can use the ImageReader in javax.imageio to read each single frame of the animated GIF and ImageWriter to create a new animated GIF from the mirrored images.

jarnbjo