private async void LoadImage() { var decoder = new WebP.Touch.WebPCodec(); var httpClient = new HttpClient(); using (var stream = await httpClient.GetStreamAsync("https://res.cloudinary.com/demo/image/upload/w_300/sample.webp").ConfigureAwait(false)) { var image = decoder.Decode(stream); InvokeOnMainThread(() => { View = new UIImageView(image); }); } }
private async void LoadImage() { var decoder = new WebP.Touch.WebPCodec(); var httpClient = new HttpClient(); using (var stream = await httpClient.GetStreamAsync("http://www.gstatic.com/webp/gallery/1.webp").ConfigureAwait(false)) { var image = decoder.Decode(stream); InvokeOnMainThread(() => { View = new UIImageView(image); }); } }
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); }
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)); }
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); }
protected virtual async Task<WithLoadingResult<UIImage>> GetImageAsync(string sourcePath, ImageSource source, bool isPlaceholder, Stream originalStream = null) { if (CancellationToken.IsCancellationRequested) return null; UIImage image = null; byte[] bytes = null; string path = sourcePath; LoadingResult? result = null; try { if (originalStream != null) { try { using (var ms = new MemoryStream()) { await originalStream.CopyToAsync(ms).ConfigureAwait(false); bytes = ms.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 null; image = data.Image; bytes = data.Data; path = data.ResultIdentifier; result = data.Result; } } } catch (System.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 && image == null) return null; var imageToDisplay = await Task.Run(() => { if (CancellationToken.IsCancellationRequested) return null; UIImage imageIn = image; 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 : _screenScale; imageIn = new UIImage(NSData.FromArray(bytes), scale); } } if (Parameters.DownSampleSize != null && ((Parameters.DownSampleSize.Item1 > 0 && imageIn.Size.Width > Parameters.DownSampleSize.Item1) || (Parameters.DownSampleSize.Item2 > 0 && imageIn.Size.Height > Parameters.DownSampleSize.Item2))) { var tempImage = imageIn; int downsampleWidth = Parameters.DownSampleSize.Item1; int downsampleHeight = Parameters.DownSampleSize.Item2; if (Parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.PointsToPixels(); downsampleHeight = downsampleHeight.PointsToPixels(); } imageIn = tempImage.ResizeUIImage(downsampleWidth, downsampleHeight, Parameters.DownSampleInterpolationMode); tempImage.Dispose(); } bool transformPlaceholdersEnabled = Parameters.TransformPlaceholdersEnabled.HasValue ? Parameters.TransformPlaceholdersEnabled.Value : ImageService.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 (CancellationToken.IsCancellationRequested) return null; 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 imageIn; }).ConfigureAwait(false); bytes = null; return WithLoadingResult.Encapsulate(imageToDisplay, result.Value); }
protected virtual async Task <WithLoadingResult <UIImage> > GetImageAsync(string sourcePath, ImageSource source, bool isPlaceholder, Stream originalStream = null) { if (CancellationToken.IsCancellationRequested) { return(null); } UIImage image = null; byte[] bytes = null; string path = sourcePath; LoadingResult?result = null; try { if (originalStream != null) { try { using (var ms = new MemoryStream()) { await originalStream.CopyToAsync(ms).ConfigureAwait(false); bytes = ms.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(null); } image = data.Image; bytes = data.Data; path = data.ResultIdentifier; result = data.Result; } } } catch (System.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 && image == null) { return(null); } var imageToDisplay = await Task.Run(() => { if (CancellationToken.IsCancellationRequested) { return(null); } UIImage imageIn = image; 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 : _screenScale; imageIn = new UIImage(NSData.FromArray(bytes), scale); } } if (Parameters.DownSampleSize != null && ((Parameters.DownSampleSize.Item1 > 0 && imageIn.Size.Width > Parameters.DownSampleSize.Item1) || (Parameters.DownSampleSize.Item2 > 0 && imageIn.Size.Height > Parameters.DownSampleSize.Item2))) { var tempImage = imageIn; imageIn = tempImage.ResizeUIImage(Parameters.DownSampleSize.Item1, Parameters.DownSampleSize.Item2, Parameters.DownSampleInterpolationMode); tempImage.Dispose(); } bool transformPlaceholdersEnabled = Parameters.TransformPlaceholdersEnabled.HasValue ? Parameters.TransformPlaceholdersEnabled.Value : ImageService.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 (CancellationToken.IsCancellationRequested) { return(null); } try { var old = imageIn; var bitmapHolder = transformation.Transform(new BitmapHolder(imageIn)); imageIn = bitmapHolder.ToNative(); // Transformation succeeded, so garbage the source if (old != null) { old.Dispose(); } } catch (Exception ex) { Logger.Error("Can't apply transformation " + transformation.Key + " to image " + path, ex); } } } return(imageIn); }).ConfigureAwait(false); return(WithLoadingResult.Encapsulate(imageToDisplay, result.Value)); }
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.SetKey(path == "Stream" ? GetKey() : GetKey(sourcePath), Parameters.CustomCacheKey); // 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), ScaleHelper.Scale, 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); }