示例#1
0
        public async Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            var cachedStream = await DownloadCache.GetStreamAsync(identifier, token, Parameters.CacheDuration).ConfigureAwait(false);

            return(WithLoadingResult.Encapsulate(cachedStream.ImageStream,
                                                 cachedStream.RetrievedFromDiskCache ? LoadingResult.DiskCache : LoadingResult.Disk));
        }
示例#2
0
        public Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            try
            {
                var imageInformation = new ImageInformation();
                imageInformation.SetPath(identifier);
                imageInformation.SetFilePath(null);

                var result = WithLoadingResult.Encapsulate(Context.Assets.Open(identifier, Access.Streaming),
                                                           LoadingResult.ApplicationBundle, imageInformation);
                return(Task.FromResult(result));
            }
            catch (Java.IO.FileNotFoundException)
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }
            catch (Java.IO.IOException)
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }
            catch (FileNotFoundException)
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }
            catch (IOException)
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }
        }
        public async Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            StorageFile file = null;

            try
            {
                var filePath = Path.GetDirectoryName(identifier);

                if (!string.IsNullOrWhiteSpace(filePath))
                {
                    file = await StorageFile.GetFileFromPathAsync(identifier);
                }
            }
            catch (Exception)
            {
            }

            if (file != null)
            {
                var imageInformation = new ImageInformation();
                imageInformation.SetPath(identifier);
                imageInformation.SetFilePath(identifier);

                return(WithLoadingResult.Encapsulate(await file.OpenStreamForReadAsync(), LoadingResult.Disk, imageInformation));
            }

            return(WithLoadingResult.Encapsulate <Stream>(null, LoadingResult.Disk));
        }
示例#4
0
        public Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            // Resource name is always without extension
            string resourceName = Path.GetFileNameWithoutExtension(identifier);

            int resourceId = 0;

            if (!_resourceIdentifiersCache.TryGetValue(resourceName, out resourceId))
            {
                resourceId = Context.Resources.GetIdentifier(resourceName.ToLower(), "drawable", Context.PackageName);
                _resourceIdentifiersCache.TryAdd(resourceName.ToLower(), resourceId);
            }

            Stream stream = null;

            if (resourceId != 0)
            {
                stream = Context.Resources.OpenRawResource(resourceId);
            }
            else
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }

            var imageInformation = new ImageInformation();

            imageInformation.SetPath(identifier);
            imageInformation.SetFilePath(null);

            var result = WithLoadingResult.Encapsulate(stream, LoadingResult.CompiledResource, imageInformation);

            return(Task.FromResult(result));
        }
        public Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            if (!FileStore.Exists(identifier))
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }

            var result = WithLoadingResult.Encapsulate(FileStore.GetInputStream(identifier), LoadingResult.Disk);

            return(Task.FromResult(result));
        }
