Ffimageloading: Feature request: load to Bitmap instead of ImageViewAsync

Created on 13 Oct 2015  Â·  13Comments  Â·  Source: luberda-molinet/FFImageLoading

FFImageLoading is pretty fantastic. I have a use case where I'm making Android notifications that require Bitmaps. Could you make an overload of Into that loads into Bitmaps or something similar instead of ImageViewAsyncs?

I did try making a SideEffectTransformation that would copy the bitmap in directly, but immediately worried that caching would prevent future notifications with the same image from displaying properly.

And I tried loading into an ImageViewAsync and doing Draw to draw into a bitmap, but the resulting bitmap was transparent even with FadeAnimation(false).

Thanks for all your hard work!

Most helpful comment

You have mixed different FFImageLoading versions in your projects, also
remove all bin / obj folders

On Nov 29, 2017 21:35, "Victor Finney" notifications@github.com wrote:

Here is an example of the stack trace:
Xamarin caused by: android.runtime.JavaProxyThrowable:
System.AggregateException: A Task's exception(s) were not observed either
by Waiting on the Task or accessing its Exception property. As a result,
the unobserved exception was rethrown by the finalizer thread. --->
System.TypeLoadException: Could not resolve type with token 0100013c (from
typeref, class/assembly FFImageLoading.TaskParameterPlatformExtensions,
FFImageLoading.Platform, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[TResult].Start[TStateMachine]
(TStateMachine& stateMachine) [0x0002c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0
at DABApp.Droid.AudioService.fetchBitmap (System.String imageUri)
[0x00023] in :0 at
DABApp.Droid.AudioService+<>c__DisplayClass29_0+<b__2>d.MoveNext
() [0x0004a] in :0 --- End of inner
exception stack trace --- ---> (Inner Exception #0)
System.TypeLoadException: Could not resolve type with token 0100013c (from
typeref, class/assembly FFImageLoading.TaskParameterPlatformExtensions,
FFImageLoading.Platform, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null) at System.Runtime.CompilerServices.
AsyncTaskMethodBuilder1[TResult].Start[TStateMachine] (TStateMachine&
stateMachine) [0x0002c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0
at DABApp.Droid.AudioService.fetchBitmap (System.String imageUri)
[0x00023] in :0
at DABApp.Droid.AudioService+<>c__DisplayClass29_0+d.MoveNext ()
[0x0004a] in :0 <---

And here is the fetchBitmap method:

async Task fetchBitmap(string imageUri) { try {
var draw = await ImageService.Instance.LoadUrl(imageUri).DownSample().AsBitmapDrawableAsync();
return draw.Bitmap; } catch (Exception e) { Debug.WriteLine($"Bitmap
exception: {e.Message}"); return null; } }

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/luberda-molinet/FFImageLoading/issues/59#issuecomment-347988096,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AM8Pv8QAxkrj1IqD_NppwNsd8b5F34GKks5s7cAtgaJpZM4GOEoV
.

All 13 comments

Thanks @softwaremills!

Your need is really a special use case, that would not fit into this lib, therefore it should not be that hard to implement it on your side. You could subclass ImageLoaderTask and totally bypass the WorkScheduler.

Your subclass could have a method RetrieveBitmapAsync:

public async Task<Bitmap> RetrieveBitmapAsync()
{
    // Try to load from cache first
    var key = GetKey();
    if (!string.IsNullOrWhiteSpace(key))
    {
        var cachedDrawable = ImageCache.Instance.Get(key);
        if (cachedDrawable != null)
            return cachedDrawable.GetBitmap();
    }

    // Otherwise load image normally
    var drawableWithResult = await GetDrawableAsync(Parameters.Path, Parameters.Source, false).ConfigureAwait(false);
    if (drawableWithResult == null || drawableWithResult.Item == null)
        return null;

    // If we have the bitmap we add it to the cache
    ImageCache.Instance.Add(GetKey(sourcePath), drawableWithResult.Item);

    return drawableWithResult.Item.GetBitmap();
}

Then if you have your own version of it, you can instantiate it and await it:

var parameters = ImageService.LoadUrl(urlToImage); // just change this to fit your needs
var task = new MyImageLoaderTaskSubclass(ImageService.Config.DownloadCache, new MainThreadDispatcher(), ImageService.Config.Logger, parameters, null); 
var bitmap = await task.RetrieveBitmapAsync();

Works great, many thanks!

For posterity, my final class looked like this:

public class BitmapLoaderTask : ImageLoaderTask {
    public BitmapLoaderTask(string url)
        : base(ImageService.Config.DownloadCache, new MainThreadDispatcher(), ImageService.Config.Logger,
            ImageService.LoadUrl(url).TransparencyChannel(true), null)
    {
    }

    public async Task<Bitmap> RetrieveBitmapAsync()
    {
        // Try to load from cache first
        var key = GetKey();
        if (!string.IsNullOrWhiteSpace(key))
        {
            var cachedDrawable = ImageCache.Instance.Get(key);
            if (cachedDrawable != null)
                return cachedDrawable.Bitmap;
        }

        // Otherwise load image normally
        var drawableWithResult = await GetDrawableAsync(Parameters.Path, Parameters.Source, false).ConfigureAwait(false);
        if (drawableWithResult == null || drawableWithResult.Item == null)
            return null;

        // If we have the bitmap we add it to the cache
        ImageCache.Instance.Add(GetKey(), drawableWithResult.Item);

        return drawableWithResult.Item.Bitmap;
    }
}

Thanks for the feedback!

Hey I am running into the same problem brought up by this question. But I have found that the syntax with inheriting and calling ImageTaskLoader has changed a lot over the last two years. I was wondering if there is an example or documentation of how one would inherit the current ImageLoaderTask to do this.

Yeah, I think there's an officially-sanctioned version of how to do it these days. Later versions of our product didn't need this functionality, so I'm not sure of the details.

Currently, you should use:

  • await ImageService.Instance.LoadFile(xxx).DownSample(width: xxx).AsBitmapDrawableAsync() for Android
  • await ImageService.Instance.LoadFile(xxx).DownSample(width: xxx).AsUIImageAsync() for iOS
  • await ImageService.Instance.LoadFile(xxx).DownSample(width: xxx).AsBitmapDrawableAsync() for Windows (yeah I noticed bad naming, we should change it in future)

Please mind that on Androidyou should call SetNoLongerDisplayed method if drawable is no longer displayed when not using it with ImageViewAsync (which does it automatically)

Hey thanks for your reply and sorry for not getting back to you in a while. I'm trying to implement your solution but for some reason the code never completes. I just get a system aggregate exception due to the task timing out. Do you know why that might be?

@Finneyv Is your image from url source?

Yes it is. It's a jpg.

Then it must be some connection issue, please attach stack trace.

Here is an example of the stack trace:
Xamarin caused by: android.runtime.JavaProxyThrowable: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.TypeLoadException: Could not resolve type with token 0100013c (from typeref, class/assembly FFImageLoading.TaskParameterPlatformExtensions, FFImageLoading.Platform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[TResult].Start[TStateMachine] (TStateMachine& stateMachine) [0x0002c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 at DABApp.Droid.AudioService.fetchBitmap (System.String imageUri) [0x00023] in <e2a16aeec5884a15b39e12b79950e58c>:0 at DABApp.Droid.AudioService+<>c__DisplayClass29_0+<<SetMetaData>b__2>d.MoveNext () [0x0004a] in <e2a16aeec5884a15b39e12b79950e58c>:0 --- End of inner exception stack trace --- ---> (Inner Exception #0) System.TypeLoadException: Could not resolve type with token 0100013c (from typeref, class/assembly FFImageLoading.TaskParameterPlatformExtensions, FFImageLoading.Platform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[TResult].Start[TStateMachine] (TStateMachine& stateMachine) [0x0002c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0
at DABApp.Droid.AudioService.fetchBitmap (System.String imageUri) [0x00023] in :0
at DABApp.Droid.AudioService+<>c__DisplayClass29_0+<b__2>d.MoveNext () [0x0004a] in :0 <---

And here is the fetchBitmap method:

async Task<Android.Graphics.Bitmap> fetchBitmap(string imageUri) { try { var draw = await ImageService.Instance.LoadUrl(imageUri).DownSample().AsBitmapDrawableAsync(); return draw.Bitmap; } catch (Exception e) { Debug.WriteLine($"Bitmap exception: {e.Message}"); return null; } }

You have mixed different FFImageLoading versions in your projects, also
remove all bin / obj folders

On Nov 29, 2017 21:35, "Victor Finney" notifications@github.com wrote:

Here is an example of the stack trace:
Xamarin caused by: android.runtime.JavaProxyThrowable:
System.AggregateException: A Task's exception(s) were not observed either
by Waiting on the Task or accessing its Exception property. As a result,
the unobserved exception was rethrown by the finalizer thread. --->
System.TypeLoadException: Could not resolve type with token 0100013c (from
typeref, class/assembly FFImageLoading.TaskParameterPlatformExtensions,
FFImageLoading.Platform, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[TResult].Start[TStateMachine]
(TStateMachine& stateMachine) [0x0002c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0
at DABApp.Droid.AudioService.fetchBitmap (System.String imageUri)
[0x00023] in :0 at
DABApp.Droid.AudioService+<>c__DisplayClass29_0+<b__2>d.MoveNext
() [0x0004a] in :0 --- End of inner
exception stack trace --- ---> (Inner Exception #0)
System.TypeLoadException: Could not resolve type with token 0100013c (from
typeref, class/assembly FFImageLoading.TaskParameterPlatformExtensions,
FFImageLoading.Platform, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null) at System.Runtime.CompilerServices.
AsyncTaskMethodBuilder1[TResult].Start[TStateMachine] (TStateMachine&
stateMachine) [0x0002c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0
at DABApp.Droid.AudioService.fetchBitmap (System.String imageUri)
[0x00023] in :0
at DABApp.Droid.AudioService+<>c__DisplayClass29_0+d.MoveNext ()
[0x0004a] in :0 <---

And here is the fetchBitmap method:

async Task fetchBitmap(string imageUri) { try {
var draw = await ImageService.Instance.LoadUrl(imageUri).DownSample().AsBitmapDrawableAsync();
return draw.Bitmap; } catch (Exception e) { Debug.WriteLine($"Bitmap
exception: {e.Message}"); return null; } }

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/luberda-molinet/FFImageLoading/issues/59#issuecomment-347988096,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AM8Pv8QAxkrj1IqD_NppwNsd8b5F34GKks5s7cAtgaJpZM4GOEoV
.

Thanks! That seemed to do the trick.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

OpticNectar picture OpticNectar  Â·  19Comments

Tommigun1980 picture Tommigun1980  Â·  16Comments

stopiccot picture stopiccot  Â·  17Comments

LeoJHarris picture LeoJHarris  Â·  22Comments

ericruelas picture ericruelas  Â·  15Comments