3

I will use this algorithm for image rotation, however I realized that it only rotates squares, not rectangles.

Would anyone know why?

Main code-problem:

public static int[] rotate(double angle, int[] pixels, int width, int height) {
    final double radians = Math.toRadians(angle);

    final double cos = Math.cos(radians);
    final double sin = Math.sin(radians);

    final int[] pixels2 = new int[pixels.length];

    for(int pixel = 0; pixel < pixels2.length; pixel++) {
        pixels2[pixel] = 0xFFFFFF;
    }

    for(int x = 0; x < width; x++) {
        for(int y = 0; y < height; y++) {
            final int centerx = width / 2;
            final int centery = height / 2;
            final int m = x - centerx;
            final int n = y - centery;
            final int j = ((int) ( m * cos + n * sin ) ) + centerx;
            final int k = ((int) ( n * cos - m * sin ) ) + centery;
            if( j >= 0 && j < width && k >= 0 && k < height ){
                pixels2[ ( y * width + x ) ] = pixels[ ( k * width + j ) ];
            }
        }
    }
    return pixels2;
}

Context application:

try {
    BufferedImage testrot = ImageIO.read(new File("./32x32.png"));

    int[] linearpixels = new int[testrot.getWidth() * testrot.getHeight()];
    int c = 0;
    for(int i = 0; i < testrot.getWidth(); i++){
        for(int j = 0; j < testrot.getHeight(); j++){
            linearpixels[c] = testrot.getRGB(i, j);
            c++;
        }
    }

    int[] lintestrot = rotate(50, linearpixels, 32, 32);
    BufferedImage image = new BufferedImage(70, 70, BufferedImage.TYPE_INT_RGB);
    c = 0;
    for(int i = 0; i < 32; i++){
        for(int j = 0; j < 32; j++){
            image.setRGB(i, j, lintestrot[c]);
            c++;
        }
    }

    File outputfile = new File("test002.bmp");
    ImageIO.write(image, "bmp", outputfile);

} catch (IOException e1) {
    e1.printStackTrace();
}

If you alter to 33 width or height the result will be wrong (wrong image).

1 Answers1

2

You algorithm actually does work. The problem is with your loops in your context application. Because the pixels are stored in raster order, the outer loop needs to iterate to the height and the inner loop iterates to the width, e.g:

for(int i = 0; i < testrot.getHeight(); i++){
    for(int j = 0; j < testrot.getWidth(); j++){
        linearpixels[c] = testrot.getRGB(j, i); //edit here, tested
        c++;
    }
}

Then if you change height to 40 for example:

int[] lintestrot = rotate(50, linearpixels, 32, 40);

The loops need to change like this:

c = 0;
for(int i = 0; i < 40; i++){
    for(int j = 0; j < 32; j++){
        image.setRGB(i, j, lintestrot[c]);
        c++;
    }
}

Note that the order is reversed in the loops (height then width) compared to the function call (width then height).

samgak
  • 23,944
  • 4
  • 60
  • 82
  • I had already observed this behavior before (others loops), I had not even tried that. I will translate your English to understand the source of the problem, thank you very much and I am testing. Samgak. – Jlmi Xczffav May 02 '17 at 01:49
  • Tested and approved! Next time attention to var name: "LINEARPIXELS" hehe. – Jlmi Xczffav May 02 '17 at 02:02