protected abstract Task <TImageContainer> GenerateImageFromDecoderContainerAsync(IDecodedImage <TDecoderContainer> decoded, ImageInformation imageInformation, bool isPlaceholder);
        async Task <TImageContainer> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            using (imageData)
            {
                var decoder          = ResolveDecoder(imageInformation.Type);
                var decoderContainer = await decoder.DecodeAsync(imageData, path, source, imageInformation, Parameters);

                if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
                {
                    var transformations = Parameters.Transformations.ToList();

                    if (decoderContainer.IsAnimated)
                    {
                        for (int i = 0; i < decoderContainer.AnimatedImages.Length; i++)
                        {
                            decoderContainer.AnimatedImages[i].Image = await TransformAsync(decoderContainer.AnimatedImages[i].Image, transformations, path, source, isPlaceholder);
                        }
                    }
                    else
                    {
                        decoderContainer.Image = await TransformAsync(decoderContainer.Image, transformations, path, source, isPlaceholder);
                    }
                }

                return(await GenerateImageFromDecoderContainerAsync(decoderContainer, imageInformation, isPlaceholder));
            }
        }
 public DataResolverResult(TImageContainer imageContainer, LoadingResult loadingResult, ImageInformation imageInformation)
 {
     ImageContainer   = imageContainer;
     LoadingResult    = loadingResult;
     ImageInformation = imageInformation;
 }
 public DataResolverResult(IDecodedImage <object> decoded, LoadingResult loadingResult, ImageInformation imageInformation)
 {
     Decoded          = decoded;
     LoadingResult    = loadingResult;
     ImageInformation = imageInformation;
 }
Exemple #5
0
        protected async override Task <PImage> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            PImage imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                int  downsampleWidth  = Parameters.DownSampleSize?.Item1 ?? 0;
                int  downsampleHeight = Parameters.DownSampleSize?.Item2 ?? 0;
                bool allowUpscale     = Parameters.AllowUpscale ?? Configuration.AllowUpscale;

                if (Parameters.DownSampleUseDipUnits)
                {
                    downsampleWidth  = downsampleWidth.PointsToPixels();
                    downsampleHeight = downsampleHeight.PointsToPixels();
                }

                // Special case to handle WebP decoding on iOS
                if (source != ImageSource.Stream && imageInformation.Type == ImageInformation.ImageType.WEBP)
                {
#if __IOS__
                    await _webpLock.WaitAsync(CancellationTokenSource.Token).ConfigureAwait(false);

                    ThrowIfCancellationRequested();
                    try
                    {
                        var decoder = _webpDecoder as WebP.Touch.WebPCodec;
                        if (decoder == null)
                        {
                            decoder      = new WebP.Touch.WebPCodec();
                            _webpDecoder = decoder;
                        }
                        var decodedWebP = decoder.Decode(imageData);
                        //TODO Add WebP images downsampling!
                        imageIn = decodedWebP;
                    }
                    finally
                    {
                        _webpLock.Release();
                    }
#else
                    throw new NotImplementedException();
#endif
                }
                else
                {
                    var nsdata = NSData.FromStream(imageData);
                    imageIn = nsdata.ToImage(new CoreGraphics.CGSize(downsampleWidth, downsampleHeight), ScaleHelper.Scale, Configuration, Parameters, NSDataExtensions.RCTResizeMode.ScaleAspectFill, imageInformation, allowUpscale);
                }
            }
            finally
            {
                imageData.TryDispose();
            }

            ThrowIfCancellationRequested();

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                await _decodingLock.WaitAsync(CancellationTokenSource.Token).ConfigureAwait(false); // Applying transformations is both CPU and memory intensive

                ThrowIfCancellationRequested();

                try
                {
                    bool isAnimation = false;
#if __IOS__
                    if (imageIn.Images != null)
                    {
                        isAnimation = true;
                    }
#endif
                    if (!isAnimation)
                    {
                        foreach (var transformation in transformations)
                        {
                            ThrowIfCancellationRequested();

                            var old = imageIn;

                            try
                            {
                                var bitmapHolder = transformation.Transform(new BitmapHolder(imageIn), path, source, isPlaceholder, Key);
                                imageIn = bitmapHolder.ToNative();
                            }
                            catch (Exception ex)
                            {
                                Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                                throw;
                            }
                            finally
                            {
                                if (old != null && old != imageIn && old.Handle != imageIn.Handle)
                                {
                                    old.TryDispose();
                                }
                            }
                        }
                    }
                    else
                    {
                        // no animted image support for mac implemented
#if __IOS__
                        var animatedImages = imageIn.Images.ToArray();

                        for (int i = 0; i < animatedImages.Length; i++)
                        {
                            var tempImage = animatedImages[i];

                            if (tempImage.CGImage == null)
                            {
                                continue;
                            }

                            foreach (var transformation in transformations)
                            {
                                ThrowIfCancellationRequested();

                                var old = tempImage;

                                try
                                {
                                    var bitmapHolder = transformation.Transform(new BitmapHolder(tempImage), path, source, isPlaceholder, Key);
                                    tempImage = bitmapHolder.ToNative();
                                }
                                catch (Exception ex)
                                {
                                    Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                                    throw;
                                }
                                finally
                                {
                                    if (old != null && old != tempImage && old.Handle != tempImage.Handle)
                                    {
                                        old.TryDispose();
                                    }
                                }
                            }

                            animatedImages[i] = tempImage;
                        }

                        var oldImageIn = imageIn;
                        imageIn = PImage.CreateAnimatedImage(animatedImages.Where(v => v.CGImage != null).ToArray(), imageIn.Duration);
                        oldImageIn.TryDispose();
#endif
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            return(imageIn);
        }
Exemple #6
0
        public async Task RunAsync()
        {
            LoadingResult loadingResult = LoadingResult.Failed;
            bool          success       = false;

            try
            {
                if (IsCompleted || IsCancelled || ImageService.ExitTasksEarly)
                {
                    throw new OperationCanceledException();
                }

                ThrowIfCancellationRequested();

                // LOAD IMAGE
                if (!(await TryLoadFromMemoryCacheAsync().ConfigureAwait(false)))
                {
                    Logger.Debug(string.Format("Generating/retrieving image: {0}", Key));
                    var resolver = Parameters.CustomDataResolver ?? DataResolverFactory.GetResolver(Parameters.Path, Parameters.Source, Parameters, Configuration);
                    resolver = new WrappedDataResolver(resolver);
                    var imageData = await resolver.Resolve(Parameters.Path, Parameters, CancellationTokenSource.Token).ConfigureAwait(false);

                    loadingResult = imageData.Item2;

                    using (imageData.Item1)
                    {
                        ImageInformation = imageData.Item3;
                        ImageInformation.SetKey(Key, Parameters.CustomCacheKey);
                        ImageInformation.SetPath(Parameters.Path);
                        ThrowIfCancellationRequested();

                        // Preload
                        if (Parameters.Preload && Parameters.CacheType.HasValue && Parameters.CacheType.Value == CacheType.Disk)
                        {
                            if (loadingResult == LoadingResult.Internet)
                            {
                                Logger?.Debug(string.Format("DownloadOnly success: {0}", Key));
                            }

                            success = true;

                            return;
                        }

                        ThrowIfCancellationRequested();

                        var image = await GenerateImageAsync(Parameters.Path, Parameters.Source, imageData.Item1, imageData.Item3, true, false).ConfigureAwait(false);

                        ThrowIfCancellationRequested();

                        try
                        {
                            BeforeLoading(image, false);

                            if (image != default(TImageContainer) && CanUseMemoryCache)
                            {
                                MemoryCache.Add(Key, imageData.Item3, image);
                            }

                            ThrowIfCancellationRequested();

                            bool isFadeAnimationEnabled = Parameters.FadeAnimationEnabled ?? Configuration.FadeAnimationEnabled;
                            await SetTargetAsync(image, isFadeAnimationEnabled).ConfigureAwait(false);
                        }
                        finally
                        {
                            AfterLoading(image, false);
                        }
                    }
                }

                success = true;
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException || ex is ObjectDisposedException)
                {
                    if (Configuration.VerboseLoadingCancelledLogging)
                    {
                        Logger.Debug(string.Format("Image loading cancelled: {0}", Key));
                    }
                }
                else
                {
                    if (_clearCacheOnOutOfMemory && ex is OutOfMemoryException)
                    {
                        MemoryCache.Clear();
                    }

                    Logger.Error(string.Format("Image loading failed: {0}", Key), ex);

                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnError != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            Parameters?.OnError?.Invoke(ex);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        Parameters?.OnError?.Invoke(ex);
                    }

                    try
                    {
                        // Error placeholder if enabled
                        if (!Parameters.Preload && !string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath))
                        {
                            await ShowPlaceholder(Parameters.ErrorPlaceholderPath, KeyForErrorPlaceholder,
                                                  Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                        }
                    }
                    catch (Exception ex2)
                    {
                        if (!(ex2 is OperationCanceledException))
                        {
                            Logger.Error(string.Format("Image loading failed: {0}", Key), ex);
                        }
                    }
                }
            }
            finally
            {
                try
                {
                    if (CancellationTokenSource?.IsCancellationRequested == false)
                    {
                        CancellationTokenSource.Cancel();
                    }
                }
                catch (Exception)
                {
                }

                IsCompleted = true;

                using (Parameters)
                {
                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnFinish != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            if (success)
                            {
                                Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                            }
                            Parameters?.OnFinish?.Invoke(this);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        if (success)
                        {
                            Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                        }
                        Parameters?.OnFinish?.Invoke(this);
                    }

                    ImageService.RemovePendingTask(this);
                }
            }
        }
        protected async override Task <NSImage> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            NSImage imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                int  downsampleWidth  = Parameters.DownSampleSize?.Item1 ?? 0;
                int  downsampleHeight = Parameters.DownSampleSize?.Item2 ?? 0;
                bool allowUpscale     = Parameters.AllowUpscale ?? Configuration.AllowUpscale;

                if (Parameters.DownSampleUseDipUnits)
                {
                    downsampleWidth  = downsampleWidth.PointsToPixels();
                    downsampleHeight = downsampleHeight.PointsToPixels();
                }

                var nsdata = NSData.FromStream(imageData);
                imageIn = nsdata.ToImage(new CoreGraphics.CGSize(downsampleWidth, downsampleHeight), ScaleHelper.Scale, Configuration, Parameters, NSDataExtensions.RCTResizeMode.ScaleAspectFill, imageInformation, allowUpscale);
            }
            finally
            {
                imageData?.Dispose();
            }

            ThrowIfCancellationRequested();

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                await _decodingLock.WaitAsync(CancellationTokenSource.Token).ConfigureAwait(false); // Applying transformations is both CPU and memory intensive

                ThrowIfCancellationRequested();

                try
                {
                    foreach (var transformation in transformations)
                    {
                        ThrowIfCancellationRequested();

                        var old = imageIn;

                        try
                        {
                            var bitmapHolder = transformation.Transform(new BitmapHolder(imageIn), path, source, isPlaceholder, Key);
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.Handle != imageIn.Handle)
                            {
                                old.Dispose();
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            return(imageIn);
        }
        protected async override Task <UIImage> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            UIImage imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                // Special case to handle WebP decoding on iOS
                if (source != ImageSource.Stream && path.ToLowerInvariant().EndsWith(".webp", StringComparison.InvariantCulture))
                {
                    imageIn = new WebP.Touch.WebPCodec().Decode(imageData);
                }
                else
                {
                    var nsdata           = NSData.FromStream(imageData);
                    int downsampleWidth  = Parameters.DownSampleSize?.Item1 ?? 0;
                    int downsampleHeight = Parameters.DownSampleSize?.Item2 ?? 0;

                    if (Parameters.DownSampleUseDipUnits)
                    {
                        downsampleWidth  = downsampleWidth.PointsToPixels();
                        downsampleHeight = downsampleHeight.PointsToPixels();
                    }

                    imageIn = nsdata.ToImage(new CoreGraphics.CGSize(downsampleWidth, downsampleHeight), ScaleHelper.Scale, NSDataExtensions.RCTResizeMode.ScaleAspectFill, imageInformation);
                }
            }
            finally
            {
                imageData?.Dispose();
            }

            ThrowIfCancellationRequested();

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                await _decodingLock.WaitAsync().ConfigureAwait(false); // Applying transformations is both CPU and memory intensive

                try
                {
                    foreach (var transformation in transformations)
                    {
                        ThrowIfCancellationRequested();

                        var old = imageIn;

                        try
                        {
                            var bitmapHolder = transformation.Transform(new BitmapHolder(imageIn));
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.Handle != imageIn.Handle)
                            {
                                old.Dispose();
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            return(imageIn);
        }
Exemple #9
0
 public static WithLoadingResult <T> Encapsulate <T>(T item, LoadingResult result, ImageInformation imageInformation) where T : class
 {
     return(new WithLoadingResult <T>(item, result, imageInformation));
 }
 public DataResolverResult(Stream stream, LoadingResult loadingResult, ImageInformation imageInformation)
 {
     Stream           = stream;
     LoadingResult    = loadingResult;
     ImageInformation = imageInformation;
 }
        protected override Task <PImage> GenerateImageFromDecoderContainerAsync(IDecodedImage <PImage> decoded, ImageInformation imageInformation, bool isPlaceholder)
        {
            PImage result;

            if (decoded.IsAnimated)
            {
#if __IOS__
                result = PImage.CreateAnimatedImage(decoded.AnimatedImages
                                                    .Select(v => v.Image)
                                                    .Where(v => v?.CGImage != null).ToArray(), decoded.AnimatedImages.Sum(v => v.Delay) / 100.0);
#elif __MACOS__
                using (var mutableData = NSMutableData.Create())
                {
                    using (var destintation = CGImageDestination.Create(mutableData, MobileCoreServices.UTType.GIF, decoded.AnimatedImages.Length))
                    {
                        for (int i = 0; i < decoded.AnimatedImages.Length; i++)
                        {
                            var options = new CGImageDestinationOptions();
                            options.GifDictionary = new NSMutableDictionary();
                            options.GifDictionary[ImageIO.CGImageProperties.GIFDelayTime] = NSNumber.FromDouble(decoded.AnimatedImages[i].Delay / 100.0d);

                            destintation.AddImage(decoded.AnimatedImages[i].Image.CGImage, options);
                        }
                        destintation.Close();
                    }

                    // TODO I really don't know why it's not working. Anyone?
                    result = new PImage(mutableData);
                }
#endif
            }
            else
            {
                result = decoded.Image;
            }

            return(Task.FromResult(result));
        }
        protected override Task <SharedEvasImage> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            TaskCompletionSource <SharedEvasImage> tcs = new TaskCompletionSource <SharedEvasImage>();

            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  = DpiToPixels(downsampleWidth);
                        downsampleHeight = DpiToPixels(downsampleHeight);
                    }

                    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(img);
            });
            return(tcs.Task);
        }
Exemple #13
0
 protected override Task <MockBitmap> GenerateImageFromDecoderContainerAsync(IDecodedImage <MockBitmap> decoded, ImageInformation imageInformation, bool isPlaceholder)
 {
     return(Task.FromResult(new MockBitmap()));
 }
        public ImageLoaderTask(IMemoryCache <TImageContainer> memoryCache, IDataResolverFactory dataResolverFactory, ITarget <TImageContainer, TImageView> target, TaskParameter parameters, IImageService imageService, Configuration configuration, IMainThreadDispatcher mainThreadDispatcher, bool clearCacheOnOutOfMemory)
        {
            _clearCacheOnOutOfMemory = clearCacheOnOutOfMemory;
            MemoryCache             = memoryCache;
            DataResolverFactory     = dataResolverFactory;
            PlatformTarget          = target;
            ImageService            = imageService;
            Configuration           = configuration;
            MainThreadDispatcher    = mainThreadDispatcher;
            Parameters              = parameters;
            CancellationTokenSource = new CancellationTokenSource();
            ImageInformation        = new ImageInformation();
            CanUseMemoryCache       = true;

            KeyRaw = Parameters.Path;
            if (Parameters.Source == ImageSource.Stream)
            {
                CanUseMemoryCache = false;
                KeyRaw            = string.Concat("Stream_", GetNextStreamIndex());
            }

            if (!string.IsNullOrWhiteSpace(Parameters.CustomCacheKey))
            {
                CanUseMemoryCache = true;
                KeyRaw            = Parameters.CustomCacheKey;
            }

            if (string.IsNullOrWhiteSpace(KeyRaw))
            {
                KeyRaw = Guid.NewGuid().ToString("N");
            }

            KeyDownsamplingOnly = string.Empty;
            if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0))
            {
                KeyDownsamplingOnly = string.Concat(";", Parameters.DownSampleSize.Item1, "x", Parameters.DownSampleSize.Item2);
            }

            KeyTransformationsOnly = string.Empty;
            if (Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                KeyTransformationsOnly = string.Concat(string.Join(";", Parameters.Transformations.Select(t => t.Key)));
            }

            Key = string.Concat(KeyRaw, KeyDownsamplingOnly, KeyTransformationsOnly);
            KeyWithoutTransformations = string.Concat(KeyRaw, KeyDownsamplingOnly);

            if (!string.IsNullOrWhiteSpace(Parameters.LoadingPlaceholderPath))
            {
                if (TransformPlaceholders)
                {
                    KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly);
                }
                else
                {
                    KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly);
                }
            }

            if (!string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath))
            {
                if (TransformPlaceholders)
                {
                    KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly);
                }
                else
                {
                    KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly);
                }
            }

            ImageInformation.SetKey(Key, Parameters.CustomCacheKey);
            ImageInformation.SetPath(Parameters.Path);

            Target?.SetImageLoadingTask(this);
        }
Exemple #15
0
        protected virtual async Task <TImageContainer> GenerateImageAsync(string path, ImageSource source, IDecodedImage <object> decoded, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            var decoderContainer = new DecodedImage <TDecoderContainer>()
            {
                IsAnimated     = decoded.IsAnimated,
                Image          = decoded.Image as TDecoderContainer,
                AnimatedImages = decoded.AnimatedImages?.Select(
                    v => new AnimatedImage <TDecoderContainer>()
                {
                    Delay = v.Delay, Image = v.Image as TDecoderContainer
                })
                                 .ToArray()
            };

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                if (decoderContainer.IsAnimated)
                {
                    for (int i = 0; i < decoderContainer.AnimatedImages.Length; i++)
                    {
                        decoderContainer.AnimatedImages[i].Image = await TransformAsync(decoderContainer.AnimatedImages[i].Image, transformations, path, source, isPlaceholder);
                    }
                }
                else
                {
                    decoderContainer.Image = await TransformAsync(decoderContainer.Image, transformations, path, source, isPlaceholder);
                }
            }

            return(await GenerateImageFromDecoderContainerAsync(decoderContainer, imageInformation, isPlaceholder));
        }
 protected override Task <SharedEvasImage> GenerateImageFromDecoderContainerAsync(IDecodedImage <SharedEvasImage> decoded, ImageInformation imageInformation, bool isPlaceholder)
 {
     if (decoded.IsAnimated)
     {
         throw new NotImplementedException();
     }
     else
     {
         return(Task.FromResult(decoded.Image));
     }
 }
        protected async override Task <WriteableBitmap> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            BitmapHolder imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                // Special case to handle WebP decoding on Windows
                if (source != ImageSource.Stream && path.ToLowerInvariant().EndsWith(".webp", StringComparison.OrdinalIgnoreCase))
                {
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }
                else if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
                {
                    imageIn = await imageData.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, imageInformation).ConfigureAwait(false);
                }
                else
                {
                    return(await imageData.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, imageInformation).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 = imageIn;

                        try
                        {
                            IBitmap bitmapHolder = transformation.Transform(imageIn);
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.Pixels != imageIn.Pixels)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            try
            {
                return(await imageIn.ToBitmapImageAsync());
            }
            finally
            {
                imageIn.FreePixels();
                imageIn = null;
            }
        }
        protected virtual async Task <WithLoadingResult <UIImage> > GetImageAsync(string sourcePath, ImageSource source,
                                                                                  bool isPlaceholder, Stream originalStream = null)
        {
            if (IsCancelled)
            {
                return(new WithLoadingResult <UIImage>(LoadingResult.Canceled));
            }

            LoadingResult?result = null;
            UIImage       image  = null;

            byte[]           bytes            = null;
            string           path             = sourcePath;
            ImageInformation imageInformation = null;

            try
            {
                if (originalStream != null)
                {
                    try
                    {
                        // check is stream is memorystream
                        var ms = originalStream as MemoryStream;
                        if (ms != null)
                        {
                            bytes = ms.ToArray();
                        }
                        else if (originalStream.CanSeek)
                        {
                            bytes = new byte[originalStream.Length];
                            await originalStream.ReadAsync(bytes, 0, (int)originalStream.Length, CancellationToken.Token).ConfigureAwait(false);
                        }
                        else
                        {
                            using (var ms2 = new MemoryStream())
                            {
                                await originalStream.CopyToAsync(ms2).ConfigureAwait(false);

                                bytes = ms2.ToArray();
                            }
                        }

                        path   = sourcePath;
                        result = LoadingResult.Stream;
                    }
                    finally
                    {
                        originalStream.Dispose();
                    }
                }
                else
                {
                    using (var resolver = DataResolverFactory.GetResolver(source, Parameters, DownloadCache, MainThreadDispatcher))
                    {
                        var data = await resolver.GetData(path, CancellationToken.Token).ConfigureAwait(false);

                        if (data == null)
                        {
                            return(new WithLoadingResult <UIImage>(LoadingResult.Failed));
                        }

                        image            = data.Image;
                        bytes            = data.Data;
                        path             = data.ResultIdentifier;
                        result           = data.Result;
                        imageInformation = data.ImageInformation;
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Logger.Debug(string.Format("Image request for {0} got cancelled.", path));
                return(new WithLoadingResult <UIImage>(LoadingResult.Canceled));
            }
            catch (Exception ex)
            {
                var message = String.Format("Unable to retrieve image data from source: {0}", sourcePath);
                Logger.Error(message, ex);
                Parameters.OnError(ex);
                return(new WithLoadingResult <UIImage>(LoadingResult.Failed));
            }

            if (bytes == null && image == null)
            {
                if (result != null && (int)result < 0)               // it's below zero if it's an error
                {
                    return(new WithLoadingResult <UIImage>(result.Value));
                }
                else
                {
                    return(new WithLoadingResult <UIImage>(LoadingResult.Failed));
                }
            }

            if (IsCancelled)
            {
                return(new WithLoadingResult <UIImage>(LoadingResult.Canceled));
            }

            UIImage imageIn = image;
            NSData  nsdata  = null;

            if (imageIn == null)
            {
                // Special case to handle WebP decoding on iOS
                if (sourcePath.ToLowerInvariant().EndsWith(".webp", StringComparison.InvariantCulture))
                {
                    imageIn = new WebP.Touch.WebPCodec().Decode(bytes);
                }
                else
                {
                    // nfloat scale = _imageScale >= 1 ? _imageScale : ScaleHelper.Scale;
                    nsdata = NSData.FromArray(bytes);
                    if (nsdata == null)
                    {
                        return(new WithLoadingResult <UIImage>(LoadingResult.Failed));
                    }
                }
            }

            bytes = null;

            // Setting image informations
            if (imageInformation == null)
            {
                imageInformation = new ImageInformation();
            }

            imageInformation.SetCacheKey(path == "Stream" ? GetKey() : GetKey(sourcePath));

            // We rely on ImageIO for all datasources except AssetCatalog, this way we don't generate temporary UIImage
            // furthermore we can do all the work in a thread safe way and in threadpool
            if (nsdata != null)
            {
                int downsampleWidth  = Parameters.DownSampleSize?.Item1 ?? 0;
                int downsampleHeight = Parameters.DownSampleSize?.Item2 ?? 0;

                if (Parameters.DownSampleUseDipUnits)
                {
                    downsampleWidth  = downsampleWidth.PointsToPixels();
                    downsampleHeight = downsampleHeight.PointsToPixels();
                }

                imageIn = nsdata.ToImage(new CoreGraphics.CGSize(downsampleWidth, downsampleHeight), _imageScale, NSDataExtensions.RCTResizeMode.ScaleAspectFill, imageInformation);
            }
            else if (Parameters.DownSampleSize != null && imageIn != null)
            {
                // if we already have the UIImage in memory it doesn't really matter to resize it
                // furthermore this will only happen for AssetCatalog images (yet)
            }

            bool transformPlaceholdersEnabled = Parameters.TransformPlaceholdersEnabled.HasValue ?
                                                Parameters.TransformPlaceholdersEnabled.Value : ImageService.Instance.Config.TransformPlaceholders;

            if (Parameters.Transformations != null && Parameters.Transformations.Count > 0 &&
                (!isPlaceholder || (isPlaceholder && transformPlaceholdersEnabled)))
            {
                foreach (var transformation in Parameters.Transformations.ToList() /* to prevent concurrency issues */)
                {
                    if (IsCancelled)
                    {
                        return(new WithLoadingResult <UIImage>(LoadingResult.Canceled));
                    }

                    try
                    {
                        var old          = imageIn;
                        var bitmapHolder = transformation.Transform(new BitmapHolder(imageIn));
                        imageIn = bitmapHolder.ToNative();

                        // Transformation succeeded, so garbage the source
                        if (old != null && old != imageIn && old.Handle != imageIn.Handle)
                        {
                            old.Dispose();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Can't apply transformation " + transformation.Key + " to image " + path, ex);
                    }
                }
            }

            return(WithLoadingResult.Encapsulate(imageIn, result.Value, imageInformation));
        }
Exemple #19
0
        protected override async Task <BitmapSource> GenerateImageFromDecoderContainerAsync(IDecodedImage <BitmapHolder> decoded, ImageInformation imageInformation, bool isPlaceholder)
        {
            if (decoded.IsAnimated)
            {
                throw new NotImplementedException();
            }
            else
            {
                try
                {
                    if (decoded.Image.HasWriteableBitmap)
                    {
                        return(decoded.Image.WriteableBitmap);
                    }

                    return(await decoded.Image.ToBitmapImageAsync().ConfigureAwait(false));
                }
                finally
                {
                    decoded.Image.FreePixels();
                    decoded.Image = null;
                }
            }
        }
Exemple #20
0
 protected abstract Task <TImageContainer> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder);
Exemple #21
0
        protected async override Task <WriteableBitmap> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            BitmapHolder imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                bool allowUpscale = Parameters.AllowUpscale ?? Configuration.AllowUpscale;
                if (source != ImageSource.Stream && imageInformation.Type == ImageInformation.ImageType.WEBP)
                {
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }
                else if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
                {
                    imageIn = await imageData.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false);
                }
                else
                {
                    return(await imageData.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false));
                }
            }
            finally
            {
                imageData.TryDispose();
            }

            ThrowIfCancellationRequested();

            if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                var transformations = Parameters.Transformations.ToList();

                await _decodingLock.WaitAsync(CancellationTokenSource.Token).ConfigureAwait(false); // Applying transformations is both CPU and memory intensive

                ThrowIfCancellationRequested();

                try
                {
                    foreach (var transformation in transformations)
                    {
                        ThrowIfCancellationRequested();

                        var old = imageIn;

                        try
                        {
                            IBitmap bitmapHolder = transformation.Transform(imageIn, path, source, isPlaceholder, Key);
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.PixelData != imageIn.PixelData)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            try
            {
                return(await imageIn.ToBitmapImageAsync());
            }
            finally
            {
                imageIn.FreePixels();
                imageIn = null;
            }
        }
Exemple #22
0
        void SetKeys()
        {
            KeyRaw = Parameters.Path;
            if (Parameters.Source == ImageSource.Stream)
            {
                if (!string.IsNullOrWhiteSpace(Parameters.StreamChecksum))
                {
                    CanUseMemoryCache = true;
                    KeyRaw            = Parameters.StreamChecksum;
                }
                else
                {
                    CanUseMemoryCache = false;
                    KeyRaw            = string.Concat("Stream_", Guid.NewGuid().ToString("N"));
                }
            }

            if (!string.IsNullOrWhiteSpace(Parameters.CustomCacheKey))
            {
                CanUseMemoryCache = true;
                KeyRaw            = Parameters.CustomCacheKey;
            }

            if (Parameters.CacheType == CacheType.Disk)
            {
                CanUseMemoryCache = false;
            }

            if (string.IsNullOrWhiteSpace(KeyRaw))
            {
                KeyRaw = Guid.NewGuid().ToString("N");
            }

            var vect = Parameters.CustomDataResolver as IVectorDataResolver;

            if (vect != null)
            {
                if (vect.ReplaceStringMap == null || vect.ReplaceStringMap.Count == 0)
                {
                    KeyRaw = string.Format("{0};(size={1}x{2},dip={3})", KeyRaw, vect.VectorWidth, vect.VectorHeight, vect.UseDipUnits);
                }
                else
                {
                    KeyRaw = string.Format("{0};(size={1}x{2},dip={3},replace=({4}))", KeyRaw, vect.VectorWidth, vect.VectorHeight, vect.UseDipUnits,
                                           string.Join(",", vect.ReplaceStringMap.Select(x => string.Format("{0}/{1}", x.Key, x.Value)).OrderBy(v => v)));
                }
            }

            KeyDownsamplingOnly = string.Empty;
            if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0))
            {
                if (Parameters.DownSampleUseDipUnits)
                {
                    KeyDownsamplingOnly = string.Concat(";", DpiToPixels(Parameters.DownSampleSize.Item1), "x", DpiToPixels(Parameters.DownSampleSize.Item2));
                }
                else
                {
                    KeyDownsamplingOnly = string.Concat(";", Parameters.DownSampleSize.Item1, "x", Parameters.DownSampleSize.Item2);
                }
            }

            KeyTransformationsOnly = string.Empty;
            if (Parameters.Transformations != null && Parameters.Transformations.Count > 0)
            {
                KeyTransformationsOnly = string.Concat(";", string.Join(";", Parameters.Transformations.Select(t => t.Key)));
            }

            Key = string.Concat(KeyRaw, KeyDownsamplingOnly, KeyTransformationsOnly);
            KeyWithoutTransformations = string.Concat(KeyRaw, KeyDownsamplingOnly);

            if (!string.IsNullOrWhiteSpace(Parameters.LoadingPlaceholderPath))
            {
                if (TransformPlaceholders)
                {
                    KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly);
                }
                else
                {
                    KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly);
                }

                var vectLo = Parameters.CustomLoadingPlaceholderDataResolver as IVectorDataResolver;
                if (vectLo != null)
                {
                    if (vectLo.ReplaceStringMap == null || vectLo.ReplaceStringMap.Count == 0)
                    {
                        KeyForLoadingPlaceholder = string.Format("{0};(size={1}x{2},dip={3})", KeyForLoadingPlaceholder, vectLo.VectorWidth, vectLo.VectorHeight, vectLo.UseDipUnits);
                    }
                    else
                    {
                        KeyForLoadingPlaceholder = string.Format("{0};(size={1}x{2},dip={3},replace=({4}))", KeyForLoadingPlaceholder, vectLo.VectorWidth, vectLo.VectorHeight, vectLo.UseDipUnits,
                                                                 string.Join(",", vectLo.ReplaceStringMap.Select(x => string.Format("{0}/{1}", x.Key, x.Value)).OrderBy(v => v)));
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath))
            {
                if (TransformPlaceholders)
                {
                    KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly);
                }
                else
                {
                    KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly);
                }

                var vectEr = Parameters.CustomLoadingPlaceholderDataResolver as IVectorDataResolver;
                if (vectEr != null)
                {
                    if (vectEr.ReplaceStringMap == null || vectEr.ReplaceStringMap.Count == 0)
                    {
                        KeyForErrorPlaceholder = string.Format("{0};(size={1}x{2},dip={3})", KeyForErrorPlaceholder, vectEr.VectorWidth, vectEr.VectorHeight, vectEr.UseDipUnits);
                    }
                    else
                    {
                        KeyForErrorPlaceholder = string.Format("{0};(size={1}x{2},dip={3},replace=({4}))", KeyForErrorPlaceholder, vectEr.VectorWidth, vectEr.VectorHeight, vectEr.UseDipUnits,
                                                               string.Join(",", vectEr.ReplaceStringMap.Select(x => string.Format("{0}/{1}", x.Key, x.Value)).OrderBy(v => v)));
                    }
                }
            }

            ImageInformation.SetKey(Key, Parameters.CustomCacheKey);
            ImageInformation.SetPath(Parameters.Path);
        }
        protected async override Task <WriteableBitmap> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
        {
            BitmapHolder imageIn = null;

            if (imageData == null)
            {
                throw new ArgumentNullException(nameof(imageData));
            }

            ThrowIfCancellationRequested();

            try
            {
                // Special case to handle WebP decoding on Windows
                string ext = null;
                if (!string.IsNullOrWhiteSpace(path) && Uri.IsWellFormedUriString(path, UriKind.RelativeOrAbsolute))
                {
                    if (source == ImageSource.Url)
                    {
                        ext = Path.GetExtension(new Uri(path).LocalPath).ToLowerInvariant();
                    }
                    else
                    {
                        ext = Path.GetExtension(path).ToLowerInvariant();
                    }
                }

                bool allowUpscale = Parameters.AllowUpscale ?? Configuration.AllowUpscale;
                if (source != ImageSource.Stream && ext == ".webp")
                {
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }
                else if (enableTransformations && Parameters.Transformations != null && Parameters.Transformations.Count > 0)
                {
                    imageIn = await imageData.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).ConfigureAwait(false);
                }
                else
                {
                    return(await imageData.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, allowUpscale, imageInformation).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 = imageIn;

                        try
                        {
                            IBitmap bitmapHolder = transformation.Transform(imageIn, path, source, isPlaceholder, Key);
                            imageIn = bitmapHolder.ToNative();
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("Transformation failed: {0}", transformation.Key), ex);
                            throw;
                        }
                        finally
                        {
                            if (old != null && old != imageIn && old.PixelData != imageIn.PixelData)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                    }
                }
                finally
                {
                    _decodingLock.Release();
                }
            }

            try
            {
                return(await imageIn.ToBitmapImageAsync());
            }
            finally
            {
                imageIn.FreePixels();
                imageIn = null;
            }
        }
Exemple #24
0
        protected override Task <PImage> GenerateImageFromDecoderContainerAsync(IDecodedImage <PImage> decoded, ImageInformation imageInformation, bool isPlaceholder)
        {
            PImage result;

            if (decoded.IsAnimated)
            {
#if __IOS__
                result = PImage.CreateAnimatedImage(decoded.AnimatedImages
                                                    .Select(v => v.Image)
                                                    .Where(v => v?.CGImage != null).ToArray(), decoded.AnimatedImages.Sum(v => v.Delay) / 100.0);
#elif __MACOS__
                using (var mutableData = NSMutableData.Create())
                {
                    var fileOptions = new CGImageDestinationOptions();
                    fileOptions.GifDictionary = new NSMutableDictionary();
                    fileOptions.GifDictionary[ImageIO.CGImageProperties.GIFLoopCount] = new NSString("0");
                    //options.GifDictionary[ImageIO.CGImageProperties.GIFHasGlobalColorMap] = new NSString("true");

                    using (var destintation = CGImageDestination.Create(mutableData, MobileCoreServices.UTType.GIF, decoded.AnimatedImages.Length, fileOptions))
                    {
                        for (int i = 0; i < decoded.AnimatedImages.Length; i++)
                        {
                            var options = new CGImageDestinationOptions();
                            options.GifDictionary = new NSMutableDictionary();
                            options.GifDictionary[ImageIO.CGImageProperties.GIFUnclampedDelayTime] = new NSString(decoded.AnimatedImages[i].Delay.ToString());
                            destintation.AddImage(decoded.AnimatedImages[i].Image.CGImage, options);
                        }

                        destintation.Close();
                    }

                    result = new PImage(mutableData);

                    // TODO I really don't know why representations count is 1, anyone?
                    // var test = result.Representations();
                }
#endif
            }
            else
            {
                result = decoded.Image;
            }

            return(Task.FromResult(result));
        }
Exemple #25
0
 protected override Task <MockBitmap> GenerateImageAsync(string path, ImageSource source, Stream imageData, ImageInformation imageInformation, bool enableTransformations, bool isPlaceholder)
 {
     return(Task.FromResult(new MockBitmap()));
 }