using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
using GrayScaleClass;

namespace AllDecNet
{
    public class TRowCols
    {
        protected bool FValid = false;
        public static float[ ] FRowCols = new float[ 8 ];
        public float this[ int ix ]
        {
            get
            {
                if ( ix < 0 ) return -1;
                if ( ix > 7 ) return -1;
                return FRowCols[ ix ];
            }
          set
          {
            FRowCols[ix] = value;
          }
        }

        public void Finished()
        {
          FValid = true;
        }
    }

    public class TAZ_Info
    {
      private byte[] result;
      public TRowCols RowCols = new TRowCols();

      internal void Init(TAZ_Info.TAZ_Info_Internal info)
      {
        RowCols[0] = info.rowcols0;
        RowCols[1] = info.rowcols1;
        RowCols[2] = info.rowcols2;
        RowCols[3] = info.rowcols3;
        RowCols[4] = info.rowcols4;
        RowCols[5] = info.rowcols5;
        RowCols[6] = info.rowcols6;
        RowCols[7] = info.rowcols7;
        RowCols.Finished();
        
        result = new byte[info.pchlen];
        unsafe
        {
          for (int i = 0; i < info.pchlen; i++)
            result[i] = info.pch[i];
        }
      }

      public TAZ_Info()
      {
      }

      public String GetDecodedChars(int codepage)
      {
        StringConvertor SC = new StringConvertor(codepage);
        return SC.ByteArrayToString(result);
      }

      internal unsafe struct TAZ_Info_Internal
      {
        public float rowcols0;  //!< symbol corner coordinates
        public float rowcols1;
        public float rowcols2;
        public float rowcols3;
        public float rowcols4;
        public float rowcols5;
        public float rowcols6;
        public float rowcols7;
        public Int32 pchlen;	    //!< length of decoded byte array
        public Byte* pch;         //!< pointer to 2-byte array (Unicode characters)
        public Int32 RSErr;	      //!< number of Reed Solomon errors
        public Int32 Dim;	        //!< dimension of AZ Code
        public Int32 Rune_AZS;    //!< ==0 for AZC,  ==1 for compact,  ==2 for Rune
        public Int32 Layers;
        public Int32 MSGLen;
      };
    }

    public class TDM_Info
    {
        class T_US_RowCols : TRowCols
        {
            unsafe public void SetInfo(T_US_DM_Info* FInfo)
            {
                if (FInfo == (T_US_DM_Info*)null) return;

                FRowCols[0] = FInfo->rowcols0;
                FRowCols[1] = FInfo->rowcols1;
                FRowCols[2] = FInfo->rowcols2;
                FRowCols[3] = FInfo->rowcols3;
                FRowCols[4] = FInfo->rowcols4;
                FRowCols[5] = FInfo->rowcols5;
                FRowCols[6] = FInfo->rowcols6;
                FRowCols[7] = FInfo->rowcols7;
            }
        }

        T_US_RowCols FRowCols = new T_US_RowCols();

        public TDM_Info(IntPtr DLLInfo)
        {
            SetInfo(DLLInfo);
        }

        unsafe private void SetInfo(IntPtr DLLInfo)
        {
            FInfo = (T_US_DM_Info*)DLLInfo;
            FRowCols.SetInfo(FInfo);
            //            FQuality.SetInfo(FInfo);
        }

        unsafe private T_US_DM_Info* FInfo;
        private unsafe struct T_US_DM_Info
        { //result of decoding per each Data Matrix symbol
            public Single rowcols0;    // symbol corners
            public Single rowcols1;    // symbol corners
            public Single rowcols2;    // symbol corners
            public Single rowcols3;    // symbol corners
            public Single rowcols4;    // symbol corners
            public Single rowcols5;    // symbol corners
            public Single rowcols6;    // symbol corners
            public Single rowcols7;    // symbol corners
            public Int32 pchlen;	   // lenght of decoded byte array
            public Byte* pch;		   // pointer to that array
            public Int32 RSErr;		   // number of reed solomon errors
            public Int32 VDim, HDim;   // vertical and horizontal dimensions of Data Matrix
            public Int32 saTotalSymbolsNumber 	// structured append: total number of matrices
                         , saSymbolPosition		// current matrix index
                         , saFileID1			// file identificators
                         , saFileID2;
            public Int32 mirrored;      // = true if mirrored
            public Int32 dotpeenstage;  // = true if dotpeenstage
            public Int32 matrixcolor;   // detected color of Data Matrix
            //TDM_Quality quality;
            public Single symbol_contrast;
            public Single axial_nonuniformity;
            public Single grid_nonuniformity;
            public Single fixed_pattern_damage;   // average
            public Single unused_error_correction;
            public Single vertical_print_growth;
            public Single horizontal_print_growth;

            public Single symbol_contrast_grade;
            public Single axial_nonuniformity_grade;
            public Single grid_nonuniformity_grade;
            public Single fixed_pattern_damage_grade;
            public Single unused_error_correction_grade;
            public Single modulation_grade;
            public Single decode_grade; // (min of grades)
            public Single overall_grade; // N/A because we don't support several scans
        }

        unsafe private bool IsInfo()
        {
            return (FInfo != null);
        }

        private byte[] GetDecodedBytes(StringConvertor SC)
        {
            byte[] Result;
            unsafe
            {
                if (IsInfo())
                {
                    Result = SC.PCharToArray((byte*)FInfo->pch, FInfo->pchlen);
                }
                else
                {
                    return new byte[0];
                }
            }
            return Result;
        }

        public byte[] GetDecodedBytes()
        {
            StringConvertor SC = new StringConvertor();
            return GetDecodedBytes(SC);
        }

        public String GetDecodedChars(int codepage)
        {
             StringConvertor SC = new StringConvertor(codepage);
             byte[] A = GetDecodedBytes(SC);
             return SC.ByteArrayToString(A);
        }

        public String GetDecodedChars()
        {
            StringConvertor SC = new StringConvertor();
            byte[] A = GetDecodedBytes();
            return SC.ByteArrayToString(A);
        }
 
        public TRowCols RowCols
        {
            get
            {
                return FRowCols;
            }
        }

    } // DM Info

    public class TQR_Info
    {
        class T_US_RowCols : TRowCols
        {
            unsafe public void SetInfo(T_US_QR_Info* FInfo)
            {
                FValid = false;
                if (FInfo == (T_US_QR_Info*)null) return;

                FRowCols[0] = FInfo->rowcols0;
                FRowCols[1] = FInfo->rowcols1;
                FRowCols[2] = FInfo->rowcols2;
                FRowCols[3] = FInfo->rowcols3;
                FRowCols[4] = FInfo->rowcols4;
                FRowCols[5] = FInfo->rowcols5;
                FRowCols[6] = FInfo->rowcols6;
                FRowCols[7] = FInfo->rowcols7;
                FValid = true;
            }
        }

        T_US_RowCols FRowCols = new T_US_RowCols();

        public TQR_Info(IntPtr DLLInfo)
        {
            SetInfo(DLLInfo);
        }
        
