Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AffineTransform truncates image, what do I wrong?

I have here an black/white png file of the dimensions 2156x1728 which I want to rotate 90 degrees using AffineTransform. The resulting image doesn't have the right proportions. Here some example code (given I have successfully loaded the png file into the BufferedImage ):

public BufferedImage transform(BufferedImage image){

    System.out.println("Input width: "+ image.getWidth());
    System.out.println("Input height: "+ image.getHeight());

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(1, image.getWidth() / 2, image.getHeight() / 2);

    AffineTransformOp opRotated = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
    BufferedImage transformedImage = opRotated.createCompatibleDestImage(image, image.getColorModel());
    System.out.println("Resulting width: "+ transformedImage.getWidth());
    System.out.println("Resulting height: "+ transformedImage.getHeight());

    transformedImage = opRotated.filter(image, transformedImage);
    return transformedImage;
}

The output is accordingly:

Input width: 2156

Input height: 1728

Resulting width: 1942

Resulting height: 1942

How comes that the rotation returns such completely unrelated dimensions?

like image 209
Kai Avatar asked Jun 04 '26 20:06

Kai


1 Answers

I'm not a pro at this, but why not just create a BufferedImage of the correct size? Also note that your center of revolution is incorrect. You will need to rotate over a center of [w/2, w/2] or [h/2, h/2] (w being width and h being height) depending on which quadrant you're rotating to, 1 or 3, and the relative height and width of the image. For instance:

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
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;

public class RotateImage {
   public static final String IMAGE_PATH = "http://duke.kenai.com/"
         + "models/Duke3DprogressionSmall.jpg";

   public static void main(String[] args) {
      try {
         URL imageUrl = new URL(IMAGE_PATH);
         BufferedImage img0 = ImageIO.read(imageUrl);
         ImageIcon icon0 = new ImageIcon(img0);

         int numquadrants = 1;
         BufferedImage img1 = transform(img0, numquadrants );
         ImageIcon icon1 = new ImageIcon(img1);

         JOptionPane.showMessageDialog(null, new JLabel(icon0));
         JOptionPane.showMessageDialog(null, new JLabel(icon1));

      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   public static BufferedImage transform(BufferedImage image, int numquadrants) {
      int w0 = image.getWidth();
      int h0 = image.getHeight();
      int w1 = w0;
      int h1 = h0;

      int centerX = w0 / 2;
      int centerY = h0 / 2;

      if (numquadrants % 2 == 1) {
         w1 = h0;
         h1 = w0;
      }

      if (numquadrants % 4 == 1) {
         if (w0 > h0) {
            centerX = h0 / 2;
            centerY = h0 / 2;
         } else if (h0 > w0) {
            centerX = w0 / 2;
            centerY = w0 / 2;
         }
         // if h0 == w0, then use default
      } else if (numquadrants % 4 == 3) {
         if (w0 > h0) {
            centerX = w0 / 2;
            centerY = w0 / 2;
         } else if (h0 > w0) {
            centerX = h0 / 2;
            centerY = h0 / 2;
         }
         // if h0 == w0, then use default
      }

      AffineTransform affineTransform = new AffineTransform();
      affineTransform.setToQuadrantRotation(numquadrants, centerX, centerY);

      AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);

      BufferedImage transformedImage = new BufferedImage(w1, h1,
            image.getType());

      transformedImage = opRotated.filter(image, transformedImage);
      return transformedImage;
   }
}

Edit 1
You asked:

can you explain to me why it must be [w/2, w/2] or [h/2, h/2] ?

To explain this best, it's best to visualize and physically manipulate a rectangle:

Cut out rectangular piece of paper and place it on a piece of paper such that its upper left corner is on the upper left corner of the piece of paper -- that's your image on the screen. Now check to see where you would need to rotate that rectangle 1 or 3 quadrants so that its new upper left corner is overlying that of the paper, and you'll see why you need to use [w/2, w/2] or [h/2, h/2].

like image 196
Hovercraft Full Of Eels Avatar answered Jun 06 '26 10:06

Hovercraft Full Of Eels



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!