Issue
I am having trouble writing a function that takes a BufferedImage and a Cardinal Direction and rotates the image accordingly. I have looked on many threads on stack and tried implementing myself while going over the docs for some time now and the best I'm getting is that the image seems to be rotating, however the last pixel is correct and the rest are set white or transparent not sure.
Here is where I have got so far:
private BufferedImage rotateImg(BufferedImage image, String direction){
int width = image.getWidth();
int height = image.getHeight();
BufferedImage rotated = null;
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
switch(direction){
case "SOUTH":
rotated = new BufferedImage(width, height, image.getType());
rotated.setRGB((width - 1) - x, (height - 1) - y, image.getRGB(x,y));
break;
case "WEST":
//ROTATE LEFT
rotated = new BufferedImage(height, width, image.getType());
rotated.setRGB(y, (width - 1) - x, image.getRGB(x,y));
break;
case "EAST":
//ROTATE RIGHT
rotated = new BufferedImage(height, width, image.getType());
rotated.setRGB((height - 1) - y, x, image.getRGB(x,y));
break;
default:
return image;
}
}
}
return rotated;
}
Below there are four images but as they are so small its really hard to see them. A bit of browser zoom will show them.
When you get close the cyan pixel is staying where it should for the rotation. Its just im loosing the rest of the image.
Solution
As commented, the actual code is creating a new image for each pixel, that is, inside the inner loop. Only the image created in the last iteration is returned, containing just the last pixel.
The following code creates one single image - I tried to maintain the original code as much as possible:
private static BufferedImage rotateImg(BufferedImage image, String direction){
int width = image.getWidth();
int height = image.getHeight();
BufferedImage rotated = null;
switch(direction){
case "SOUTH":
rotated = new BufferedImage(width, height, image.getType());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB((width - 1) - x, (height - 1) - y, image.getRGB(x,y));
}
}
break;
case "WEST":
//ROTATE LEFT
rotated = new BufferedImage(height, width, image.getType());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB(y, (width - 1) - x, image.getRGB(x,y));
}
}
break;
case "EAST":
//ROTATE RIGHT
rotated = new BufferedImage(height, width, image.getType());
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB((height - 1) - y, x, image.getRGB(x,y));
}
}
break;
default:
return image;
}
return rotated;
}
To avoid having the loop code repeated (easier to maintain) we can use two functions - calX
and calcY
:
private static BufferedImage rotateImg(BufferedImage image, String direction){
int width = image.getWidth();
int height = image.getHeight();
BufferedImage rotated = null;
IntBinaryOperator calcX;
IntBinaryOperator calcY;
switch(direction){
case "SOUTH":
rotated = new BufferedImage(width, height, image.getType());
calcX = (x, y) -> (width - 1) - x;
calcY = (x, y) -> (height - 1) - y;
break;
case "WEST":
//ROTATE LEFT
rotated = new BufferedImage(height, width, image.getType());
calcX = (x, y) -> y;
calcY = (x, y) -> (width - 1) - x;
break;
case "EAST":
//ROTATE RIGHT
rotated = new BufferedImage(height, width, image.getType());
calcX = (x, y) -> (height - 1) - y;
calcY = (x, y) -> x;
break;
default:
return image;
}
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
rotated.setRGB(calcX.applyAsInt(x, y), calcY.applyAsInt(x, y), image.getRGB(x,y));
}
}
return rotated;
}
Answered By - user16320675
Answer Checked By - Marilyn (JavaFixing Volunteer)