FFImageLoading EmbeddedResourceImageSource to Android Bitmap/byte[]

GraverobberGraverobber Member ✭✭✭
edited July 8 in Xamarin.Forms

Hi,

I have the need to transform a EmbeddedResourceImageSource of the FFImageLoading library into either a Bitmap (Android) or a byte array.
Before I used a StreamImageSource and was able to do it like this:

    Bitmap bit = await new StreamImagesourceHandler().LoadImageAsync(person.Photo,MainActivity.Instance);
    byte[] photoBytes;
    using(var stream = new MemoryStream())
    {
bit.Compress(Bitmap.CompressFormat.Png, 100, stream);
                photoBytes = stream.ToArray();

                List<IParcelable> data = new List<IParcelable>();
                ContentValues row = new ContentValues();
                row.Put(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.Photo.ContentItemType);
                row.Put(ContactsContract.CommonDataKinds.Photo.PhotoColumnId, photoBytes);
                data.Add(row);
                contactIntent.PutParcelableArrayListExtra(ContactsContract.Intents.Insert.Data, data);
}

But of course StreamImagesourceHandler is not working anymore for EmbeddedResourceImageSource.
Also I tried loading the BitmapDrawable by
BitmapDrawable dr = await ImageService.Instance.LoadEmbeddedResource((person.Photo as EmbeddedResourceImageSource).Uri.ToString()).AsBitmapDrawableAsync();

but then it crashes with System.ArgumentNullException with Message Value cannot be null.
Parameter name: Stream and Decoded

StackTrace:

at FFImageLoading.DataResolvers.WrappedDataResolver.Resolve (System.String identifier, FFImageLoading.Work.TaskParameter parameters, System.Threading.CancellationToken token) [0x000c1] in C:\projects\ffimageloading\source\FFImageLoading.Common\DataResolvers\WrappedDataResolver.cs:24 \n at FFImageLoading.Work.ImageLoaderTask`3[TDecoderContainer,TImageContainer,TImageView].RunAsync () [0x00300] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\ImageLoaderTask.cs:618 \n at MyApp.Droid.DependencyServices.ContactHelper.AddContact (MyApp.Models.PeopleFinder.Person person) [0x0012f] in /Users/ddz/Develop/XamarinWorkspace/MyApp/MyApp.Android/DependencyServices/ContactHelper.cs:43 \n at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__6_0 (System.Object state) [0x00000] in <3a61d48d66dd458fa0b64990b6c8f8cc>:0 \n at Android.App.SyncContext+<>c__DisplayClass2_0.b__0 () [0x00000] in :0 \n at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in :0 \n at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00009] in :0 \n at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.56(intptr,intptr)"

Does anyone know how I can get the Bitmap and or the byte[], I guess I'm just missing something.

Thx!

Best Answer

Answers

  • GraverobberGraverobber Member ✭✭✭

    Thank you for your reply @Amar_Bait

    I tried it bit what you suggested even that I believe it is not the right way to do it ;) FFImageLoading already has the image cached somewhere, reloading it again would destroy the purpose of FFImageLoading. (I think but I might be wrong)

    However, if your solution would work it would be an acceptable solution for the moment as I'm only working on a PoC.

    So, I tried but the problem is that stream is always null therefore await stream.CopyToAsync crashed with NullPointer.
    The Uri of an EmbeddedSourceImageSource looks like this {resource://myapp.resources.images.people.profile.jpg/?assembly=MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}

    I tried by directly passing the URI with the Assembly of the class. I then tried to directly pass it with the Assembly loaded by var assembly = Assembly.Load("MyApp"); which is the supposed Assembly. It didn't work neither.

    Then I tried to clean up the URI to just look like this: myapp.resources.images.people.profile.jpg which is how the file is represented in the Forms Resources. But it fails as well.

  • Amar_BaitAmar_Bait DZMember ✭✭✭✭✭
    edited July 8

    I don't see why FFImage would cache an embedded resource nor the benefit of having it cached... The only reason I can think of it being useful is if the image is downscaled (or you applied some transformations to the image), but you want to access the original file right?

    Well if FFImage can read the embedded resource, so could you. Just check your code again and make sure you're using the right Assembly and resource path.

  • GraverobberGraverobber Member ✭✭✭

    Ok thank you, I found a workaround but it is a mess... At least I believe :D
    I post it here but if someone knows a better or the correct way please let me know.

    As said the uri of EmbeddedResourceImageSource looks like this:

    {resource://myapp.resources.images.people.profile.jpg/?assembly=MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}

    The part that I need is myapp.resources.images.people.profile.jpg and assembly=MyApp. So I take the Uri, transform it to string, cut everything into nice little pieces and then just keep doing what I did in my original question but create a StreamImageSource out of the chunks.
    Now the trick was that the uri is all lowercase but the name of the resource is CamelCase (like MyApp.Resources.Images etc)
    So the uri as string had to be converted accordingly, then it worked.

    This seems highly dirty but as the presentation is coming closer I will take it!

  • Amar_BaitAmar_Bait DZMember ✭✭✭✭✭

    @Graverobber said:
    Ok thank you, I found a workaround but it is a mess... At least I believe :D
    I post it here but if someone knows a better or the correct way please let me know.

    As said the uri of EmbeddedResourceImageSource looks like this:

    {resource://myapp.resources.images.people.profile.jpg/?assembly=MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}

    The part that I need is myapp.resources.images.people.profile.jpg and assembly=MyApp. So I take the Uri, transform it to string, cut everything into nice little pieces and then just keep doing what I did in my original question but create a StreamImageSource out of the chunks.
    Now the trick was that the uri is all lowercase but the name of the resource is CamelCase (like MyApp.Resources.Images etc)
    So the uri as string had to be converted accordingly, then it worked.

    This seems highly dirty but as the presentation is coming closer I will take it!

Sign In or Register to comment.