2

I'm trying to rotate an image, but it's getting slightly messed up when I'm rotating it, and it looks like it's not rotating it on center. So if I go around it looks like it's being truncated. Is there a better method to get the "center" of the image?

public void RotateImageLeft() {
    try {
        BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), originalImage.getType());
        AffineTransform tx = new AffineTransform();
        tx.rotate(Math.toRadians(-90.0), originalImage.getWidth() / 2, originalImage.getHeight() / 2);



        Graphics2D g2 = newImage.createGraphics();
        g2.drawImage(originalImage, tx, null);

        originalImage = newImage;


        this.repaint();

        g2.dispose();
    } catch (Exception ex) {
        ex.toString();
    }


    //g2d.drawImage(getResImage(), rescale, x, y);


}

For full code disclosure, here's more code. Here's my painComponent overridden method:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    resizeImage();

    Graphics2D g2d = (Graphics2D) g;
    g2d.drawImage(getResImage(), rescale, x, y);


}

Here's the resizeImage() method that gets called:

public void resizeImage() {
    Graphics g = getResImage().getGraphics();
    g.setColor(Color.WHITE);

    g.fillRect(0, 0, getResImage().getWidth(), getResImage().getHeight());
    int scaledWidth = (int) ((getOriginalImage().getWidth() * getHeight()
            / getOriginalImage().getHeight()));
    if (scaledWidth < getWidth()) {
        int leftOffset = getWidth() / 2 - scaledWidth / 2;
        int rightOffset = getWidth() / 2 + scaledWidth / 2;

        g.drawImage(getOriginalImage(),
                leftOffset, 0, rightOffset, getHeight(),
                0, 0, getOriginalImage().getWidth(), getOriginalImage().getHeight(),
                null);
    } else {
        int scaledHeight = (getOriginalImage().getHeight() * getWidth())
                / getOriginalImage().getWidth();

        int topOffset = getHeight() / 2 - scaledHeight / 2;
        int bottomOffset = getHeight() / 2 + scaledHeight / 2;

        g.drawImage(getOriginalImage(),
                0, topOffset, getWidth(), bottomOffset,
                0, 0, getOriginalImage().getWidth(), getOriginalImage().getHeight(),
                null);
    }
}

I'm using the ResizeImage method since I want any image to fit correctly on my 720/432 panel.

Here's some example pictures. Pre-rotated enter image description here

Post-rotated:

enter image description here

New code: (new image is the correct height/width of rotated image, still getting black bars. Screens below.

public void RotateImageLeft() {
    try {
        BufferedImage newImage = new BufferedImage( originalImage.getHeight(),originalImage.getWidth(), originalImage.getType());
        AffineTransform tx = new AffineTransform();
        tx.rotate(Math.toRadians(-90.0), newImage.getWidth() / 2, (newImage.getHeight() / 2));
        Graphics2D g2 = newImage.createGraphics();
        g2.drawImage(originalImage, tx, null);
        originalImage = newImage;
        this.repaint();
        g2.dispose();
    } catch (Exception ex) {
        ex.toString();
    }
}

Post rotate: enter image description here

kevingreen
  • 1,541
  • 2
  • 18
  • 40
  • I think I got it, I'm just an idiot. – kevingreen Mar 19 '12 at 19:46
  • 1
    Width/Height typo, just to confirm? These kinds of mistakes happen all the time :p – Thomas Mar 19 '12 at 19:50
  • yeah, I just noticed that. When I fixed it, it still adds this black bars to the sides, I'm not sure why. It's not truncating anything, it's just making the picture look smaller . – kevingreen Mar 19 '12 at 19:51
  • 1
    [plus one for self criticism](http://stackoverflow.com/a/6993818/714968) – mKorbel Mar 19 '12 at 19:53
  • is it because the newimage is being created with the same width/height as the originalImage? I did a flip on those values (since it's being rotated). But that caused even more issues. – kevingreen Mar 19 '12 at 20:18
  • You fixed it now but I assumed the fact that you created the image with dimensions (Width, Width) instead of (Width, Height) was the issue. Adding an answer now... – Thomas Mar 19 '12 at 20:23
  • @Thomas yeah, I edited to correct for that. But the pictures are what I'm still seeing. – kevingreen Mar 19 '12 at 20:31

2 Answers2

3

From my answer to another similar question

If you're rotating then this will work for 90 degrees.

  • move image so centered "around" the origin
  • plain rotate() call with no extra parameters
  • Move image back into the center remembering that now width = old height and height = old width.

Also remember the affine transform steps work in reverse order.

AffineTransform tx = new AffineTransform();

// last, width = height and height = width
tx.translate(originalImage.getHeight() / 2,originalImage.getWidth() / 2);
tx.rotate(Math.PI / 2);
// first - center image at the origin so rotate works OK
tx.translate(-originalImage.getWidth() / 2,-originalImage.getHeight() / 2);
Community
  • 1
  • 1
Adam
  • 35,919
  • 9
  • 100
  • 137
  • That cow pic is a Google image search result. All out cow pics are at the correct size/aspect ratio. This new program will be for ones that aren't, so Google had to fill in since I'm too lazy to go manually photograph a cow. – kevingreen Mar 19 '12 at 20:56
1

If you want to rotate an image without cropping you need to add black bars around it first, since a rotated rectangle will always have a bigger bounding box than an axis-aligned one (exception: rotating a square by multiples of 90 degrees).

So what you want to do is do some trigonometric calculations beforehand to decide the maximum Width/Height of the rotated image, and combine that with the original Width/Height. Resize your image (centering it) using those dimensions, rotate it, and then crop it back to the Width/Height of the rotated image.

Thomas
  • 3,321
  • 1
  • 21
  • 44
  • I'm only going 90º, do I still need to add the black bars? – kevingreen Mar 19 '12 at 20:28
  • I still think it's something to do with the rotation not being completely centered. – kevingreen Mar 19 '12 at 20:39
  • Yes you still need to. If you go for 90 degree rotations, an image of dimensions (w, h) will become an image of dimensions (h, w). If you don't add some space around the image, it will be cropped and you will only get an effective image of (min(w, h), min(w, h)), i.e. a square with black borders either on the sides or on the top/bottom (which is what your images show). – Thomas Mar 19 '12 at 20:43
  • Right, but even if I create the new image as the rotated version of the old, it still creates black borders. I'll edit my question to show what I mean… – kevingreen Mar 19 '12 at 20:45
  • Now that looks like it isn't centered properly. Seems like the image is translated to the top-left of the image slightly, otherwise it would fit the dimensions properly. Strange, I'll think about it. – Thomas Mar 19 '12 at 20:51