Usually when you try to flip an image like this using a scale transform, you will have to translate it as well. Think of a single image being flipped horizontally. When this happens, the flip occurs about the y axis, and so the image which used to go from 0 to the image's width now goes from 0 to the negative of the image's width. To correct for this, you would need to translate the image over. For example, my slightly larger than an sscce code:
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FlipViaTransform {
private static final String SPRITE_SHEET_SPEC = "http://www.funorb.com/img/images/game/"
+ "central/dev_diary/sprite_sheet_full.gif";
private static final int TIMER_DELAY = 200;
private static final int SPRITE_ROWS = 8; // an 8 x 8 sprite sheet
public static void main(String[] args) {
try {
URL spriteSheetUrl = new URL(SPRITE_SHEET_SPEC);
BufferedImage spriteSheet = ImageIO.read(spriteSheetUrl);
final ImageIcon[] iconsA = new ImageIcon[64];
final ImageIcon[] iconsB = new ImageIcon[64];
double wD = (double) spriteSheet.getWidth() / SPRITE_ROWS;
double hD = (double) spriteSheet.getHeight() / SPRITE_ROWS;
int w = (int) wD;
int h = (int) hD;
AffineTransform at = AffineTransform.getScaleInstance(-1, 1);
at.translate(-wD, 0); // *********** the key is here!!! ***********
for (int i = 0; i < SPRITE_ROWS; i++) {
for (int j = 0; j < SPRITE_ROWS; j++) {
int x = (int) (i * wD);
int y = (int) (j * hD);
BufferedImage imgA = spriteSheet.getSubimage(x, y, w, h);
BufferedImage imgB = new BufferedImage(imgA.getWidth(),
imgA.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = imgB.createGraphics();
g2.setTransform(at);
g2.drawImage(imgA, 0, 0, null);
g2.dispose();
iconsA[j * SPRITE_ROWS + i] = new ImageIcon(imgA);
iconsB[j * SPRITE_ROWS + i] = new ImageIcon(imgB);
}
}
final JLabel labelA = new JLabel("Image");
final JLabel labelB = new JLabel("Mirror Image");
labelA.setVerticalTextPosition(JLabel.BOTTOM);
labelB.setVerticalTextPosition(JLabel.BOTTOM);
labelA.setHorizontalTextPosition(JLabel.CENTER);
labelB.setHorizontalTextPosition(JLabel.CENTER);
labelA.setIcon(iconsA[0]);
labelB.setIcon(iconsB[0]);
final JPanel panel = new JPanel(new GridLayout(1, 0));
panel.add(labelA);
panel.add(labelB);
Timer spriteTimer = new Timer(TIMER_DELAY, new ActionListener() {
int spriteIndex = 0;
@Override
public void actionPerformed(ActionEvent arg0) {
labelA.setIcon(iconsA[spriteIndex]);
labelB.setIcon(iconsB[spriteIndex]);
spriteIndex++;
spriteIndex %= iconsA.length;
}
});
spriteTimer.start();
JOptionPane.showMessageDialog(null, panel, "AffineTransform Example", JOptionPane.PLAIN_MESSAGE);
spriteTimer.stop();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The key bit of code is the second line below:
AffineTransform at = AffineTransform.getScaleInstance(-1, 1);
at.translate(-wD, 0); // *********** the key is here!!! ***********