protected async override Task SetTargetAsync(ISelfDisposingBitmapDrawable image, bool animated) { ThrowIfCancellationRequested(); var ffDrawable = image as FFBitmapDrawable; if (ffDrawable != null) { if (ffDrawable.IsAnimationRunning) { await Task.Delay(ffDrawable.FadeDuration + 25); } if (animated) { ISelfDisposingBitmapDrawable placeholderDrawable = null; if (_loadingPlaceholderWeakReference != null && _loadingPlaceholderWeakReference.TryGetTarget(out placeholderDrawable) && placeholderDrawable != null) { int fadeDuration = Parameters.FadeAnimationDuration.HasValue ? Parameters.FadeAnimationDuration.Value : Configuration.FadeAnimationDuration; placeholderDrawable?.SetIsRetained(true); ffDrawable?.SetPlaceholder(placeholderDrawable as BitmapDrawable, fadeDuration); placeholderDrawable?.SetIsRetained(false); } } } await MainThreadDispatcher.PostAsync(() => { ThrowIfCancellationRequested(); PlatformTarget.Set(this, image, animated); }).ConfigureAwait(false); }
public void Add(string key, ImageInformation imageInformation, ISelfDisposingBitmapDrawable bitmap) { if (string.IsNullOrWhiteSpace(key) || bitmap == null || bitmap.Handle == IntPtr.Zero || !bitmap.HasValidBitmap || _cache.ContainsKey(key)) { return; } _imageInformations.TryAdd(key, imageInformation); _cache.Add(key, bitmap); }
public static bool IsValidAndHasValidBitmap(this ISelfDisposingBitmapDrawable drawable) { try { return(drawable != null && drawable.Handle != IntPtr.Zero && drawable.HasValidBitmap); } catch (ObjectDisposedException) { return(false); } }
public Tuple <ISelfDisposingBitmapDrawable, ImageInformation> Get(string key) { ISelfDisposingBitmapDrawable drawable = null; if (_cache.TryGetValue(key, out drawable)) { var imageInformation = GetInfo(key); return(new Tuple <ISelfDisposingBitmapDrawable, ImageInformation>(drawable, imageInformation)); } return(null); }
public override void SetIsDisplayed(bool isDisplayed) { base.SetIsDisplayed(isDisplayed); if (baseDrawable != null) { ISelfDisposingBitmapDrawable sdbDraw = null; if (baseDrawable.TryGetTarget(out sdbDraw) && sdbDraw.IsValidAndHasValidBitmap()) { sdbDraw.SetIsDisplayed(isDisplayed); } } }
void AddInBitmapOptions(BitmapFactory.Options options) { // inBitmap only works with mutable bitmaps so force the decoder to // return mutable bitmaps. options.InMutable = true; // Try and find a bitmap to use for inBitmap ISelfDisposingBitmapDrawable bitmapDrawable = null; try { bitmapDrawable = ImageCache.Instance.GetBitmapDrawableFromReusableSet(options); var bitmap = bitmapDrawable == null ? null : bitmapDrawable.Bitmap; if (bitmap != null && bitmap.Handle != IntPtr.Zero && !bitmap.IsRecycled) { options.InBitmap = bitmapDrawable.Bitmap; } } finally { bitmapDrawable?.SetIsRetained(false); } }
protected override void BeforeLoading(ISelfDisposingBitmapDrawable image, bool fromMemoryCache) { image?.SetIsRetained(true); }
protected override void AfterLoading(ISelfDisposingBitmapDrawable image, bool fromMemoryCache) { base.AfterLoading(image, fromMemoryCache); image?.SetIsRetained(false); }
public static bool IsValidAndHasValidBitmap(this ISelfDisposingBitmapDrawable drawable) { return(drawable != null && drawable.Handle != IntPtr.Zero && drawable.HasValidBitmap); }
public async Task <IDecodedImage <Bitmap> > DecodeAsync(Stream imageData, string path, ImageSource source, ImageInformation imageInformation, TaskParameter parameters) { BitmapFactory.Options options = null; Bitmap bitmap = null; if (imageData == null) { throw new ArgumentNullException(nameof(imageData)); } if (options == null) { // First decode with inJustDecodeBounds=true to check dimensions options = new BitmapFactory.Options { InJustDecodeBounds = true, }; await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } options.InPurgeable = true; options.InJustDecodeBounds = false; options.InDither = true; options.InScaled = false; options.InDensity = 0; options.InTargetDensity = 0; imageInformation.SetOriginalSize(options.OutWidth, options.OutHeight); imageInformation.SetCurrentSize(options.OutWidth, options.OutHeight); if (!Configuration.BitmapOptimizations || (parameters.BitmapOptimizationsEnabled.HasValue && !parameters.BitmapOptimizationsEnabled.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; options.InPreferQualityOverSpeed = false; } // CHECK IF BITMAP IS EXIF ROTATED int exifRotation = 0; if ((source == ImageSource.Filepath || source == ImageSource.Stream || source == ImageSource.Url) && imageInformation.Type != ImageInformation.ImageType.SVG) { try { exifRotation = imageData.GetExifRotationDegrees(); } catch (Exception ex) { Logger.Error("Reading EXIF orientation failed", ex); } } if (imageData.Position != 0) { imageData.Position = 0; } // DOWNSAMPLE 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 (parameters.DownSampleUseDipUnits) { downsampleWidth = downsampleWidth.DpToPixels(); downsampleHeight = downsampleHeight.DpToPixels(); } options.InSampleSize = CalculateInSampleSize(options, downsampleWidth, downsampleHeight, parameters.AllowUpscale ?? Configuration.AllowUpscale); if (options.InSampleSize > 1) { imageInformation.SetCurrentSize( (int)((double)options.OutWidth / options.InSampleSize), (int)((double)options.OutHeight / options.InSampleSize)); } // If we're running on Honeycomb or newer, try to use inBitmap if (Utils.HasHoneycomb()) { AddInBitmapOptions(options); } } if (imageData.Position != 0) { imageData.Position = 0; } try { bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } catch (Java.Lang.IllegalArgumentException) { ISelfDisposingBitmapDrawable old = options.InBitmap as object as ISelfDisposingBitmapDrawable; old?.SetIsRetained(true); options.InBitmap = null; bitmap = await BitmapFactory.DecodeStreamAsync(imageData, null, options).ConfigureAwait(false); } // if image is rotated, swap width/height if (exifRotation != 0) { var oldBitmap = bitmap; bitmap = bitmap.ToRotatedBitmap(exifRotation); ImageCache.Instance.AddToReusableSet(new SelfDisposingBitmapDrawable(oldBitmap) { InCacheKey = Guid.NewGuid().ToString() }); } return(new DecodedImage <Bitmap>() { Image = bitmap }); }
public void Add(string key, ImageInformation imageInformation, ISelfDisposingBitmapDrawable bitmap) { if (string.IsNullOrWhiteSpace(key) || bitmap == null || bitmap.Handle == IntPtr.Zero || !bitmap.HasValidBitmap || _cache.ContainsKey(key)) return; _imageInformations.TryAdd(key, imageInformation); _cache.Add(key, bitmap); }