package net.pms.image.thumbnailator;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import net.coobird.thumbnailator.builders.BufferedImageBuilder;
import net.coobird.thumbnailator.filters.ImageFilter;
/**
* This class is a bugfix of {@link net.coobird.thumbnailator.filters.Rotation}.
*
* When the original class <a
* href="https://github.com/coobird/thumbnailator/pull/92">is fixed</a>, this
* class can be removed.
*/
public class Rotation
{
/**
* This class is not intended to be instantiated.
*/
private Rotation() {}
/**
* An {@link ImageFilter} which applies a rotation to an image.
* <p>
* An instance of a {@link Rotator} can be obtained through the
* {@link Rotation#newRotator(double)} method.
*
* @author coobird
*
*/
public abstract static class Rotator implements ImageFilter
{
/**
* This class is not intended to be instantiated.
*/
private Rotator() {}
}
/**
* Creates a new instance of {@code Rotator} which rotates an image at
* the specified angle.
* <p>
* When the {@link Rotator} returned by this method is applied, the image
* will be rotated clockwise by the specified angle.
*
* @param angle The angle at which the instance of {@code Rotator}
* is to rotate a image it acts upon.
* @return An instance of {@code Rotator} which will rotate
* a given image.
*/
public static Rotator newRotator(final double angle)
{
Rotator r = new Rotator() {
private double[] calculatePosition(double x, double y, double angle)
{
angle = Math.toRadians(angle);
double nx = (Math.cos(angle) * x) - (Math.sin(angle) * y);
double ny = (Math.sin(angle) * x) + (Math.cos(angle) * y);
return new double[] {nx, ny};
}
public BufferedImage apply(BufferedImage img)
{
int width = img.getWidth();
int height = img.getHeight();
BufferedImage newImage;
double[][] newPositions = new double[4][];
newPositions[0] = calculatePosition(0, 0, angle);
newPositions[1] = calculatePosition(width, 0, angle);
newPositions[2] = calculatePosition(0, height, angle);
newPositions[3] = calculatePosition(width, height, angle);
double minX = Math.min(
Math.min(newPositions[0][0], newPositions[1][0]),
Math.min(newPositions[2][0], newPositions[3][0])
);
double maxX = Math.max(
Math.max(newPositions[0][0], newPositions[1][0]),
Math.max(newPositions[2][0], newPositions[3][0])
);
double minY = Math.min(
Math.min(newPositions[0][1], newPositions[1][1]),
Math.min(newPositions[2][1], newPositions[3][1])
);
double maxY = Math.max(
Math.max(newPositions[0][1], newPositions[1][1]),
Math.max(newPositions[2][1], newPositions[3][1])
);
int newWidth = (int)Math.round(maxX - minX);
int newHeight = (int)Math.round(maxY - minY);
newImage = new BufferedImageBuilder(newWidth, newHeight, img.getType()).build();
Graphics2D g = newImage.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR
);
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
double w = newWidth / 2.0;
double h = newHeight / 2.0;
g.rotate(Math.toRadians(angle), w, h);
int centerX = (int)Math.round((newWidth - width) / 2.0);
int centerY = (int)Math.round((newHeight - height) / 2.0);
g.drawImage(img, centerX, centerY, null);
g.dispose();
return newImage;
}
};
return r;
}
/**
* A {@code Rotator} which will rotate a specified image to the left 90
* degrees.
*/
public static final Rotator LEFT_90_DEGREES = newRotator(-90);
/**
* A {@code Rotator} which will rotate a specified image to the right 90
* degrees.
*/
public static final Rotator RIGHT_90_DEGREES = newRotator(90);
/**
* A {@code Rotator} which will rotate a specified image to the 180 degrees.
*/
public static final Rotator ROTATE_180_DEGREES = newRotator(180);
}