예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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;
                }
            }
        }
예제 #3
0
        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;
                }
            }
        }
예제 #5
0
        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));
                }
            }
        }
예제 #6
0
        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));
                }
            }
        }
예제 #7
0
 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));
     }
 }
예제 #8
0
        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);
        }
예제 #9
0
        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));
        }
예제 #10
0
        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);
            }
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        // 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;
                }
            }
        }
예제 #13
0
        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);
                }
            }
        }
예제 #14
0
        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;
        }
예제 #15
0
        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
            });
        }
예제 #16
0
        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);
        }
예제 #17
0
        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
            });
        }
예제 #18
0
        // 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);
            }
        }
예제 #19
0
        // 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);
            }
        }