Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExifUtil.getExifOrientation does not work for images containing other exif data alongwith Orientation #108

Closed
datsabk opened this issue Dec 21, 2016 · 13 comments
Assignees
Labels

Comments

@datsabk
Copy link

datsabk commented Dec 21, 2016

314

Expected behavior

Give orientation for all the images with whatever exif data being present

Actual behavior

Currently it accepts only the images which contains EXIF data of orientation alone.
It gives exception
javax.imageio.IIOException: JFIF APP0 must be first marker after SOI
at com.sun.imageio.plugins.jpeg.JPEGMetadata.(Unknown Source)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.getImageMetadata(Unknown Source)
at net.coobird.thumbnailator.util.exif.ExifUtils.getExifOrientation(Unknown Source)
at com.abk.ImageAutoRotate.main(ImageAutoRotate.java:24)

Steps to reproduce the behavior

Use any images taken using a mobile phone and you will face issues
Attached the image for which it gives exception

Environment

JDK 8

  • OS vendor and version:Windows 7
  • JDK vendor and version: JDK 8 - Downloaded from Oracle.com
  • Thumbnailator version: 0.4.8
@loheander
Copy link

With most of our users using mobile phones to take pictures now, this is becoming a serious issue. Is there anyone still maintaining this library? Would you accept pull requests?

@coobird
Copy link
Owner

coobird commented Nov 15, 2018

@jheander Thank you for the comment. Do you have any more information regarding which mobile phones are exhibiting this issue? (Are they happening in particular series of phones? Particular OS or version? etc?) If you have any examples of JPEGs that have the same issue as the one described here, it could be helpful for diagnosis.

@shelined
Copy link

We've experienced this issue with photos from the Samsung SM-G960U.

I would share the photo but I am not comfortable sharing it with the GPS location in the EXIF data and if I remove just the location from the EXIF data with Preview on Mac OS the issue is no longer reproducible with the modified image.

@loheander
Copy link

loheander commented Nov 15, 2018 via email

@havwig
Copy link

havwig commented Jan 28, 2019

I have a small web app that uses Thumbnailator, and have a lot of mobile photo uploads. It's been running for a few years and have handled resize with correct orientation according to EXIF data, but it fails portrait images with Asus Zenphone 5. I suspect that this is caused by this bug. I'm attaching two sample images, one taken in portrait mode, and one landscape.

p_20190128_213322
p_20190128_213315

@luankevinferreira
Copy link

I've experienced this issue with Samsung SM-T825

I've extracted the EXIF information of two images, I hope it helps the diagnosis

  • The below information was extracted from a image that works perfectly
    Orientation Mirror horizontal and rotate 270 CW
    XResolution 72
    YResolution 72
    ResolutionUnit inches
    ExifImageWidth 500
    ExifImageHeight 330

  • The below information was extracted from a picture taken with Samsung SM-T825
    ImageWidth 1072
    ImageHeight 1072
    Make samsung
    Model SM-T825
    Orientation Rotate 270 CW
    XResolution 72
    YResolution 72
    ResolutionUnit inches
    Software T825UBU1BRE2
    ModifyDate 2018:11:06 14:13:59
    YCbCrPositioning Centered
    ExposureTime 1/30
    FNumber 2.2
    ExposureProgram Program AE
    ISO 100
    ExifVersion 0220
    DateTimeOriginal 2018:11:06 14:13:59
    CreateDate 2018:11:06 14:13:59
    MaxApertureValue 2.2
    MeteringMode Center-weighted average
    Flash No Flash
    FocalLength 1.9 mm
    ColorSpace sRGB
    ExifImageWidth 1072
    ExifImageHeight 1072
    ExposureMode Auto
    WhiteBalance Auto
    FocalLengthIn35mmFormat 23 mm
    SceneCaptureType Standard
    GPSLatitudeRef South
    GPSLatitude 26.908889
    GPSLongitudeRef West
    GPSLongitude 49.073611
    Compression JPEG (old-style)
    ThumbnailOffset 872
    ThumbnailLength 52004

@wendal
Copy link

wendal commented Jul 10, 2019

it happen at Xiaomi 8 SE too.

@coobird
Copy link
Owner

