Create a ImageIcon that is the mirror of another o

2019-08-01 02:07发布

问题:

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.

回答1:

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);
    }

}


回答2:

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



回答3:

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.