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

namespace icLDecNetPro
{
#pragma warning disable 0649
#pragma warning disable 0169
	
	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_TCODE93 = 16,

		TC_TADF = 17,
		TC_TNZP = 18,
		TC_TUPCA = 19,    // ONLY for returning the type of decoded symbologes. Decoded as EAN13.

		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_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_BREAK_REASON
	{
		L_ALL_INSPECTED = 0, //!< Normal termination (whole image was inspected)
		L_TIMEOUT = 1, //!< Termination by time-out
		L_TERMINATED = 2  //!< Termination by user break (not implemented)
	};

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

	/*! Directions of Pharmacode*/
	enum L_PHARMACODEDIR
	{
		L_LR = 0, //!< Barcode goes approximately from image left to image right
		L_TB = 1, //!< From image top to bottom
		L_RL = 2, //!< From image right to left
		L_BT = 3, //!< From image bottom to top
		L_LRL = 4, //!< left -> right -> left (result as "XXXX YYYY")
		L_TBT = 5  //!< top -> bottom -> top
	};

	public enum L_Color
	{
		L_BLACK = 1,
		L_WHITE = 2, //!< Is valide for NZP 
		L_DEFAULT = 3  //!< Any, if type code = -1..7,14,15. Black for all other code types
	};

	public enum L_Mode
	{
		L_M_STANDARD = 0,
		L_M_SMALL_QZ = 1,
		L_M_STANDARD_AND_SMALL_QZ = 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 PostNet or USPS IMB
		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;    //!< 1<=quietzone<=15
		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, PostNet and USPS IMB
								   */
		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;
		public Int32 mode;
	};

	//        ADDITIONAL OPTIONS. 
	// Can be set using the function Set_L_Addition_Option.
	//
	enum L_AdditionalOptions
	{
		// When decoding, replace the code UPCE with UPCA by adding zeros. Default ON
		L_OPT_EXT_UPCE_TO_UPCA = 1000,
		// A quiet zone for the pharmacode is required. Default ON
		L_OPT_PHARMACODE_QUEIT_ZONE_MANDATORY = 1001
	};

