<commit_before>// MvxAndroidLocalFileImageLoader.cs
// (c) Copyright Cirrious Ltd. http://www.cirrious.com
// MvvmCross is licensed using Microsoft Public License (Ms-PL)
// Contributions and inspirations noted in readme.md and license.txt
//
// Project Lead - Stuart Lodge, @slodge, <EMAIL>

using Android.Graphics;
using MvvmCross.Platform;
using MvvmCross.Platform.Droid;
using MvvmCross.Platform.Platform;
using MvvmCross.Binding;
using MvvmCross.Plugins.File;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MvvmCross.Plugins.DownloadCache.Droid
{
    public class MvxAndroidLocalFileImageLoader
        : IMvxLocalFileImageLoader<Bitmap>
    {
        private const string ResourcePrefix = "res:";

        private readonly IDictionary<CacheKey, WeakReference<Bitmap>> _memCache =
            new Dictionary<CacheKey, WeakReference<Bitmap>>();

        public async Task<MvxImage<Bitmap>> Load(string localPath, bool shouldCache, int maxWidth, int maxHeight)
        {
            Bitmap bitmap;
            var shouldAddToCache = shouldCache;
            if (shouldCache && TryGetCachedBitmap(localPath, maxWidth, maxHeight, out bitmap))
            {
                shouldAddToCache = false;
            }
            else if (localPath.StartsWith(ResourcePrefix))
            {
                var resourcePath = localPath.Substring(ResourcePrefix.Length);
                bitmap = await LoadResourceBitmapAsync(resourcePath).ConfigureAwait(false);
            }
            else
            {
                bitmap = await LoadBitmapAsync(localPath, maxWidth, maxHeight).ConfigureAwait(false);
            }

            if (shouldAddToCache)
            {
                AddToCache(localPath, maxWidth, maxHeight, bitmap);
            }

            return (MvxImage<Bitmap>)new MvxAndroidImage(bitmap);
        }

        private IMvxAndroidGlobals _androidGlobals;

        protected IMvxAndroidGlobals AndroidGlobals => _androidGlobals ?? (_androidGlobals = Mvx.Resolve<IMvxAndroidGlobals>());

        private async Task<Bitmap> LoadResourceBitmapAsync(string resourcePath)
        {
            var resources = AndroidGlobals.ApplicationContext.Resources;
            var id = resources.GetIdentifier(resourcePath, "drawable", AndroidGlobals.ApplicationContext.PackageName);
            if (id == 0)
            {
                MvxBindingTrace.Trace(MvxTraceLevel.Warning,
                                      "Value '{0}' was not a known drawable name", resourcePath);
                return null;
            }

            return
                await BitmapFactory.DecodeResourceAsync(resources, id,
                    new BitmapFactory.Options { InPurgeable = true }).ConfigureAwait(false);
        }

        private static async Task<Bitmap> LoadBitmapAsync(string localPath, int maxWidth, int maxHeight)
        {
            if (maxWidth > 0 || maxHeight > 0)
            {
                // load thumbnail - see: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
                var options = new BitmapFactory.Options { InJustDecodeBounds = true };
                await BitmapFactory.DecodeFileAsync(localPath, options).ConfigureAwait(false);

                // Calculate inSampleSize
                options.InSampleSize = CalculateInSampleSize(options, maxWidth, maxHeight);
                // see http://slodge.blogspot.co.uk/2013/02/huge-android-memory-bug-and-bug-hunting.html
                options.InPurgeable = true;

                // Decode bitmap with inSampleSize set
                options.InJustDecodeBounds = false;
                return await BitmapFactory.DecodeFileAsync(localPath, options).ConfigureAwait(false);
            }
            else
            {
                var fileStore = Mvx.Resolve<IMvxFileStore>();
                byte[] contents;
                if (!fileStore.TryReadBinaryFile(localPath, out contents))<commit_msg>Added FileDescriptor based Decode for content:// urls<commit_after>// MvxAndroidLocalFileImageLoader.cs
// (c) Copyright Cirrious Ltd. http://www.cirrious.com
// MvvmCross is licensed using Microsoft Public License (Ms-PL)
// Contributions and inspirations noted in readme.md and license.txt
//
// Project Lead - Stuart Lodge, @slodge, <EMAIL>

using Android.Graphics;
using MvvmCross.Platform;
using MvvmCross.Platform.Droid;
using MvvmCross.Platform.Platform;
using MvvmCross.Binding;
using MvvmCross.Plugins.File;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MvvmCross.Plugins.DownloadCache.Droid
{
    public class MvxAndroidLocalFileImageLoader
        : IMvxLocalFileImageLoader<Bitmap>
    {
        private const string ResourcePrefix = "res:";

        private readonly IDictionary<CacheKey, WeakReference<Bitmap>> _memCache =
            new Dictionary<CacheKey, WeakReference<Bitmap>>();

        public async Task<MvxImage<Bitmap>> Load(string localPath, bool shouldCache, int maxWidth, int maxHeight)
        {
            Bitmap bitmap;
            var shouldAddToCache = shouldCache;
            if (shouldCache && TryGetCachedBitmap(localPath, maxWidth, maxHeight, out bitmap))
            {
                shouldAddToCache = false;
            }
            else if (localPath.StartsWith(ResourcePrefix))
            {
                var resourcePath = localPath.Substring(ResourcePrefix.Length);
                bitmap = await LoadResourceBitmapAsync(resourcePath).ConfigureAwait(false);
            }
            else
            {
                bitmap = await LoadBitmapAsync(localPath, maxWidth, maxHeight).ConfigureAwait(false);
            }

            if (shouldAddToCache)
            {
                AddToCache(localPath, maxWidth, maxHeight, bitmap);
            }

            return (MvxImage<Bitmap>)new MvxAndroidImage(bitmap);
        }

        private IMvxAndroidGlobals _androidGlobals;

        protected IMvxAndroidGlobals AndroidGlobals => _androidGlobals ?? (_androidGlobals = Mvx.Resolve<IMvxAndroidGlobals>());

        private async Task<Bitmap> LoadResourceBitmapAsync(string resourcePath)
        {
            var resources = AndroidGlobals.ApplicationContext.Resources;
            var id = resources.GetIdentifier(resourcePath, "drawable", AndroidGlobals.ApplicationContext.PackageName);
            if (id == 0)
            {
                MvxBindingTrace.Trace(MvxTraceLevel.Warning,
                                      "Value '{0}' was not a known drawable name", resourcePath);
                return null;
            }

            return
                await BitmapFactory.DecodeResourceAsync(resources, id,
                    new BitmapFactory.Options { InPurgeable = true }).ConfigureAwait(false);
        }

        private static async Task<Bitmap> LoadBitmapAsync(string localPath, int maxWidth, int maxHeight)
        {
            if (localPath.ToLower().StartsWith("content"))
            {
                Bitmap bmp = null;

                await Task.Factory.StartNew(() =>
                {
                    var globals = Mvx.Resolve<IMvxAndroidGlobals>();
                    var uri = Android.Net.Uri.Parse(localPath);
                    var parcelFileDescriptor = globals?.ApplicationContext?.ContentResolver.OpenFileDescriptor(uri, "r");
                    var fileDescriptor = parcelFileDescriptor?.FileDescriptor;

                    var opts = new BitmapFactory.Options { InJustDecodeBounds = true };
                    BitmapFactory.DecodeFileDescriptor(fileDescriptor, null, opts);

                    opts.InSampleSize = CalculateInSampleSize(opts, maxWidth, maxHeight);
                    opts.InPurgeable = true;
                    opts.InJustDecodeBounds = false;
                    bmp = BitmapFactory.DecodeFileDescriptor(fileDescriptor, null, opts);

                    parcelFileDescriptor?.Close();
                }).ConfigureAwait(false);

                return bmp;
            }

            if (maxWidth > 0 || maxHeight > 0)
            {
                // load thumbnail - see: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
                var options = new BitmapFactory.Options { InJustDecodeBounds = true };
                await BitmapFactory.DecodeFileAsync(localPath, options).ConfigureAwait(false);

                // Calculate inSampleSize
                options.InSampleSize = CalculateInSampleSize(options, maxWidth, maxHeight);
                // see http://slodge.blogspot.co.uk/2013/02/huge-android-memory-bug-and-bug-hunting.html
                options.InPurgeable = true;

                // Decode bitmap with inSampleSize set
                options.InJustDecodeBounds = false;
                return await BitmapFactory.DecodeFileAsync(localPath, options).ConfigureAwait(false);
            }
            else
            {
                var fileStore = Mvx.Resolve<IMvxFileStore>();
                byte[] contents;
                if (!fileStore.TryReadBinaryFile(localPath, out contents))
{'fraction_non_alphanumeric': 0.08413275995148307, 'fraction_numerical': 0.0022053148086889404, 'mean_word_length': 2.1591779867641936, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6893222', 'n_tokens_mistral': 2393, 'n_tokens_neox': 2239, 'n_words': 490}