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 |
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.
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:
Leadtools.Viewer.Controls.XamarinLeadtools.Formats.Raster.Common
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.
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:
using Xamarin.Essentials; Add the following global variable:
bool PermissionsGranted; Add a MainPage_Appearing() event handler to the MainPage class.
public MainPage(){// Keep rest of code as isInitializeComponent();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.
private async void MainPage_Appearing(object sender, EventArgs e){PermissionsGranted = await VerifyPermissions();if (PermissionsGranted == false)return;elseApp.Current.MainPage = new ImageViewerPage();}private async Task<bool> VerifyPermissions(){try{PermissionStatus status = PermissionStatus.Unknown;// Storage Read permissionstatus = 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 grantedreturn true;}catch (Exception ex){await DisplayAlert("Error", ex.ToString(), "OK");return false;}}
In the Solution Explorer, right-click on Info.plist. Click Open With.... Select Generic PList Editor, then click OK.

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.

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.
// Using block at the topusing 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.
// Add this global variableprivate ImageViewer _imageViewer;private RasterImage _image;
Add a new method called InitImageViewer() and call it inside the ImageViewerPage() method after InitializeComponent(); call.
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.
// Dependency servicenamespace DataService{public interface IPicturePicker{Task<Stream> GetImageStreamAsync();}}
Right-click on <Project>.Android and select Add -> New Item. Select the Class option and name the class PicturePickerImplementation.cs, then click Add.

Add the below using statements to the new class:
using System.IO;using System.Threading.Tasks;using Xamarin.Forms;using Android.Content;using <Project_Namespace>.Droid; // Replace with project's namespaceusing 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.
[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.
// 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);}}}
Right-click on <Project>.iOS and select Add -> New Item. Select the Class option and name the class PicturePickerImplementation.cs, then click Add.

Add the below using statements to the new class:
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.
[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 UIImagePickerControllerimagePicker = new UIImagePickerController{SourceType = UIImagePickerControllerSourceType.PhotoLibrary,MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary)};// Set event handlersimagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;// Present UIImagePickerController;UIWindow window = UIApplication.SharedApplication.KeyWindow;var viewController = window.RootViewController;viewController.PresentModalViewController(imagePicker, true);// Return Task objecttaskCompletionSource = 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 objectNSData data = image.AsJPEG(1);Stream stream = data.AsStream();// Set the Stream as the completion of the TasktaskCompletionSource.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:
Leadtools.Controls.iOS.Assembly.Use();
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.
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");}}
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:

iOS:

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