'******************************************************************************
'
' File name: Mdmr.vb
' Location: See Matrox Example Launcher in the MIL Control Center
' 
'
' Synopsis:  This program uses the Dot Matrix Reader (SureDotOCR®) module to read 
'            a product expiry date and lot number printed using a CIJ printer.
'
' Copyright (C) Matrox Electronic Systems Ltd., 1992-2020.
' All Rights Reserved
'
Imports System
Imports System.Text
Imports Microsoft.VisualBasic
Imports Matrox.MatroxImagingLibrary

Module Module1

    ' MIL file specifications.
    Private Const IMAGE_FILE_TO_READ As String = MIL.M_IMAGE_PATH & "ExpiryDateAndLot.mim"
    Private Const FONT_FILE_TO_IMPORT As String = MIL.M_CONTEXT_PATH & "ExpiryDateAndLotFont5x7.mdmrf"

    ' Dot Matrix Reader settings.
    Private Const STRING_DOT_DIAMETER As Double = 6.0
    Private Const STRING_BOX_WIDTH As Double = 400
    Private Const STRING_BOX_HEIGHT As Double = 100
    Private ReadOnly EXPIRY_DATE_LENGTH As MIL_INT = 7
    Private ReadOnly LOT_NUMBER_LENGTH As MIL_INT = 7

    ' Util
    Private Const TEXT_MAX_SIZE As Integer = 128

    Sub Main()
        Dim MilApplication As MIL_ID = MIL.M_NULL ' Application identifier.
        Dim MilSystem As MIL_ID = MIL.M_NULL ' System identifier.
        Dim MilDisplay As MIL_ID = MIL.M_NULL ' Display identifier.
        Dim MilImage As MIL_ID = MIL.M_NULL ' Image buffer identifier.
        Dim MilOverlay As MIL_ID = MIL.M_NULL ' Overlay image.
        Dim MilDmrContext As MIL_ID = MIL.M_NULL ' Dot Matrix context identifier.
        Dim MilDmrResult As MIL_ID = MIL.M_NULL ' Dot Matrix result identifier.

        Dim NumberOfStrings As MIL_INT = 0 ' Total number of strings to read.
        Dim StringSize As MIL_INT = 0 ' Number of strings characters.
        Dim StringModelIndex As MIL_INT = 0 ' String model index.
        Dim Index As MIL_INT = 0 ' Result index.

        Dim StringResult As New StringBuilder(TEXT_MAX_SIZE + 1) ' String of characters read.
        Dim PrintText As String ' Util text.

        ' Print module name.
        Console.Write(Constants.vbLf & "DOT MATRIX READER (SureDotOCR) MODULE:" & Constants.vbLf)
        Console.Write("--------------------------------------" & Constants.vbLf + Constants.vbLf)

        ' Allocate defaults
        MIL.MappAllocDefault(MIL.M_DEFAULT, MilApplication, MilSystem, MilDisplay, CType(MIL.M_NULL, IntPtr), CType(MIL.M_NULL, IntPtr))

        ' Restore the font definition image
        MIL.MbufRestore(IMAGE_FILE_TO_READ, MilSystem, MilImage)

        ' Display the image and prepare for overlay annotations.
        MIL.MdispSelect(MilDisplay, MilImage)
        MIL.MdispControl(MilDisplay, MIL.M_OVERLAY, MIL.M_ENABLE)
        MIL.MdispInquire(MilDisplay, MIL.M_OVERLAY_ID, MilOverlay)

        ' Allocate a new empty Dot Matrix Reader context.
        MIL.MdmrAlloc(MilSystem, MIL.M_DOT_MATRIX, MIL.M_DEFAULT, MilDmrContext)

        ' Allocate a new empty Dot Matrix Reader result buffer.
        MIL.MdmrAllocResult(MilSystem, MIL.M_DOT_MATRIX, MIL.M_DEFAULT, MilDmrResult)

        ' Import a Dot Matrix font.
        MIL.MdmrImportFont(FONT_FILE_TO_IMPORT, MIL.M_DMR_FONT_FILE, MilDmrContext, MIL.M_DEFAULT, MIL.M_NULL, MIL.M_DEFAULT)

        ' Add a new string model definition for the product lot number.
        ' -------------------------------------------------------------
        MIL.MdmrControl(MilDmrContext, MIL.M_STRING_ADD, MIL.M_DEFAULT)

        ' Set the string model rank and size
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(0), MIL.M_DEFAULT, MIL.M_STRING_RANK, 1, MIL.M_DEFAULT, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(0), MIL.M_DEFAULT, MIL.M_STRING_SIZE_MIN_MAX, LOT_NUMBER_LENGTH, LOT_NUMBER_LENGTH, MIL.M_NULL)

        ' Add a new string model definition for the expiry date (YYYY MM DD).
        ' -------------------------------------------------------------------
        MIL.MdmrControl(MilDmrContext, MIL.M_STRING_ADD, MIL.M_DEFAULT)

        ' Set the string model rank and size
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_DEFAULT, MIL.M_STRING_RANK, 0, MIL.M_DEFAULT, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_DEFAULT, MIL.M_STRING_SIZE_MIN_MAX, EXPIRY_DATE_LENGTH, EXPIRY_DATE_LENGTH, MIL.M_NULL)

        ' Set the string model constraint for an expiry date (DDMMMYY).
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(0), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_DIGITS, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(1), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_DIGITS, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(2), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_LETTERS_UPPERCASE, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(3), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_LETTERS_UPPERCASE, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(4), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_LETTERS_UPPERCASE, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(5), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_DIGITS, MIL.M_NULL)
        MIL.MdmrControlStringModel(MilDmrContext, MIL.M_STRING_INDEX(1), MIL.M_POSITION_IN_STRING(6), MIL.M_ADD_PERMITTED_CHARS_ENTRY, MIL.M_FONT_LABEL(MIL.M_ANY), MIL.M_DIGITS, MIL.M_NULL)

        Console.Write("A Dot Matrix Reader (SureDotOCR) context was set up to read" & Constants.vbLf & "an expiry date and a lot number from a target image." & Constants.vbLf + Constants.vbLf)

        ' Set the Dot Matrix dot diameter.
        MIL.MdmrControl(MilDmrContext, MIL.M_DOT_DIAMETER, STRING_DOT_DIAMETER)

        ' Set the maximum size of the string box.
        MIL.MdmrControl(MilDmrContext, MIL.M_STRING_BOX_WIDTH, STRING_BOX_WIDTH)
        MIL.MdmrControl(MilDmrContext, MIL.M_STRING_BOX_HEIGHT, STRING_BOX_HEIGHT)

        ' Preprocess the context.
        MIL.MdmrPreprocess(MilDmrContext, MIL.M_DEFAULT)

        ' Reading the string from a target image.
        MIL.MdmrRead(MilDmrContext, MilImage, MilDmrResult, MIL.M_DEFAULT)

        ' Get number of strings read and show the result.
        MIL.MdmrGetResult(MilDmrResult, MIL.M_GENERAL, MIL.M_DEFAULT, MIL.M_STRING_NUMBER + MIL.M_TYPE_MIL_INT, NumberOfStrings)

        ' Draw the read result.
        MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_GREEN)
        MIL.MdmrDraw(MIL.M_DEFAULT, MilDmrResult, MilOverlay, MIL.M_DRAW_STRING_CHAR_BOX, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT)
        MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_CYAN)
        MIL.MdmrDraw(MIL.M_DEFAULT, MilDmrResult, MilOverlay, MIL.M_DRAW_STRING_CHAR_POSITION, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT)

        If NumberOfStrings > 0 Then
            Console.Write("Result: {0} strings have been read:" & Constants.vbLf + Constants.vbLf, NumberOfStrings)

            For Index = 0 To NumberOfStrings - 1
                ' Print the read result.
                MIL.MdmrGetResult(MilDmrResult, Index, MIL.M_GENERAL, MIL.M_STRING_MODEL_INDEX + MIL.M_TYPE_MIL_INT, StringModelIndex)
                MIL.MdmrGetResult(MilDmrResult, Index, MIL.M_GENERAL, MIL.M_STRING + MIL.M_STRING_SIZE + MIL.M_TYPE_MIL_INT, StringSize)
                MIL.MdmrGetResult(MilDmrResult, Index, MIL.M_GENERAL, MIL.M_STRING, StringResult)

                Select Case StringModelIndex
                    Case 0
                        PrintText = String.Format(" LOT# : {0} ", StringResult)
                        MIL.MgraText(MIL.M_DEFAULT, MilOverlay, 20, 20 + Index * 20, PrintText)
                        Console.Write(" LOT# : {0}" & Constants.vbLf, StringResult)

                    Case 1
                        PrintText = String.Format(" EXP. : {0} ", StringResult)
                        MIL.MgraText(MIL.M_DEFAULT, MilOverlay, 20, 20 + Index * 20, PrintText)
                        Console.Write(" EXPIRY DATE: {0}" & Constants.vbLf, StringResult)

                    Case Else
                        Console.Write("Unexpected model index" & Constants.vbLf)

                End Select
            Next Index
        Else
            Console.Write("Error: no string found." & Constants.vbLf)
        End If

        ' Pause to show results.
        Console.Write(Constants.vbLf & "Press <Enter> to end." & Constants.vbLf + Constants.vbLf)
        Console.ReadKey()

        ' Free all allocations.
        MIL.MdmrFree(MilDmrContext)
        MIL.MdmrFree(MilDmrResult)
        MIL.MbufFree(MilImage)

        ' Free defaults.
        MIL.MappFreeDefault(MilApplication, MilSystem, MilDisplay, MIL.M_NULL, MIL.M_NULL)
    End Sub

End Module