예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
 public static bool IsValidAndHasValidBitmap(this ISelfDisposingBitmapDrawable drawable)
 {
     try
     {
         return(drawable != null && drawable.Handle != IntPtr.Zero && drawable.HasValidBitmap);
     }
     catch (ObjectDisposedException)
     {
         return(false);
     }
 }
예제 #4
0
        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);
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
 protected override void BeforeLoading(ISelfDisposingBitmapDrawable image, bool fromMemoryCache)
 {
     image?.SetIsRetained(true);
 }
예제 #8
0
 protected override void AfterLoading(ISelfDisposingBitmapDrawable image, bool fromMemoryCache)
 {
     base.AfterLoading(image, fromMemoryCache);
     image?.SetIsRetained(false);
 }
예제 #9
0
 public static bool IsValidAndHasValidBitmap(this ISelfDisposingBitmapDrawable drawable)
 {
     return(drawable != null && drawable.Handle != IntPtr.Zero && drawable.HasValidBitmap);
 }
예제 #10
0
        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
            });
        }
예제 #11
0
		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);
		}