Display Image in an Image Viewer - Xamarin C#

This tutorial shows how to use the LEADTOOLS SDK in a C# Xamarin application and display images in an Image Viewer.

Xamarin Framework Deprecation

As of LEADTOOLS v23, The cross-platform Xamarin framework has been deprecated and replaced with LEADTOOLS .NET MAUI framework.

For any LEADTOOLS Xamarin apps you have already built, we recommend you migrate to the LEADTOOLS .NET MAUI framework. To help you with the migration, review the LEADTOOLS .NET MAUI tutorials to get you started.

This change is driven by Microsoft's announcement to end Xamarin support.

Overview  
Summary This tutorial covers how to display images in a LEADTOOLS Image Viewer a C# Xamarin application
Completion Time 30 minutes
Visual Studio Project Download tutorial project (463 KB)
Platform C# Xamarin Cross-Platform Application
IDE Visual Studio 2017, 2019, 2022
Development License Download LEADTOOLS

Required Knowledge

Get familiar with the basic steps of creating a project by reviewing the Add References and Set a License tutorial, before working on the Display Image in an Image Viewer - Xamarin C# tutorial.

Create the Project and Add the LEADTOOLS References

In Visual Studio, create a new C# Xamarin project, and add the following necessary LEADTOOLS references.

The references needed depend upon the purpose of the project. For this project, the following NuGet package are needed:

Set the License File

The License unlocks the features needed for the project. It must be set before any toolkit function is called. For details, including tutorials for different platforms, refer to Setting a Runtime License.

There are two types of runtime licenses:

Note

Adding LEADTOOLS NuGet references and setting a license are covered in more detail in the Add References and Set a License tutorial.

Add Code to Check and Ask for Storage Read Permission

With the project created, the references added, and the license set, coding can begin.

In the Solution Explorer, open the MainPage.xaml.cs and ensure that the following are added to the using area at the top of the code:

C#
using Xamarin.Essentials; 

Add the following global variable:

C#
bool PermissionsGranted; 

Add a MainPage_Appearing() event handler to the MainPage class.

C#
public MainPage() 
{ 
   // Keep rest of code as is 
   InitializeComponent(); 
 
   Appearing += MainPage_Appearing; 
} 

Use the code below to check the Storage Read permission for the application and prompt the user to enable them before loading the ContentPage with the Image Viewer control.

C#
private async void MainPage_Appearing(object sender, EventArgs e) 
{ 
   PermissionsGranted = await VerifyPermissions(); 
   if (PermissionsGranted == false) 
      return; 
   else 
      App.Current.MainPage = new ImageViewerPage(); 
} 
 
private async Task<bool> VerifyPermissions() 
{ 
   try 
   { 
      PermissionStatus status = PermissionStatus.Unknown; 
 
      // Storage Read permission 
      status = await Permissions.CheckStatusAsync<Permissions.StorageRead>(); 
      if (status != PermissionStatus.Granted) 
      { 
         await DisplayAlert("Storage Read Permission Required", "This app will load images from storage for display", "OK"); 
         status = await Permissions.RequestAsync<Permissions.StorageRead>(); 
 
         if (status != PermissionStatus.Granted) 
            return false; 
      } 
 
      // All needed permissions granted 
      return true; 
   } 
   catch (Exception ex) 
   { 
      await DisplayAlert("Error", ex.ToString(), "OK"); 
      return false; 
   } 
} 

Add Application Permissions (iOS)

In the Solution Explorer, right-click on Info.plist. Click Open With.... Select Generic PList Editor, then click OK.

Select Generic PList Editor

Click the + button on the last row in the editor. This will be called Custom Property, with the Type set to String and an empty value. Click on the Property name and the dropdown will appear. From that dropdown select the Privacy - Photo Library Usage Description. Then enter a description into the Value column for why the application wants to access that given feature.

Add Photo Library Access

Initialize the Image Viewer

With the project created, the references added, and the license set, coding can begin.

In Solution Explorer, right-Click on the base C# project and select Add -> New Item. Select the Content Page option and name the class ImageViewerPage.xaml

Open ImageViewer.xaml and add the following code inside the ContentPage to add a load image button and Image Viewer container.

   <ContentPage.Content> 
      <Grid x:Name="imageViewerContainer" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Black"> 
         <Grid.RowDefinitions> 
            <RowDefinition x:Name="row0" Height="*"/> 
            <RowDefinition x:Name="loadButtonRow" Height="50"/> 
         </Grid.RowDefinitions> 
         <Grid Margin="10,5" Grid.Row="1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> 
            <Grid.ColumnDefinitions> 
               <ColumnDefinition Width="*"/> 
            </Grid.ColumnDefinitions> 
            <Button x:Name="_loadFromGallery" Text="Load" BorderColor="LightCoral" Clicked="_loadFromGallery_Clicked" HorizontalOptions="FillAndExpand"/> 
         </Grid> 
      </Grid> 
   </ContentPage.Content> 

