Image rotation in java

11

I need an algorithm to rotate an image in java. On the internet I found a promising algorithm in this link , and I gave a tidy up in it and adapted to use angles in degrees. It looks like this:

public static BufferedImage rotateImage(BufferedImage rotateImage, double angle) {
    AffineTransform tx = new AffineTransform();
    tx.rotate(Math.toRadians(angle), rotateImage.getWidth() / 2.0, rotateImage.getHeight() / 2.0);

    double ytrans = tx.transform(new Point2D.Double(0.0, 0.0), null).getY();
    double xtrans = tx.transform(new Point2D.Double(0, rotateImage.getHeight()), null).getX();

    AffineTransform translationTransform = new AffineTransform();
    translationTransform.translate(-xtrans, -ytrans);
    tx.preConcatenate(translationTransform);

    return new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR).filter(rotateImage, null);
}

However, this method does not work correctly for angles greater than 90 degrees (and probably for smaller than -90 too). I solved this with a game that depends on an intermediate image:

public static BufferedImage rotateImage(BufferedImage rotateImage, double angle) {
    angle %= 360;
    if (angle < 0) angle += 360;
    int quadrants = (int) angle / 90;
    double restAngle = angle % 90;
    if (restAngle < 0) restAngle += 90;

    AffineTransform tx = new AffineTransform();
    tx.rotate(Math.toRadians(restAngle), rotateImage.getWidth() / 2.0, rotateImage.getHeight() / 2.0);

    double ytrans = tx.transform(new Point2D.Double(0.0, 0.0), null).getY();
    double xtrans = tx.transform(new Point2D.Double(0, rotateImage.getHeight()), null).getX();

    AffineTransform translationTransform = new AffineTransform();
    translationTransform.translate(-xtrans, -ytrans);
    tx.preConcatenate(translationTransform);

    BufferedImage b2 = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR).filter(rotateImage, null);

    AffineTransform fix = AffineTransform.getQuadrantRotateInstance(
            quadrants, b2.getWidth() / 2.0, b2.getHeight() / 2.0);
    return new AffineTransformOp(fix, AffineTransformOp.TYPE_BILINEAR).filter(b2, null);
}

It worked. However, I know you can solve this without needing an intermediate image. I've already severed my head and I can not make it work better, I've only had images cut and distorted as a result. Anyone have an idea?

Edit: I found a bug: It does not work correctly for images that are not square, and I do not know why.

    
asked by anonymous 02.02.2014 / 06:06

2 answers

8

From what I've tested here, it works:

public static BufferedImage rotateImage(BufferedImage rotateImage, double angle) {
    angle %= 360;
    if (angle < 0) angle += 360;

    AffineTransform tx = new AffineTransform();
    tx.rotate(Math.toRadians(angle), rotateImage.getWidth() / 2.0, rotateImage.getHeight() / 2.0);

    double ytrans = 0;
    double xtrans = 0;
    if( angle <= 90 ){
        xtrans = tx.transform(new Point2D.Double(0, rotateImage.getHeight()), null).getX();
        ytrans = tx.transform(new Point2D.Double(0.0, 0.0), null).getY();
    }
    else if( angle <= 180 ){
        xtrans = tx.transform(new Point2D.Double(rotateImage.getWidth(), rotateImage.getHeight()), null).getX();
        ytrans = tx.transform(new Point2D.Double(0, rotateImage.getHeight()), null).getY();
    }
    else if( angle <= 270 ){
        xtrans = tx.transform(new Point2D.Double(rotateImage.getWidth(), 0), null).getX();
        ytrans = tx.transform(new Point2D.Double(rotateImage.getWidth(), rotateImage.getHeight()), null).getY();
    }
    else{
        xtrans = tx.transform(new Point2D.Double(0, 0), null).getX();
        ytrans = tx.transform(new Point2D.Double(rotateImage.getWidth(), 0), null).getY();
    }

    AffineTransform translationTransform = new AffineTransform();
    translationTransform.translate(-xtrans, -ytrans);
    tx.preConcatenate(translationTransform);

    return new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR).filter(rotateImage, null);
}

Here's an image to help you understand logic:

    
02.02.2014 / 13:24
12

The @RodrigodeBonaSartor answer works perfectly and the big balcony is that the algorithm makes an adjustment considering the corners of the image that are "hidden" after the rotation, in order to prevent the image from being truncated in those regions. >

The graph of Rodrigo's own answer helps a lot in this understanding, but I'll try to explain it in a bit more detail. I will use as an example the following (square) image of Lenna :

Rotationisanoperationthatsimplytransformseachpixeloftheimagebyagivenangle(see

02.02.2014 / 19:07