        unsafe private void SetInfo(IntPtr DLLInfo)
        {
            FInfo = (T_US_QR_Info*)DLLInfo;
            FRowCols.SetInfo(FInfo);
//            FQuality.SetInfo(FInfo);
        }

        unsafe private T_US_QR_Info* FInfo;
        private unsafe struct T_US_QR_Info
        { //result of decoding per each Data Matrix symbol
            public Single rowcols0;    // symbol corners
            public Single rowcols1;    // symbol corners
            public Single rowcols2;    // symbol corners
            public Single rowcols3;    // symbol corners
            public Single rowcols4;    // symbol corners
            public Single rowcols5;    // symbol corners
            public Single rowcols6;    // symbol corners
            public Single rowcols7;    // symbol corners
            public Int32 pchlen;	   // lenght of decoded byte array
            public Int16* pch;		   // pointer to that array
            //            public UnicodeEncoding pch;		   // pointer to that array
            public Int32 RSErr;	       //!< number of Reed Solomon errors
            public Int32 Dim;	       //!< dimension of QR Code
            public Int32 Version;      // 1 -...
            public Int32 level;        // L, M, H, Q
            public Int32 Mask;
            public Int32 Micro_QRC;    // = true if micro
            public Int32 color;        // detected color of symbol
            public Int32 mirrored;     // = true if mirrored

            public Single symbol_contrast;
            public Single axial_nonuniformity;
            public Single grid_nonuniformity;
            public Single unused_error_correction;

            public Single symbol_contrast_grade;
            public Single axial_nonuniformity_grade;
            public Single grid_nonuniformity_grade;
            public Single unused_error_correction_grade;
            public Single modulation_grade;
            public Single fixed_pattern_damage_grade;
            public Single format_grade;
            public Single version_grade;
            public Single decode_grade;
            public Single overall_grade; // (min of grades)
        }

        unsafe private bool IsInfo()
        {
            return (FInfo != null);
        }

        private byte[] GetDecodedBytes(StringConvertor SC)
        {
            byte[] Result;
            unsafe
            {
                if (IsInfo())
                {
                    Result = SC.PCharToArray((byte*)FInfo->pch, 2 * FInfo->pchlen);
                }
                else
                {
                    return new byte[0];
                }
            }
            return Result;
        }

        public byte[] GetDecodedBytes()
        {
            StringConvertor SC = new StringConvertor();
            return GetDecodedBytes(SC);
        }

        public String QR_GetDecodedChars()
        {
            byte[] A = GetDecodedBytes();
            string res = Encoding.Unicode.GetString(A);
            return res; // SC.ByteArrayToString(A);
        }

        public TRowCols RowCols
        {
            get
            {
                return FRowCols;
            }
        }

    } // QR Info

    //  ================== 1D Code =================
    struct TL_ImageInfo
    {
        int LCount;          //!< Number of well decoded Linear symbols within image
        int RejectionReason;	//!< not 0 if no one symbol was well decoded
        int BreakReason;	    //!< 0 - normal termination (whole image inspected),
        //!< 1 - termination by time-out
    };

    public class TL_Info
   {
        public TL_Info(IntPtr DLLInfo)
        {
            SetInfo(DLLInfo);
        }
        unsafe public void SetInfo(IntPtr DLLInfo)
        {
            FInfo = (T_US_L_Info*)DLLInfo;
            FRowCols.SetInfo(FInfo);
        }

        unsafe public struct LINEAR_SCAN_LINE
        {
            public Int16 scan_line_start_x;  //!< column of scan line begin
            public Int16 scan_line_start_y;  //!< row of scan line begin
            public Int16 scan_line_end_x;    //!< column of scan line end
            public Int16 scan_line_end_y;    //!< row of scan line end
            public Byte first;                    //!< flag of main scan line
            Byte quietzone;                //!< QZ OK
            Byte checksum;                 //!< checksum OK
            Byte length;           //!< number of decoded characters
            Byte* dataRes;                  //!< result of decoding the scan line
        };

        //--------------------------------------------------------------------------
        /// Descriptor of 10 scan lines in each L_Info
        //        unsafe public LINEAR_SCAN_LINE*  SCAN_LINE_ALL;

        unsafe public T_US_L_Info* FInfo;
        public unsafe struct T_US_L_Info
        { //result of decoding per each 1D symbol
            public Int16 RejectionReason;
            //            public Int16[] rowcols;    //!< Coordinates of barcode rectangle
            public Int16 rowcols0;    // symbol corners
            public Int16 rowcols1;    // symbol corners
            public Int16 rowcols2;    // symbol corners
            public Int16 rowcols3;    // symbol corners
            public Int16 rowcols4;    // symbol corners
            public Int16 rowcols5;    // symbol corners
            public Int16 rowcols6;    // symbol corners
            public Int16 rowcols7;    // symbol corners
            public Int16 type;          //!< Actual type of a barcode
            public Byte idx_scan_line; //!< Index of "main" scan line (0<=idx_scan_line<10)
            public Byte pchlen;        //!< Length of decoded byte array
            public Byte* pch;           //!<Pointer to that array

            //            SCAN_LINE_ALL  sl;   //!< Descriptors of 10 scan lines
            public LINEAR_SCAN_LINE sl1;
            public LINEAR_SCAN_LINE sl2;
            public LINEAR_SCAN_LINE sl3;
            public LINEAR_SCAN_LINE sl4;
            public LINEAR_SCAN_LINE sl5;
            public LINEAR_SCAN_LINE sl6;
            public LINEAR_SCAN_LINE sl7;
            public LINEAR_SCAN_LINE sl8;
            public LINEAR_SCAN_LINE sl9;
            public LINEAR_SCAN_LINE sl10;
            //            public LINEAR_QUALITY lq;   //!< ISO 15416 Quality Parameters
            public Single decode;
            public Single symbol_contrast;
            public Single min_reflectance;
            public Single max_reflectance;
            public Single global_threshold;
            public Single min_edge_contrast;
            public Single modulation;
            public Single defects;
            public Single decodability;
            public Single decode_grade;
            public Single symbol_contrast_grade;
            public Single min_reflectance_grade;
            public Single global_threshold_grade;
            public Single min_edge_contrast_grade;
            public Single modulation_grade;
            public Single defects_grade;
            public Single decodability_grade;
            public Single overall_grade;

            public Single decode_grade_av;
            public Single symbol_contrast_grade_av;
            public Single min_reflectance_grade_av;
            public Single global_threshold_grade_av;
            public Single min_edge_contrast_grade_av;
            public Single modulation_grade_av;
            public Single defects_grade_av;
            public Single decodability_grade_av;
            public Single overall_grade_av;
            //  TIMB_L_QUALITY* add_lq; //!< In accordance with code type: PL_IMBQuality...

            public Int32 RSErr;		   // number of reed solomon errors
            public Single unused_error_correction;
            public Single unused_error_correction_grade;
        }

