How to get native image (bitmap) from ImageSource?

Igor Kravchenko 281 Reputation points
2022-05-06T14:30:44.387+00:00

I need to get native bitmap from ImageSource. In Xamarin Forms we have a LoadImageAsync method in IImageSourceHandler. And for example to get bitmap from FontImageSource we needed to create FontImageSourceHandler and call LoadImageAsync.
How to get bitmap in MAUI?

For example, I have a custom entry with property LeadingImageSource of type ImageSource. And I want to use this in handler.

public static void MapImage(IMaterialEntryHandler handler, IMaterialEntry entry)
        {
            Bitmap bitmap = entry.LeadingImageSource //how to get from ImageSource?
            BitmapDrawable leadingDrawable = new BitmapDrawable(handler.MauiContext.Context.Resources, bitmap);
            handler.PlatformView.EditText.SetCompoundDrawablesWithIntrinsicBounds(leadingDrawable, null, null, null);
        }

I found ImageSourcePartLoader class but this is not clear for me how to use it. I see in maui sources usage like this: new ImageSourcePartLoader(this, () => VirtualView, OnSetImageSource);.
Should I implement IImageSourcePart to get bitmap and use it in OnSetImageSource?
Thanks.

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,207 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 71,936 Reputation points Microsoft Vendor
    2022-05-09T09:15:53.38+00:00

    Hello,​

    Firstly, you need to get the MaterialEntry by entry, then get ImageSource by LeadingImageSource.

    Then you can convert ImageSource to IImageSourceHandler, please notice you need to convert specific ImageSourceHandler by ImageSource type.

    In the end, you can get Bitmap by await iImageSourceHandler.LoadImageAsync(imageSource, MainActivity.Instance);, You can refer to following code

       public static async void MapImage(IMaterialEntryHandler handler, IMaterialEntry entry)  
                {  
                //    Bitmap bitmap = entry.LeadingImageSource //how to get from ImageSource?  
         
                  if (entry != null)  
                   {  
         
                       MaterialEntry materialEntry = entry as MaterialEntry;  
                       ImageSource imageSource = materialEntry.LeadingImageSource;  
         
                       IImageSourceHandler iImageSourceHandler;  
         
                       if (imageSource is FileImageSource)  
                       {  
                           iImageSourceHandler = new FileImageSourceHandler();  
                       }  
                       else if (imageSource is StreamImageSource)  
                       {  
                           iImageSourceHandler = new StreamImagesourceHandler(); // sic  
                       }  
                       else if (imageSource is UriImageSource)  
                       {  
                           iImageSourceHandler = new ImageLoaderSourceHandler(); // sic  
                       }  
                       else  
                       {  
                           throw new NotImplementedException();  
                       }  
         
                       Bitmap bitmap = await iImageSourceHandler.LoadImageAsync(imageSource, MainActivity.Instance);  
                   }  
         
                }  
    

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Igor Kravchenko 281 Reputation points
    2022-05-17T15:08:16.287+00:00

    Hi.
    I get error when calling handler.LoadImageAsync (handler is FontImageSourceHandler).

    System.InvalidOperationException: IMauiContext not found.
    [mono-rt]    at Microsoft.Maui.Controls.ViewExtensions.RequireMauiContext(Element element, Boolean fallbackToAppMauiContext) in D:\a\_work\1\s\src\Controls\src\Core\ViewExtensions.cs:line 200
    [mono-rt]    at Microsoft.Maui.Controls.ViewExtensions.RequireFontManager(Element element, Boolean fallbackToAppMauiContext) in D:\a\_work\1\s\src\Controls\src\Core\ViewExtensions.cs:line 217
    [mono-rt]    at Microsoft.Maui.Controls.Compatibility.Platform.Android.FontImageSourceHandler.LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken) in D:\a\_work\1\s\src\Compatibility\Core\src\Android\Renderers\FontImageSourceHandler.cs:line 36
    [mono-rt]    at TcuMaui.Platforms.Android.Extensions.Extensions.ToBitmap(ImageSource imageSource, CancellationToken cancellationToken) in C:\Users\Igor\source\Workspaces\TcuMaui\TcuMaui\Platforms\Android\Extensions\Extensions.cs:line 31
    

    Code:

    public static IImageSourceHandler GetHandler(this ImageSource imageSource)
            {
                if (imageSource is FileImageSource)
                    return new FileImageSourceHandler();
                if (imageSource is StreamImageSource)
                    return new StreamImagesourceHandler();
                if (imageSource is UriImageSource)
                    return new ImageLoaderSourceHandler();
                if (imageSource is FontImageSource)
                    return new FontImageSourceHandler();
                return null;
            }
    
            public static Task<Bitmap> ToBitmap(this ImageSource imageSource, CancellationToken cancellationToken = default)
            {
                if (imageSource == null)
                    return null;
                IImageSourceHandler handler = imageSource.GetHandler();
                return handler.LoadImageAsync(imageSource, MainActivity.Instance, cancellationToken);
            }
    
            public static async Task<BitmapDrawable> ToBitmapDrawable(this ImageSource imageSource, CancellationToken cancellationToken = default)
            {
                if (imageSource == null)
                    return null;
                Bitmap bitmap = await imageSource.ToBitmap(cancellationToken);
                return new BitmapDrawable(MainActivity.Instance.Resources, bitmap);
            }
    

    I use FontImageSource in custom control.

    <controls:MaterialEntry Placeholder="Contractor">
                    <controls:MaterialEntry.LeadingImageSource>
                        <FontImageSource FontFamily="MaterialOutline"
                                         Glyph="{Static icons:MaterialOutline.Person}"
                                         Color="Blue"/>
                    </controls:MaterialEntry.LeadingImageSource>
                </controls:MaterialEntry>
    

    Full project
    How can I solve this issue? Thanks.

    0 comments No comments