jamesmontemagno / MediaPlugin

Take & Pick Photos and Video Plugin for Xamarin and Windows
MIT License
712 stars 358 forks source link

[iOS] Image rotation not correct in portrait mode after cropping #446

Open khuongntrd opened 6 years ago

khuongntrd commented 6 years ago

Bug Information

Version Number of Plugin: v3.1.3 Device Tested On: iPhone 11.2.5 Version of VS (for Mac): 7.3

Steps to reproduce the Behavior

Expected Behavior

Set info.plish to:

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
</array>
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
         Directory = "myapp",
         Name = "avatar.jpg",
         SaveToAlbum = false,
         PhotoSize = PhotoSize.Large,
         AllowCropping = true
});

Actual Behavior

Capture photo with landscape mode -> cropping -> woking. Capture photo with portrait mode -> cropping -> image rotate to 90 degree

Technojo01 commented 6 years ago

I'm having the same problem using version 3.1.2 wihtout cropping. Every pictures taken in portrait are rotated left by 90 degree. Tried different option to no avail.

            var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
           {
               Directory = "Sample",
               Name = filename,
               PhotoSize = PhotoSize.Medium,
               SaveToAlbum = false,
               RotateImage = false,
               SaveMetaData = false
           });

Thanks for looking into this.

Technojo01 commented 6 years ago

OK, nevermind my last comment. Using GetStreamWithImageRotatedForExternalStorage with RotateImage = true fixed my problems.

jamesmontemagno commented 6 years ago

@KhuongNtrd can you validate that @Technojo01's fix is the same as yours?

MikaTml commented 6 years ago

With AllowCropping=true RotateImage = true SaveToAlbum = true SaveMetaData = true image is rotated 90 degree ccw with file.GetStream(), but with file.GetStreamWithImageRotatedForExternalStorage(), image is not rotated.

If I only set AllowCropping=false, image is not rotated with file.GetStream(). Perhaps this is the problem?

Plugin.Media = 3.1.3.0 iPhone = 11.2.5 Phone was on portrait mode all the time.

jamesmontemagno commented 6 years ago

It is most likely that the cropped image doesn't have the correct exif data from apple.

Osmosis311 commented 6 years ago

Same thing happening to me. Taking a photo "portrait-wise" in iOS, and the result with .GetStream is rotated 90 degrees. I tried changing it to GetStreamWithImageRotatedForExternalStorage() but it doesn't return any data.

foxanna commented 6 years ago

I had faced the same problem: .GetStream() returned rotated image on iOS, while .GetStreamWithImageRotatedForExternalStorage() seemed to be returning no data, while in fact, it was returning a Stream which was already read. I ended up with the code like this:

var stream = mediaFile.GetStreamWithImageRotatedForExternalStorage();
stream.Seek(0, SeekOrigin.Begin);

which totally solved the issue for me!

zanesc commented 6 years ago

I can confirm that all three of the following options workaround this issue: 1) AllowCropping = false 2) AllowCropping = true, mediaFile.GetStreamWithImageRotatedForExternalStorage instead of mediaFile.GetStream 3) AllowCropping = true, SaveMetaData = false

angelieri commented 5 years ago

I can confirm that all three of the following options workaround this issue:

  1. AllowCropping = false
  2. AllowCropping = true, mediaFile.GetStreamWithImageRotatedForExternalStorage instead of mediaFile.GetStream
  3. AllowCropping = true, SaveMetaData = false

Zanesc, THANKS A LOT for your help. But only 3th option worked for me.

Version Number of Plugin: v4.0.1.5 Device Tested On: iPhone 12.1.3

Kapusch commented 4 years ago

Same problem with the following configuration :

This snippet canceled the unexpected rotation after cropping :

var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
    SaveToAlbum = true,
    Name = $"{DateTime.UtcNow.ToString("yyyy-MM-dd")}_{photoUsage}_{UserData.Username}.jpg",
    CompressionQuality = 92,
    AllowCropping = true,
    DefaultCamera = Plugin.Media.Abstractions.CameraDevice.Rear
});

if (file == null)
    return null;

return ImageSource.FromStream(() =>
{
    // Unexpected 90° rotation according to https://github.com/jamesmontemagno/MediaPlugin/issues/446
    //var stream = file.GetStream();

    var stream = file.GetStreamWithImageRotatedForExternalStorage();
    return stream;
});
saidbehaine commented 4 years ago

This configuration worked for me:

  1. Take the photo
    var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
    {
    PhotoSize = PhotoSize.MaxWidthHeight,
    MaxWidthHeight = 500,
    CompressionQuality = Device.RuntimePlatform == Device.Android ? 60 : 60,
    DefaultCamera = CameraDevice.Rear,
    AllowCropping = false,
    SaveMetaData = true
    });
  2. Save as ImageSource to use it in your XAML
    
    if (file == null)
    return;

var photoSource = ImageSource.FromStream(() => { var stream = file.GetStream();

return stream;

});

3. Convert to byte array for send to any API
```c#
byte[] photoArray = null;
if (file != null)
{
    using (var ms = new MemoryStream())
    {
        file.GetStreamWithImageRotatedForExternalStorage().CopyTo(ms);

        photoArray = ms.ToArray();
    }
}

MediaPlugin: v5.0.1 Xamarin.Forms : v4.6 iOS : v13.5 Version of VS (for Mac): v8.6.2 Device Tested On: iPhone 11