Search code examples
javaimageexif

How to retain original color of Image on rotation using java


I have a java application that receives image files. I want to rotate them using the exif information.

Here on StackOverflow, i found two different approaches, in both cases I start with an BufferedImage:

        BufferedImage image=ImageIO.read(sourceFile.getInputStream());

The first solution is coming from this post.

        ImageTransformer.ImageInformation imageInformation=ImageTransformer.readImageInformation(sourceFile.getInputStream());
        AffineTransform tranform=ImageTransformer.getExifTransformation(imageInformation);
        image=ImageTransformer.transformImage(image,tranform);

The second one was also recommended in some post here, using Thumbnailator:

BufferedImage image = Thumbnails.of(sourceFile.getInputStream()).scale(1).asBufferedImage();

Both ways do properly rotate my image. But also both solutions change the coloring, which i do not want. I will attache two files, the "white" one is the original file with wrong rotation. This is exactly what I achieve when I comment out both rotation codes. White image

The other, the red one, is the one with proper rotation, but wrong color. Red Image

How can I have the original color with just changing the rotation?


Solution

  • Ive been trying to allign the center of the image with the center of the frame and I did not find a good way of doing it but Ive managed to rotate the image without losing its properties:

    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.geom.AffineTransform;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JComponent;
    
    public class Rotate extends JComponent {
        // Attributes
        private String route = null;
        private double degree = 0.0;
    
        // Constructor
        public Rotate(String route, double degree) {
            this.setRoute(route);
            this.setDegree(degree);
        }
    
        // Create a bufferedImage for the given route
        private BufferedImage getBufferedImage() {
            Image image = null;
            try {
                image = ImageIO.read(new File(getRoute()));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return (BufferedImage) image;
        }
    
        // Paint the image
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(getDegree()));
            g2.setTransform(at);
            // Here I tried to calculate you must add the coordenates to start
            // drawing the image in your frame
            g2.drawImage(getBufferedImage(), 0, 0, null);
        }
    
        public double getDiagonal() {
            return Math.hypot(getBufferedImage().getWidth(), getBufferedImage().getHeight());
        }
    
        public String getRoute() {
            return route;
        }
    
        public void setRoute(String route) {
            this.route = route;
        }
    
        public double getDegree() {
            return degree;
        }
    
        public void setDegree(double degree) {
            this.degree = degree;
        }
    
    }
    

    For testing it:

    import java.awt.Container;
    
    import javax.swing.JFrame;
    
    public class ImageRotation {
    
        public static void main(String[] args) {
            // The route of the image and the degrees of rotation
            String route = "C:\\Users\\Public\\Pictures\\Sample Pictures\\download.jpg";
            double degrees = 30;
            // Frame to display the image
            JFrame jf = new JFrame("Image Rotated");
            // Introduce the route and degrees
            Rotate tl = new Rotate(route, degrees);
            // Set the size of the frame
            int hyp = (int) tl.getDiagonal();
            jf.setSize(hyp, hyp);
            // Print the rotated image in the frame
            Container cp = jf.getContentPane();
            cp.add(tl);
            // Display
            jf.setVisible(true);
        }
    }