示例#6
0
        protected override async Task<GenerateResult> TryGeneratingImageAsync()
        {
            WithLoadingResult<WriteableBitmap> imageWithResult;
            WriteableBitmap image = null;

            try
            {
                imageWithResult = await RetrieveImageAsync(Parameters.Path, Parameters.Source, false).ConfigureAwait(false);
                image = imageWithResult.Item;
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                imageWithResult = new WithLoadingResult<WriteableBitmap>(LoadingResult.Failed);
                image = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                return imageWithResult.GenerateResult;
            }

			if (IsCancelled)
                return GenerateResult.Canceled;

            if (_getNativeControl() == null)
                return GenerateResult.InvalidTarget;

            try
            {
                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
					if (IsCancelled)
                        return;

                    _doWithImage(image, imageWithResult.Result.IsLocalOrCachedResult(), false);
                    Completed = true;
                    Parameters?.OnSuccess(new ImageSize(image.PixelWidth, image.PixelHeight), imageWithResult.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                    return GenerateResult.Failed;
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                throw ex2;
            }

            return GenerateResult.Success;
        }
示例#7
0
        public async Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            var cachedStream = await DownloadCache.GetStreamAsync(identifier, token, Parameters.CacheDuration, Parameters.CustomCacheKey).ConfigureAwait(false);

            var imageInformation = new ImageInformation();

            imageInformation.SetPath(identifier);
            imageInformation.SetFilePath(await DownloadCache.GetDiskCacheFilePathAsync(identifier, Parameters.CustomCacheKey));

            return(WithLoadingResult.Encapsulate(cachedStream.ImageStream,
                                                 cachedStream.RetrievedFromDiskCache ? LoadingResult.DiskCache : LoadingResult.Internet, imageInformation));
        }
		/// <summary>
		/// Runs the image loading task: gets image from file, url, asset or cache. Then assign it to the imageView.
		/// </summary>
		protected override async Task<GenerateResult> TryGeneratingImageAsync()
		{
			WithLoadingResult<UIImage> imageWithResult;
			UIImage image = null;
			try
			{
				imageWithResult = await RetrieveImageAsync(Parameters.Path, Parameters.Source, false).ConfigureAwait(false);
				image = imageWithResult.Item;
			}
			catch (Exception ex)
			{
				Logger.Error("An error occured while retrieving image.", ex);
				imageWithResult = new WithLoadingResult<UIImage>(LoadingResult.Failed);
				image = null;
			}

			if (image == null)
			{
				await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, true).ConfigureAwait(false);
				return imageWithResult.GenerateResult;
			}

			if (IsCancelled)
				return GenerateResult.Canceled;

			if (!_target.IsTaskValid(this))
				return GenerateResult.InvalidTarget;

			try
			{
				// Post on main thread
				await MainThreadDispatcher.PostAsync(() =>
					{
						if (IsCancelled)
							return;

						_target.Set(this, image, imageWithResult.Result.IsLocalOrCachedResult(), false);
						Completed = true;
						Parameters?.OnSuccess(imageWithResult.ImageInformation, imageWithResult.Result);
					}).ConfigureAwait(false);

				if (!Completed)
					return GenerateResult.Failed;
			}
			catch (Exception ex2)
			{
				await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
				throw ex2;
			}

			return GenerateResult.Success;
		}
示例#9
0
        public Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            if (!FileStore.Exists(identifier))
            {
                return(Task.FromResult(WithLoadingResult.Encapsulate((Stream)null, LoadingResult.NotFound)));
            }

            var imageInformation = new ImageInformation();

            imageInformation.SetPath(identifier);
            imageInformation.SetFilePath(identifier);

            var result = WithLoadingResult.Encapsulate(FileStore.GetInputStream(identifier), LoadingResult.Disk, imageInformation);

            return(Task.FromResult(result));
        }
        public async Task <WithLoadingResult <Stream> > GetStream(string identifier, CancellationToken token)
        {
            StorageFile file = null;

            try
            {
                string resPath = identifier.TrimStart('\\', '/');

                if (!resPath.StartsWith(@"Assets\") && !resPath.StartsWith("Assets/"))
                {
                    resPath = @"Assets\" + resPath;
                }

                var imgUri = new Uri("ms-appx:///" + resPath);
                file = await StorageFile.GetFileFromApplicationUriAsync(imgUri);
            }
            catch (Exception)
            {
                try
                {
                    var imgUri = new Uri("ms-appx:///" + identifier);
                    file = await StorageFile.GetFileFromApplicationUriAsync(imgUri);
                }
                catch (Exception)
                {
                }
            }


            if (file != null)
            {
                var imageInformation = new ImageInformation();
                imageInformation.SetPath(identifier);
                imageInformation.SetFilePath(file.Path);

                return(WithLoadingResult.Encapsulate(await file.OpenStreamForReadAsync(), LoadingResult.CompiledResource, imageInformation));
            }

            return(WithLoadingResult.Encapsulate <Stream>(null, LoadingResult.CompiledResource));
        }
示例#11
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);
        }