        class T_US_RowCols : TRowCols
        {
            unsafe public void SetInfo(T_US_L_Info* FInfo)
            {
                FValid = false;
                if (FInfo == (T_US_L_Info*)null) return;

                FRowCols[0] = FInfo->rowcols0;
                FRowCols[1] = FInfo->rowcols1;
                FRowCols[2] = FInfo->rowcols2;
                FRowCols[3] = FInfo->rowcols3;
                FRowCols[4] = FInfo->rowcols4;
                FRowCols[5] = FInfo->rowcols5;
                FRowCols[6] = FInfo->rowcols6;
                FRowCols[7] = FInfo->rowcols7;
                FValid = true;
            }
        }
        T_US_RowCols FRowCols = new T_US_RowCols();
        unsafe private bool IsInfo()
        {
            return (FInfo != null);
        }

        public int RSErr
        {
            get
            {
                if (!IsInfo())
                    return -1;

                unsafe { return FInfo->RSErr; };
            }
        }

        private byte[] GetDecodedBytes(StringConvertor SC)
        {
            byte[] Result;
            unsafe
            {
                if (IsInfo())
                {
                    Result = SC.PCharToArray(FInfo->pch, FInfo->pchlen);
                }
                else
                {
                    return new byte[0];
                }
            }
            return Result;
        }

        public byte[] GetDecodedBytes()
        {
            StringConvertor SC = new StringConvertor();
            return GetDecodedBytes(SC);
        }
        public String GetDecodedChars(int codepage)
        {
            StringConvertor SC = new StringConvertor(codepage);
            byte[] A = GetDecodedBytes(SC);
            return SC.ByteArrayToString(A);
        }

        public String GetDecodedChars()
        {
            StringConvertor SC = new StringConvertor();
            byte[] A = GetDecodedBytes();
            return SC.ByteArrayToString(A);
        }
/*
 * 
 * 
        public String QR_GetDecodedChars()
        {
            byte[] A = GetDecodedBytes();
            string res = Encoding.Unicode.GetString(A);
            return res; // SC.ByteArrayToString(A);
        }
*/
        unsafe public String GetSymbologyID()
        {
            StringConvertor SC = new StringConvertor();
            byte[] SIDch = new byte[4];
            SIDch[0] = (byte)(FInfo->pch)[-3];
            SIDch[1] = (byte)(FInfo->pch)[-2];
            SIDch[2] = (byte)(FInfo->pch)[-1];
            SIDch[3] = (byte)0;
            return SC.ByteArrayToString(SIDch);
        }

        unsafe public String GetTypecode()
        {
            int typecode = FInfo->type;
            String[] type = {
            "CODE128",      // 1,
            "CODE39",       // 2,
            "CODABAR",      // 3,
            "INTERLEAVED",  // 4,
            "EAN13",        // 5,
            "EAN8",         // 6,
            "UPCE",         // 7,
            "POSTNET",      // 8,
            "IMB",          // 9,
            "PHARMACODE",   // 10,

            "RSS",          // 11,
            "RSS_L",        // 12,
            "RSS_E",        // 13,

            "EAN13EX",      // 14,
            "UPCEEX",       // 15,

            "CODE93",       // 16

            "TADF",         // 17,
            "NZP",          // 18,
            "SuissPost",    // 19,
            };
            if (typecode < 1 || typecode > 19)
                return "?";
            else
                return type[typecode - 1];
        }

        public TRowCols RowCols
        {
            get
            {
                return FRowCols;
            }
        }

    }
    // TL_Info

// ================================== pdf417 ===============================

    unsafe struct TPDF_ImageInfo
    {
        int Count;              //!< Number of well decoded PDF417 symbols within image
        int RejectionReason;	//!< not 0 if no one symbol was well decoded
        Byte* RRString;
        int BreakReason;	    //!< 0 - normal termination (whole image inspected),
                                //!< 1 - termination by time-out
        Byte* BRString;
    };

    public class TPDF_Info
    {
        class T_US_RowCols : TRowCols
        {
            unsafe public void SetInfo(T_US_PDF_Info* FInfo)
            {
                FValid = false;
                if (FInfo == (T_US_PDF_Info*)null) return;

                FRowCols[0] = FInfo->rowcols0;
                FRowCols[1] = FInfo->rowcols1;
                FRowCols[2] = FInfo->rowcols2;
                FRowCols[3] = FInfo->rowcols3;
                FRowCols[4] = FInfo->rowcols4;
                FRowCols[5] = FInfo->rowcols5;
                FRowCols[6] = FInfo->rowcols6;
                FRowCols[7] = FInfo->rowcols7;
                FValid = true;
            }
        }

        T_US_RowCols FRowCols = new T_US_RowCols();

        public TPDF_Info(IntPtr DLLInfo)
        {
            SetInfo(DLLInfo);
        }

        unsafe private void SetInfo(IntPtr DLLInfo)
        {
            FInfo = (T_US_PDF_Info*)DLLInfo;
            FRowCols.SetInfo(FInfo);
            //            FQuality.SetInfo(FInfo);
        }
/*
struct TPDF417_Info{ //result of decoding per each PDF417 symbol
  int RejectionReason;     // Result
  int rowcols[8];    // symbol corners
  int rcFlag;        // true if a qudrangle symbol was found
  int RSErrorCount;  // number of Reed Solomon errors
  int ColCount;      // horizontal dimension (from 1 to 30)
  int RowCount;      // vertical dimension   (from 4 to 90)
  char* RejectionString; // pointer to error string
  int ECLevel;       // Error Correction Level (from 0 to 8)
  int pchlen;        // length of decoded byte array
  unsigned char* pch;// decoded byte array
  char* c_str;       // decoded char array (points to the same allocation in memory)
  TPDF417_Quality Quality;
};
*/
        unsafe private T_US_PDF_Info* FInfo;
        private unsafe struct T_US_PDF_Info
        { //result of decoding per each Data Matrix symbol
            public Int32  RejectionReason;     
            public Int32 rowcols0;    // symbol corners
            public Int32 rowcols1;    // symbol corners
            public Int32 rowcols2;    // symbol corners
            public Int32 rowcols3;    // symbol corners
            public Int32 rowcols4;    // symbol corners
            public Int32 rowcols5;    // symbol corners
            public Int32 rowcols6;    // symbol corners
            public Int32 rowcols7;    // symbol corners
            public Int32 rcFlag;       // true if a qudrangle symbol was found
            public Int32 RSErr;		   // number of reed solomon errors
            public Int32 ColCount;     // in Symbol
            public Int32 RowCount;     // in Symbol
            public Byte* RejString;	   // pointer to that array
            public Int32 ECLevel;      // Error Correction Level (from 0 to 8)
            public Int32 pchlen;	   // lenght of decoded byte array
            public Byte* pch;		   // pointer to that array
            public char* c_str;        // decoded char array (points to the same allocation in memory)
            
            public Single symbol_contrast;            // symbol contrast(SC)  = Rmax-Rmin
            public Single min_reflectance;            // Rmin
            public Single max_reflectance;            // Rmax
            public Single global_threshold;           // global_threshold(GT) = (Rmax+Rmin)/2
            public Single min_edge_contrast;          // ECmin
            public Single modulation;                 // modulation (MOD)     = ECmin/SC
            public Single defects;                    //
            public Single decodability;               // V
            public Single width_height_proportion;
            public Single unused_error_correction;    // UEC

