public async Task <IDecodedImage <Bitmap> > DecodeAsync(Stream stream, string path, ImageSource source, ImageInformation imageInformation, TaskParameter parameters) { var result = new DecodedImage <Bitmap>(); var helper = new PlatformGifHelper(); await helper.ReadGifAsync(stream, path, parameters); result.IsAnimated = helper.Frames.Count > 1; if (result.IsAnimated && Configuration.AnimateGifs) { result.AnimatedImages = new AnimatedImage <Bitmap> [helper.Frames.Count]; for (int i = 0; i < helper.Frames.Count; i++) { var animatedImage = new AnimatedImage <Bitmap> { Delay = helper.Frames[i].Delay, Image = helper.Frames[i].Image }; result.AnimatedImages[i] = animatedImage; } } else { result.IsAnimated = false; result.Image = helper.Frames[0].Image; } if (result.Image != null) { imageInformation.SetOriginalSize(result.Image.Width, result.Image.Height); imageInformation.SetCurrentSize(result.Image.Width, result.Image.Height); } else if (result.AnimatedImages != null) { if (result.AnimatedImages.Length > 0) { if (result.AnimatedImages[0].Image != null) { imageInformation.SetOriginalSize(result.AnimatedImages[0].Image.Width, result.AnimatedImages[0].Image.Height); imageInformation.SetCurrentSize(result.AnimatedImages[0].Image.Width, result.AnimatedImages[0].Image.Height); } } } return(result); }
public static async Task <WriteableBitmap> ToBitmapImageAsync(this Stream imageStream, Tuple <int, int> downscale, bool downscaleDipUnits, InterpolationMode mode, bool allowUpscale, ImageInformation imageInformation = null) { if (imageStream == null) { return(null); } using (imageStream) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { return(imageStream.ResizeImage(downscale.Item1, downscale.Item2, mode, downscaleDipUnits, allowUpscale, imageInformation)); } BitmapDecoder decoder = NewDecoder(imageStream); BitmapFrame firstFrame = decoder.Frames.First(); firstFrame.Freeze(); imageStream.Seek(0L, SeekOrigin.Begin); WriteableBitmap bitmap = null; if (imageInformation != null) { imageInformation.SetCurrentSize(firstFrame.PixelWidth, firstFrame.PixelHeight); imageInformation.SetOriginalSize(firstFrame.PixelWidth, firstFrame.PixelHeight); } await ImageService.Instance.Config.MainThreadDispatcher.PostAsync(delegate { bitmap = new WriteableBitmap(firstFrame); bitmap.Freeze(); }).ConfigureAwait(continueOnCapturedContext: false); return(bitmap); } }
public static Task <ImageSource> ToBitmapImageAsync(this Stream imageStream, Tuple <int, int> downscale, bool downscaleDipUnits, InterpolationMode mode, bool allowUpscale, ImageInformation imageInformation = null) { if (imageStream == null) { return(Task.FromResult <ImageSource>(null)); } var task = new Task <ImageSource>(() => { var decoder = BitmapDecoder.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); var frame = decoder.Frames[0]; frame.Freeze(); if (imageInformation != null) { imageInformation.SetCurrentSize(frame.PixelWidth, frame.PixelHeight); imageInformation.SetOriginalSize(frame.PixelWidth, frame.PixelHeight); } return(frame); }); task.Start(); return(task); }
public Task <IDecodedImage <SharedEvasImage> > DecodeAsync(Stream imageData, string path, ImageSource source, ImageInformation imageInformation, TaskParameter parameters) { if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } TaskCompletionSource <IDecodedImage <SharedEvasImage> > tcs = new TaskCompletionSource <IDecodedImage <SharedEvasImage> >(); ImageService.Instance.Config.MainThreadDispatcher.PostAsync(() => { SharedEvasImage img = new SharedEvasImage(MainWindow); img.IsFilled = true; img.Show(); img.SetStream(imageData); imageData.TryDispose(); img.AddRef(); EcoreMainloop.AddTimer(1.0, () => { img.RemoveRef(); return(false); }); imageInformation.SetOriginalSize(img.Size.Width, img.Size.Height); imageInformation.SetCurrentSize(img.Size.Width, img.Size.Height); // DOWNSAMPLE if (parameters.DownSampleSize != null && (parameters.DownSampleSize.Item1 > 0 || parameters.DownSampleSize.Item2 > 0)) { // Calculate inSampleSize int downsampleWidth = parameters.DownSampleSize.Item1; int downsampleHeight = parameters.DownSampleSize.Item2; if (parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } int scaleDownFactor = CalculateScaleDownFactor(img.Size.Width, img.Size.Height, downsampleWidth, downsampleHeight); if (scaleDownFactor > 1) { //System.//Console.WriteLine("GenerateImageAsync:: DownSample with {0}", scaleDownFactor); imageInformation.SetCurrentSize( (int)((double)img.Size.Width / scaleDownFactor), (int)((double)img.Size.Height / scaleDownFactor)); EvasInterop.evas_object_image_load_scale_down_set(img.RealHandle, scaleDownFactor); } } tcs.SetResult(new DecodedImage <SharedEvasImage>() { Image = img }); }).ConfigureAwait(false); return(tcs.Task); }
public async static Task <WriteableBitmap> ToBitmapImageAsync(this Stream imageStream, Tuple <int, int> downscale, bool useDipUnits, InterpolationMode mode, ImageInformation imageInformation = null) { if (imageStream == null) { return(null); } using (IRandomAccessStream image = new RandomStream(imageStream)) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, useDipUnits, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); downscaledImage.Seek(0); WriteableBitmap resizedBitmap = null; await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { resizedBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); using (var s = downscaledImage.AsStream()) { resizedBitmap.SetSource(s); } }); return(resizedBitmap); } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); image.Seek(0); WriteableBitmap bitmap = null; if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); bitmap.SetSource(imageStream); }); return(bitmap); } } }
public async static Task <WriteableBitmap> ToBitmapImageAsync(this Stream imageStream, Tuple <int, int> downscale, bool downscaleDipUnits, InterpolationMode mode, bool allowUpscale, ImageInformation imageInformation = null) { if (imageStream == null) { return(null); } using (IRandomAccessStream image = imageStream.AsRandomAccessStream()) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, downscaleDipUnits, allowUpscale, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); downscaledImage.Seek(0); WriteableBitmap resizedBitmap = null; await MainThreadDispatcher.Instance.PostAsync(async() => { resizedBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); await resizedBitmap.SetSourceAsync(downscaledImage); }); return(resizedBitmap); } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); image.Seek(0); WriteableBitmap bitmap = null; if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } await MainThreadDispatcher.Instance.PostAsync(async() => { bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); await bitmap.SetSourceAsync(image); }); return(bitmap); } } }
public async static Task<WriteableBitmap> ToBitmapImageAsync(this Stream imageStream, Tuple<int, int> downscale, bool useDipUnits, InterpolationMode mode, ImageInformation imageInformation = null) { if (imageStream == null) return null; using (IRandomAccessStream image = new RandomStream(imageStream)) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, useDipUnits, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); downscaledImage.Seek(0); WriteableBitmap resizedBitmap = null; await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { resizedBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); using (var s = downscaledImage.AsStream()) { resizedBitmap.SetSource(s); } }); return resizedBitmap; } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); image.Seek(0); WriteableBitmap bitmap = null; if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); bitmap.SetSource(imageStream); }); return bitmap; } } }
public static WriteableBitmap ResizeImage(this Stream imageStream, int width, int height, InterpolationMode interpolationMode, bool useDipUnits, bool allowUpscale, ImageInformation imageInformation = null) { if (useDipUnits) { width = width.DpToPixels(); height = height.DpToPixels(); } WriteableBitmap writeableBitmap = null; BitmapDecoder bitmapDecoder = NewDecoder(imageStream); BitmapFrame bitmapFrame = bitmapDecoder.Frames.First(); if ((height > 0 && bitmapFrame.PixelHeight > height) || (width > 0 && bitmapFrame.PixelWidth > width) || allowUpscale) { using (imageStream) { double num = (double)width / (double)bitmapFrame.PixelWidth; double num2 = (double)height / (double)bitmapFrame.PixelHeight; double num3 = Math.Min(num, num2); if (width == 0) { num3 = num2; } if (height == 0) { num3 = num; } uint height2 = (uint)Math.Floor((double)bitmapFrame.PixelHeight * num3); uint width2 = (uint)Math.Floor((double)bitmapFrame.PixelWidth * num3); TransformedBitmap source = new TransformedBitmap(bitmapFrame, new ScaleTransform(num3, num3)); if (imageInformation != null) { imageInformation.SetOriginalSize(bitmapFrame.PixelWidth, bitmapFrame.PixelHeight); imageInformation.SetCurrentSize((int)width2, (int)height2); } writeableBitmap = new WriteableBitmap(source); } } else { writeableBitmap = new WriteableBitmap(bitmapFrame); } if (!writeableBitmap.IsFrozen) { writeableBitmap.Freeze(); } return(writeableBitmap); }
public async static Task<WriteableBitmap> ToBitmapImageAsync(this Stream imageStream, Tuple<int, int> downscale, bool downscaleDipUnits, InterpolationMode mode, ImageInformation imageInformation = null) { if (imageStream == null) return null; using (IRandomAccessStream image = imageStream.AsRandomAccessStream()) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, downscaleDipUnits, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); downscaledImage.Seek(0); WriteableBitmap resizedBitmap = null; await MainThreadDispatcher.Instance.PostAsync(async () => { resizedBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); await resizedBitmap.SetSourceAsync(downscaledImage); }); return resizedBitmap; } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); image.Seek(0); WriteableBitmap bitmap = null; if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } await MainThreadDispatcher.Instance.PostAsync(async () => { bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); await bitmap.SetSourceAsync(image); }); return bitmap; } } }
public async static Task <BitmapHolder> ToBitmapHolderAsync(this Stream imageStream, Tuple <int, int> downscale, bool downscaleDipUnits, InterpolationMode mode, bool allowUpscale, ImageInformation imageInformation = null) { if (imageStream == null) { return(null); } using (IRandomAccessStream image = imageStream.AsRandomAccessStream()) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, downscaleDipUnits, allowUpscale, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); PixelDataProvider pixelDataProvider = await decoder.GetPixelDataAsync( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, new BitmapTransform(), ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage); var bytes = pixelDataProvider.DetachPixelData(); return(new BitmapHolder(bytes, (int)decoder.PixelWidth, (int)decoder.PixelHeight)); } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); PixelDataProvider pixelDataProvider = await decoder.GetPixelDataAsync( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, new BitmapTransform(), ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage); if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } var bytes = pixelDataProvider.DetachPixelData(); return(new BitmapHolder(bytes, (int)decoder.PixelWidth, (int)decoder.PixelHeight)); } } }
public async static Task <BitmapHolder> ToBitmapHolderAsync(this Stream imageStream, Tuple <int, int> downscale, bool useDipUnits, InterpolationMode mode, ImageInformation imageInformation = null) { if (imageStream == null) { return(null); } using (IRandomAccessStream image = new RandomStream(imageStream)) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, useDipUnits, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); PixelDataProvider pixelDataProvider = await decoder.GetPixelDataAsync(); var bytes = pixelDataProvider.DetachPixelData(); int[] array = new int[decoder.PixelWidth * decoder.PixelHeight]; CopyPixels(bytes, array); return(new BitmapHolder(array, (int)decoder.PixelWidth, (int)decoder.PixelHeight)); } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); PixelDataProvider pixelDataProvider = await decoder.GetPixelDataAsync(); if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } var bytes = pixelDataProvider.DetachPixelData(); int[] array = new int[decoder.PixelWidth * decoder.PixelHeight]; CopyPixels(bytes, array); return(new BitmapHolder(array, (int)decoder.PixelWidth, (int)decoder.PixelHeight)); } } }
public static async Task <BitmapHolder> ToBitmapHolderAsync(this Stream imageStream, Tuple <int, int> downscale, bool downscaleDipUnits, InterpolationMode mode, bool allowUpscale, ImageInformation imageInformation = null) { if (imageStream == null) { return(null); } using (imageStream) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { WriteableBitmap downscaledImage = imageStream.ResizeImage(downscale.Item1, downscale.Item2, mode, downscaleDipUnits, allowUpscale, imageInformation); return(new BitmapHolder(await downscaledImage.ToBytesAsync(), downscaledImage.PixelWidth, downscaledImage.PixelHeight)); } BitmapDecoder decoder = NewDecoder(imageStream); BitmapFrame firstFrame = decoder.Frames.First(); firstFrame.Freeze(); if (imageInformation != null) { imageInformation.SetCurrentSize(firstFrame.PixelWidth, firstFrame.PixelHeight); imageInformation.SetOriginalSize(firstFrame.PixelWidth, firstFrame.PixelHeight); } return(new BitmapHolder(await firstFrame.ToBytesAsync(), firstFrame.PixelWidth, firstFrame.PixelHeight)); } }
public async Task <IDecodedImage <Bitmap> > DecodeAsync(Stream imageData, string path, ImageSource source, ImageInformation imageInformation, TaskParameter parameters) { BitmapFactory.Options options = null; Bitmap bitmap = null; if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } if (options == null) { // First decode with inJustDecodeBounds=true to check dimensions options = new BitmapFactory.Options { InJustDecodeBounds = true, }; await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } options.InPurgeable = true; options.InJustDecodeBounds = false; options.InDither = true; options.InScaled = false; options.InDensity = 0; options.InTargetDensity = 0; imageInformation.SetOriginalSize(options.OutWidth, options.OutHeight); imageInformation.SetCurrentSize(options.OutWidth, options.OutHeight); if (!Configuration.BitmapOptimizations || (parameters.BitmapOptimizationsEnabled.HasValue && !parameters.BitmapOptimizationsEnabled.Value)) { // Same quality but no transparency channel. This allows to save 50% of memory: 1 pixel=2bytes instead of 4. options.InPreferredConfig = Bitmap.Config.Rgb565; options.InPreferQualityOverSpeed = false; } // CHECK IF BITMAP IS EXIF ROTATED var exifOrientation = ExifOrientation.ORIENTATION_UNDEFINED; if ((source == ImageSource.Filepath || source == ImageSource.Stream || source == ImageSource.Url) && imageInformation.Type != ImageInformation.ImageType.SVG && imageInformation.Exif != null) { try { var ifd0 = imageInformation.Exif.FirstOrDefault(v => v.HasTagName(ExifDirectoryBase.TagOrientation)); var orientationTag = ifd0?.Tags?.FirstOrDefault(v => v.Type == ExifDirectoryBase.TagOrientation); if (int.TryParse(orientationTag?.Value, out var orientation) && orientation >= 0 && orientation <= 8) { exifOrientation = (ExifOrientation)orientation; } } catch (Exception ex) { Logger.Error("Reading EXIF orientation failed", ex); } } if (imageData.Position != 0) { imageData.Position = 0; } // DOWNSAMPLE if (parameters.DownSampleSize != null && (parameters.DownSampleSize.Item1 > 0 || parameters.DownSampleSize.Item2 > 0)) { // Calculate inSampleSize var downsampleWidth = parameters.DownSampleSize.Item1; var downsampleHeight = parameters.DownSampleSize.Item2; if (parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } options.InSampleSize = CalculateInSampleSize(options.OutWidth, options.OutHeight, downsampleWidth, downsampleHeight, parameters.AllowUpscale ?? Configuration.AllowUpscale); if (options.InSampleSize > 1) { imageInformation.SetCurrentSize( (int)((double)options.OutWidth / options.InSampleSize), (int)((double)options.OutHeight / options.InSampleSize)); } // If we're running on Honeycomb or newer, try to use inBitmap if (Utils.HasHoneycomb()) { AddInBitmapOptions(options); } } if (imageData.Position != 0) { imageData.Position = 0; } try { bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } catch (Java.Lang.IllegalArgumentException) { var old = options.InBitmap as object as ISelfDisposingBitmapDrawable; old?.SetIsRetained(true); options.InBitmap = null; bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } // if image is rotated, swap width/height if (exifOrientation != ExifOrientation.ORIENTATION_UNDEFINED && exifOrientation != ExifOrientation.ORIENTATION_NORMAL) { bitmap = bitmap.ToRotatedBitmap(exifOrientation); //ImageCache.Instance.AddToReusableSet(new SelfDisposingBitmapDrawable(Context.Resources, oldBitmap) { InCacheKey = Guid.NewGuid().ToString() }); } return(new DecodedImage <Bitmap>() { Image = bitmap }); }
async Task <Bitmap> PlatformGenerateBitmapAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder, BitmapFactory.Options options = null) { Bitmap bitmap = null; if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } ThrowIfCancellationRequested(); try { if (options == null) { // First decode with inJustDecodeBounds=true to check dimensions options = new BitmapFactory.Options { InJustDecodeBounds = true, }; await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } ThrowIfCancellationRequested(); options.InPurgeable = true; options.InJustDecodeBounds = false; options.InDither = true; imageInformation.SetOriginalSize(options.OutWidth, options.OutHeight); imageInformation.SetCurrentSize(options.OutWidth, options.OutHeight); if (!Configuration.BitmapOptimizations || (Parameters.BitmapOptimizationsEnabled.HasValue && !Parameters.BitmapOptimizationsEnabled.Value)) { // Same quality but no transparency channel. This allows to save 50% of memory: 1 pixel=2bytes instead of 4. options.InPreferredConfig = Bitmap.Config.Rgb565; options.InPreferQualityOverSpeed = false; } // CHECK IF BITMAP IS EXIF ROTATED int exifRotation = 0; if (source == ImageSource.Filepath) { try { exifRotation = path.GetExifRotationDegrees(); } catch (Exception ex) { Logger.Error("Reading EXIF orientation failed", ex); } } ThrowIfCancellationRequested(); // DOWNSAMPLE if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0)) { // Calculate inSampleSize int downsampleWidth = Parameters.DownSampleSize.Item1; int downsampleHeight = Parameters.DownSampleSize.Item2; // if image is rotated, swap width/height if (exifRotation == 90 || exifRotation == 270) { downsampleWidth = Parameters.DownSampleSize.Item2; downsampleHeight = Parameters.DownSampleSize.Item1; } if (Parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } options.InSampleSize = CalculateInSampleSize(options, downsampleWidth, downsampleHeight, Parameters.AllowUpscale ?? Configuration.AllowUpscale); if (options.InSampleSize > 1) { imageInformation.SetCurrentSize( (int)((double)options.OutWidth / options.InSampleSize), (int)((double)options.OutHeight / options.InSampleSize)); } // If we're running on Honeycomb or newer, try to use inBitmap if (Utils.HasHoneycomb()) { AddInBitmapOptions(options); } } if (imageData.Position != 0) { imageData.Position = 0; } ThrowIfCancellationRequested(); bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } finally { imageData.TryDispose(); } ThrowIfCancellationRequested(); bitmap = await PlatformTransformAsync(path, source, enableTransformations, isPlaceholder, bitmap); return(bitmap); }
public async Task <IDecodedImage <Bitmap> > DecodeAsync(Stream imageData, string path, ImageSource source, ImageInformation imageInformation, TaskParameter parameters) { BitmapFactory.Options options = null; Bitmap bitmap = null; if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } if (options == null) { // First decode with inJustDecodeBounds=true to check dimensions options = new BitmapFactory.Options { InJustDecodeBounds = true, }; await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } options.InPurgeable = true; options.InJustDecodeBounds = false; options.InDither = true; imageInformation.SetOriginalSize(options.OutWidth, options.OutHeight); imageInformation.SetCurrentSize(options.OutWidth, options.OutHeight); if (!Configuration.BitmapOptimizations || (parameters.BitmapOptimizationsEnabled.HasValue && !parameters.BitmapOptimizationsEnabled.Value)) { // Same quality but no transparency channel. This allows to save 50% of memory: 1 pixel=2bytes instead of 4. options.InPreferredConfig = Bitmap.Config.Rgb565; options.InPreferQualityOverSpeed = false; } // CHECK IF BITMAP IS EXIF ROTATED int exifRotation = 0; if ((source == ImageSource.Filepath || source == ImageSource.Stream || source == ImageSource.Url) && imageInformation.Type != ImageInformation.ImageType.SVG) { try { exifRotation = imageData.GetExifRotationDegrees(); } catch (Exception ex) { Logger.Error("Reading EXIF orientation failed", ex); } } if (imageData.Position != 0) { imageData.Position = 0; } // DOWNSAMPLE if (parameters.DownSampleSize != null && (parameters.DownSampleSize.Item1 > 0 || parameters.DownSampleSize.Item2 > 0)) { // Calculate inSampleSize int downsampleWidth = parameters.DownSampleSize.Item1; int downsampleHeight = parameters.DownSampleSize.Item2; if (parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } options.InSampleSize = CalculateInSampleSize(options, downsampleWidth, downsampleHeight, parameters.AllowUpscale ?? Configuration.AllowUpscale); if (options.InSampleSize > 1) { imageInformation.SetCurrentSize( (int)((double)options.OutWidth / options.InSampleSize), (int)((double)options.OutHeight / options.InSampleSize)); } // If we're running on Honeycomb or newer, try to use inBitmap if (Utils.HasHoneycomb()) { AddInBitmapOptions(options); } } if (imageData.Position != 0) { imageData.Position = 0; } bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); // if image is rotated, swap width/height if (exifRotation != 0) { var oldBitmap = bitmap; bitmap = bitmap.ToRotatedBitmap(exifRotation); ImageCache.Instance.AddToReusableSet(new SelfDisposingBitmapDrawable(oldBitmap) { InCacheKey = Guid.NewGuid().ToString() }); } return(new DecodedImage <Bitmap>() { Image = bitmap }); }
public static async Task<IRandomAccessStream> ResizeImage(this IRandomAccessStream imageStream, int width, int height, InterpolationMode interpolationMode, bool useDipUnits, ImageInformation imageInformation = null) { if (useDipUnits) { width = width.PointsToPixels(); height = height.PointsToPixels(); } IRandomAccessStream resizedStream = imageStream; var decoder = await BitmapDecoder.CreateAsync(imageStream); if (decoder.PixelHeight > height || decoder.PixelWidth > width) { using (imageStream) { resizedStream = new InMemoryRandomAccessStream(); BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder); double widthRatio = (double)width / decoder.PixelWidth; double heightRatio = (double)height / decoder.PixelHeight; double scaleRatio = Math.Min(widthRatio, heightRatio); if (width == 0) scaleRatio = heightRatio; if (height == 0) scaleRatio = widthRatio; uint aspectHeight = (uint)Math.Floor(decoder.PixelHeight * scaleRatio); uint aspectWidth = (uint)Math.Floor(decoder.PixelWidth * scaleRatio); if (interpolationMode == InterpolationMode.None) encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.NearestNeighbor; else if (interpolationMode == InterpolationMode.Low) encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear; else if (interpolationMode == InterpolationMode.Medium) encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Cubic; else if (interpolationMode == InterpolationMode.High) encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant; else encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear; encoder.BitmapTransform.ScaledHeight = aspectHeight; encoder.BitmapTransform.ScaledWidth = aspectWidth; if (imageInformation != null) { imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetCurrentSize((int)aspectWidth, (int)aspectHeight); } await encoder.FlushAsync(); resizedStream.Seek(0); } } return resizedStream; }
public static async Task <IRandomAccessStream> ResizeImage(this IRandomAccessStream imageStream, int width, int height, InterpolationMode interpolationMode, bool useDipUnits, ImageInformation imageInformation = null) { if (useDipUnits) { width = width.PointsToPixels(); height = height.PointsToPixels(); } IRandomAccessStream resizedStream = imageStream; var decoder = await BitmapDecoder.CreateAsync(imageStream); if (decoder.PixelHeight > height || decoder.PixelWidth > width) { using (imageStream) { resizedStream = new InMemoryRandomAccessStream(); BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder); double widthRatio = (double)width / decoder.PixelWidth; double heightRatio = (double)height / decoder.PixelHeight; double scaleRatio = Math.Min(widthRatio, heightRatio); if (width == 0) { scaleRatio = heightRatio; } if (height == 0) { scaleRatio = widthRatio; } uint aspectHeight = (uint)Math.Floor(decoder.PixelHeight * scaleRatio); uint aspectWidth = (uint)Math.Floor(decoder.PixelWidth * scaleRatio); if (interpolationMode == InterpolationMode.None) { encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.NearestNeighbor; } else if (interpolationMode == InterpolationMode.Low) { encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear; } else if (interpolationMode == InterpolationMode.Medium) { encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Cubic; } else if (interpolationMode == InterpolationMode.High) { encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant; } else { encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear; } encoder.BitmapTransform.ScaledHeight = aspectHeight; encoder.BitmapTransform.ScaledWidth = aspectWidth; if (imageInformation != null) { imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetCurrentSize((int)aspectWidth, (int)aspectHeight); } await encoder.FlushAsync(); resizedStream.Seek(0); } } return(resizedStream); }
async Task <ISelfDisposingBitmapDrawable> PlatformGenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder) { Bitmap bitmap = null; if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } ThrowIfCancellationRequested(); // First decode with inJustDecodeBounds=true to check dimensions var options = new BitmapFactory.Options { InJustDecodeBounds = true }; try { await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); ThrowIfCancellationRequested(); options.InPurgeable = true; options.InJustDecodeBounds = false; options.InDither = true; imageInformation.SetOriginalSize(options.OutWidth, options.OutHeight); imageInformation.SetCurrentSize(options.OutWidth, options.OutHeight); if (!Configuration.BitmapOptimizations || (Parameters.BitmapOptimizationsEnabled.HasValue && !Parameters.BitmapOptimizationsEnabled.Value)) { // Same quality but no transparency channel. This allows to save 50% of memory: 1 pixel=2bytes instead of 4. options.InPreferredConfig = Bitmap.Config.Rgb565; options.InPreferQualityOverSpeed = false; } // CHECK IF BITMAP IS EXIF ROTATED int exifRotation = 0; if (source == ImageSource.Filepath) { exifRotation = path.GetExifRotationDegrees(); } ThrowIfCancellationRequested(); // DOWNSAMPLE if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0)) { // Calculate inSampleSize int downsampleWidth = Parameters.DownSampleSize.Item1; int downsampleHeight = Parameters.DownSampleSize.Item2; // if image is rotated, swap width/height if (exifRotation == 90 || exifRotation == 270) { downsampleWidth = Parameters.DownSampleSize.Item2; downsampleHeight = Parameters.DownSampleSize.Item1; } if (Parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } options.InSampleSize = CalculateInSampleSize(options, downsampleWidth, downsampleHeight); if (options.InSampleSize > 1) { imageInformation.SetCurrentSize( (int)((double)options.OutWidth / options.InSampleSize), (int)((double)options.OutHeight / options.InSampleSize)); } // If we're running on Honeycomb or newer, try to use inBitmap if (Utils.HasHoneycomb()) { AddInBitmapOptions(options); } } ThrowIfCancellationRequested(); if (!imageData.CanSeek || imageData.Position != 0) { if (imageData.CanSeek) { imageData.Position = 0; } else { var resolver = DataResolverFactory.GetResolver(path, source, Parameters, Configuration); var resolved = await resolver.Resolve(path, Parameters, CancellationTokenSource.Token).ConfigureAwait(false); imageData?.Dispose(); imageData = resolved.Item1; } } ThrowIfCancellationRequested(); bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } 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 = bitmap; try { var bitmapHolder = transformation.Transform(new BitmapHolder(bitmap)); bitmap = bitmapHolder.ToNative(); } catch (Exception ex) { Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex); throw; } finally { // Transformation succeeded, so garbage the source if (old != null && old.Handle != IntPtr.Zero && !old.IsRecycled && old != bitmap && old.Handle != bitmap.Handle) { old?.Recycle(); old?.Dispose(); } } } } finally { _decodingLock.Release(); } } if (isPlaceholder) { return(new SelfDisposingBitmapDrawable(Context.Resources, bitmap)); } //var imageDrawable = new SelfDisposingBitmapDrawable(Context.Resources, bitmap); //ISelfDisposingBitmapDrawable placeholderDrawable = null; //if (_loadingPlaceholderWeakReference != null && _loadingPlaceholderWeakReference.TryGetTarget(out placeholderDrawable) && placeholderDrawable != null) //{ // return new SelfDisposingTransitionDrawable(imageDrawable, placeholderDrawable as SelfDisposingBitmapDrawable); //} //return imageDrawable; return(new FFBitmapDrawable(Context.Resources, bitmap)); }
public async static Task<BitmapHolder> ToBitmapHolderAsync(this Stream imageStream, Tuple<int, int> downscale, bool useDipUnits, InterpolationMode mode, ImageInformation imageInformation = null) { if (imageStream == null) return null; using (IRandomAccessStream image = new RandomStream(imageStream)) { if (downscale != null && (downscale.Item1 > 0 || downscale.Item2 > 0)) { using (var downscaledImage = await image.ResizeImage(downscale.Item1, downscale.Item2, mode, useDipUnits, imageInformation).ConfigureAwait(false)) { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(downscaledImage); PixelDataProvider pixelDataProvider = await decoder.GetPixelDataAsync(); var bytes = pixelDataProvider.DetachPixelData(); int[] array = new int[decoder.PixelWidth * decoder.PixelHeight]; CopyPixels(bytes, array); return new BitmapHolder(array, (int)decoder.PixelWidth, (int)decoder.PixelHeight); } } else { BitmapDecoder decoder = await BitmapDecoder.CreateAsync(image); PixelDataProvider pixelDataProvider = await decoder.GetPixelDataAsync(); if (imageInformation != null) { imageInformation.SetCurrentSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); imageInformation.SetOriginalSize((int)decoder.PixelWidth, (int)decoder.PixelHeight); } var bytes = pixelDataProvider.DetachPixelData(); int[] array = new int[decoder.PixelWidth * decoder.PixelHeight]; CopyPixels(bytes, array); return new BitmapHolder(array, (int)decoder.PixelWidth, (int)decoder.PixelHeight); } } }
public static async Task <IDecodedImage <PImage> > SourceRegfToDecodedImageAsync(NSData nsdata, CGSize destSize, nfloat destScale, Configuration config, TaskParameter parameters, RCTResizeMode resizeMode = RCTResizeMode.ScaleAspectFit, ImageInformation imageinformation = null, bool allowUpscale = false) { using (var sourceRef = CGImageSource.FromData(nsdata)) { if (sourceRef == null) { throw new BadImageFormatException("Decoded image is null or corrupted"); } var imageProperties = sourceRef.GetProperties(0); if (imageProperties == null || !imageProperties.PixelWidth.HasValue || !imageProperties.PixelHeight.HasValue) { throw new BadImageFormatException("Can't read image size properties. File corrupted?"); } imageinformation.SetOriginalSize(imageProperties.PixelWidth.Value, imageProperties.PixelHeight.Value); var sourceSize = new CGSize(imageProperties.PixelWidth.Value, imageProperties.PixelHeight.Value); if (destSize.IsEmpty) { destSize = sourceSize; if (destScale <= 0) { destScale = 1; } } else if (destScale <= 0) { destScale = ScaleHelper.Scale; } // Calculate target size var targetSize = RCTTargetSize(sourceSize, 1, destSize, destScale, resizeMode, allowUpscale); var targetPixelSize = RCTSizeInPixels(targetSize, destScale); var maxPixelSize = (int)Math.Max( allowUpscale ? targetPixelSize.Width : Math.Min(sourceSize.Width, targetPixelSize.Width), allowUpscale ? targetPixelSize.Height : Math.Min(sourceSize.Height, targetPixelSize.Height) ); var options = new CGImageThumbnailOptions() { ShouldAllowFloat = true, CreateThumbnailWithTransform = true, CreateThumbnailFromImageAlways = true, MaxPixelSize = maxPixelSize, ShouldCache = false, }; PImage image = null; IAnimatedImage <PImage>[] images = null; // GIF if (sourceRef.ImageCount > 1 && config.AnimateGifs && imageinformation.Type != ImageInformation.ImageType.ICO) { try { await _gifLock.WaitAsync().ConfigureAwait(false); var frameCount = sourceRef.ImageCount; // no need to animate, fail safe. if (frameCount <= 1) { using (var imageRef = sourceRef.CreateThumbnail(0, options)) { #if __IOS__ || __TVOS__ image = new PImage(imageRef, destScale, UIImageOrientation.Up); #elif __MACOS__ image = new PImage(imageRef, CGSize.Empty); #endif } } #if __IOS__ || __TVOS__ var frames = GetFrames(sourceRef, options); var delays = GetDelays(sourceRef); var totalDuration = delays.Sum(); var adjustedFrames = AdjustFramesToSpoofDurations(frames, destScale, delays, totalDuration); var avgDuration = (double)totalDuration / adjustedFrames.Length; images = new AnimatedImage <PImage> [adjustedFrames.Length]; for (int i = 0; i < images.Length; i++) { images[i] = new AnimatedImage <PImage>() { Image = adjustedFrames[i], Delay = (int)avgDuration }; } #elif __MACOS__ images = new AnimatedImage <PImage> [frameCount]; var delays = GetDelays(sourceRef); for (var i = 0; i < images.Length; i++) { var nsImage = new PImage(sourceRef.CreateThumbnail(i, options), CGSize.Empty); images[i] = new AnimatedImage <PImage>() { Image = nsImage, Delay = delays[i] }; } #endif } finally { _gifLock.Release(); } } else { // Get thumbnail using (var imageRef = sourceRef.CreateThumbnail(0, options)) { if (imageRef != null) { #if __IOS__ || __TVOS__ image = new PImage(imageRef, destScale, UIImageOrientation.Up); #elif __MACOS__ image = new PImage(imageRef, CGSize.Empty); #endif } } } var result = new DecodedImage <PImage>(); if (images != null && images.Length > 1) { result.IsAnimated = true; result.AnimatedImages = images; if (imageinformation != null) { var width = (int)images[0].Image.Size.Width; var height = (int)images[0].Image.Size.Height; imageinformation.SetCurrentSize(width.DpToPixels(), height.DpToPixels()); } } else { result.Image = image; if (imageinformation != null) { var width = (int)image.Size.Width; var height = (int)image.Size.Height; imageinformation.SetCurrentSize(width.DpToPixels(), height.DpToPixels()); } } return(result); } }
// 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) { using (var sourceRef = CGImageSource.FromData(data)) { if (sourceRef == null) { return null; } // Get original image size var imageProperties = sourceRef.GetProperties(0); if (imageProperties == null) { return 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, false); 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, }; // Get thumbnail using (var imageRef = sourceRef.CreateThumbnail(0, options)) { if (imageRef == null) { return null; } // Return image var image = new UIImage(imageRef, destScale, UIImageOrientation.Up); if (imageinformation != null) { int width = (int)image.Size.Width; int height = (int)image.Size.Height; imageinformation.SetCurrentSize(width.PointsToPixels(), height.PointsToPixels()); } return image; } } }
public async Task <IDecodedImage <Bitmap> > DecodeAsync(Stream stream, string path, ImageSource source, ImageInformation imageInformation, TaskParameter parameters) { var result = new DecodedImage <Bitmap>(); using (var gifDecoder = new GifHelper()) { var insampleSize = 1; // DOWNSAMPLE if (parameters.DownSampleSize != null && (parameters.DownSampleSize.Item1 > 0 || parameters.DownSampleSize.Item2 > 0)) { // Calculate inSampleSize var downsampleWidth = parameters.DownSampleSize.Item1; var downsampleHeight = parameters.DownSampleSize.Item2; if (parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } await gifDecoder.ReadHeaderAsync(stream).ConfigureAwait(false); insampleSize = BaseDecoder.CalculateInSampleSize(gifDecoder.Width, gifDecoder.Height, downsampleWidth, downsampleHeight, false); } await gifDecoder.ReadAsync(stream, insampleSize).ConfigureAwait(false); gifDecoder.Advance(); imageInformation.SetOriginalSize(gifDecoder.Width, gifDecoder.Height); if (insampleSize > 1) { imageInformation.SetCurrentSize(gifDecoder.DownsampledWidth, gifDecoder.DownsampledHeight); } else { imageInformation.SetCurrentSize(gifDecoder.Width, gifDecoder.Height); } result.IsAnimated = gifDecoder.FrameCount > 1 && Configuration.AnimateGifs; if (result.IsAnimated && Configuration.AnimateGifs) { result.AnimatedImages = new AnimatedImage <Bitmap> [gifDecoder.FrameCount]; for (var i = 0; i < gifDecoder.FrameCount; i++) { var animatedImage = new AnimatedImage <Bitmap> { Delay = gifDecoder.GetDelay(i), Image = await gifDecoder.GetNextFrameAsync() }; result.AnimatedImages[i] = animatedImage; gifDecoder.Advance(); } } else { result.IsAnimated = false; result.Image = await gifDecoder.GetNextFrameAsync(); } if (result.Image != null) { imageInformation.SetOriginalSize(result.Image.Width, result.Image.Height); imageInformation.SetCurrentSize(result.Image.Width, result.Image.Height); } else if (result.AnimatedImages != null) { if (result.AnimatedImages.Length > 0) { if (result.AnimatedImages[0].Image != null) { imageInformation.SetOriginalSize(result.AnimatedImages[0].Image.Width, result.AnimatedImages[0].Image.Height); imageInformation.SetCurrentSize(result.AnimatedImages[0].Image.Width, result.AnimatedImages[0].Image.Height); } } } return(result); } }
// 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); } }
// Shamelessly copied from React-Native: https://github.com/facebook/react-native/blob/2cbc9127560c5f0f89ae5aa6ff863b1818f1c7c3/Libraries/Image/RCTImageUtils.m public static NSImage ToImage(this NSData data, CGSize destSize, nfloat destScale, Configuration config, TaskParameter parameters, RCTResizeMode resizeMode = RCTResizeMode.ScaleAspectFit, ImageInformation imageinformation = null, bool allowUpscale = false) { using (var sourceRef = CGImageSource.FromData(data)) { if (sourceRef == null) { throw new BadImageFormatException("Decoded image is null or corrupted"); } var imageProperties = sourceRef.GetProperties(0); if (imageProperties == null || !imageProperties.PixelWidth.HasValue || !imageProperties.PixelHeight.HasValue) { throw new BadImageFormatException("Can't read image size properties. File corrupted?"); } imageinformation.SetOriginalSize(imageProperties.PixelWidth.Value, imageProperties.PixelHeight.Value); var sourceSize = new CGSize(imageProperties.PixelWidth.Value, imageProperties.PixelHeight.Value); 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( allowUpscale ? targetPixelSize.Width : Math.Min(sourceSize.Width, targetPixelSize.Width), allowUpscale ? targetPixelSize.Height : Math.Min(sourceSize.Height, targetPixelSize.Height) ); var options = new CGImageThumbnailOptions() { ShouldAllowFloat = true, CreateThumbnailWithTransform = true, CreateThumbnailFromImageAlways = true, MaxPixelSize = maxPixelSize, ShouldCache = false, }; NSImage image = null; // Get thumbnail using (var imageRef = sourceRef.CreateThumbnail(0, options)) { if (imageRef != null) { // Return image image = new NSImage(imageRef, CGSize.Empty); } } 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); } }