Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate JPEG images based on the orientation metadata?

I have some server code that is generating thumbnails when an image is uploaded. The issue is that when the image was taken and the camera/device was rotated, the thumbnails are rotated, even though the full size images themselves are displayed in the correct orientation in any image viewing software. This is only happening with jpgs.

Using Preview on OSX, I can see that jpgs have orientation metadata embedded within. When I use ImageTools (Grails Plugin) to generate a thumbnail, the EXIF metadata is not in the thumbnail, which is why the thumbnails appear rotated.

Via offline conversations, I have learned that while it is relatively easy to read EXIF metadata, there is no easy way to write it, which is why the data is lost when generating a jpg thumbnail.

So it seems I have two options:

  1. Use ImageMagick to generate the thumbnails. The downside is it requires installed more software on our servers.
  2. Read the EXIF Orientation data is code and rotate the thumbnail appropriately.

Does anyone know of any other options?

like image 548
hvgotcodes Avatar asked May 06 '11 01:05

hvgotcodes


People also ask

How do I change the orientation of a JPEG image?

Rotate a pictureMove the mouse pointer over the image. Two buttons with arrow will appear at the bottom. Select either Rotate the image 90 degrees to the left or Rotate the image 90 degrees to the right. If you want to keep the picture rotated in this way, click Save.

What is EXIF orientation metadata?

EXIF data is useful information about a JPEG image, hidden inside the file. When images are photographed, digital cameras use orientation sensors to store an EXIF orientation value for how the camera is held. There are 8 possible values (not just landscape and portrait!).

How do I view EXIF orientation?

IrfanView. IrfanView is a great image viewer on Windows, which respects the image Exif info. To view the image Exif info, open an image and click Image -> Information . If the image contains Exif info, you can then click the EXIF info button at the bottom left of the popup window to check the image Exif info.


2 Answers

If you want to rotate your images, I would suggest to use the metadata extractor library http://code.google.com/p/metadata-extractor/. You can get the image information with the following code:

// Inner class containing image information public static class ImageInformation {     public final int orientation;     public final int width;     public final int height;      public ImageInformation(int orientation, int width, int height) {         this.orientation = orientation;         this.width = width;         this.height = height;     }      public String toString() {         return String.format("%dx%d,%d", this.width, this.height, this.orientation);     } }   public static ImageInformation readImageInformation(File imageFile)  throws IOException, MetadataException, ImageProcessingException {     Metadata metadata = ImageMetadataReader.readMetadata(imageFile);     Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);     JpegDirectory jpegDirectory = metadata.getFirstDirectoryOfType(JpegDirectory.class);      int orientation = 1;     try {         orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);     } catch (MetadataException me) {         logger.warn("Could not get orientation");     }     int width = jpegDirectory.getImageWidth();     int height = jpegDirectory.getImageHeight();      return new ImageInformation(orientation, width, height); } 

Then given the orientation you retrieve, you can rotate and/or flip the image to the right orientation. The Affine transform for the EXIF orientation is given by the following method:

// Look at http://chunter.tistory.com/143 for information public static AffineTransform getExifTransformation(ImageInformation info) {      AffineTransform t = new AffineTransform();      switch (info.orientation) {     case 1:         break;     case 2: // Flip X         t.scale(-1.0, 1.0);         t.translate(-info.width, 0);         break;     case 3: // PI rotation          t.translate(info.width, info.height);         t.rotate(Math.PI);         break;     case 4: // Flip Y         t.scale(1.0, -1.0);         t.translate(0, -info.height);         break;     case 5: // - PI/2 and Flip X         t.rotate(-Math.PI / 2);         t.scale(-1.0, 1.0);         break;     case 6: // -PI/2 and -width         t.translate(info.height, 0);         t.rotate(Math.PI / 2);         break;     case 7: // PI/2 and Flip         t.scale(-1.0, 1.0);         t.translate(-info.height, 0);         t.translate(0, info.width);         t.rotate(  3 * Math.PI / 2);         break;     case 8: // PI / 2         t.translate(0, info.width);         t.rotate(  3 * Math.PI / 2);         break;     }      return t; } 

The rotation of the image would be done by the following method:

public static BufferedImage transformImage(BufferedImage image, AffineTransform transform) throws Exception {      AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);      BufferedImage destinationImage = op.createCompatibleDestImage(image, (image.getType() == BufferedImage.TYPE_BYTE_GRAY) ? image.getColorModel() : null );     Graphics2D g = destinationImage.createGraphics();     g.setBackground(Color.WHITE);     g.clearRect(0, 0, destinationImage.getWidth(), destinationImage.getHeight());     destinationImage = op.filter(image, destinationImage);     return destinationImage; } 

In a server environment, don't forget to run with -Djava.awt.headless=true

like image 155
Antoine Martin Avatar answered Sep 20 '22 13:09

Antoine Martin


The Thumbnailator library honors EXIF orientation flags. To read an image at full size with correct orientation:

BufferedImage image = Thumbnails.of(inputStream).scale(1).asBufferedImage(); 
like image 38
dnault Avatar answered Sep 21 '22 13:09

dnault