// Shamelessly copied from React-Native: https://github.com/facebook/react-native/blob/2cbc9127560c5f0f89ae5aa6ff863b1818f1c7c3/Libraries/Image/RCTImageUtils.m public static UIImage ToImage(this NSData data, CGSize destSize, nfloat destScale, RCTResizeMode resizeMode = RCTResizeMode.ScaleAspectFit, ImageInformation imageinformation = null, bool allowUpscale = false) { using (var sourceRef = CGImageSource.FromData(data)) { var imageProperties = GetImageProperties(sourceRef); if (imageProperties == null) { throw new BadImageFormatException("Image is null"); } if (imageinformation != null) { if (imageProperties.PixelWidth.HasValue && imageProperties.PixelHeight.HasValue) { imageinformation.SetOriginalSize(imageProperties.PixelWidth.Value, imageProperties.PixelHeight.Value); } } var sourceSize = new CGSize((nfloat)imageProperties.PixelWidth, (nfloat)imageProperties.PixelHeight); if (destSize.IsEmpty) { destSize = sourceSize; if (destScale <= 0) { destScale = 1; } } else if (destScale <= 0) { destScale = ScaleHelper.Scale; } // Calculate target size CGSize targetSize = RCTTargetSize(sourceSize, 1, destSize, destScale, resizeMode, allowUpscale); CGSize targetPixelSize = RCTSizeInPixels(targetSize, destScale); int maxPixelSize = (int)Math.Max( Math.Min(sourceSize.Width, targetPixelSize.Width), Math.Min(sourceSize.Height, targetPixelSize.Height) ); var options = new CGImageThumbnailOptions() { ShouldAllowFloat = true, CreateThumbnailWithTransform = true, CreateThumbnailFromImageAlways = true, MaxPixelSize = maxPixelSize, ShouldCache = false, }; UIImage image = null; // gif if (sourceRef.ImageCount > 1) { image = GifHelper.AnimateGif(sourceRef, destScale); } else { // Get thumbnail using (var imageRef = sourceRef.CreateThumbnail(0, options)) { if (imageRef != null) { // Return image image = new UIImage(imageRef, destScale, UIImageOrientation.Up); } } } if (imageinformation != null && image != null) { int width = (int)image.Size.Width; int height = (int)image.Size.Height; imageinformation.SetCurrentSize(width.PointsToPixels(), height.PointsToPixels()); } return(image); } }
protected async override Task <UIImage> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder) { UIImage imageIn = null; if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } ThrowIfCancellationRequested(); try { // Special case to handle WebP decoding on iOS string ext = null; if (!string.IsNullOrWhiteSpace(path)) { if (source == ImageSource.Url) { ext = Path.GetExtension(new Uri(path).LocalPath).ToLowerInvariant(); } else { ext = Path.GetExtension(path).ToLowerInvariant(); } } if (source != ImageSource.Stream && ext == ".webp") { imageIn = new WebP.Touch.WebPCodec().Decode(imageData); } // Special case to handle gif animations on iOS else if (source != ImageSource.Stream && ext == ".gif") { using (var nsdata = NSData.FromStream(imageData)) imageIn = GifHelper.AnimateGif(nsdata); } else { var nsdata = NSData.FromStream(imageData); int downsampleWidth = Parameters.DownSampleSize?.Item1 ?? 0; int downsampleHeight = Parameters.DownSampleSize?.Item2 ?? 0; if (Parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.PointsToPixels(); downsampleHeight = downsampleHeight.PointsToPixels(); } imageIn = nsdata.ToImage(new CoreGraphics.CGSize(downsampleWidth, downsampleHeight), ScaleHelper.Scale, NSDataExtensions.RCTResizeMode.ScaleAspectFill, imageInformation); } } finally { imageData?.Dispose(); } ThrowIfCancellationRequested(); if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0) { var transformations = Parameters.Transformations.ToList(); await _decodingLock.WaitAsync().ConfigureAwait(false); // Applying transformations is both CPU and memory intensive try { foreach (var transformation in transformations) { ThrowIfCancellationRequested(); var old = imageIn; try { var bitmapHolder = transformation.Transform(new BitmapHolder(imageIn), path, source, isPlaceholder, Key); imageIn = bitmapHolder.ToNative(); } catch (Exception ex) { Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex); throw; } finally { if (old != null && old != imageIn && old.Handle != imageIn.Handle) { old.Dispose(); } } } } finally { _decodingLock.Release(); } } return(imageIn); }