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; } }
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)); }