            // grades
            // 0..4,  0 = Worst , 4 = Best, -1 = have not been calculated
            public Single decode_grade;
            public Single symbol_contrast_grade;
            public Single min_reflectance_grade;
            public Single min_edge_contrast_grade;
            public Single modulation_grade;
            public Single defects_grade;
            public Single decodability_grade;
            public Single unused_error_correction_grade;

            public Single overall_grade;

        }

        unsafe private bool IsInfo()
        {
            return (FInfo != null);
        }

        private byte[] GetDecodedBytes(StringConvertor SC)
        {
            byte[] Result;
            unsafe
            {
                if (IsInfo())
                {
                    Result = SC.PCharToArray((byte*)FInfo->pch, FInfo->pchlen);
                }
                else
                {
                    return new byte[0];
                }
            }
            return Result;
        }

        public byte[] GetDecodedBytes()
        {
            StringConvertor SC = new StringConvertor();
            return GetDecodedBytes(SC);
        }

        public String GetDecodedChars(int codepage)
        {
            StringConvertor SC = new StringConvertor(codepage);
            byte[] A = GetDecodedBytes(SC);
            return SC.ByteArrayToString(A);
        }

        public String GetDecodedChars()
        {
            StringConvertor SC = new StringConvertor();
            byte[] A = GetDecodedBytes();
            return SC.ByteArrayToString(A);
        }

        public TRowCols RowCols
        {
            get
            {
                return FRowCols;
            }
        }

    } // PDF Info

    public class Total_Decoder
    {

      [DllImport("All.dll", EntryPoint = "Connect_Total_Decoder", CallingConvention = CallingConvention.StdCall)]
      internal static extern int Connect_Total_Decoder();

      public int FRejectionReason = 1; //RR_UNKNOWN (if no one shape has been recognized)
        public int FCount = 0;        // number of well decoded symbols within image

// PDF ==================================================================================
        public struct TPDF_OptMode
        {
            public Int32 maxcount;    //!<\brief From 1 to 100. Equals to 1 by Default.
            public Int32 speedmode;   // 1 - fast, 0 - robust, 2 - smart
            public Int32 calcQP;      // 0 - don't calculate QP, 1 - do calculate
            public Int32 directmode;  // 0: left->right,  2: all directions
            public Int32 BWfilter;    // 0: none, +1 => BW+1,  -1 => BW-1 (bar width - 1)
            public Int32 timeout;     // 0 - infinite time 
            public Int32 scanstep;    // the recommended values are between 3 and 6
        }

        [DllImport("All.dll", EntryPoint = "Connect_PDF417_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Connect_PDF417_Decoder([In] Int32 MaxRowCount, [In] Int32 MaxColCount);

        [DllImport("All.dll", EntryPoint = "Disconnect_PDF417_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Disonnect_PDF417_Decoder([In] IntPtr Decoder);

        [DllImport("All.dll", EntryPoint = "Create_PDF417_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Create_PDF417_Options(
              [In] IntPtr Decoder,
              [In] TPDF_OptMode opt);

        [DllImport("All.dll", EntryPoint = "Delete_PDF417_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Delete_PDF417_Options([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "DecodePDF417_Bits", CallingConvention = CallingConvention.StdCall)]
        internal static extern int Decode_PDF_Bits([In] IntPtr DecoderO, [In] Int32 RowCount, [In] Int32 ColCount, [In] IntPtr[] PPBits);

        [DllImport("All.dll", EntryPoint = "GetPDF417_ImageInfo", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetPDF_ImageInfo([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetPDF417_Info", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetPDF_Info([In] IntPtr DecoderO, [In] Int32 SymbolNumber);


        private IntPtr FPDF_DecoderW = IntPtr.Zero;
        public IntPtr PDF_DecoderO = IntPtr.Zero;

        private unsafe struct T_US_PDF_ImageInfo
        { // averall image properties
            public Int32 Count;        // number of well decoded symbols within image
            public Int32 RejectionReason;// >0 if no one symbol has been successfully decoded
            public Byte* RRString;
            public Int32 BreakReason;// >0 if no one symbol has been successfully decoded
            public Byte* BRString;
        }

        public IntPtr CreatePDF_Opt()
        {
            unsafe
            {
                TPDF_OptMode newopt;
                IntPtr PD = FPDF_DecoderW;

                newopt = new TPDF_OptMode();
                newopt.maxcount   = 1;
                newopt.speedmode  = 0;  // 1 - fast, 0 - robust, 2 - smart
                newopt.calcQP     = 0;  // 0 - don't calculate QP, 1 - do calculate
                newopt.directmode = 2;  // 0: left->right,  2: all directions
                newopt.BWfilter   = 0;  // 0: none, +1 => BW+1,  -1 => BW-1 (bar width - 1)
                newopt.timeout    = 0;  // 0 - infinite time 
                newopt.scanstep   = 4;  // the recommended values are between 3 and 6
                
                PDF_DecoderO = Create_PDF417_Options(PD, newopt);
            }
            return PDF_DecoderO;
        }

        public void DeletePDF_Opt(IntPtr DecO)
        {
            unsafe
            {
                fixed (void* PO = &PDF_DecoderO)
                {
                    IntPtr P = new IntPtr(PO);
                    Delete_PDF417_Options(P);
                    PDF_DecoderO = IntPtr.Zero;
                }
            }
        }

        private int DecodePDF_BitsO(Int32 RowCount, Int32 ColCount, IntPtr[] PPBits)
        {
            int Result = 0;
            Result = Decode_PDF_Bits(PDF_DecoderO, RowCount, ColCount, PPBits);
            return Result;
        }

        public int DecPDF_Image(IntPtr DecO, Bitmap BMP)
        {
            GrayScale G = new GrayScale(BMP);
            PDF_DecoderO = DecO;
            G.OnDecBits += this.DecodePDF_BitsO;

            G.DecodeBits();

            IntPtr II = GetPDF_ImageInfo(PDF_DecoderO);
            FCount = 0;
            unsafe
            {
                T_US_PDF_ImageInfo* UII = (T_US_PDF_ImageInfo*)II.ToPointer();
                {
                    FRejectionReason = UII->RejectionReason;
                    if (FRejectionReason == 0) // successful
                        FCount = UII->Count;
                }
            }
            return FCount;
        }

        public TPDF_Info Get_PDF_Info(int Index)
        {
            TPDF_Info Result = null;
            IntPtr II = IntPtr.Zero;
            if (Index < 0) return null;
            if (Index >= FCount) return null;

            II = GetPDF_Info(PDF_DecoderO, Index);
            Result = new TPDF_Info(II);

            return Result;
        }


// 1D ===================================================================================
        public enum TYPE_CODE
        {
            TC_ANY = -1,
            TC_TCODE128 = 1,
            TC_TCODE39 = 2,
            TC_TCODABAR = 3,
            TC_TINTERLEAVED = 4,
            TC_TEAN13 = 5,
            TC_TEAN8 = 6,
            TC_TUPCE = 7,
            TC_TPOSTNET = 8,
            TC_TIMB = 9,
            TC_TPHARMACODE = 10,

            TC_TRSS = 11,
            TC_TRSS_L = 12,
            TC_TRSS_E = 13,

            TC_TEAN13EX = 14,
            TC_TUPCEEX = 15,

            TC_TADF = 17,
            TC_TNZP = 18,
            TC_TSP = 19,

            TCM_TCODE128 = 0x00200,
            TCM_TCODE39 = 0x00400,
            TCM_TCODABAR = 0x00800,
            TCM_TINTERLEAVED = 0x01000,
            TCM_TEAN13 = 0x02000,
            TCM_TEAN8 = 0x04000,
            TCM_TUPCE = 0x08000,
            TCM_TEAN13EX = 0x400000, // 0x100<<14
            TCM_TUPCEEX = 0x800000,

            TCM_TRSS = 0x80000,
            TCM_TRSS_L = 0x100000,
            TCM_TRSS_E = 0x200000,

            TCM_TRSS_ALL = 0x380000
        };

        public enum L_REJECTION_REASON
        {
            L_SUCCESSFUL = 0,
            L_NO_LINEAR_FOUND = 1,
            L_POOR_IMAGE_QUALITY = 2,
            L_RR_UNKNOWN = 3,
            //    L_LICENSE_EXPIRED    = 4,
            //
            L_RS_ERROR = 5,
            L_CHECKSUM_FAILED = 6,
            L_NOT_CONFIRMED = 7,
            L_NOT_QUIET_ZONE = 8
                //UseRSS
            ,L_2D_FAILED = 9 //!< obligatory 2D-symbol is not found
            ,L_NOT_SUPPORTED = 10 // symbology is not supported by this release

        };

        enum L_SCAN_DIR
        {
            L_SCAN_VERTICAL = 0,
            L_SCAN_HORIZONTAL = 1,
            L_SCAN_ALL = 2
        };

        //--------------------------------------------------------------------------
        /// The structure accumulates decoder options.
        public struct TL_OptMode
        {
            public Int32 maxLcount;    //!<\brief From 1 to 100. Equals to 1 by Default.
            //!<
            //!< Maximum number of barcodes.
            //!< Should be equal to 1 if code type is Postal
            public Int32 typecode;     /*!<\brief Equals to -1 by Default.
                         Value TC_ANY (=-1) means search within all linear barcode types
                         except of Pharma, PostNet and USPS IMB
                    */
            public Int32 timeout;     //!< TimeOut in mls. Timeout = 0 - the infinite timeout.
            public Int32 paramq;      //!< 1 - on, 0 - off
            public Int32 checksum_I25; //!< 1 - on, 0 - off
            public Int32 checksum_C39; //!< 1 - on, 0 - off
            public Int32 quietzone;    //!< 0<=quietzone<=15, 0 - default
            public Int32 smartmode;    //!< \brief Not assigned  (=0) by Default
            /*!<
             Is equal to number of couples bar+space at both sides of a barcode
             that we can treat as noise.
             Negative value means the unlimited quantity of "excessive" bars and spaces.
             Option is valid for all code types except Pharma, and Postal Codes
            */
            public Int32 EC_Factor;  //!< [0..4] - Maximum errors in USPS IMB (1..2 are preferable)
            public Int32 pharmacodedir;
            public Int32 scandir;    //!< Option is valid for all code types except of Postal codes
            public Int32 scanstep;   //!< \brief By Default is equal to 8
            //!<
            //!< The value should conform to 1<= scanstep<=20.
            //!< Option is valid for all code types except of Postal codes

            public Int32 checksum_CB; //!< 1 - on, 0 - off
            public Int32 FullASCII_C39;

            public Int32 colbeg;  //!<Left column of ROI. -1 for leftmost
            public Int32 colend;  //!<Right column of ROI. -1 for rightmost
            public Int32 rowbeg;  //!< Top row of  ROI. -1 for upper row
            public Int32 rowend;  //!< Bottom row of ROI. -1 for lower row

            public Int32 TADF_num;
            public Int32 color;

        };

        //--------------------------------------------------------------------------
        /// Linear Image properties.

// 1D Code------------
//        [DllImport("All64.dll", EntryPoint = "Connect_L_Decoder", CallingConvention = CallingConvention.StdCall)]
        [DllImport("All.dll", EntryPoint = "Connect_L_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Connect_L_Decoder([In] Int32 MaxRowCount, [In] Int32 MaxColCount);

        [DllImport("All.dll", EntryPoint = "Disconnect_L_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Disonnect_L_Decoder([In] IntPtr Decoder);

        [DllImport("All.dll", EntryPoint = "Create_L_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Create_L_Options(
              [In] IntPtr Decoder,
              [In] TL_OptMode opt);

        [DllImport("All.dll", EntryPoint = "Delete_L_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Delete_L_Options([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetL_ImageInfo", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetL_ImageInfo([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetL_Info", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetL_Info([In] IntPtr DecoderO, [In] Int32 SymbolNumber);

        [DllImport("All.dll", EntryPoint = "Decode_L_Bits", CallingConvention = CallingConvention.StdCall)]
        internal static extern int Decode_L_Bits([In] IntPtr DecoderO, [In] Int32 RowCount, [In] Int32 ColCount, [In] IntPtr[] PPBits);


//        public int FRejectionReason = 1; //RR_UNKNOWN (if no one shape has been recognized)
//        public int FCount = 0;        // number of well decoded symbols within image

        private IntPtr FL_DecoderW = IntPtr.Zero;
        public IntPtr L_DecoderO = IntPtr.Zero;

        private unsafe struct T_US_L_ImageInfo
        { // averall image properties
            public Int32 Count;        // number of well decoded symbols within image
            public Int32 RejectionReason;// >0 if no one symbol has been successfully decoded
            public Int32 BreakReason;// >0 if no one symbol has been successfully decoded
        }

        public IntPtr CreateL_Opt(int codetype, int color)
        {
            unsafe
            {
                TL_OptMode newopt;
                IntPtr PD = FL_DecoderW;

                newopt = new TL_OptMode();
                newopt.maxLcount = 1;// FL_OptMode.maxLCount;
                newopt.typecode = codetype;// FL_OptMode.codeType;
                newopt.paramq = 0;// FL_OptMode.paramq;
                newopt.color = color;// FL_OptMode.Color;
                newopt.colbeg = newopt.colend = newopt.rowbeg = newopt.rowend = -1;
                newopt.scanstep = 8;
                newopt.scandir = (Int32)(L_SCAN_DIR.L_SCAN_ALL);
                L_DecoderO = Create_L_Options(PD, newopt);
            }
            return L_DecoderO;
        }

        public void DeleteL_Opt(IntPtr DecO)
        {
            unsafe
            {
                fixed (void* PO = &L_DecoderO)
                {
                    IntPtr P = new IntPtr(PO);
                    Delete_L_Options(P);
                    L_DecoderO = IntPtr.Zero;
                }
            }
        }
        
        private int DecodeL_BitsO(Int32 RowCount, Int32 ColCount, IntPtr[] PPBits)
        {
            int Result = 0;
            Result = Decode_L_Bits(L_DecoderO, RowCount, ColCount, PPBits);
            return Result;
        }

        public Total_Decoder(int maxRowCount, int maxColCount)
        {
            Connect_Total_Decoder();
            FL_DecoderW   = Connect_L_Decoder(maxRowCount, maxColCount);
            FQR_DecoderW  = Connect_QR_Decoder(maxRowCount, maxColCount);
            FDM_DecoderW  = Connect_DM_Decoder(maxRowCount, maxColCount);
            FPDF_DecoderW = Connect_PDF417_Decoder(maxRowCount, maxColCount);
            AZ_Decoder = Connect_AZ_Decoder(maxRowCount, maxColCount);
        }

        public int DecL_Image(IntPtr DecO,  Bitmap BMP)
        {
            GrayScale G = new GrayScale(BMP);
            L_DecoderO = DecO;
            G.OnDecBits += this.DecodeL_BitsO;

            G.DecodeBits();

            IntPtr II = GetL_ImageInfo(L_DecoderO);
            FCount = 0;
            unsafe
            {
                T_US_L_ImageInfo* UII = (T_US_L_ImageInfo*)II.ToPointer();
                {
                    FRejectionReason = UII->RejectionReason;
                    if (FRejectionReason==0) // successful
                        FCount = UII->Count;
                }
            }
            return FCount;
        }

/*
        public int Rejection_Reason
        {
            get { return FRejectionReason; }
        }
        public int LCount
        {
            get { return FCount; }
        }
*/
        public TL_Info Get_L_Info(int Index)
        {
            TL_Info Result = null;
            IntPtr II = IntPtr.Zero;
            if (Index < 0) return null;
            if (Index >= FCount) return null;

            II = GetL_Info(L_DecoderO, Index);
            Result = new TL_Info(II);

            return Result;
        }

        //  ================== QR Code =================
        [DllImport("All.dll", EntryPoint = "Connect_QR_Decoder", CallingConvention = CallingConvention.StdCall)]
//        [DllImport("All64.dll", EntryPoint = "Connect_QR_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Connect_QR_Decoder([In] Int32 MaxRowCount, [In] Int32 MaxColCount);

        [DllImport("All.dll", EntryPoint = "Disconnect_QR_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Disonnect_QR_Decoder([In] IntPtr Decoder);

        [DllImport("All.dll", EntryPoint = "Create_QR_OptionsP", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Create_QR_OptionsP(
              [In] IntPtr Decoder
            , [In] Int32 maxQRCount   // from 1 to 10
            , [In] Int32 cellColor    // CL_BLACKONWHITE, CL_WHITEONBLACK, CL_ANY
            , [In] Int32 mirrorMode   // MM_NORMAL, MM_MIRROR, MM_ANY
            , [In] Int32 speedMode    // always = 0
            , [In] Int32 qualityMask  // QR_QM_NO, QR_QM_ALL
            , [In] Int32 labelMode    // = 0
            , [In] Int32 timeOut
            , [In] Int32 filterMode   // non || auto
            , [In] Int32 Symbiligy    // standard, micro, any
            , [In] Int32 qzMode       // normal, small
            );

        [DllImport("All.dll", EntryPoint = "Delete_QR_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Delete_QR_Options([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetQR_ImageInfo", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetQR_ImageInfo([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetQR_Info", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetQR_Info([In] IntPtr DecoderO, [In] Int32 SymbolNumber);

        [DllImport("All.dll", EntryPoint = "DecodeQR_Bits", CallingConvention = CallingConvention.StdCall)]
        internal static extern int Decode_QR_Bits([In] IntPtr DecoderO, [In] Int32 RowCount, [In] Int32 ColCount, [In] IntPtr[] PPBits);
    
        public enum QR_REJECTION_REASON
        {
        QR_SUCCESSFUL = 0,
        QR_NO_IMAGE_FOUND = 2,
        QR_POOR_IMAGE_QUALITY = 3,
        QR_ERROR_OF_RS_CODE = 4,
        QR_ERR_DECODE = 5,
        QR_ERR_MODE = 6,
        QR_LICENSE_EXPIRED = 7,
        QR_MODE_STRUCTURED_APPEND = 10,
        QR_MODE_ECI_BASIC = 11,
        QR_MODE_ECI_BEGIN = 12,
        QR_MODE_ECI_END = 13
        }
/*
    public enum QR_Break_Reason
    {
        ALL_INSPECTED = 0,
        TIMEOUT = 1,
        TERMINATED = 2
    }
*/
        public enum QRCELL_COLOR
        {
        QRCL_BLACKONWHITE = 1
       ,QRCL_WHITEONBLACK = 2
       ,QRCL_ANY = 3
        }

        public enum QR_MIRROR_MODE
        {
        QRMM_NORMAL = 1,
        QRMM_MIRROR = 2,
        QRMM_ANY = 3
        }

        public enum QR_DECODER_SPEED
        {
        QRSP_ROBUST = 0
        }

        public enum QR_LABEL_MODE
        {
        QRLM_STANDARD = 0 // ISO 18004
        }

        public enum QR_QUALITY_MASK
        {
        QR_QM_NO = 0x0000,
        QR_QM_ALL = 0x7FFF
        }

        public enum QR_FILTER_MODE
        {
        QRFM_NON = 0, //!< no filter
        QRFM_AUTO = 1  //!< Auto selection of sharpening parameters
        }

        public enum QRQZ_MODE
        {
        QRQZ_STANDARD = 0 //!< allows QZ>= 4 moduls
       ,QRQZ_SMALL = 1 //!< allows QZ>= 1 module
        }

        public enum QRSYMBOL_MODE
        {
        QRC_NORMAL = 0     //!<- Ordinary QR Code (with 3 finder patterns)
       ,QRC_MICRO = 1     //!<- Micro QR Code (1 finder pattern)
       ,QRC_ANY = 2     //!<- Symbols of both type will be decoded simultaneously 
        }

        private IntPtr FQR_DecoderW = IntPtr.Zero;
        public IntPtr QR_DecoderO = IntPtr.Zero;

        private unsafe struct T_US_QR_ImageInfo
        { // averall image properties
            public Int32 Count;        // number of well decoded symbols within image
            public Int32 RejectionReason;// >0 if no one symbol has been successfully decoded
            public Int32 BreakReason;// >0 if no one symbol has been successfully decoded
            private int reserve1, reserve2, reserve3;
        }

        public IntPtr CreateQR_Opt()
        {
            unsafe
            {
                IntPtr PD = FQR_DecoderW;

                QR_DecoderO = Create_QR_OptionsP(PD,
                                                1, // maxcount
                                                3, // color = any
                                                3, // mirror = any
                                                0, // speedMode always = 0 
                                                0, // qualityMask = QR_QM_NO
                                                0, // labelMode = 0
                                                0, // timeOut
                                                0, // filterMode = non
                                                2, // Symbiligy  = any ( st + micro)
                                                1  // qzMode = small
                                                );
            }
            return QR_DecoderO;
        }

        private int DecodeQR_BitsO(Int32 RowCount, Int32 ColCount, IntPtr[] PPBits)
        {
            int Result = 0;
            Result = Decode_QR_Bits(QR_DecoderO, RowCount, ColCount, PPBits);
            return Result;
        }
        
        public int DecQR_Image(IntPtr DecO, Bitmap BMP)
        {
            GrayScale G = new GrayScale(BMP);
            QR_DecoderO = DecO;
            G.OnDecBits += this.DecodeQR_BitsO;

            G.DecodeBits();

            IntPtr II = GetQR_ImageInfo(QR_DecoderO);
            FCount = 0;
            unsafe
            {
                T_US_QR_ImageInfo* UII = (T_US_QR_ImageInfo*)II.ToPointer();
                {
                    FRejectionReason = UII->RejectionReason;
                    if (FRejectionReason == 0) // successful
                        FCount = UII->Count;
                }
            }
            return FCount;
        }

        public TQR_Info Get_QR_Info(int Index)
        {
            TQR_Info Result = null;
            IntPtr II = IntPtr.Zero;
            if (Index < 0) return null;
            if (Index >= FCount) return null;

            II = GetQR_Info(QR_DecoderO, Index);
            Result = new TQR_Info(II);

            return Result;
        }

        //--------------- Aztec code  ---------------
        public struct TAZ_OptMode
        {
           public Int32 maxAZCount;   //!< 1..10
           public Int32 speedMode;    //!< Always SP_ROBUST
           public Int32 qualityMask;  //!< 0 – no QP, 1 – estimate QP, (0 by default)
           public Int32 labelMode;    //!< Always LM_NORMAL
           public Int32 cellColor;
           public Int32 timeOut;      //!< timeOut in mls.
           public Int32 filterMode;   //!< AZFM_NON | AZFM_AUTO
           public Int32 symbology;    //!< AZ_S_NORMAL | AZ_S_RUNES
           public Int32 qzMode;       //!< AZ_QZ_STANDARD | AZ_QZ_SMALL
        }

        public enum AZ_SYMBOL_MODE
        {
          AZ_S_NORMAL = 0,     //!<- Ordinary Aztec Code
          AZ_S_RUNES = 1     //!<- Runes Aztec Code
        };

        public enum AZ_QZ_MODE
        {
          AZ_QZ_STANDARD = 0, //!< allows QZ>= 3 module sizes, decoder in average more fast and robust
          AZ_QZ_SMALL = 1 //!< allows QZ>= 1 module size, affects speed and robustness
        };

        private unsafe struct TAZ_ImageInfo
        {
          public Int32 AZCount;        //!< number of well decoded symbols within image
          public Int32 RejectionReason;//!< not AZ_SUCCESSFUL if no one AZ Code was decoded
          public Int32 BreakReason;    //!< 0 - normal termination, 1 - termination by time-out
        };

        
        
        [DllImport("All.dll", EntryPoint = "Connect_AZ_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Connect_AZ_Decoder([In] Int32 MaxRowCount, [In] Int32 MaxColCount);

        [DllImport("All.dll", EntryPoint = "Disconnect_AZ_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Disconnect_AZ_Decoder([In] IntPtr Decoder);

        [DllImport("All.dll", EntryPoint = "Create_AZ_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Create_AZ_Options([In] IntPtr Decoder, [In] TAZ_OptMode opt);

        [DllImport("All.dll", EntryPoint = "Delete_AZ_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Delete_AZ_Options([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "Decode_AZ_Bits", CallingConvention = CallingConvention.StdCall)]
        internal static extern int Decode_AZ_Bits([In] IntPtr DecoderO, [In] Int32 RowCount, [In] Int32 ColCount, [In] IntPtr[] PPBits);

        [DllImport("All.dll", EntryPoint = "Get_AZ_ImageInfo", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Get_AZ_ImageInfo([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "Get_AZ_Info", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Get_AZ_Info([In] IntPtr DecoderO, [In] Int32 SymbolNumber);

        private IntPtr AZ_Decoder = IntPtr.Zero;
        public IntPtr AZ_DecoderO = IntPtr.Zero;

        public IntPtr CreateAZ_Opt()
        {
          unsafe
          {
            TAZ_OptMode opt = new TAZ_OptMode();
            opt.maxAZCount = 1;
            opt.timeOut    = 0; // 0 ms => don't check time-out
            opt.speedMode  = 0;
            opt.qualityMask= 0;
            opt.symbology = (Int32)AZ_SYMBOL_MODE.AZ_S_NORMAL;
            opt.filterMode = 0;
            opt.labelMode  = 0;
            opt.qzMode = (Int32)AZ_QZ_MODE.AZ_QZ_STANDARD;
            AZ_DecoderO = Create_AZ_Options(AZ_Decoder, opt);
          }
          return AZ_DecoderO;
        }

        private int DecodeAZ_BitsO(Int32 RowCount, Int32 ColCount, IntPtr[] PPBits)
        {
          int Result = 0;
          Result = Decode_AZ_Bits(AZ_DecoderO, RowCount, ColCount, PPBits);
          return Result;
        }

        public int DecAZ_Image(Bitmap BMP)
        {
          GrayScale G = new GrayScale(BMP);
          G.OnDecBits += this.DecodeAZ_BitsO;

          G.DecodeBits();

          IntPtr II = Get_AZ_ImageInfo(AZ_DecoderO);
          FCount = 0;
          unsafe
          {
            TAZ_ImageInfo* UII = (TAZ_ImageInfo*)II.ToPointer();
            {
              FRejectionReason = UII->RejectionReason;
              if (FRejectionReason == 0) // successful
                FCount = UII->AZCount;
            }
          }
          return FCount;
        }

        public TAZ_Info Get_AZ_Info(int Index)
        {
          TAZ_Info Result = new TAZ_Info();
          IntPtr II = IntPtr.Zero;
          if (Index < 0) return null;
          if (Index >= FCount) return null;

          II = Get_AZ_Info(AZ_DecoderO, Index);
          unsafe
          {
            TAZ_Info.TAZ_Info_Internal* info = (TAZ_Info.TAZ_Info_Internal*)II.ToPointer();
            {
              Result.Init(*info);
            }
          }
          return Result;
        }
        
        // -------------- Data Matrix ---------------
        [DllImport("All.dll", EntryPoint = "Connect_DM_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Connect_DM_Decoder([In] Int32 MaxRowCount, [In] Int32 MaxColCount);

        [DllImport("All.dll", EntryPoint = "Disconnect_DM_Decoder", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Disonnect_DM_Decoder([In] IntPtr Decoder);

        [DllImport("All.dll", EntryPoint = "Create_DM_OptionsP", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr Create_DM_OptionsP(
              [In] IntPtr Decoder
            , [In] Int32 maxDMCount   // from 1 to 400
            , [In] Int32 cellColor    // CL_BLACKONWHITE, CL_WHITEONBLACK, CL_ANY
            , [In] Int32 mirrorMode   // MM_NORMAL, MM_MIRROR, MM_ANY
            , [In] Int32 speedMode    // Express,...Regular, Ultimate
            , [In] Int32 qualityMask  // QM_NO = 0x0000, QM_ALL = 0xFFFF
            , [In] Int32 labelMode    // Standard, ... st+dot
            , [In] Int32 timeOut
            , [In] Int32 filterMode   // non, ..., auto, BWR
            , [In] Int32 qzMode       // normal, small
            );

        [DllImport("All.dll", EntryPoint = "Delete_DM_Options", CallingConvention = CallingConvention.StdCall)]
        internal static extern void Delete_DM_Options([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetDM_ImageInfo", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetDM_ImageInfo([In] IntPtr DecoderO);

        [DllImport("All.dll", EntryPoint = "GetDM_Info", CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetDM_Info([In] IntPtr DecoderO, [In] Int32 SymbolNumber);

        [DllImport("All.dll", EntryPoint = "DecodeDM_Bits", CallingConvention = CallingConvention.StdCall)]
        internal static extern int Decode_DM_Bits([In] IntPtr DecoderO, [In] Int32 RowCount, [In] Int32 ColCount, [In] IntPtr[] PPBits);

        public enum DM_Rejection_Reasons
        {
            DM_RR_OK = 0,   // Decoding is OK
            DM_RR_NON = 1,   // No rectangle has been found (default error value)
            DM_RR_NODATAMATRIX = 2,   // No Data Matrix has been found
            DM_RR_BYCRIT = 3,   // Poor image quality
            DM_RR_REEDSOLOMON = 5,   // Too many errors in Reed-Solomon code
            DM_RR_NOMEMORY = 99,  // Memory limit is over
            DM_RR_UNKNOWN = 100, // The exception occured
            DM_RR_DISCONNECTED = 200
        }
        public enum DM_Break_Reason
        {
            ALL_INSPECTED = 0,
            TIMEOUT = 1,
            TERMINATED = 2
        }
        public enum DM_CELL_COLOR
        {
            CL_BLACKONWHITE = 1,
            CL_WHITEONBLACK = 2,
            CL_ANY = 3
        }
        public enum DM_MIRROR_MODE
        {
            MM_NORMAL = 1,
            MM_MIRROR = 2,
            MM_ANY = 3
        }
        public enum DM_DECODER_SPEED
        {
            SP_ROBUST = 0,
            SP_FAST = 1,
            SP_GRID_ADJUSTMENT = 2,
            SP_EQUALIZATION = 3, //!< re-equalizing the regions of probable Data Matrix
            SP_EQUAL_GRADJ = 4,
            SP_ACCURATE = 5,
            SP_ACCURATEPLUS = 6
      }
        public enum DM_SPEED
        {
            DMSP_ULTIMATEPLUS = DM_DECODER_SPEED.SP_ACCURATEPLUS,
            DMSP_ULTIMATE = DM_DECODER_SPEED.SP_ACCURATE,    //!< most careful and time-expensive
            DMSP_REGULAR = DM_DECODER_SPEED.SP_EQUAL_GRADJ, //!< recommended ratio "speed/quality"
            DMSP_EXPRESS = DM_DECODER_SPEED.SP_ROBUST       //!< basic algorithm (more fast)
        }
        public enum DM_LABEL_MODE
        {
            LM_STANDARD = 0, // ISO 16022
            LM_DOTPEEN = 1,
            LM_FAX = 2,
            LM_ST_DOT = 3      //!< Combines Standard & Dotpeen
        }

        public enum DM_QUALITY_MASK
        {
            DM_QM_NO = 0x0000,
            //DM_QM_AXNU = 0x0001,
            //DM_QM_PRGR = 0x0002,
            //DM_QM_SYMCTR = 0x0004,
            //DM_QM_CELLINFO = 0x0008,
            DM_QM_ALL = 0x7FFF
        }
        public enum DM_FILTER_MODE
        {
            FM_NON = 0, //!< no filter
            FM_SHARP1 = 1, //!< First  Filter Mode (recursive sharpening)
            FM_SHARP2 = 2, //!< Second Filter Mode (recursive sharpening)
            FM_SHARPMASK = 3, //!< Sharpening Mask Filter
            FM_AUTO = 4  //!< Auto selection of sharpening parameters
            ,FM_BWR = 5  //!< Bar Width Reduction (spaces enlargement)
            ,FM_SM_BWR = 6  //!< Sharpening Mask + Bar Width Reduction
        }
        public enum DMQZ_MODE
        {
            DMQZ_NORMAL = 0 //!< allows QZ>= 5.7 pixels
           ,DMQZ_SMALL = 1 //!< allows QZ>= 4.5 pixels, affects speed and robustness
        }

        private IntPtr FDM_DecoderW = IntPtr.Zero;
        public IntPtr DM_DecoderO = IntPtr.Zero;

        private unsafe struct T_US_DM_ImageInfo
        { // averall image properties
            public Int32 Count;        // number of well decoded symbols within image
            public Int32 RejectionReason;// >0 if no one symbol has been successfully decoded
            public Int32 BreakReason;// >0 if no one symbol has been successfully decoded
        }

        public IntPtr CreateDM_Opt()
        {
            unsafe
            {
                IntPtr PD = FDM_DecoderW;

                DM_DecoderO = Create_DM_OptionsP(PD,
                                                1, // maxcount
                                                3, // color = any
                                                3, // mirror = any
                                                6, // speed = UltimatePlus 
                                                0, // qualityMask = QM_NO
                                                3, // labelMode = ST_DOT
                                                0, // timeOut
                                                0, // filterMode = Non
                                                0  // qzMode = Normal
                                                );
            }
            return DM_DecoderO;
        }

        private int DecodeDM_BitsO(Int32 RowCount, Int32 ColCount, IntPtr[] PPBits)
        {
            int Result = 0;
            Result = Decode_DM_Bits(DM_DecoderO, RowCount, ColCount, PPBits);
            return Result;
        }

        public int DecDM_Image(IntPtr DecO, Bitmap BMP)
        {
            GrayScale G = new GrayScale(BMP);
            DM_DecoderO = DecO;
            G.OnDecBits += this.DecodeDM_BitsO;

            G.DecodeBits();

            IntPtr II = GetDM_ImageInfo(DM_DecoderO);
            FCount = 0;
            unsafe
            {
                T_US_DM_ImageInfo* UII = (T_US_DM_ImageInfo*)II.ToPointer();
                {
                    FRejectionReason = UII->RejectionReason;
                    if (FRejectionReason == 0) // successful
                        FCount = UII->Count;
                }
            }
            return FCount;
        }

        public TDM_Info Get_DM_Info(int Index)
        {
            TDM_Info Result = null;
            IntPtr II = IntPtr.Zero;
            if (Index < 0) return null;
            if (Index >= FCount) return null;

            II = GetDM_Info(DM_DecoderO, Index);
            Result = new TDM_Info(II);

            return Result;
        }


    }

}