Right click on the page and select View Code to bring up the code behind ImageViewerPage.xaml. Add the following statements to the using block at the top of ImageViewerPage.xaml.cs.

C#
// Using block at the top 
using System; 
using System.IO; 
using System.Threading.Tasks; 
using Xamarin.Forms; 
using Xamarin.Forms.Xaml; 
using Leadtools; 
using Leadtools.Codecs; 
using Leadtools.Controls; 
using DataService; 

Add the below code to initialize the Image Viewer.

C#
// Add this global variable 
private ImageViewer _imageViewer; 
private RasterImage _image; 

Add a new method called InitImageViewer() and call it inside the ImageViewerPage() method after InitializeComponent(); call.

C#
private void InitImageViewer() 
{ 
    _imageViewer = new ImageViewer 
    { 
        ViewHorizontalAlignment = ControlAlignment.Center, 
        ViewVerticalAlignment = ControlAlignment.Center, 
        BackgroundColor = Color.FromHex("#1E1E1E"), 
        VerticalOptions = LayoutOptions.FillAndExpand, 
        HorizontalOptions = LayoutOptions.FillAndExpand, 
        Margin = new Thickness(0, 0), 
        AutoDisposeImages = true, 
    }; 
    Grid.SetRow(_imageViewer, 0); 
    Grid.SetRowSpan(_imageViewer, 1); 
    ImageViewerPanZoomInteractiveMode panZoom = new ImageViewerPanZoomInteractiveMode(); 
    _imageViewer.InteractiveModes.Add(panZoom); 
 
    imageViewerContainer.Children.Add(_imageViewer); 
} 

Add a new namespace to the bottom of ImageViewerPage.xaml.cs called DataService. This namespace will be the dependency service for the picture picker.

C#
// Dependency service 
namespace DataService 
{ 
   public interface IPicturePicker 
   { 
      Task<Stream> GetImageStreamAsync(); 
   } 
} 

Add the PicturePicker Implementation Class (Android)

Right-click on <Project>.Android and select Add -> New Item. Select the Class option and name the class PicturePickerImplementation.cs, then click Add.

Add PicturePickerImplementation.cs to Android project

Add the below using statements to the new class:

C#
using System.IO; 
using System.Threading.Tasks; 
using Xamarin.Forms; 
using Android.Content; 
using <Project_Namespace>.Droid; // Replace with project's namespace 
using DataService; 

Add a new method to the PicturePickerImplementation class called GetImageStreamAsync() that returns a Task<Stream>. Add the below code to implement the PicturePicker on an Android device.

C#
[assembly: Dependency(typeof(PicturePickerImplementation))] 
namespace <Project_Namespace>.Droid // Replace with project's namespace 
{ 
   class PicturePickerImplementation : IPicturePicker 
   { 
      public Task<Stream> GetImageStreamAsync() 
      { 
         Intent intent = new Intent(); 
         intent.SetType("image/*"); 
         intent.SetAction(Intent.ActionGetContent); 
         MainActivity activity = MainActivity.Instance; 
         if (activity.PickImageTaskCompletionSource == null || activity.PickImageTaskCompletionSource.Task.IsCompleted || activity.PickImageTaskCompletionSource.Task.IsCanceled) 
         { 
            activity.StartActivityForResult(Intent.CreateChooser(intent, "Select Picture"), MainActivity.PickImageId); 
            activity.PickImageTaskCompletionSource = new TaskCompletionSource<Stream>(); 
            return activity.PickImageTaskCompletionSource.Task; 
         } 
         else 
         { 
            return activity.PickImageTaskCompletionSource.Task; 
         } 
      } 
   } 
} 

Make sure to add the [assembly: Dependency(typeof(PicturePickerImplementation))] line of code so that it can find the implementation of the DependencyService.

In the Solution Explorer, open MainActivity.cs. Add the below code to the OnActivityResult method to handle the image selected with the picture picker, gather the stream, and hand the stream to the task completion source.

C#
// Add these variables used in `OnActivityResult()` 
public TaskCompletionSource<Stream> PickImageTaskCompletionSource { set; get; } 
public static readonly int PickImageId = 1000; 
 
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) 
{ 
    base.OnActivityResult(requestCode, resultCode, data); 
 
    if (requestCode == PickImageId) 
    { 
        if (resultCode == Result.Ok && data != null) 
        { 
            Android.Net.Uri uri = data.Data; 
            Stream stream = ContentResolver.OpenInputStream(uri); 
 
            PickImageTaskCompletionSource.SetResult(stream); 
        } 
        else 
        { 
            PickImageTaskCompletionSource.SetResult(null); 
        } 
    } 
} 

Add the PicturePicker Implementation Class (iOS)

Right-click on <Project>.iOS and select Add -> New Item. Select the Class option and name the class PicturePickerImplementation.cs, then click Add.

Add PicturePickerImplementation.cs to iOS project

Add the below using statements to the new class:

C#
using System; 
using System.IO; 
using System.Threading.Tasks; 
using Xamarin.Forms; 
using Foundation; 
using UIKit; 
using Display_Images_in_an_Image_Viewer.iOS; 
using DataService; 

Add a new method to the PicturePickerImplementation class called GetImageStreamAsync() that returns a Task<Stream>. Add the below code to implement the PicturePicker on an iOS device.

C#
[assembly: Dependency(typeof(PicturePickerImplementation))] 
namespace Display_Images_in_an_Image_Viewer.iOS 
{ 
    [Xamarin.Forms.Internals.Preserve(AllMembers = true)] 
    class PicturePickerImplementation : IPicturePicker 
    { 
        TaskCompletionSource<Stream> taskCompletionSource; 
        UIImagePickerController imagePicker; 
        public Task<Stream> GetImageStreamAsync() 
        { 
            try 
            { 
                // Create and define UIImagePickerController 
                imagePicker = new UIImagePickerController 
                { 
                    SourceType = UIImagePickerControllerSourceType.PhotoLibrary, 
                    MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary) 
                }; 
                // Set event handlers 
                imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia; 
                // Present UIImagePickerController; 
                UIWindow window = UIApplication.SharedApplication.KeyWindow; 
                var viewController = window.RootViewController; 
                viewController.PresentModalViewController(imagePicker, true); 
                // Return Task object 
                taskCompletionSource = new TaskCompletionSource<Stream>(); 
                return taskCompletionSource.Task; 
            } 
            catch (Exception ex) { Console.WriteLine(ex.Message); return null; } 
        } 
        void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args) 
        { 
            UIImage image = args.EditedImage ?? args.OriginalImage; 
            if (image != null) 
            { 
                // Convert UIImage to .NET Stream object 
                NSData data = image.AsJPEG(1); 
                Stream stream = data.AsStream(); 
                // Set the Stream as the completion of the Task 
                taskCompletionSource.SetResult(stream); 
            } 
            else 
            { 
                taskCompletionSource.SetResult(null); 
            } 
            imagePicker.DismissModalViewController(true); 
        } 
    } 
} 

Make sure to add the [assembly: Dependency(typeof(PicturePickerImplementation))] line of code so that it can find the implementation of the DependencyService.

In the Solution Explorer, open AppDelegate.cs . Add the below line to the FinishedLaunching() method:

C#
Leadtools.Controls.iOS.Assembly.Use(); 

Add the Load Image Code

In the Solution Explorer, open ImageViewerPage.xaml.cs . Add a new Clicked event handler for loadFromGallery, if it does not already exist. Add the below code inside the handler to load the image from the device's gallery.

C#
private async void _loadFromGallery_Clicked(object sender, EventArgs e) 
{ 
    try 
    { 
        Stream imageStream = await DependencyService.Get<IPicturePicker>().GetImageStreamAsync(); 
 
        if (imageStream != null) 
        { 
            using (RasterCodecs codecs = new RasterCodecs()) 
            { 
                codecs.Options.Load.XResolution = 200; 
                codecs.Options.Load.YResolution = 200; 
                _image = codecs.Load(imageStream); 
                _imageViewer.Image = _image; 
            } 
        } 
    } 
    catch (Exception ex) 
    { 
        await DisplayAlert("Error", ex.ToString(), "OK"); 
    } 
} 

Run the Project

Select the desired project (iOS or Android) and run the project by pressing F5, or by selecting Debug -> Start Debugging.

If the steps were followed correctly, the application runs and it will ask to allow Storage permissions which is required. For testing, click the Load button at the bottom of the device's screen and select any of the images in the device's gallery. The image will then be loaded as a RasterImage and will be displayed in the ImageViewer.

Android:

Android Device Screen Capture

iOS:

iOS Device Screen Capture

Wrap-up

This tutorial showed how to load and display images. In addition, it showed how to use the ImageViewer and RasterCodecs classes.

See Also

Help Version 23.0.2024.5.22
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2024 LEAD Technologies, Inc. All Rights Reserved.

Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.