	//--------------------------------------------------------------------------
	/// Linear Image properties.
	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
	};

	//--------------------------------------------------------------------------
	/// Linear codes ISO 15416 Standard Quality Parameters.
	struct LINEAR_QUALITY
	{
		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;
	};

	public class TRowCols
	{
		protected float[] FRowCols = new float[8];
		protected bool FValid;
		public float this[int ix]
		{
			get
			{
				if (ix < 0) return -1;
				if (ix > 7) return -1;
				if (!FValid) return -1;
				return FRowCols[ix];
			}
		}
		public bool Valid { get { return FValid; } }
	}

	public class TL_Quality
	{
		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;
	}

	public class TL_Info
	{
		public TL_Info(IntPtr DLLInfo)
		{
			SetInfo(DLLInfo);
		}
		unsafe private void SetInfo(IntPtr DLLInfo)
		{
			FInfo = (T_US_L_Info*)DLLInfo;
			FRowCols.SetInfo(FInfo);
			FQuality.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;

		//        #region PrivateFields
		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;
				//if ( FInfo->rcFlag == 0 ) 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;
			}
		}
		class T_US_Quality : TL_Quality
		{
			unsafe public void SetInfo(T_US_L_Info* FInfo)
			{
				if (FInfo == (T_US_L_Info*)null)
				{
					decode = -1;
					symbol_contrast = -1;
					global_threshold = -1;
					min_reflectance = -1;
					max_reflectance = -1;
					min_edge_contrast = -1;
					defects = -1;
					decodability = -1;

					symbol_contrast_grade = -1;
					global_threshold_grade = -1;
					min_reflectance_grade = -1;
					min_edge_contrast_grade = -1;
					defects_grade = -1;
					decodability_grade = -1;
					modulation_grade = -1;
					decode_grade = -1;
					overall_grade = -1;
				}
				else
				{
					decode = FInfo->decode;
					symbol_contrast = FInfo->symbol_contrast;
					global_threshold_grade = FInfo->global_threshold_grade;
					min_reflectance = FInfo->min_reflectance;
					max_reflectance = FInfo->max_reflectance;
					min_edge_contrast = FInfo->min_edge_contrast;
					defects = FInfo->defects;
					decodability = FInfo->decodability;

					decode_grade = FInfo->decode_grade;
					symbol_contrast_grade = FInfo->symbol_contrast_grade;
					global_threshold_grade = FInfo->global_threshold_grade;
					min_reflectance_grade = FInfo->min_reflectance_grade;
					min_edge_contrast_grade = FInfo->min_edge_contrast_grade;
					defects_grade = FInfo->defects_grade;
					decodability_grade = FInfo->decodability_grade;
					modulation_grade = FInfo->modulation_grade;
					overall_grade = FInfo->overall_grade;
				}
			}
		}

		private T_US_Quality FQuality = new T_US_Quality();
		private T_US_RowCols FRowCols = new T_US_RowCols();
		unsafe private bool IsInfo()
		{
			return (FInfo != null);
		}

		//        #endregion

		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);
		}

		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)
		{
			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,
            "UPCA",         // 19,
            };
			if (typecode < 0 || typecode > 19)
				return "?";
			else
				return type[typecode - 1];
		}

		public TRowCols RowCols
		{
			get
			{
				return FRowCols;
			}
		}

		public TL_Quality Quality
		{
			get { return FQuality; }
		}

	}
	// TL_Info

	public class icLC_Decoder_Pro
	{
		//        #region Private_Fields
		const string DLL_NAME = "LC_PRO.dll";

		[DllImport(DLL_NAME, EntryPoint = "Connect_L_Decoder", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern void* Connect_L_Decoder ([In] Int32 MaxRowCount, [In] Int32 MaxColCount);

		[DllImport(DLL_NAME, EntryPoint = "Disconnect_L_Decoder", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern void Disonnect_L_Decoder(void* Decoder);

		[DllImport(DLL_NAME, EntryPoint = "Create_L_Options", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern void* Create_L_Options(void* Decoder, [In] TL_OptMode opt);

		[DllImport(DLL_NAME, EntryPoint = "Delete_L_Options", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern void Delete_L_Options(void* Options);

		[DllImport(DLL_NAME, EntryPoint = "GetL_ImageInfo", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern IntPtr GetL_ImageInfo(void* DecoderO);

		[DllImport(DLL_NAME, EntryPoint = "GetL_Info", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern IntPtr GetL_Info(void* DecoderO, [In] Int32 SymbolNumber);

		[DllImport(DLL_NAME, EntryPoint = "Decode_L_Bits", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern int Decode_L_Bits(void* Decoder, [In] Int32 RowCount, [In] Int32 ColCount, [In] IntPtr[] PPBits);

		[DllImport(DLL_NAME, EntryPoint = "Set_L_Addition_Option", CallingConvention = CallingConvention.StdCall)]
		unsafe internal static extern int Set_L_Addition_Option(void* options, [In] Int32 optCode, [In] Int32 optValue);

		unsafe private void* decoder = null;
		unsafe private void* options = null;
		private bool FOptionChanged = true;
		public L_REJECTION_REASON FRejectionReason = L_REJECTION_REASON.L_RR_UNKNOWN;// if no one matrix has been decoded
		private int FcornQ = 0;
		private int FLCount = 0;

		private int ExtendUPCE_to_UPCA = 1;
		private int PHARMACODE_QUEIT_ZONE_MANDATORY = 1;

		public void Disconnect()
		{
			unsafe
			{
				Delete_L_Options(options);
				Disonnect_L_Decoder(decoder);
				decoder = null;
				options = null;
			}
		}
		
		public unsafe struct T_US_L_OptMode
		{
			public Int32 maxLCount;   // from 1 to 100
			public Int32 codeType;
			public Int32 paramq;
			public Int32 Color;
			public Int32 ScanStep;
			public Int32 mode;
		}

		private unsafe struct T_US_L_ImageInfo
		{ // averall image properties
			public Int32 LCount;        // number of well decoded symbols within image
			public Int32 RejectionReason;// if no one matrix has been decoded
			public byte cornQ;// number of detected corners in symbol ( = 4 if a rectangle was detected)
		}
#pragma warning restore 0649
#pragma warning restore 0169

		public T_US_L_OptMode FOptMode;

		private int DecodeBitsO(Int32 RowCount, Int32 ColCount, IntPtr[] PPBits)
		{
			int Result = 0;
			TL_OptMode newopt;

			unsafe
			{
				if (decoder == null) return -1;

				if (FOptionChanged)
				{
					if (options != null)
					{
						Delete_L_Options(options);
					}

					newopt = new TL_OptMode();
					newopt.maxLcount = FOptMode.maxLCount;
					newopt.typecode = FOptMode.codeType;
					newopt.paramq = FOptMode.paramq;
					newopt.color = FOptMode.Color;
					newopt.colbeg = newopt.colend = newopt.rowbeg = newopt.rowend = -1;
					newopt.scanstep = FOptMode.ScanStep;
					newopt.scandir = (Int32)(L_SCAN_DIR.L_SCAN_ALL);
					newopt.mode = FOptMode.mode;
					options = Create_L_Options(decoder, newopt);
					FOptionChanged = false;
				}

				Set_L_Addition_Option(options, (int)L_AdditionalOptions.L_OPT_EXT_UPCE_TO_UPCA, ExtendUPCE_to_UPCA);
				Set_L_Addition_Option(options, (int)L_AdditionalOptions.L_OPT_PHARMACODE_QUEIT_ZONE_MANDATORY, PHARMACODE_QUEIT_ZONE_MANDATORY);

				Result = Decode_L_Bits(options, RowCount, ColCount, PPBits);
				return Result;
			}
		}

		unsafe private int Get_maxLCount()
		{
			return FOptMode.maxLCount;
		}
		unsafe private void Set_maxLCount(int Value)
		{
			if (FOptMode.maxLCount == Value) return;
			if (Value < 1) Value = 1;
			else if (Value > 100) Value = 100;
			FOptMode.maxLCount = Value;
			FOptionChanged = true;
		}

		public void SetMode(L_Mode mode)
		{
			if (FOptMode.mode == (int)mode) return;
			FOptMode.mode = (int)mode;
			FOptionChanged = true;
		}

		unsafe private int Get_codeType()
		{
			return FOptMode.codeType;
		}
		unsafe private void Set_codeType(int Value)
		{
			if (FOptMode.codeType == Value) return;
			if (Value < 0 || (Value > 19 && Value != (int)TYPE_CODE.TCM_TRSS_ALL))
				Value = -1; // all 
			FOptMode.codeType = Value;
			FOptionChanged = true;
		}

		unsafe private int Get_paramq()
		{
			return FOptMode.paramq;
		}
		unsafe private void Set_paramq(int Value)
		{
			if (FOptMode.paramq == Value) return;
			if (Value < 0 || Value > 1)
				Value = 1; // YES
			FOptMode.paramq = Value;
			FOptionChanged = true;
		}

		unsafe private int Get_L_Color()
		{
			return FOptMode.Color;
		}
		unsafe private void Set_L_Color(int Value)
		{
			if (FOptMode.Color == Value) return;
			if (Value < 1 || Value > 3)
				Value = 3; // L_DEFAULT
			FOptMode.Color = Value;
			FOptionChanged = true;
		}

		private bool SetAddOption(L_AdditionalOptions code, int value)
		{
			unsafe
			{
				int res = Set_L_Addition_Option(options, (int)code, value);
				return res == 0;
			}
		}

		//        #endregion
		public void SetExtendUPCE_to_UPCA(bool on)
		{
			ExtendUPCE_to_UPCA = 0;
			if (on)
				ExtendUPCE_to_UPCA = 1;
		}

		public void SetPharmacodeRequredQuietZone(bool on)
		{
			if (on)
				PHARMACODE_QUEIT_ZONE_MANDATORY = 1;
			else
				PHARMACODE_QUEIT_ZONE_MANDATORY = 0;
		}

		public int MaxLCount
		{
			get { return Get_maxLCount(); }
			set { Set_maxLCount(value); }
		}

		public int codeType
		{
			get { return Get_codeType(); }
			set { Set_codeType(value); }
		}

		public int paramq
		{
			get { return Get_paramq(); }
			set { Set_paramq(value); }
		}

		public int L_Color
		{
			get { return Get_L_Color(); }
			set { Set_L_Color(value); }
		}

		public int ScanStep
		{
			get { return FOptMode.ScanStep; }
			set { FOptMode.ScanStep = value; FOptionChanged = true; }
		}

		public icLC_Decoder_Pro()
		{
			unsafe
			{
				decoder = Connect_L_Decoder(5000, 8000);
			}

			FOptMode.maxLCount = 10;
			FOptMode.codeType = -1;
			FOptMode.paramq = 1;
			FOptMode.Color = 3; // L_Default
			FOptMode.ScanStep = 8;
			FOptMode.mode = (int)L_Mode.L_M_STANDARD;
			FOptionChanged = true;
		}


		public int DecodeImage(Bitmap BMP)
		{
			int Result;
			GrayScale G = new GrayScale(BMP);
			G.OnDecBits += this.DecodeBitsO;

			Result = G.DecodeBits();

			unsafe
			{
				IntPtr II = GetL_ImageInfo(options);
				T_US_L_ImageInfo* UII = (T_US_L_ImageInfo*)II.ToPointer();
				{
					FRejectionReason = (L_REJECTION_REASON)UII->RejectionReason;
					FLCount = UII->LCount;
					FcornQ = UII->cornQ;
				}
			}
			return Result;
		}

		public L_REJECTION_REASON Rejection_Reason
		{
			get { return FRejectionReason; }
		}
		public int LCount
		{
			get { return FLCount; }
		}

		public TL_Info Get_L_Info(int Index)
		{
			TL_Info Result = null;
			IntPtr II = IntPtr.Zero;
			if (Index < 0) return null;
			if (Index >= FLCount) return null;

			unsafe
			{
				II = GetL_Info(options, Index);
				Result = new TL_Info(II);
			}
			return Result;
		}
	}
}
