17

I want to create a web application that allow users to upload their image to the server. When they click send, their image will be uploaded to the server (multipart). Before saving, I want to make some operation with the image, so I decided to use ..

ImageIO.read(InputStream)

to get BufferedImage object

here is the code:

public static BufferedImage getBufferedImageFromMultipartFile(MultipartFile file) 
throws APIException
{
    BufferedImage bi = null;

    try
    {
        bi = ImageIO.read(file.getInputStream());
    }
    catch (IOException e)
    {
        throw new APIException(ErrorCode.SERVER_ERROR, e);
    }

    return bi;
}

The problem is when I try to upload a picture that has height more than width such as 3264 x 2448 (height x width), the result always an image that has been rotated (2448 x 3264).

Is there any solution to solve this problem ?

Is this a bug or any defined API specification ?

Thx.

PS. sorry for my english :D

kp_ping
  • 485
  • 5
  • 14
  • I have found similar question now, http://stackoverflow.com/questions/9453367/is-javax-imageio-imageio-broken-it-imports-some-images-as-rotated?rq=1. So, my problem is not what a bug of ImageIO but it is the API specification that ImageIO can not read image detail (EXIF-orientation). THX. – kp_ping Apr 12 '13 at 19:44

2 Answers2

13

ImageIO.read( ) can't read the orientation of the image if it was taken with mobile device.

I used metadata-extractor to read metadata, i think it's a good solution: github.com/drewnoakes/metadata-extractor/wiki

<dependency> 
  <groupId>com.drewnoakes</groupId> 
  <artifactId>metadata-extractor</artifactId> 
  <version>2.7.2</version> 
</dependency>

Read orientation filed in exif directory:

ExifIFD0Directory exifIFD0 = metadata.getDirectory(ExifIFD0Directory.class);
int orientation = exifIFD0.getInt(ExifIFD0Directory.TAG_ORIENTATION);

switch (orientation) {
  case 1: // [Exif IFD0] Orientation - Top, left side (Horizontal / normal)
    return null;
  case 6: // [Exif IFD0] Orientation - Right side, top (Rotate 90 CW)
    return Rotation.CW_90;
  case 3: // [Exif IFD0] Orientation - Bottom, right side (Rotate 180)
    return Rotation.CW_180;
  case 8: // [Exif IFD0] Orientation - Left side, bottom (Rotate 270 CW)
    return Rotation.CW_270;
}

(Rotation is a class from the org.imgscalr.Scalr framework I use ti rotate image).

Paolo Biavati
  • 562
  • 6
  • 16
  • This was extremely helpful. The code with the Scalr constants was also exactly what I needed. – Bill May 11 '15 at 02:04
0

Quite interesting issue... you can try to fix it by introducing a check on the image width and height to be larger than 2448 and 3264 respectively and then just swap its width and height

Use below piece of code:

BufferedImage oldImage = ImageIO.read(file.getInputStream());

if (oldImage.getWidth() > 2448 || oldImage.getHeight() > 3264) {

    BufferedImage newImage = new BufferedImage(oldImage.getWidth(),
                oldImage.getHeight(), oldImage.getType());

    Graphics2D graphics = (Graphics2D) newImage.getGraphics();

    graphics.drawImage(oldImage, 0, 0, oldImage.getHeight(),
                oldImage.getWidth(), null);

    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    ImageIO.write(newImage, "JPG", bos);
}
Bond - Java Bond
  • 3,792
  • 6
  • 37
  • 57