Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
[iOSResizeMultiplePhotosCrash] I have fixed the crash of iOS when sel…
Browse files Browse the repository at this point in the history
…ecting multiple photographs with resize. This can allow more than 100 photographs with resize.
  • Loading branch information
ManbirSinghRakhra committed Jul 29, 2019
1 parent 16bd9b4 commit 81378a4
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 106 deletions.
82 changes: 2 additions & 80 deletions src/Media.Plugin/iOS/ECLImagePickerViewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,89 +164,11 @@ private MediaFile GetPictureMediaFile(ALAsset asset, long index = 0)
rep?.Dispose();
rep = null;

var percent = 1.0f;
if (_options.PhotoSize != PhotoSize.Full)
{
try
{
switch (_options.PhotoSize)
{
case PhotoSize.Large:
percent = .75f;
break;
case PhotoSize.Medium:
percent = .5f;
break;
case PhotoSize.Small:
percent = .25f;
break;
case PhotoSize.Custom:
percent = (float)_options.CustomPhotoSize / 100f;
break;
}

if (_options.PhotoSize == PhotoSize.MaxWidthHeight && _options.MaxWidthHeight.HasValue)
{
var max = Math.Max(image.CGImage.Width, image.CGImage.Height);
if (max > _options.MaxWidthHeight.Value)
{
percent = (float)_options.MaxWidthHeight.Value / (float)max;
}
}

if (percent < 1.0f)
{
//begin resizing image
image = image.ResizeImageWithAspectRatio(percent);
}

}
catch (Exception ex)
{
Console.WriteLine($"Unable to compress image: {ex}");
}
}


NSDictionary meta = null;
try
{
//meta = PhotoLibraryAccess.GetPhotoLibraryMetadata(asset.AssetUrl);

//meta = info[UIImagePickerController.MediaMetadata] as NSDictionary;
if (meta != null && meta.ContainsKey(ImageIO.CGImageProperties.Orientation))
{
var newMeta = new NSMutableDictionary();
newMeta.SetValuesForKeysWithDictionary(meta);
var newTiffDict = new NSMutableDictionary();
newTiffDict.SetValuesForKeysWithDictionary(meta[ImageIO.CGImageProperties.TIFFDictionary] as NSDictionary);
newTiffDict.SetValueForKey(meta[ImageIO.CGImageProperties.Orientation], ImageIO.CGImageProperties.TIFFOrientation);
newMeta[ImageIO.CGImageProperties.TIFFDictionary] = newTiffDict;

meta = newMeta;
}
var location = _options.Location;
if (meta != null && location != null)
{
meta = MediaPickerDelegate.SetGpsLocation(meta, location);
}
}
catch (Exception ex)
{
Console.WriteLine($"Unable to get metadata: {ex}");
}

//iOS quality is 0.0-1.0
var quality = (_options.CompressionQuality / 100f);
var savedImage = false;
if (meta != null)
savedImage = MediaPickerDelegate.SaveImageWithMetadata(image, quality, meta, path);

if (!savedImage)
image.AsJPEG(quality).Save(path, true);
image.AsJPEG().Save(path, true);

image?.Dispose();
image = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Default);

string aPath = null;
//try to get the album path's url
Expand Down
101 changes: 97 additions & 4 deletions src/Media.Plugin/iOS/MediaImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ public class MediaImplementation : IMedia
/// </summary>
public static UIStatusBarStyle StatusBarStyle { get; set; }



///<inheritdoc/>
public Task<bool> Initialize() => Task.FromResult(true);
///<inheritdoc/>
public Task<bool> Initialize() => Task.FromResult(true);

/// <summary>
/// Implementation
Expand Down Expand Up @@ -379,10 +378,104 @@ private static MediaPickerController SetupController(MediaPickerDelegate mpDeleg
return Task.FromResult(new List<MediaFile>());
}

var files = t.Result;
Parallel.ForEach(files, mediaFile =>
{
ResizeAndCompressImage(options, mediaFile);
});

return t;
}).Unwrap();
}