coobird commented Jan 27, 2020

After a little bit of research, this appears to be an "issue" with the Java Image I/O's JRE-bundled JPEG reader being very strict about the well-formedness of the Exif metadata. As mentioned in the comment to this Stackoverflow question, using the TwelveMonkeys JPEG support does indeed cause this issue to go away.

To "fix" this issue in Thumbnailator would mean that I'd have to implement a lower-level Exif reader that doesn't rely on the JPEG reader implementation exposed through Java Image I/O, which isn't trivial, but would require a little bit of work.

For the time-being, I'd recommend invoking the TwelveMonkeys JPEG support which avoids the JFIF APP0 must be first marker after SOI from happening. It's a fairly trivial process if you're using Maven. Basically, just include the artifact in your <dependencies> (scoping it to runtime is enough) and you'll be able to use the TwelveMonkeys version of the JPEG support rather than the implementation bundled in the JRE.

@coobird coobird added the bug label Jan 27, 2020
@coobird coobird self-assigned this Jan 27, 2020
@Emmenemoi
Copy link

Emmenemoi commented Dec 8, 2020

Even when we include TwelveMonkeys it is not enough for ExifUtil.getExifOrientation to work reliably.
Below is how we detect ExifOrientation using JPEGSegmentUtil from TwelveMonkeys. Works like a charm even on Samsung SM-G973F, where ExifUtil.getExifOrientation fails.

static CompoundDirectory getImageIOExifData(InputStream is) {
        try ( ImageInputStream segmentStream = ImageIO.createImageInputStream(is) ) {
            List<JPEGSegment> exifSegment = JPEGSegmentUtil.readSegments(segmentStream, JPEG.APP1, "Exif");
            if (!exifSegment.isEmpty()) {
                InputStream exifData = exifSegment.get(0).data();
                exifData.read(); // Skip 0-pad for Exif in JFIF
                try (ImageInputStream exifStream = ImageIO.createImageInputStream(exifData)) {
                    return (CompoundDirectory) new TIFFReader().read(exifStream);
                }
            }
        } catch (Exception e) {
            LoggerFactory.getLogger(CommonsFilesManager.class).warn("getImageIOExifData failed for stream", e);
        }
        return null;
    }

static Orientation getImageIOExifOrientation(InputStream is) {
        if (exif != null && exif.getEntryById(TIFF.TAG_ORIENTATION) != null) {
            return Orientation.typeOf((Integer) exif.getEntryById(TIFF.TAG_ORIENTATION).getValue());
        }
        return Orientation.TOP_LEFT;
    }

@bajajsahil
Copy link

I have an image of 622 X 1280 clicked from Samsung S9 mobile. When I am trying to resize it with forceSize(150, 150), the image is getting rotated automatically to 90 degrees anti-clockwise. Then I tried using the useExifOrientation(true) but still the same result. And, while debugging I am seeing the same exception listed in this issue.

I tried including the TwelveMonkeys but still same result.

@Emmenemoi Where did you put these methods?

@johnbonds
Copy link

johnbonds commented Jan 12, 2021

Just for the record, including TwelveMonkeys JPEG in my deps worked for me...

		<!-- https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-jpeg -->
		<dependency>
		    <groupId>com.twelvemonkeys.imageio</groupId>
		    <artifactId>imageio-jpeg</artifactId>
		    <version>3.6.1</version>
		    <scope>runtime</scope>
		</dependency>

@coobird
Copy link
Owner

coobird commented Dec 12, 2021

A fix for this issue (workaround for the default JPEG reader's strict behavior) is available in the snapshot repository as 0.4.16-SNAPSHOT.

coobird added a commit that referenced this issue Jan 1, 2022
…putStream`. (#108)

The default JPEG reader bundled with the JRE cannot handle JPEG images
that doesn't have a JFIF APP0 marker segment as the first one, as some JPEG
images will include Exif (APP1) as the first one. This workaround falls back
to use Exif data captured from the `InputStream` if the JPEG reader chosen by
Image I/O fails to retrieve the Exif data.
@coobird
Copy link
Owner

coobird commented Jan 4, 2022

Fixed in 0.4.16.

@coobird coobird closed this as completed Jan 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants