---
title: "Building a custom OMR template | Nutrient .NET SDK"
canonical_url: "https://www.nutrient.io/guides/dotnet/extraction/omr/templates/"
md_url: "https://www.nutrient.io/guides/dotnet/extraction/omr/templates.md"
last_updated: "2026-05-21T17:12:02.203Z"
description: "Learn how to build custom templates for optical mark recognition (OMR) in C# using Nutrient .NET SDK. Design specific layouts for accurate data extraction from forms."
---

# Building a custom template for OMR

This guide outlines how to build a custom optical mark recognition (OMR) template.

## Scanning the template

The GdPicture.NET Library comes equipped with TWAIN and WIA scanning driver support, which enables you to control almost any type of scanner using software.

Begin with a scanned template image and its `GdPictureImage` identifier `templateId`.

## Creating the template anchor

Create the anchor using the [`CreateAnchorTemplate`](https://www.nutrient.io/api/gdpicture/GdPicture.NET.14~GdPicture14.GdPictureImaging~CreateAnchorTemplate.html) function to specify the coordinates of the rectangle surrounding the anchor.

This can be done using code, by specifying the exact values, or using mouse, by using the GdViewer.

### Using the GdViewer to specify the anchor position using mouse

The following code shows how to capture the `mouseup` event of the GdViewer, [get the coordinates of the area selection](https://www.nutrient.io/api/gdpicture/GdPicture.NET.14~GdPicture14.GdViewer~GetRectCoordinatesOnDocument.html) in the GdViewer, and then set them to be the coordinates of the anchor template:

```csharp

// We assume GdPicture has been correctly installed and unlocked.
// We assume a GdViewer object called `GdViewer1` has been created and painted on the form.
GdPictureImaging oGdPictureImaging = new GdPictureImaging();
IntPtr anchorTemplate;
int anchorLeft;
int anchorTop;
int anchorWidth;
int anchorHeight;
// Loading the image from a file.
int template = oGdPictureImaging.CreateGdPictureImageFromFile("template.tif");
// Checking if the image has been loaded correctly.
if (oGdPictureImaging.GetStat()!= GdPictureStatus.OK)
{
    MessageBox.Show("The image can't be loaded. Error: " + oGdPictureImaging.GetStat().ToString());
}
else
{
    GdViewer1.DisplayFromGdPictureImage(template);
}

/// <summary>
/// On the `mouseup` event on the GdViewer, create an anchor template.
/// </summary>
/// <param name="eventSender">The object the event occurred on.
/// <param name="eventArgs">The event's data.
public void CreateOMRANCHOR(System.Object eventSender, System.EventArgs eventArgs)
{
   // Checking if a rectangle of selection was painted on the GdViewer.
   if (GdViewer1.IsRect())
   {
   // Getting the location of the selection on the document.
   GdViewer1.GetRectCoordinatesOnDocument(ref anchorLeft, ref anchorTop, ref anchorWidth, ref heightArea);

   // Setting the anchor template.
   anchorTemplate = oGdPictureImaging.CreateAnchorTemplate(template, anchorLeft, anchorTop, anchorWidth, anchorHeight);
   }
}

```

In the code above, the `anchorleft`, `anchorTop`, `anchorWidth`, and `anchorHeight` parameters hold the position of the area selected with the mouse.

## Choosing OMR rectangles

Each OMR rectangle surrounding an OMR field can be chosen using mouse on a GdViewer. To do this, save the coordinates of the selected area in the `GdViewer.MouseUp` event to the entry of the rectangle’s array.

Note that if you have, e.g. 50 OMR fields, you should create a rectangle array of length `50`. The OMR detection function takes this rectangle array as a parameter and uses it to remember the locations of the OMR fields.

The following code shows how to create a rectangle array of length `8` — assuming you have eight OMR fields — and fills their coordinates one by one using mouse upon creating a selected area on the GdViewer:

```csharp

// We assume GdPicture has been correctly installed and unlocked.
// We assume a GdViewer object called `GdViewer1` has been created and painted on the form.
GdPictureImaging oGdPictureImaging = new GdPictureImaging();
Rectangle[] omrRECT = new Rectangle[8];
int currentRect = 0;
// Loading the image from a file.
 int template = oGdPictureImaging.CreateGdPictureImageFromFile("template.tif");
 // Checking if the image has been loaded correctly.
if (oGdPictureImaging.GetStat()!= GdPictureStatus.OK)
{
   MessageBox.Show("The image can't be loaded. Error: " + oGdPictureImaging.GetStat().ToString());
}
else
{
   GdViewer1.DisplayFromGdPictureImage(template);
}

/// <summary>
/// On the `mouseup` event on the GdViewer, create a selected area of the GdViewer.
/// </summary>
/// <param name="eventSender">The object the event occurred on.
/// <param name="eventArgs">The event's data.
public void CreateOMRRect(System.Object eventSender, System.EventArgs eventArgs)
{
   // Initialize variables to hold the position of the rectangle of selection on the document.
   int leftArea = 0;
   int topArea = 0;
   int widthArea = 0;
   int heightArea = 0;

   // Checking if a rectangle of selection has been painted on the GdViewer.
   if (GdViewer1.IsRect())
   {
      // Checking if we have already set up all OMR field locations.
      if (currentRect > 7)
      {
         return;
      }
      // Getting the location of the selection on the document.
      GdViewer1.GetRectCoordinatesOnDocument(ref leftArea, ref topArea, ref widthArea, ref heightArea);
      // Setting the OMR rectangle.
      omrRECT(currentRect).X = leftArea;
      omrRECT(currentRect).Y = topArea;
      omrRECT(currentRect).Width = widthArea;
      omrRECT(currentRect).Height = heightArea;

      // Incrementing the rectangle counter.
      currentRect = currentRect + 1;
   }
}

```

The code above creates the array of rectangles, `omrRECT`, which is populated with the coordinates of the GdViewer selection rectangles one by one. This is achieved by creating a counter, `currentRect`, and using it to index the array. Each time we enter a new rectangle, we increment it by one.

Don’t forget to check if you’ve already set up all rectangles in `omrRECT` before you try to index a new entry and set it up.
---

## Related pages

- [OMR in C#](/guides/dotnet/extraction/omr/introduction.md)
- [Extracting optical marks](/guides/dotnet/extraction/omr/extract-optical-marks.md)

