On TakePhoto, Photo's orientation gets changed from Portrait to Landscape on Android Device
See original GitHub issueBug Information
Version Number of Plugin: 3.0.0.66-alpha Device Tested On: Sony Xperia Z2 (Android 6.0.1) Simulator Tested On: Version of VS: 2017: 15.2(26430.14) Version of Xamarin: Xamarin.Forms: 2.3.5.255-pre Versions of other things you are using: Xamarin: 4.5.0.486, Xamarin.Android: 7.3.1.12, Xamarin.iOS: 10.10.0.37 Target Framework: Android 7.1
Steps to reproduce the Behavior
- Take a portrait photo from the camera
- The orientation gets changed to landscape
Expected Behavior
Image width should be < then height.
Actual Behavior
- The photo appears as landscape
- Image width > height
Code snippet
this is my class for working with Media Plugin
public static class ImageHelper
{
public static async Task<MediaFile> TakePhoto(int maxWidthHeight = 0, int quality = 100)
{
try
{
await CrossMedia.Current.Initialize();
}
catch (Exception e)
{
App.Dbg(e);
throw new Exception("Ошибка инициализации: " + e.Message);
}
//var file = await CrossMedia.Current.PickPhotoAsync();
if (!CrossMedia.Current.IsCameraAvailable) {
App.Dbg("!!! Камера недоступна !!!");
throw new Exception("Камера недоступна !!");
}
if (!CrossMedia.Current.IsTakePhotoSupported) {
App.Dbg("!!! Получение фото недоступно !!");
throw new Exception("Получение фото недоступно !!");
}
MediaFile file = null;
try
{
file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg",
RotateImage = true,
DefaultCamera = CameraDevice.Rear,
//SaveToAlbum = true
PhotoSize = maxWidthHeight == 0 ? PhotoSize.Full : PhotoSize.MaxWidthHeight,
MaxWidthHeight = maxWidthHeight,
CompressionQuality = quality,
});
}
catch (Exception e) {
App.Dbg($"TakePhotoAsync Exception: {e.Message}");
throw;
}
return file;
}
public static async Task<MediaFile> PickPhoto(int maxWidthHeight = 0, int quality = 100)
{
try
{
await CrossMedia.Current.Initialize();
}
catch (Exception e)
{
App.Dbg(e);
throw new Exception("Ошибка инициализации: " + e.Message);
}
//var file = await CrossMedia.Current.PickPhotoAsync();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
App.Dbg("!!! Получение фото недоступно !!");
throw new Exception("Получение фото недоступно !!");
}
MediaFile file = null;
try
{
file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions()
{
PhotoSize = maxWidthHeight == 0 ? PhotoSize.Full : PhotoSize.MaxWidthHeight,
MaxWidthHeight = maxWidthHeight,
CompressionQuality = quality,
}
);
}
catch (Exception e)
{
App.Dbg($"TakePhotoAsync Exception: {e.Message}");
throw;
}
return file;
}
}
this is my helper for streams:
public static class StreamHelper
{
public static async Task<byte[]> GetBytes(this Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
MemoryStream memStream = new MemoryStream();
await stream.CopyToAsync(memStream);
memStream.Seek(0, SeekOrigin.Begin);
byte[] bytes = memStream.ToArray();
memStream.Dispose();
return bytes;
}
}
this is my snippet:
file = await ImageHelper.PickPhoto(maxWidthHeight: 1600, quality: 70);
Stream stream = file.GetStream();
byte[] imageData = await stream.GetBytes();
then i use ImageEdit plugin [https://github.com/muak/Xamarin.Plugin.ImageEdit] :
var image = await CrossImageEdit.Current.CreateImageAsync(imageData)
and image.Widrh > image.Height
if you don’t like ImageEdit, you can use custom native android function:
public Size GetImageSizeFromBytes(byte[] bytes)
{
var options = new BitmapFactory.Options
{
InJustDecodeBounds = true
};
BitmapFactory.DecodeByteArray(bytes, 0, bytes.Length, options);
return new Size((double)options.OutWidth, (double)options.OutHeight);
}
same result
p.s. sorry my english )
Screenshotst
Issue Analytics
- State:
- Created 6 years ago
- Comments:33 (9 by maintainers)
Top GitHub Comments
Orientation works fine for me as long as I set AllowCropping = false. As soon as I set AllowCropping = true, the image is rotated.
iOS 11.4 / Media Plug In 4.0.1.5
UPDATE:
I’ve discovered this strange behavior… If I copy the resulting image from TakePhotoAsync into another image with the UIImageOrientation set to Up, the new image has the correct orientation. (see code below). It’s counterintuitive but it works.
Solved:
` private void TakePhotoCommandExecute() { if (this.IsBusy) return; this.IsBusy = true; this.fileIndex = 0; this.Files[this.fileIndex] = null; Device.BeginInvokeOnMainThread(async() => { var active = await CrossMedia.Current.Initialize(); if (!active || !CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported) await Application.Current.MainPage.DisplayAlert(“😦”, “Camera not available.”, “Ok”); else { var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions { //AllowCropping = true, CompressionQuality = 70, DefaultCamera = CameraDevice.Rear, Directory = “MyUploads”, ModalPresentationStyle = MediaPickerModalPresentationStyle.OverFullScreen, PhotoSize = PhotoSize.Medium, RotateImage = true, // Important SaveToAlbum = true }); if (file != null) this.SetupFileArrayContent(file); } this.IsBusy = false; }); }
protected void SetupFileArrayContent(MediaFile file) { if (file != null) { var currentSize = file.GetStream().Length; var buffer = new byte[16 * 1024]; using (var memStream = new System.IO.MemoryStream()) { int read = 0; //var readStream = file.GetStream(); var readStream = file.GetStreamWithImageRotatedForExternalStorage(); // Important while ((read = readStream.Read(buffer, 0, buffer.Length)) > 0) memStream.Write(buffer, 0, read); this.Files[this.fileIndex] = memStream.ToArray(); readStream.Dispose(); readStream = null; } file.Dispose(); } }
`