1

I'm creating a domino game in java. I have the following code that loads, resizes and then display the domino image on the screen:

ImageIcon imageIcon = new ImageIcon("images\\4-4.png");
Image image = imageIcon.getImage(); 
Image newimg = image.getScaledInstance(60, 120,  java.awt.Image.SCALE_SMOOTH);  
imageIcon = new ImageIcon(newimg);

JLabel img = new JLabel(imageIcon);
img.setBounds(100, 100, 60, 120);
getContentPane().add(img);

What I want to do is rotate the image either 90 or -90 degrees. I've searched the internet but the examples I've found seems very complicated.

Any idea how I can rotate my image?

Btw, if you think that this is not the correct way to display dominoes in a domino game then please let me know. I'me a java newbie.

camickr
  • 321,443
  • 19
  • 166
  • 288
Farliesz
  • 43
  • 1
  • 3
  • *"..but the examples I've found seems very complicated."* Link to the three easiest examples you found. It's pointless anyone attempting to answer this until we can gauge what you deem to be 'complicated'. – Andrew Thompson Jun 16 '18 at 00:24
  • *"if you think that this is not the correct way to display dominoes in a domino game then please let me know"* The Unicode charset includes dominoes. If not using them, I'd tend to scale and rotate the tiles before they ever get to the app. – Andrew Thompson Jun 16 '18 at 00:28
  • "*I've searched the internet but the examples I've found seems very complicated."* - Why do you think that any solution we would provide won't be "complicated"? Rotating an image (and enlarging the image to fit) is going to require some trig, which is always complicated (to me) – MadProgrammer Jun 16 '18 at 00:31
  • 1
    `I've searched the internet but the examples I've found seems very complicated.` - How about using the [Rotated Icon](https://tips4java.wordpress.com/2009/04/06/rotated-icon/). Its a reusable class and you just choose the angle of rotation in a single line of code. – camickr Jun 16 '18 at 14:11
  • if the number of image is known at the origin why not require all rotation image in your ressources? rotate an image is an heavy/long) operation ... – Arnault Le Prévost-Corvellec Jun 16 '18 at 14:17

2 Answers2

5

Rotating an image is non-trival, even just 90 degrees requires a certain amount of work.

So, based on pretty much every other question about rotating images, I'd start with something like...

public BufferedImage rotate(BufferedImage image, Double degrees) {
    // Calculate the new size of the image based on the angle of rotaion
    double radians = Math.toRadians(degrees);
    double sin = Math.abs(Math.sin(radians));
    double cos = Math.abs(Math.cos(radians));
    int newWidth = (int) Math.round(image.getWidth() * cos + image.getHeight() * sin);
    int newHeight = (int) Math.round(image.getWidth() * sin + image.getHeight() * cos);

    // Create a new image
    BufferedImage rotate = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = rotate.createGraphics();
    // Calculate the "anchor" point around which the image will be rotated
    int x = (newWidth - image.getWidth()) / 2;
    int y = (newHeight - image.getHeight()) / 2;
    // Transform the origin point around the anchor point
    AffineTransform at = new AffineTransform();
    at.setToRotation(radians, x + (image.getWidth() / 2), y + (image.getHeight() / 2));
    at.translate(x, y);
    g2d.setTransform(at);
    // Paint the originl image
    g2d.drawImage(image, 0, 0, null);
    g2d.dispose();
    return rotate;
}

While you're only rotate 90 degrees, this takes care of calculating the required size the new image needs in order to be able to paint the rotated image, at any angle.

It then simply makes use of AffineTransform to manipulate the origin point from which painting occurs - get use to this, you will do it a lot.

Then, I load the images, rotate them and display them...

Rotated

try {
    BufferedImage original = ImageIO.read(getClass().getResource("domino.jpg"));
    BufferedImage rotated90 = rotate(original, 90.0d);
    BufferedImage rotatedMinus90 = rotate(original, -90.0d);

    JPanel panel = new JPanel();
    panel.add(new JLabel(new ImageIcon(original)));
    panel.add(new JLabel(new ImageIcon(rotated90)));
    panel.add(new JLabel(new ImageIcon(rotatedMinus90)));

    JOptionPane.showMessageDialog(null, panel, null, JOptionPane.PLAIN_MESSAGE, null);
} catch (IOException ex) {
    ex.printStackTrace();
}

I prefer to use ImageIO to load images, because it throws an IOException when something goes wrong, rather then failing silently like ImageIcon.

You should also be embedding your resources within your application's context, this makes it easier to load them at runtime. Depending on IDE and how your project is set up, how you do this will change, but in "most" cases, you should be able to add the resource directly to your source directory (preferably in sub directory) and the IDE will make it available for you and package it when you export the project

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thanks. I changed some small details but your solution works! – Farliesz Jun 16 '18 at 11:58
  • `AffineTransform` has a rotation method so you don't have to fiddle with trigonometry. Java has a `AffineTransformOp` so you don't have to fiddle with images and graphics yourself altough there are reports that you lose control over the quality (with a `Graphics2D` you can control all quality parameters yourself). – Mark Jeronimus Jun 18 '18 at 15:26
  • @MarkJeronimus Yes, and I used it all - the trig is used to calculate the resulting size of the new image. Sure, you could do this kind of thing in a paint pass, but compounding transformations get messy, besides, the question, as I read it, was how to take an existing image and rotate it, creating a new one – MadProgrammer Jun 18 '18 at 19:33
  • @MarkJeronimus So, I was mucking around with your solution (because it's always nice to find better way of doing something) and I had an image of `600x315` that I was rotating 90 degrees, which, when using your solution game a result of `457x457` instead of `315x600`. If I use a different rotation (say 45 degrees), it still returns an incorrect result and truncates the image – MadProgrammer Jun 18 '18 at 21:56
0

Solution from: http://www.java2s.com/Code/Java/Advanced-Graphics/RotatingaBufferedImage.htm

AffineTransform tx = new AffineTransform();
tx.rotate(0.5, bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2);

AffineTransformOp op = new AffineTransformOp(tx,
    AffineTransformOp.TYPE_BILINEAR);
bufferedImage = op.filter(bufferedImage, null);
Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50