1

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?

Emeka Obianom
  • 1,736
  • 3
  • 17
  • 36
AsconX
  • 161
  • 1
  • 15
  • Does Windows Explorer rotate the image correctly? – Mike Nakis Jul 01 '17 at 13:26
  • Yes. But the webbrowser component i am using in a C# client does not. And i am doing OCR on the image, which also requires the rotation to be fixed. – AsconX Jul 01 '17 at 13:35
  • 1
    Possible duplicate: https://stackoverflow.com/questions/40551110/rotating-bufferedimage-changes-its-colors – c0der Jul 01 '17 at 13:52
  • I will try this. Do you have any idea how to fix this for the thumbnailator variant? Because this is the one i prefer. I only used the other because of the red image :/ – AsconX Jul 01 '17 at 14:12
  • AffineTransformOp.TYPE_NEAREST_NEIGHBOR this is solved for one approach. I would still apreciate one for the shorter solution ;) – AsconX Jul 01 '17 at 14:15

2 Answers2

2

I had the same problem, and it turns out that you should not convert one format to another (BufferedImage to the ByteArrayOutputStream and vice versa). If you have byte array - use ByteArrayOutputStream and ByteArrayInputStream.

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ByteArrayInputStream in = new ByteArrayInputStream(file.getContents());
    Thumbnails.of(in)
        .size(2000,1500)
        .toOutputStream(baos);
    byte[] bytes = baos.toByteArray();
Anton Petrovskyi
  • 442
  • 5
  • 18
  • What i finally did, was just setting the tesseract PageSegmentationMode to tesseract.setPageSegMode(ITessAPI.TessPageSegMode.PSM_AUTO_OSD); This way tesseract handles preprocessing completely. – AsconX Oct 21 '18 at 12:03
1

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);
    }
}
ffer
  • 38
  • 6
  • I would appreciate if someone could tell me how to alling both centers, Ive been searching and trying but I didnt find the way. – ffer Jul 05 '17 at 21:56
  • yeah but this isnt using exif - the users can change their minds any time, cant they!!??!! – gpasch Sep 10 '18 at 16:24