Пример #1
0
        private async Task<WithLoadingResult<WriteableBitmap>> RetrieveImageAsync(string sourcePath, ImageSource source, bool isPlaceholder)
        {
            // If the image cache is available and this task has not been cancelled by another
            // thread and the ImageView that was originally bound to this task is still bound back
            // to this task and our "exit early" flag is not set then try and fetch the bitmap from
            // the cache
            if (IsCancelled || _getNativeControl() == null || ImageService.ExitTasksEarly)
                return null;

            var imageWithResult = await GetImageAsync(sourcePath, source, isPlaceholder).ConfigureAwait(false);

            if (imageWithResult == null || imageWithResult.Item == null)
                return null;

            // FMT: even if it was canceled, if we have the bitmap we add it to the cache
            ImageCache.Instance.Add(GetKey(sourcePath), imageWithResult.Item);

            return imageWithResult;
        }
Пример #2
0
        protected virtual async Task<WithLoadingResult<WriteableBitmap>> GetImageAsync(string path, ImageSource source,
            bool isPlaceholder, Stream originalStream = null)
        {
            if (IsCancelled)
                return null;

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

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

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

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

                stream = streamWithResult.Item;

                if (IsCancelled)
                    return null;

                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 null;
                            }
                            else
                            {
                                // Assets stream can't be seeked to origin position
                                stream.Dispose();
                                streamWithResult = await GetStreamAsync(path, source).ConfigureAwait(false);
                                stream = streamWithResult == null ? null : streamWithResult.Item;

                                if (stream == null)
                                    return null;
                            }
                        }
                        else
                        {
                            stream.Seek(0, SeekOrigin.Begin);
                        }

                        if (CancellationToken.IsCancellationRequested)
                            return null;
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Something wrong happened while asynchronously retrieving image size from file: " + path, ex);
                        return null;
                    }

                    WriteableBitmap writableBitmap = null;

                    // Special case to handle WebP decoding
                    if (path.ToLowerInvariant().EndsWith(".webp"))
                    {
                        //TODO
                        Logger.Error("Webp is not implemented on Windows");
                        return null;
                    }

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

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

                        try
                        {
                            await _decodingLock.WaitAsync();
                            imageIn = await stream.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("Something wrong happened while asynchronously loading/decoding image: " + path, ex);
                            return null;
                        }
                        finally
                        {
                            _decodingLock.Release();
                        }

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

                            try
                            {
                                var old = imageIn;

                                try
                                {
                                    await _decodingLock.WaitAsync();
                                    IBitmap bitmapHolder = transformation.Transform(imageIn);
                                    imageIn = bitmapHolder.ToNative();
                                }
                                finally
                                {
                                    _decodingLock.Release();
                                }

                                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
                        {
                            await _decodingLock.WaitAsync();
                            writableBitmap = await stream.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleUseDipUnits, Parameters.DownSampleInterpolationMode);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("Something wrong happened while asynchronously loading/decoding image: " + path, ex);
                            return null;
                        }
                        finally
                        {
                            _decodingLock.Release();
                        }
                    }

                    return WithLoadingResult.Encapsulate(writableBitmap, streamWithResult.Result);
                }
                finally
                {
                    if (stream != null)
                        stream.Dispose();
                }
            }).ConfigureAwait(false);
        }
Пример #3
0
        private async Task<bool> LoadPlaceHolderAsync(string placeholderPath, ImageSource source)
        {
            if (string.IsNullOrWhiteSpace(placeholderPath))
                return false;

            WriteableBitmap image = ImageCache.Instance.Get(GetKey(placeholderPath));

            if (image == null)
            {
                try
                {
                    var imageWithResult = await RetrieveImageAsync(placeholderPath, source, true).ConfigureAwait(false);
                    image = imageWithResult == null ? null : imageWithResult.Item;
                }
                catch (Exception ex)
                {
                    Logger.Error("An error occured while retrieving placeholder's drawable.", ex);
                    return false;
                }
            }

            if (image == null)
                return false;

            var view = _getNativeControl();
            if (view == null)
                return false;

            if (IsCancelled)
                return false;

            // Post on main thread but don't wait for it
            MainThreadDispatcher.Post(() =>
            {
                if (IsCancelled)
                    return;

                _doWithImage(image, false);
            });

            return true;
        }
        /// <summary>
        /// Returns a <see cref="Image"/> from the <see cref="ImageSource"/> provided.
        /// </summary>
        /// <param name="source">The <see cref="ImageSource"/> to load the image from.</param>
        /// <param name="height">The height for the image (divides by 2 for the Windows Phone platform).</param>
        /// <param name="width">The width for the image (divides by 2 for the Windows Phone platform).</param>
        /// <returns>A properly sized image.</returns>
        private async static Task<System.Windows.Controls.Image> GetImageAsync(ImageSource source, int height, int width)
        {
            var image = new System.Windows.Controls.Image();
            var handler = GetHandler(source);
            var imageSource = await handler.LoadImageAsync(source);

            image.Source = imageSource;
            image.Height = Convert.ToDouble(height / 2);
            image.Width = Convert.ToDouble(width / 2);
            return image;
        }
