Search code examples
javaimageswinggraphics2d

I'm rotating image in java but want to save rotated image


I'm using AffineTransform to rotate the image and I had tried to save the rotated image by ImageIo.write it is saving the image but not the rotated image it's saving the original image. so please tell me how to correct it Thanks in advance.

This is my code for rotation and saving the image

public class Image {

public static void main(String[] args) {
    new Image();
}

public Image() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception ex) {
            }

            JFrame frame = new JFrame("Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new TestPane());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}
public class TestPane extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JSlider slider;
    private BufferedImage image;

    public TestPane() {
        setLayout(new BorderLayout());

        try {
           File imagefile = new File("C:/pics/1206.jpg");
              image = ImageIO.read(imagefile);


              ImageIO.write(image, "jpg",new File("C:/pics"));
              ImageIO.write(image, "bmp",new File("C:/pics"));
              ImageIO.write(image, "gif",new File("C:/picsf"));
              ImageIO.write(image, "png",new File("C:/pics"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        slider = new JSlider();
        slider.setMinimum(0);
        slider.setMaximum(360);
        slider.setMinorTickSpacing(5);
        slider.setMajorTickSpacing(10);
        slider.setValue(0);
        add(slider, BorderLayout.SOUTH);
        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                repaint();
            }
        });
    }

    @Override
    public Dimension getPreferredSize() {
        return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
    }

    public double getAngle() {

        return Math.toRadians(slider.getValue());

    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g.create();

        g2d.setColor(Color.RED);
        g2d.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
        g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);

        g2d.setColor(Color.BLACK);
        int x = (getWidth() - image.getWidth()) / 2;
        int y = (getHeight() - image.getHeight()) / 2;
        AffineTransform at = new AffineTransform();
        at.setToRotation(getAngle(), x + (image.getWidth() / 2), y + (image.getHeight() / 2));
        at.translate(x, y);
        g2d.setTransform(at);
        g2d.drawImage(image, 0, 0, this);
        g2d.dispose();
    }
    }
}

Solution

  • Let's start with, this isn't rotating the image, it's rotating the Graphics context which is used to display the image, it doesn't affect the original image at all

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
    
        Graphics2D g2d = (Graphics2D) g.create();
    
        g2d.setColor(Color.RED);
        g2d.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
        g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
    
        g2d.setColor(Color.BLACK);
        int x = (getWidth() - image.getWidth()) / 2;
        int y = (getHeight() - image.getHeight()) / 2;
        AffineTransform at = new AffineTransform();
        at.setToRotation(getAngle(), x + (image.getWidth() / 2), y + (image.getHeight() / 2));
        at.translate(x, y);
        g2d.setTransform(at);
        g2d.drawImage(image, 0, 0, this);
        g2d.dispose();
    }
    

    And then this...

      try {
            File imagefile = new File("C:/pics/1206.jpg");
            image = ImageIO.read(imagefile);
    
    
            ImageIO.write(image, "jpg",new File("C:/pics"));
            ImageIO.write(image, "bmp",new File("C:/pics"));
            ImageIO.write(image, "gif",new File("C:/picsf"));
            ImageIO.write(image, "png",new File("C:/pics"));
      } catch (IOException ex) {
            ex.printStackTrace();
      }
    

    which just saves the original image to a number of different formats ... to the same file 😕, but doesn't even react to any changes to the angle

    Instead, you need to use something which generates a new image from the original, rotated by the amount you want...

      public BufferedImage rotateImageByDegrees(BufferedImage img, double degrees) {
            double rads = Math.toRadians(degrees);
            double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads));
            int w = img.getWidth();
            int h = img.getHeight();
            int newWidth = (int) Math.floor(w * cos + h * sin);
            int newHeight = (int) Math.floor(h * cos + w * sin);
    
            BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = rotated.createGraphics();
            AffineTransform at = new AffineTransform();
            at.translate((newWidth - w) / 2, (newHeight - h) / 2);
    
            int x = clickPoint == null ? w / 2 : clickPoint.x;
            int y = clickPoint == null ? h / 2 : clickPoint.y;
    
            at.rotate(rads, x, y);
            g2d.setTransform(at);
            g2d.drawImage(img, 0, 0, this);
            g2d.setColor(Color.RED);
            g2d.drawRect(0, 0, newWidth - 1, newHeight - 1);
            g2d.dispose();
    
            return rotated;
      }
    

    Then you can save it...

    File imagefile = new File("C:/pics/1206.jpg");
    image = ImageIO.read(imagefile);
    
    BufferedImage rotated = rotateImageByDegrees(image, 22.5);
    ImageIO.write(rotated, "png", new File("RotatedBy225.png"));
    

    So, the next time you use one of my previous examples and I tell you it's not doing what you think/want it to, I hope you will understand my meaning better 😉 and look more closly at the other examples we show you