Open ozzy1873 opened 6 years ago
I have exactly the same issue. On the backend I use System.Drawing
to read the base64 image, however i'm also getting "Parameter is not valid". @ozzy1873 Did you ever figure out a workaround?
Sorry it took so long for me to get back to you. Yes, I found a workaround. This code has been working well for months:
` file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions() { CompressionQuality = 100, PhotoSize = PhotoSize.MaxWidthHeight, MaxWidthHeight = MAX_WIDTH_HEIGHT, RotateImage = Device.RuntimePlatform != Device.iOS, SaveMetaData = true });
using (var strmToUpload = await PhotoUtils.GetPhotoStreamToUpload(file)) { if (strmToUpload == null) { await _dialogService.ShowMessage("Sorry, there is a problem with that photo.", "Camera"); return; }
…do something with photo...
}
public static async Task<Stream> GetPhotoStreamToUpload(MediaFile file)
{
byte[] resizedImage = null;
var resizer = DependencyService.Get<IImageResizer>();
try
{
resizedImage = await resizer.ResizeImage(file.GetStream(), MAX_WIDTH_HEIGHT, MAX_WIDTH_HEIGHT);
}
catch (Exception e)
{
}
}
return new MemoryStream(resizedImage);
}
public Task<byte[]> ResizeImageIOS(System.IO.Stream imageData, float width, float height)
{
UIImage originalImage = ImageFromStream(imageData);
var resizedImage = RotateCameraImageToProperOrientation(originalImage, Math.Max(width, height));
var imageBytes = resizedImage.AsJPEG().ToArray();
resizedImage.Dispose();
var bytes = Task.FromResult(imageBytes);
return bytes;
}
public UIKit.UIImage ImageFromStream(System.IO.Stream data)
{
if (data == null)
{
return null;
}
//
UIKit.UIImage image;
try
{
image = new UIKit.UIImage(Foundation.NSData.FromStream(data));
}
catch (Exception e)
{
Console.WriteLine("Image load failed: " + e.Message);
return null;
}
return image;
}
public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution)
{
var imgRef = imageSource.CGImage;
var width = (nfloat)imgRef.Width;
var height = (nfloat)imgRef.Height;
var bounds = new CGRect(0, 0, width, height);
nfloat scaleRatio = 1;
if (width > maxResolution || height > maxResolution)
{
scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height);
bounds.Height = bounds.Height * scaleRatio;
bounds.Width = bounds.Width * scaleRatio;
}
var transform = CGAffineTransform.MakeIdentity();
var orient = imageSource.Orientation;
var imageSize = new CGSize(imgRef.Width, imgRef.Height);
nfloat storedHeight;
switch (imageSource.Orientation)
{
case UIImageOrientation.Up:
transform = CGAffineTransform.MakeIdentity();
break;
case UIImageOrientation.UpMirrored:
transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f);
transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
break;
case UIImageOrientation.Down:
transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height);
transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI);
break;
case UIImageOrientation.DownMirrored:
transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height);
transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f);
break;
case UIImageOrientation.Left:
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width);
transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
break;
case UIImageOrientation.LeftMirrored:
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width);
transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
break;
case UIImageOrientation.Right:
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f);
transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
break;
case UIImageOrientation.RightMirrored:
storedHeight = bounds.Height;
bounds.Height = bounds.Width;
bounds.Width = storedHeight;
transform = CGAffineTransform.MakeScale(-1.0f, 1.0f);
transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
break;
default:
break;
}
UIGraphics.BeginImageContext(bounds.Size);
var context = UIGraphics.GetCurrentContext();
if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left)
{
context.ScaleCTM(-scaleRatio, scaleRatio);
context.TranslateCTM(-height, 0);
}
else
{
context.ScaleCTM(scaleRatio, -scaleRatio);
context.TranslateCTM(0, -height);
}
context.ConcatCTM(transform);
context.DrawImage(new CGRect(0, 0, width, height), imgRef);
var imageCopy = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return imageCopy;
}
`
Bug Information
Version Number of Plugin: 3.1.3 Device Tested On: iPhone 5S, iPhone X simulator Simulator Tested On: 11.2 Version of VS: 15.5.7 Version of Xamarin: XF 2.5.0.280555 On the server: .NET Framework 4.6.1
Steps to reproduce the Behavior
Pick an existing photo and call GetStreamWithImageRotatedForExternalStorage to get the stream. Then load the stream with System.Drawing.Image.FromStream.
Expected Behavior
A valid System.Drawing.Image should be created.
Actual Behavior
The file stream is invalid and causes an exception to be thrown with "Parameter is not valid". This happens nearly 100% of the time on iOS, never seen it on Android. Once in a while it will work OK on iOS, but very seldom. If I change GetStreamWithImageRotatedForExternalStorage to GetStream, the exception is never thrown; however, the photos are rotated incorrectly.
Code snippet
On the server: