FreePixels() public method

public FreePixels ( ) : void
return void
Example #1
0
        protected override async Task <BitmapHolder> TransformAsync(BitmapHolder bitmap, IList <ITransformation> transformations, string path, ImageSource source, bool isPlaceholder)
        {
            await StaticLocks.DecodingLock.WaitAsync(base.CancellationTokenSource.Token).ConfigureAwait(continueOnCapturedContext: false);

            ThrowIfCancellationRequested();
            try
            {
                foreach (ITransformation transformation in transformations)
                {
                    ThrowIfCancellationRequested();
                    BitmapHolder old = bitmap;
                    try
                    {
                        IBitmap bitmapHolder = transformation.Transform(bitmap, path, source, isPlaceholder, base.Key);
                        bitmap = bitmapHolder.ToNative();
                    }
                    catch (Exception ex2)
                    {
                        Exception ex = ex2;
                        base.Logger.Error($"Transformation failed: {transformation.Key}", ex);
                        throw;
                    }
                    finally
                    {
                        if (old != null && old != bitmap && old.PixelData != bitmap.PixelData)
                        {
                            old.FreePixels();
                        }
                    }
                }
            }
            finally
            {
                StaticLocks.DecodingLock.Release();
            }
            return(bitmap);
        }
        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;
            }
        }
Example #3
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;
            }
        }
        protected virtual async Task <WithLoadingResult <WriteableBitmap> > GetImageAsync(string path, ImageSource source,
                                                                                          bool isPlaceholder, Stream originalStream = null)
        {
            if (IsCancelled)
            {
                return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Canceled));
            }

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

            Stream stream = null;
            WithLoadingResult <Stream> streamWithResult;

            if (originalStream != null)
            {
                streamWithResult = new WithLoadingResult <Stream>(originalStream, LoadingResult.Stream);
            }
            else
            {
                streamWithResult = await GetStreamAsync(path, source).ConfigureAwait(false);
            }

            if (streamWithResult.HasError)
            {
                if (streamWithResult.Result == LoadingResult.NotFound)
                {
                    Logger.Error(string.Format("Not found: {0} from {1}", path, source.ToString()));
                }

                return(new WithLoadingResult <WriteableBitmap>(streamWithResult.Result));
            }

            stream = streamWithResult.Item;

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

            try
            {
                try
                {
                    if (stream.Position != 0 && !stream.CanSeek)
                    {
                        if (originalStream != null)
                        {
                            // If we cannot seek the original stream then there's not much we can do
                            return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed));
                        }
                        else
                        {
                            // Assets stream can't be seeked to origin position
                            stream.Dispose();
                            streamWithResult = await GetStreamAsync(path, source).ConfigureAwait(false);

                            if (streamWithResult.HasError)
                            {
                                return(new WithLoadingResult <WriteableBitmap>(streamWithResult.Result));
                            }

                            stream = streamWithResult.Item;
                        }
                    }
                    else
                    {
                        stream.Seek(0, SeekOrigin.Begin);
                    }

                    if (IsCancelled)
                    {
                        return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Canceled));
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error("Something wrong happened while asynchronously retrieving image size from file: " + path, ex);
                    return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed));
                }

                WriteableBitmap writableBitmap = null;

                // Special case to handle WebP decoding
                if (path.ToLowerInvariant().EndsWith(".webp"))
                {
                    //TODO
                    Logger.Error("Webp is not implemented on Windows");
                    return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed));
                }

                // Setting image informations
                var imageInformation = streamWithResult.ImageInformation ?? new ImageInformation();
                imageInformation.SetKey(path == "Stream" ? GetKey() : GetKey(path), Parameters.CustomCacheKey);

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

                if (Parameters.Transformations != null && Parameters.Transformations.Count > 0 &&
                    (!isPlaceholder || (isPlaceholder && transformPlaceholdersEnabled)))
                {
                    BitmapHolder imageIn = null;

                    try
                    {
                        imageIn = await stream.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, imageInformation).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Something wrong happened while asynchronously loading/decoding image: " + path, ex);
                        return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed));
                    }

                    foreach (var transformation in Parameters.Transformations.ToList() /* to prevent concurrency issues */)
                    {
                        if (IsCancelled)
                        {
                            return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Canceled));
                        }

                        try
                        {
                            var old = imageIn;

                            IBitmap bitmapHolder = transformation.Transform(imageIn);
                            imageIn = bitmapHolder.ToNative();

                            if (old != null && old != imageIn && old.Pixels != imageIn.Pixels)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("Can't apply transformation " + transformation.Key + " to image " + path, ex);
                        }
                    }

                    writableBitmap = await imageIn.ToBitmapImageAsync();

                    imageIn.FreePixels();
                    imageIn = null;
                }
                else
                {
                    try
                    {
                        writableBitmap = await stream.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode, imageInformation);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Something wrong happened while asynchronously loading/decoding image: " + path, ex);
                        return(new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed));
                    }
                }

                return(WithLoadingResult.Encapsulate(writableBitmap, streamWithResult.Result, imageInformation));
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                }
            }
        }
        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 <WriteableBitmap> > GetImageAsync(string sourcePath, ImageSource source,
                                                                                          bool isPlaceholder, Stream originalStream = null)
        {
            if (CancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            byte[]        bytes  = null;
            string        path   = sourcePath;
            LoadingResult?result = null;

            try
            {
                if (originalStream != null)
                {
                    using (var ms = new MemoryStream())
                    {
                        await originalStream.CopyToAsync(ms).ConfigureAwait(false);

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

                        if (data == null)
                        {
                            return(null);
                        }

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

            if (bytes == null)
            {
                return(null);
            }

            var image = await Task.Run(async() =>
            {
                if (CancellationToken.IsCancellationRequested)
                {
                    return(null);
                }

                WriteableBitmap writableBitmap = null;

                // Special case to handle WebP decoding
                if (sourcePath.ToLowerInvariant().EndsWith(".webp"))
                {
                    //TODO
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }

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

                if (Parameters.Transformations != null && Parameters.Transformations.Count > 0 &&
                    (!isPlaceholder || (isPlaceholder && transformPlaceholdersEnabled)))
                {
                    BitmapHolder imageIn = await bytes.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode).ConfigureAwait(false);

                    foreach (var transformation in Parameters.Transformations.ToList() /* to prevent concurrency issues */)
                    {
                        if (CancellationToken.IsCancellationRequested)
                        {
                            return(null);
                        }

                        try
                        {
                            var old = imageIn;

                            IBitmap bitmapHolder = transformation.Transform(imageIn);
                            imageIn = bitmapHolder.ToNative();

                            if (old != null && old != imageIn && old.Pixels != imageIn.Pixels)
                            {
                                old.FreePixels();
                                old = null;
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("Can't apply transformation " + transformation.Key + " to image " + path, ex);
                        }
                    }

                    writableBitmap = await imageIn.ToBitmapImageAsync();
                    imageIn.FreePixels();
                    imageIn = null;
                }
                else
                {
                    writableBitmap = await bytes.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode);
                }

                bytes = null;

                return(writableBitmap);
            }).ConfigureAwait(false);

            return(WithLoadingResult.Encapsulate(image, result.Value));
        }