Revolve image around center (blurry and not exactly at center)

46 Views Asked by At

I'm trying to revolve a BufferedImage around its center. Here's my Code:

frame = new JFrame();
GridBagLayout gLayout = new GridBagLayout();
frame.getContentPane().setLayout(gLayout);

lbIm1 = new JLabel(new ImageIcon(img));
lbIm1.setPreferredSize(new Dimension(800, 800));
Timer timer = new Timer(100, e -> {
        AffineTransform transform = new AffineTransform();
        transform.translate(img.getWidth()/2, img.getHeight()/2);
        transform.rotate(Math.toRadians(1), 0, 0);
        transform.translate(-img.getWidth()/2, -img.getHeight()/2);
        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage rotatedImage = op.createCompatibleDestImage(img, img.getColorModel());
        op.filter(img, rotatedImage);
        lbIm1.setIcon(new ImageIcon(rotatedImage));
        img = rotatedImage;
        lbIm1.repaint();
});
timer.start();

c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
frame.getContentPane().add(lbIm1, c);

frame.pack();
frame.setVisible(true);

The image size is 512 x 512. The problem in this code are:

  1. The rotation is not exactly at center. It would rotate out of the screen.
  2. The imagine became blurry over time.

I have searched online for a very long time and nothing seems to help. Any suggestions would be much appreciated. Thanks.

1

There are 1 best solutions below

0
matt On

I would suggestion always rotating form the original image. Keep track of the total rotation.

int angleDegrees = 0;

That way there is less image quality degradation. Normally each time you use a bi-linear interpolation there will be some blurring.

AffineTransform transform = new AffineTransform();
angle += (angle + 1)%360;
transform.rotate(Math.toRad(angle), img.getWidth()/2, img.getHeight()/2);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
BufferedImage rotatedImage = op.createCompatibleDestImage(img, ColorModel.getRGBdefault());
op.filter(img, rotatedImage);
lbIm1.setIcon(new ImageIcon(rotatedImage));
lbIm1.repaint();

Note the icon is changing sizes because the destination image is large enough to hold the whole image. That means the center of the icon will appear to move.

If you create the destination image this way.

BufferedImage rotatedImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);

Then the destination will be cropped, but stay the same size. That way the center of the image doesn't appear to move.

The transform you're using, translate + rotate + translate back, work with this technique to. The 1 degree rotation causes some rounding error in the size of the image. So I wonder if that is why the image "runs away"