private static void ResizeAndCompressImage(StoreCameraMediaOptions options, MediaFile mediaFile)
{
var image = UIImage.FromFile(mediaFile.Path);
var percent = 1.0f;
if (options.PhotoSize != PhotoSize.Full)
{
try
{
switch (options.PhotoSize)
{
case PhotoSize.Large:
percent = .75f;
break;
case PhotoSize.Medium:
percent = .5f;
break;
case PhotoSize.Small:
percent = .25f;
break;
case PhotoSize.Custom:
percent = (float)options.CustomPhotoSize / 100f;
break;
}

if (options.PhotoSize == PhotoSize.MaxWidthHeight && options.MaxWidthHeight.HasValue)
{
var max = Math.Max(image.Size.Width, image.Size.Height);
if (max > options.MaxWidthHeight.Value)
{
percent = (float)options.MaxWidthHeight.Value / (float)max;
}
}

if (percent < 1.0f)
{
//begin resizing image
image = image.ResizeImageWithAspectRatio(percent);
}

NSDictionary meta = null;
try
{
//meta = PhotoLibraryAccess.GetPhotoLibraryMetadata(asset.AssetUrl);

//meta = info[UIImagePickerController.MediaMetadata] as NSDictionary;
if (meta != null && meta.ContainsKey(ImageIO.CGImageProperties.Orientation))
{
var newMeta = new NSMutableDictionary();
newMeta.SetValuesForKeysWithDictionary(meta);
var newTiffDict = new NSMutableDictionary();
newTiffDict.SetValuesForKeysWithDictionary(meta[ImageIO.CGImageProperties.TIFFDictionary] as NSDictionary);
newTiffDict.SetValueForKey(meta[ImageIO.CGImageProperties.Orientation], ImageIO.CGImageProperties.TIFFOrientation);
newMeta[ImageIO.CGImageProperties.TIFFDictionary] = newTiffDict;

meta = newMeta;
}
var location = options.Location;
if (meta != null && location != null)
{
meta = MediaPickerDelegate.SetGpsLocation(meta, location);
}
}
catch (Exception ex)
{
Console.WriteLine($"Unable to get metadata: {ex}");
}

//iOS quality is 0.0-1.0
var quality = (options.CompressionQuality / 100f);
var savedImage = false;
if (meta != null)
savedImage = MediaPickerDelegate.SaveImageWithMetadata(image, quality, meta, mediaFile.Path);

if (!savedImage)
image.AsJPEG(quality).Save(mediaFile.Path, true);

image?.Dispose();
image = null;

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
}
catch (Exception ex)
{
Console.WriteLine($"Unable to compress image: {ex}");
}
}
}

private void Dismiss(UIPopoverController popover, UIViewController picker)
{
if (popover != null)
Expand All @@ -399,7 +492,7 @@ private void Dismiss(UIPopoverController popover, UIViewController picker)
{

}

GC.Collect(GC.MaxGeneration, GCCollectionMode.Default);
Interlocked.Exchange(ref pickerDelegate, null);
}

Expand Down
51 changes: 29 additions & 22 deletions src/Media.Plugin/iOS/UIImageExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Drawing;
using UIKit;
using CoreImage;
using Foundation;

namespace Plugin.Media
{
Expand All @@ -21,34 +22,40 @@ public static UIImage ResizeImageWithAspectRatio(this UIImage imageSource, float
{
if (scale > 1.0f)
return imageSource;

using (var c = CIContext.Create())
{
var sourceImage = CIImage.FromCGImage(imageSource.CGImage);

var f = new CILanczosScaleTransform
{
Scale = scale,
Image = sourceImage,
AspectRatio = 1.0f
};

using (var c = CIContext.Create())
{
var sourceImage = CIImage.FromCGImage(imageSource.CGImage);
var orientation = imageSource.Orientation;
imageSource?.Dispose();

var output = f.OutputImage;
var transform = new CILanczosScaleTransform
{
Scale = scale,
Image = sourceImage,
AspectRatio = 1.0f
};

var cgi = c.CreateCGImage(output, output.Extent);
return UIImage.FromImage(cgi, 1.0f, imageSource.Orientation);
}
}
var output = transform.OutputImage;
using (var cgi = c.CreateCGImage(output, output.Extent))
{
transform?.Dispose();
output?.Dispose();
sourceImage?.Dispose();

/// <summary>
/// Resize image to maximum size
/// keeping the aspect ratio
/// </summary>
public static UIImage ResizeImageWithAspectRatio(this UIImage sourceImage, float maxWidth, float maxHeight)
{

return UIImage.FromImage(cgi, 1.0f, orientation);
}

}
}

/// <summary>
/// Resize image to maximum size
/// keeping the aspect ratio
/// </summary>
public static UIImage ResizeImageWithAspectRatio(this UIImage sourceImage, float maxWidth, float maxHeight)
{
var sourceSize = sourceImage.Size;
var maxResizeFactor = Math.Max(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
if (maxResizeFactor > 1)
Expand Down

0 comments on commit 81378a4

Please sign in to comment.