Rotate an image in java

34,886

Solution 1

You need to be using trigonometry to determine the correct width/height, using transparency to prevent the black area, and I think the Transform is wrong, which is making it off center.

Try this:

public static BufferedImage rotate(BufferedImage image, double angle) {
    double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
    int w = image.getWidth(), h = image.getHeight();
    int neww = (int)Math.floor(w*cos+h*sin), newh = (int) Math.floor(h * cos + w * sin);
    GraphicsConfiguration gc = getDefaultConfiguration();
    BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT);
    Graphics2D g = result.createGraphics();
    g.translate((neww - w) / 2, (newh - h) / 2);
    g.rotate(angle, w / 2, h / 2);
    g.drawRenderedImage(image, null);
    g.dispose();
    return result;
}

private static GraphicsConfiguration getDefaultConfiguration() {
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gd = ge.getDefaultScreenDevice();
    return gd.getDefaultConfiguration();
}

from http://flyingdogz.wordpress.com/2008/02/11/image-rotate-in-java-2-easier-to-use/

Solution 2

You could try using a Rotated Icon.

Solution 3

Based on a previous example, but actually working with recent JDKs and in headless mode:

public static BufferedImage rotate(BufferedImage image, double angle) {
    double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
    int w = image.getWidth(), h = image.getHeight();
    int neww = (int)Math.floor(w*cos+h*sin), newh = (int) Math.floor(h * cos + w * sin);
    BufferedImage result = deepCopy(image, false);
    Graphics2D g = result.createGraphics();
    g.translate((neww - w) / 2, (newh - h) / 2);
    g.rotate(angle, w / 2, h / 2);
    g.drawRenderedImage(image, null);
    g.dispose();
    return result;
}

public static BufferedImage deepCopy(BufferedImage bi, boolean copyPixels) {
    ColorModel cm = bi.getColorModel();
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
    WritableRaster raster = bi.getRaster().createCompatibleWritableRaster();
    if (copyPixels) {
        bi.copyData(raster);
    }
    return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}    
Share:
34,886
user489041
Author by

user489041

Updated on July 09, 2022

Comments

  • user489041
    user489041 almost 2 years

    I am looking to rotate an image. I have a JInternalFrame which contains a JLabel. The label contains the image. After the image has been rotated, I need to resize the internal frame. The code I have currently rotates the image, but there is black around the edges of the image and it is off centered. Any suggestions on how to fix this?

    public void rotateIcon(int angle)
    {
            int w = theLabel.getIcon().getIconWidth();
            int h = theLabel.getIcon().getIconHeight();
            int type = BufferedImage.TYPE_INT_RGB;  // other options, see api
    
            BufferedImage DaImage = new BufferedImage(h, w, type);
            Graphics2D g2 = DaImage.createGraphics();
    
            double x = (h - w)/2.0;
            double y = (w - h)/2.0;
            AffineTransform at = AffineTransform.getTranslateInstance(x, y);
    
            at.rotate(Math.toRadians(angle), w/2.0, h/2.0);
            g2.drawImage(new ImageIcon(getData()).getImage(), at, theLabel);
            g2.dispose();
    
            theLabel.setIcon(new ImageIcon(DaImage));
            this.setSize(DaImage.getWidth(),DaImage.getHeight()); //resize the frame
    }
    
  • user489041
    user489041 over 13 years
    This is really cool. I am having one issue with it though. My image only needs to rotate 90 degrees. at a time. If I pass in 90 for angle, it will actually rotate more than 90 degrees
  • user489041
    user489041 over 13 years
    Yea, I switched those back and forth, still no success.
  • user489041
    user489041 over 13 years
    Thanks, I am going to have to look into this.
  • Reverend Gonzo
    Reverend Gonzo over 13 years
    This is using radians, so just use Math.toRadians(degree) first.
  • user1050755
    user1050755 almost 5 years
    can we get rid of the screen device dependence?