示例#12
0
        public override async Task<GenerateResult> LoadFromStreamAsync(Stream stream)
        {
            if (stream == null)
                return GenerateResult.Failed;

			if (IsCancelled)
                return GenerateResult.Canceled;

            WithLoadingResult<WriteableBitmap> imageWithResult;
            WriteableBitmap image = null;
            try
            {
                imageWithResult = await GetImageAsync("Stream", ImageSource.Stream, false, stream).ConfigureAwait(false);
                image = imageWithResult.Item;
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                imageWithResult = new WithLoadingResult<WriteableBitmap>(LoadingResult.Failed);
                image = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                return imageWithResult.GenerateResult;
            }

			if (CanUseMemoryCache())
			{
				ImageCache.Instance.Add(GetKey(), image);
			}

			if (IsCancelled)
                return GenerateResult.Canceled;

            if (_getNativeControl() == null)
                return GenerateResult.InvalidTarget;

            try
            {
                int pixelWidth = 0;
                int pixelHeight = 0;

                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
					if (IsCancelled)
                        return;

                    _doWithImage(image, true, false);
                    pixelWidth = image.PixelWidth;
                    pixelHeight = image.PixelHeight;
                    Completed = true;
                    Parameters?.OnSuccess(new ImageSize(pixelWidth, pixelHeight), imageWithResult.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                    return GenerateResult.Failed;
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                throw ex2;
            }

            return GenerateResult.Success;
        }
示例#13
0
		protected virtual async Task<WithLoadingResult<SelfDisposingBitmapDrawable>> GetDrawableAsync(string path, ImageSource source, bool isLoadingPlaceHolder, bool isPlaceholder, Stream originalStream = null)
		{
			if (IsCancelled)
				return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Canceled);

			// First decode with inJustDecodeBounds=true to check dimensions
			var options = new BitmapFactory.Options
			{
				InJustDecodeBounds = true
			};

			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<SelfDisposingBitmapDrawable>(streamWithResult.Result);
			}

			stream = streamWithResult.Item;

			try
			{
				try
				{
// NOTE: CURRENTLY NOT NEEDED							
//							if (streamWithResult.Result == LoadingResult.Internet)
//							{
//								// When loading from internet stream we shouldn't block otherwise other downloads will be paused
//								BitmapFactory.DecodeStream(stream, null, options);
//							}
//							else
//							{
						lock (_decodingLock)
						{
							BitmapFactory.DecodeStream(stream, null, options);
						}
//							}

					if (!stream.CanSeek)
					{
						if (stream == originalStream)
						{
							// If we cannot seek the original stream then there's not much we can do
							return new WithLoadingResult<SelfDisposingBitmapDrawable>(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<SelfDisposingBitmapDrawable>(streamWithResult.Result);
							}

							stream = streamWithResult.Item;
						}
					}
					else
					{
						stream.Seek(0, SeekOrigin.Begin);
					}
				}
				catch (Exception ex)
				{
					Logger.Error("Something wrong happened while asynchronously retrieving image size from file: " + path, ex);
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Failed);
				}

				if (IsCancelled)
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Canceled);

				options.InPurgeable = true;
				options.InJustDecodeBounds = false;

				if (!ImageService.Config.LoadWithTransparencyChannel || Parameters.LoadTransparencyChannel == null || !Parameters.LoadTransparencyChannel.Value)
				{
					// Same quality but no transparency channel. This allows to save 50% of memory: 1 pixel=2bytes instead of 4.
					options.InPreferredConfig = Bitmap.Config.Rgb565;
				}

				// CHECK IF BITMAP IS EXIF ROTATED
				int exifRotation = 0;
				if (source == ImageSource.Filepath)
				{
					exifRotation = path.GetExifRotationDegrees();
				}

				try
				{
					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 image is rotated, swap width/height
						if (exifRotation == 90 || exifRotation == 270) 
						{
							downsampleWidth = Parameters.DownSampleSize.Item2;
							downsampleHeight = Parameters.DownSampleSize.Item1;
						}

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

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

						options.InSampleSize = CalculateInSampleSize(options, downsampleWidth, downsampleHeight);

						// If we're running on Honeycomb or newer, try to use inBitmap
						if (Utils.HasHoneycomb())
							AddInBitmapOptions(options);	
					}
				}
				catch (Exception ex)
				{
					Logger.Error("Something wrong happened while adding decoding options to image: " + path, ex);
				}

				if (IsCancelled)
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Canceled);

				Bitmap bitmap;
				try
				{
// NOTE: CURRENTLY NOT NEEDED
//							if (streamWithResult.Result == LoadingResult.Internet)
//							{
//								// When loading from internet stream we shouldn't block otherwise other downloads will be paused
//								bitmap = BitmapFactory.DecodeStream(stream, null, options);
//							}
//							else
//							{
						lock (_decodingLock)
						{
							bitmap = BitmapFactory.DecodeStream(stream, null, options);
						}
//							}
				}
				catch (Java.Lang.Throwable vme)
				{
					if (vme.Class == Java.Lang.Class.FromType(typeof(Java.Lang.OutOfMemoryError)))
					{
						ImageCache.Instance.Clear(); // Clear will also force a Garbage collection
					}
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Failed);
				}
				catch (Exception ex)
				{
					Logger.Error("Something wrong happened while asynchronously loading/decoding image: " + path, ex);
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Failed);
				}

				if (bitmap == null)
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Failed);

				if (IsCancelled)
					return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Canceled);

				// APPLY EXIF ORIENTATION IF NEEDED
				if (exifRotation != 0)
					bitmap = bitmap.ToRotatedBitmap(exifRotation);

				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 (IsCancelled)
							return new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Canceled);

						try
						{
							var old = bitmap;

							// Applying a transformation is both CPU and memory intensive
							lock (_decodingLock)
							{
								var bitmapHolder = transformation.Transform(new BitmapHolder(bitmap));
								bitmap = bitmapHolder.ToNative();
							}

							// Transformation succeeded, so garbage the source
							if (old != null && old.Handle != IntPtr.Zero && !old.IsRecycled && old != bitmap && old.Handle != bitmap.Handle)
							{
								old.Recycle();
								old.Dispose();
							}

						}
						catch (Exception ex)
						{
							Logger.Error("Can't apply transformation " + transformation.Key + " to image " + path, ex);
						}
					}
				}

				if (isLoadingPlaceHolder)
				{
					return WithLoadingResult.Encapsulate<SelfDisposingBitmapDrawable>(new SelfDisposingAsyncDrawable(Context.Resources, bitmap, this), streamWithResult.Result);
				}
				else
				{
					bool isFadeAnimationEnabled = Parameters.FadeAnimationEnabled.HasValue ?
						Parameters.FadeAnimationEnabled.Value : ImageService.Config.FadeAnimationEnabled;

					bool isFadeAnimationEnabledForCached = isFadeAnimationEnabled && (Parameters.FadeAnimationForCachedImages.HasValue ?
						Parameters.FadeAnimationForCachedImages.Value : ImageService.Config.FadeAnimationForCachedImages);

					int fadeDuration = Parameters.FadeAnimationDuration.HasValue ?
						Parameters.FadeAnimationDuration.Value : ImageService.Config.FadeAnimationDuration;

					bool isLocalOrCached = streamWithResult.Result.IsLocalOrCachedResult();

					BitmapDrawable placeholderDrawable = null;
					if (_loadingPlaceholderWeakReference != null)
					{
						_loadingPlaceholderWeakReference.TryGetTarget(out placeholderDrawable);
					}

					if (isLocalOrCached)
					{
						return WithLoadingResult.Encapsulate<SelfDisposingBitmapDrawable>(
							new FFBitmapDrawable(Context.Resources, bitmap, placeholderDrawable, 
								fadeDuration, isFadeAnimationEnabled && isFadeAnimationEnabledForCached), streamWithResult.Result);
					}

					return WithLoadingResult.Encapsulate<SelfDisposingBitmapDrawable>(
						new FFBitmapDrawable(Context.Resources, bitmap, placeholderDrawable, 
							fadeDuration, isFadeAnimationEnabled), streamWithResult.Result);
				}
			}
			finally
			{
				if (stream != null)
					stream.Dispose();
			}
		}
