Math is fun; why waste it on the computer?
double angle = Math.toRadians(90);
double sin = Math.sin(angle);
double cos = Math.cos(angle);
This is the same as
int sin = 1;
int cos = 0;
So
int xx = (int) (+a * cos - b * sin + x0);
int yy = (int) (+a * sin + b * cos + y0);
simplifies to
int xx = (int) (- b + x0);
int yy = (int) (+a + y0);
which simplifies to
int xx = (int) (y0 + x0) - y;
int yy = x + (int) (y0 - x0);
And you don't need a
or b
at all. But you could precalculate
int sum = (int) (y0 + x0);
int difference = (int) (y0 - x0);
right after you calculate y0
and x0
(i.e. before the loop). Then in the loop, you just need
int xx = sum - y;
int yy = difference + x;
Then you could rewrite
if (xx >= 0 && xx < width && yy >= 0 && yy < height) {
outRaster.setPixel(x, y, inRaster.getPixel(xx, yy, pixel));
}
as
if (sum >= y && sum - width < y && x >= -difference && x < height - difference) {
outRaster.setPixel(x, y, inRaster.getPixel(xx, yy, pixel));
}
But then we can change
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
to
int right = Math.min(width, height - difference);
int bottom = Math.min(height, sum + 1)
for (int x = Math.max(0, -difference); x < right; x++) {
for (int y = Math.max(0, sum - width + 1); y < bottom; y++) {
Now we don't have to check if xx
and yy
fit in the bounds. We only iterate over the pixels where they do. So we can drop the if
and just say
outRaster.setPixel(x, y, inRaster.getPixel(xx, yy, pixel));
TL;DR
private static void rotateImage(BufferedImage pic1) throws IOException {
int width = pic1.getWidth(null);
int height = pic1.getHeight(null);
// point to rotate about center of image
double x0 = 0.5 * (width - 1);
double y0 = 0.5 * (height - 1);
int sum = (int) (y0 + x0);
int difference = (int) (y0 - x0);
WritableRaster inRaster = pic1.getRaster();
BufferedImage pic2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
WritableRaster outRaster = pic2.getRaster();
int[] pixel = new int[3];
// rotation
int right = Math.min(width, height - difference);
int bottom = Math.min(height, sum + 1)
for (int x = Math.max(0, -difference); x < right; x++) {
for (int y = Math.max(0, sum - width + 1); y < bottom; y++) {
int xx = sum - y;
int yy = difference + x;
outRaster.setPixel(x, y, inRaster.getPixel(xx, yy, pixel));
}
}
ImageIO.write(pic2, "bmp", new File("Images/Output2.bmp"));
}
I also changed the spelling to rotateImage
.
Now the only math done inside the loops is incrementing the index variables and simple integer subtraction and addition.
And we only increment over pixels that we're copying.
It's odd to take an image as input and then write a different image to a file. Why not return the image instead? Then the caller can save it.
Consider if you can make inRaster
a Raster
instead. I don't think that it needs to be writable, just outRaster
.