bigflood / dartexif

Dart package to decode Exif data from tiff, jpeg and heic files
https://pub.dev/packages/exif
MIT License
30 stars 29 forks source link

EXIF orientation is incorrect #6

Closed nachtmaar closed 5 years ago

nachtmaar commented 5 years ago

Hi, I am using Flutter with the camera plugin. It seems that the library always reports orientation 6 which means landscape left which is incorrect.

I use the following code to determine the orientation from EXIF:

Future<int> getEXIFOrientationCorrection(List<int> image) async {

  int rotationCorrection = 0;
  Map<String, IfdTag> exif = await readExifFromBytes(image);

  if (exif == null || exif.isEmpty) {
    print("No EXIF information found");
  } else {
    print("Found EXIF information");
    // http://sylvana.net/jpegcrop/exif_orientation.html
    IfdTag orientation = exif["Image Orientation"];
    int orientationValue = orientation.values[0];
    // in degress
    print("orientation: ${orientation.printable}/${orientation.values[0]}");
    switch (orientationValue) {
      case 6:
        rotationCorrection = 90;
        break;
      case 3:
        rotationCorrection = 180;
        break;
      case 8:
        rotationCorrection = 270;
        break;
    }
  }
  return rotationCorrection;
}

orientation.values[0] seems to always be 6. Tested with Iphone 7 (should have orientation=1) and Samsung Galaxy S3 mini (should have orientation=6).

However, for both phones the library reports orientation=6 which is wrong for the iPhone. If I analyze the image with imagemagick, it reports orientation=1 which is correct for the iPhone 7:

$ identify -format '%[EXIF:Orientation]' flutter_camera_portrait.jpg
1

I took the image with the camera plugin on Iphone 7 and retrieved it from the device by printing it's base64 value to stdout. See the image here: flutter_camera_portrait

bigflood commented 5 years ago

This may related to camera plugin issue: https://github.com/flutter/flutter/issues/16587

nachtmaar commented 5 years ago

So your guess is that the camera plugin sets the wrong EXIF orientation? I thought the same, but then I copied the image taken with the camera plugin to my computer and tested it with imagemagick. However, imagemagick reports the correct EXIF information as well as Apple Preview.

The image above is taken with the camera plugin. On the other side, I just realize that the image is wider than high.

bigflood commented 5 years ago

Tested with iphone 8s (https://github.com/bigflood/exifviewer)

nachtmaar commented 5 years ago

I can confirm your result.

I used your example app to take a picture from the camera. So I think you are right, the EXIF information is read correct, but the camera plugin writes wrong EXIF information to the image file.

EXIF orientation is 6 (Rotated 90 CW), but should be 1 (Horizontal (normal)) img_a69567380a33-1

nachtmaar commented 5 years ago

I did a more detailed study of EXIF orientation using an Iphone 7 and Samsung GT-I9195 with the help of your https://github.com/bigflood/exifviewer

Actual EXIF orientation:

Android (tested using Samsung GT-I9195 back camera):

Device Orientation EXIF Orientation Correction Image Correction Camera Preview
Portrait Rotated 90CW 0 0
Landscape left Horizontal (normal) -90 -90
Landscape right Rotated 180 90 90
Portrait Down Rotated 90 CCW 180 180

where Correction Image = The number of degrees by which to rotate the picture taken by camera such that it is displayed correctly Correction Camera Preview = The number of degrees by which to rotate the camera preview widget such that it is displayed correctly

iOS (iPhone 7 back camera):

Device Orientation EXIF Orientation Correction Image Correction Camera Preview
Portrait Rotated 90 CW 0 0
Landscape left Rotated 90 CW -90 -90
Landscape right Rotated 90 CW 90 90
- - - -

Findings

=> Camera Preview Widget needs rotation on both iOS & Android => EXIF information for iOS are always the same => EXIF information for Android are reported correctly

Implementation Idea to show image and camera preview correctly on both iOS and Android: => iOS: rotate images by device orientation and assume that all iPhones have EXIF=1 in portrait mode, so there is hopefully no EXIF orientation to be applied => Android: rotate images by EXIF orientation, e.g. Samsung GT-I9195 needs 90° rotation in portrait mode

I implemented these changes to your app and opened a pull request to demonstrate the fixed camera image and camera preview: https://github.com/bigflood/exifviewer/pull/1

duongsang97 commented 1 week ago

If you used SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitDown, DeviceOrientation.portraitUp, ]);

then get orientation by exif be not work, try remove in and retry agant