示例#14
0
		/// <summary>
		/// Runs the image loading task: gets image from file, url, asset or cache. Then assign it to the imageView.
		/// </summary>
		protected override async Task<GenerateResult> TryGeneratingImageAsync()
		{
			WithLoadingResult<SelfDisposingBitmapDrawable> drawableWithResult;
			if (string.IsNullOrWhiteSpace(Parameters.Path))
			{
				drawableWithResult = new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Failed);
			}
			else
			{
				try
				{
					drawableWithResult = await RetrieveDrawableAsync(Parameters.Path, Parameters.Source, false, false).ConfigureAwait(false);
				}
				catch (Exception ex)
				{
					Logger.Error("An error occured while retrieving drawable.", ex);
					drawableWithResult = new WithLoadingResult<SelfDisposingBitmapDrawable>(LoadingResult.Failed);
				}
			}

			var imageView = GetAttachedImageView();
			if (imageView == null)
				return GenerateResult.InvalidTarget;

			if (drawableWithResult.HasError)
			{
				// Show error placeholder
				await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);
				return drawableWithResult.GenerateResult;
			}
				
			try
			{
				if (IsCancelled)
					return GenerateResult.Canceled;

				// Post on main thread
				await MainThreadDispatcher.PostAsync(() =>
					{
						if (IsCancelled)
							return;
						
						if (imageView.Handle == IntPtr.Zero)
							return;
						
						SetImageDrawable(imageView, drawableWithResult.Item);
						
						Completed = true;
						Parameters?.OnSuccess(new ImageSize(drawableWithResult.Item.IntrinsicWidth, drawableWithResult.Item.IntrinsicHeight), drawableWithResult.Result);
					}).ConfigureAwait(false);

				if (!Completed)
					return GenerateResult.Failed;
			}
			catch (Exception ex2)
			{
				await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);
				throw ex2;
			}

			return GenerateResult.Success;
		}
