-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Save photo orientation on iOS #1037
Conversation
This patch works by calculating the device's physical orientation from accelerometer data. This is a tricky approach and I'd rather avoid it, but it looks like a necessary evil based on a few reasons. 1. The specific callback we're registering doesn't give us any EXIF data or data on the photo's orientation. https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/1778647-captureoutput?language=objc 2. There is a better callback to use that does give us this data, but it's only supported on ios 11.0+ and the camera plugin supports 10.0+. https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/2873949-captureoutput?language=objc 3. There's a straightforward iOS API that's supposed to give the physical device orientation that would normally be perfect for this, but it doesn't work when the UI is locked to portrait mode. https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation?language=objc We've had Android issues in the past based on the Android API we used having this same limitation.
|
Would it not make more sense for the image orientation to depend on the orientation of the UI, rather than the device's accelerometer? |
No unfortunately, because the UI orientation can be permanently locked (to portrait) while the user is taking a picture with the phone rotated (to landscape). flutter/flutter#18391 was filed separately on Android for this a little while ago, and you can see some comments mentioning the problem happening on Android while the UI is locked earlier in the linked issue for this PR: 1, 2, 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood. This does look like the best answer right now. The user should always want the picture properly rotated based on the device rotation over UI anyways.
LGTM
|
well done, many thanks. |
|
Hi @mklim . Thanks so much for working to solve this problem; it is a blocker for the launch of our product so it's very much appreciated. Also, sorry for coming in late to this PR. I've been testing it out with camera lib 0.2.9+1, and it seems like there is a problem with the orientation that is being detected with the CMMotionManager. In general, we do not always get the correct orientations for our photos, especially when the device is pitched at an angle > 45% (I'm using the term pitch as defined in https://developer.apple.com/documentation/coremotion/getting_processed_device-motion_data/understanding_reference_frames_and_device_attitude ) I think I've isolated it to two issues in the getImageRotation method. One is an easy fix, which is that I believe pitch is being used where yaw should instead be used. You can notice this if you take a photo in portrait with top of the phone titled downward, e.g. as though taking a picture of something on a table from 45% above the table. When I switch the calculation from using pitch to using yaw, things generally get more stable, although there is actually still a major problem. Below is the change I made to use yaw instead of pitch. The second issue seems harder to overcome though, which is that the yaw value returned by the motion manager seems to be relative to the position of the device when the application is started. What this means is that everything works as expected if you start the application while the phone is in portrait mode, but if you start the application while it is in landscape, or at some other odd angle, orientations start coming back wrong. Incidentally, most of my testing was with iPhoneX, although I also tested some of the potential fixes on an iPad. I was searching for alternative libraries to use to compute orientation, and came across the same as you: https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation?language=objc. However, on my devices, it does not seem to suffer from the problem you mentioned in your 3rd list item -- of not working when the interface is locked in portrait mode. The documentation also seems to suggest that it should work correctly even when UI is locked: "This value represents the physical orientation of the device and may be different from the current orientation of your application’s user interface." Here is a definition of getImageRotation that seems to work for my device, even when the UI is locked in portrait (although the begin and end notification calls may belong outside of this method ultimately): Let me know what you think. Thanks! |
|
Thanks for the detailed look and debugging info @idealopamp! I'm still digging into this in more detail, but in general I think there's possibly device or OS specific inconsistencies going on here. Opened flutter/flutter#26786 to track this. |
This patch works by calculating the device's physical orientation from accelerometer data. This is a tricky approach and I'd rather avoid it, but it looks like a necessary evil based on a few reasons. 1. The specific callback we're registering doesn't give us any EXIF data or data on the photo's orientation. https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/1778647-captureoutput?language=objc 2. There is a better callback to use that does give us this data, but it's only supported on ios 11.0+ and the camera plugin supports 10.0+. https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/2873949-captureoutput?language=objc 3. There's a straightforward iOS API that's supposed to give the physical device orientation that would normally be perfect for this, but it doesn't work when the UI is locked to portrait mode. https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation?language=objc We've had Android issues in the past based on the Android API we used having this same limitation. fixes flutter/flutter#16587
This reverts commit d06ab71.
This patch works by calculating the device's physical orientation from accelerometer data. This is a tricky approach and I'd rather avoid it, but it looks like a necessary evil based on a few reasons. 1. The specific callback we're registering doesn't give us any EXIF data or data on the photo's orientation. https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/1778647-captureoutput?language=objc 2. There is a better callback to use that does give us this data, but it's only supported on ios 11.0+ and the camera plugin supports 10.0+. https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/2873949-captureoutput?language=objc 3. There's a straightforward iOS API that's supposed to give the physical device orientation that would normally be perfect for this, but it doesn't work when the UI is locked to portrait mode. https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation?language=objc We've had Android issues in the past based on the Android API we used having this same limitation. fixes flutter/flutter#16587
This patch works by calculating the device's physical orientation from
accelerometer data. This is a tricky approach and I'd rather avoid it,
but it looks like a necessary evil based on a few reasons.
or data on the photo's orientation.
https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/1778647-captureoutput?language=objc
it's only supported on ios 11.0+ and the camera plugin supports
10.0+.
https://developer.apple.com/documentation/avfoundation/avcapturephotocapturedelegate/2873949-captureoutput?language=objc
physical device orientation that would normally be perfect for this,
but it doesn't work when the UI is locked to portrait mode.
https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation?language=objc
We've had Android issues in the past based on the Android API we used
having this same limitation.
fixes flutter/flutter#16587