Пример #5
0
        private async Task<WithLoadingResult<Stream>> GetStreamAsync(string path, ImageSource source)
        {
            if (string.IsNullOrWhiteSpace(path)) return null;

            try
            {
                using (var resolver = DataResolverFactory.GetResolver(source, Parameters, DownloadCache))
                {
                    return await resolver.GetStream(path, CancellationToken.Token).ConfigureAwait(false);
                }
            }
            catch (OperationCanceledException)
            {
                Logger.Debug(string.Format("Image request for {0} got cancelled.", path));
                return null;
            }
            catch (Exception ex)
            {
                Logger.Error("Unable to retrieve image data", ex);
                return null;
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        private void CreatePageWithImage(RadFixedDocument document, string imageExtension, EncodedImageData imageData, double[] decode = null)
        {
            RadFixedPage page = document.Pages.AddPage();
            page.Size = PageSize;
            FixedContentEditor editor = new FixedContentEditor(page);
            editor.Position.Translate(Margins.Left, Margins.Top);

            Block block = new Block();
            block.HorizontalAlignment = Telerik.Windows.Documents.Fixed.Model.Editing.Flow.HorizontalAlignment.Center;
            block.TextProperties.FontSize = 22;
            block.InsertText(string.Format("This is {0} image in {1} color space encoded with {2} filter.", imageExtension, imageData.ColorSpace, imageData.Filters.FirstOrDefault() ?? "None"));
            Size blockSize = block.Measure(RemainingPageSize);
            editor.DrawBlock(block, RemainingPageSize);

            editor.Position.Translate(Margins.Left, blockSize.Height + Margins.Top + 50);

            Block imageBlock = new Block();
            imageBlock.HorizontalAlignment = Telerik.Windows.Documents.Fixed.Model.Editing.Flow.HorizontalAlignment.Center;
            ImageSource imageSource = new ImageSource(imageData);
            imageSource.DecodeArray = decode;
            imageBlock.InsertImage(imageSource, new Size(imageData.Width, imageData.Height));
            editor.DrawBlock(imageBlock, RemainingPageSize);
        }
Пример #8
0
        private void AddPageWithImage(string description, ImageSource imageSource)
        {
            RadFixedPage page = this.document.Pages.AddPage();
            page.Size = PageSize;
            FixedContentEditor editor = new FixedContentEditor(page);
            editor.GraphicProperties.FillColor = new RgbColor(200, 200, 200);
            editor.DrawRectangle(new Rect(0, 0, PageSize.Width, PageSize.Height));
            editor.Position.Translate(Margins.Left, Margins.Top);

            Block block = new Block();
            block.HorizontalAlignment = Telerik.Windows.Documents.Fixed.Model.Editing.Flow.HorizontalAlignment.Center;
            block.TextProperties.FontSize = 22;
            block.InsertText(description);
            Size blockSize = block.Measure(RemainingPageSize);
            editor.DrawBlock(block, RemainingPageSize);

            editor.Position.Translate(Margins.Left, blockSize.Height + Margins.Top + 20);

            Block imageBlock = new Block();
            imageBlock.HorizontalAlignment = Telerik.Windows.Documents.Fixed.Model.Editing.Flow.HorizontalAlignment.Center;
            imageBlock.InsertImage(imageSource);
            editor.DrawBlock(imageBlock, RemainingPageSize);
        }
Пример #9
0
        private async Task<WithLoadingResult<WriteableBitmap>> RetrieveImageAsync(string sourcePath, ImageSource source, bool isPlaceholder)
        {
            if (string.IsNullOrWhiteSpace(sourcePath))
                return new WithLoadingResult<WriteableBitmap>(LoadingResult.Failed);

            // If the image cache is available and this task has not been cancelled by another
            // thread and the ImageView that was originally bound to this task is still bound back
            // to this task and our "exit early" flag is not set then try and fetch the bitmap from
            // the cache
            if (IsCancelled || ImageService.Instance.ExitTasksEarly)
                return new WithLoadingResult<WriteableBitmap>(LoadingResult.Canceled);

            if (!_target.IsTaskValid(this))
                return new WithLoadingResult<WriteableBitmap>(LoadingResult.InvalidTarget);

            var resultWithImage = await GetImageAsync(sourcePath, source, isPlaceholder).ConfigureAwait(false);

            if (resultWithImage.HasError)
                return resultWithImage;

            // FMT: even if it was canceled, if we have the bitmap we add it to the cache
            ImageCache.Instance.Add(GetKey(sourcePath), resultWithImage.ImageInformation, resultWithImage.Item);

            return resultWithImage;
        }
Пример #10
0
        private async Task<bool> LoadPlaceHolderAsync(string placeholderPath, ImageSource source, bool isLoadingPlaceholder)
        {
            if (string.IsNullOrWhiteSpace(placeholderPath))
                return false;

            var cacheEntry = ImageCache.Instance.Get(GetKey(placeholderPath));
            WriteableBitmap image = cacheEntry == null ? null : cacheEntry.Item1;

            bool isLocalOrFromCache = true;

            if (image == null)
            {
                try
                {
                    var imageWithResult = await RetrieveImageAsync(placeholderPath, source, true).ConfigureAwait(false);
                    image = imageWithResult.Item;
                    isLocalOrFromCache = imageWithResult.Result.IsLocalOrCachedResult();
                }
                catch (Exception ex)
                {
                    Logger.Error("An error occured while retrieving placeholder's drawable.", ex);
                    return false;
                }
            }

            if (image == null)
                return false;

            if (!_target.IsValid)
                return false;

            if (IsCancelled)
                return false;

            // Post on main thread but don't wait for it
            MainThreadDispatcher.Post(() => _target.Set(this, image, isLocalOrFromCache, isLoadingPlaceholder));

            return true;
        }