示例#15
0
		protected virtual async Task<WithLoadingResult<BitmapDrawable>> GetDrawableAsync(string path, ImageSource source, bool isLoadingPlaceHolder, Stream originalStream = null)
		{
			if (CancellationToken.IsCancellationRequested)
				return null;

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

					// First decode with inJustDecodeBounds=true to check dimensions
					var options = new BitmapFactory.Options
					{
						InJustDecodeBounds = true
					};

					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 || streamWithResult.Item == null)
						return null;

					stream = streamWithResult.Item;

					try
					{
						try
						{
							lock (_decodingLock)
							{
								BitmapFactory.DecodeStream(stream, null, options);
							}

							if (!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);
							}
						}
						catch (Exception ex)
						{
							Logger.Error("Something wrong happened while asynchronously retrieving image size from file: " + path, ex);
							return null;
						}

						if (CancellationToken.IsCancellationRequested)
							return null;

						options.InPurgeable = true;
						options.InJustDecodeBounds = false;

						if (!ImageService.Config.LoadWithTransparencyChannel || Parameters.LoadTransparencyChannel == null || !Parameters.LoadTransparencyChannel.Value)
						{
							// Same quality but no transparency channel. This allows to save 50% of memory: 1 pixel=2bytes instead of 4.
							options.InPreferredConfig = Bitmap.Config.Rgb565;
						}

						try
						{
							if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0))
							{
								// Calculate inSampleSize
								options.InSampleSize = CalculateInSampleSize(options, (int)Parameters.DownSampleSize.Item1, (int)Parameters.DownSampleSize.Item2);
							}

							// If we're running on Honeycomb or newer, try to use inBitmap
							if (Utils.HasHoneycomb())
								AddInBitmapOptions(options);
						}
						catch (Exception ex)
						{
							Logger.Error("Something wrong happened while adding decoding options to image: " + path, ex);
						}

						if (CancellationToken.IsCancellationRequested)
							return null;

						Bitmap bitmap;
						try
						{
							lock (_decodingLock)
							{
								bitmap = BitmapFactory.DecodeStream(stream, null, options);
							}
						}
						catch (Java.Lang.Throwable vme)
						{
							if (vme.Class == Java.Lang.Class.FromType(typeof(Java.Lang.OutOfMemoryError)))
							{
								ImageCache.Instance.Clear(); // Clear will also force a Garbage collection
							}
							return null;
						}
						catch (Exception ex)
						{
							Logger.Error("Something wrong happened while asynchronously loading/decoding image: " + path, ex);
							return null;
						}

						try
						{
							if (bitmap == null || CancellationToken.IsCancellationRequested)
								return null;

							if (Parameters.Transformations != null && Parameters.Transformations.Count > 0)
							{
								foreach (var transformation in Parameters.Transformations.ToList() /* to prevent concurrency issues */)
								{
									if (CancellationToken.IsCancellationRequested)
										return null;

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

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

							if (isLoadingPlaceHolder)
							{
								return WithLoadingResult.Encapsulate<BitmapDrawable>(new AsyncDrawable(Context.Resources, bitmap, this), streamWithResult.Result);
							}
							else
							{
								Drawable placeholderDrawable = null;
								if (_loadingPlaceholderWeakReference != null)
								{
									_loadingPlaceholderWeakReference.TryGetTarget(out placeholderDrawable);
								}

								return WithLoadingResult.Encapsulate<BitmapDrawable>(new FFBitmapDrawable(Context.Resources, bitmap, placeholderDrawable, FADE_TRANSITION_MILISECONDS, UseFadeInBitmap), streamWithResult.Result);
							}
						}
						finally
						{
							if (bitmap != null)
								bitmap.Dispose(); // .NET space no longer needs to care about the Bitmap. It should exist in Java world only so we break the relationship .NET/Java for the object.
						}
					}
					finally
					{
						if (stream != null)
							stream.Dispose();
					}
				});
		}
示例#16
0
		/// <summary>
		/// Loads the image from given stream asynchronously.
		/// </summary>
		/// <returns>An awaitable task.</returns>
		/// <param name="stream">The stream to get data from.</param>
		public override async Task<GenerateResult> LoadFromStreamAsync(Stream stream)
		{
			if (stream == null)
				return GenerateResult.Failed;

			if (IsCancelled)
				return GenerateResult.Canceled;

			WithLoadingResult<UIImage> resultWithImage;
			UIImage image = null;
			try
			{
				resultWithImage = await GetImageAsync("Stream", ImageSource.Stream, false, stream).ConfigureAwait(false);
				image = resultWithImage.Item;
			}
			catch (Exception ex)
			{
				Logger.Error("An error occured while retrieving image.", ex);
				resultWithImage = new WithLoadingResult<UIImage>(LoadingResult.Failed);
				image = null;
			}

			if (image == null)
			{
				await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
				return resultWithImage.GenerateResult;
			}

			if (CanUseMemoryCache())
			{
				ImageCache.Instance.Add(GetKey(), resultWithImage.ImageInformation, image);
			}

			if (IsCancelled)
				return GenerateResult.Canceled;

			if (!_target.IsTaskValid(this))
				return GenerateResult.InvalidTarget;

			try
			{
				// Post on main thread
				await MainThreadDispatcher.PostAsync(() =>
					{
						if (IsCancelled)
							return;

						_target.Set(this, image, true, false);
						Completed = true;
						Parameters?.OnSuccess(resultWithImage.ImageInformation, resultWithImage.Result);
					}).ConfigureAwait(false);

				if (!Completed)
					return GenerateResult.Failed;
			}
			catch (Exception ex2)
			{
				await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
				throw ex2;
			}

			return GenerateResult.Success;
		}