context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Text;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Data;
  using System.IO;
  using System.Drawing.Imaging;
  using BarcodeLib.Symbologies;
  
  /* 
   * ***************************************************
   *                 Barcode Library                   *
   *                                                   *
   *             Written by: Brad Barnhill             *
   *                   Date: 09-21-2007                *
   *          Last Modified: 11-02-2013                *
   *                                                   *
   *  This library was designed to give developers an  *
   *  easy class to use when they need to generate     *
   *  barcode images from a string of data.            *
   * ***************************************************
   */
  namespace BarcodeLib
  {
      #region Enums
      public enum TYPE : int { UNSPECIFIED, UPCA, UPCE, UPC_SUPPLEMENTAL_2DIGIT, UPC_SUPPLEMENTAL_5DIGIT, EAN13, EAN8, Interleaved2of5, Standard2of5, Industrial2of5, CODE39, CODE39Extended, CODE39_Mod43, Codabar, PostNet, BOOKLAND, ISBN, JAN13, MSI_Mod10, MSI_2Mod10, MSI_Mod11, MSI_Mod11_Mod10, Modified_Plessey, CODE11, USD8, UCC12, UCC13, LOGMARS, CODE128, CODE128A, CODE128B, CODE128C, ITF14, CODE93, TELEPEN, FIM, PHARMACODE };
      public enum SaveTypes : int { JPG, BMP, PNG, GIF, TIFF, UNSPECIFIED };
      public enum AlignmentPositions : int { CENTER, LEFT, RIGHT};
      public enum LabelPositions : int { TOPLEFT, TOPCENTER, TOPRIGHT, BOTTOMLEFT, BOTTOMCENTER, BOTTOMRIGHT };
      #endregion
      /// <summary>
      /// Generates a barcode image of a specified symbology from a string of data.
      /// </summary>
      public class Barcode: IDisposable
      {
          #region Variables
          private IBarcode ibarcode = new BarcodeLib.Symbologies.Blank();
          private string Raw_Data = "";
          private string Encoded_Value = "";
          private string _Country_Assigning_Manufacturer_Code = "N/A";
          private TYPE Encoded_Type = TYPE.UNSPECIFIED;
          private Image _Encoded_Image = null;
          private Color _ForeColor = Color.Black;
          private Color _BackColor = Color.White;
          private int _Width = 300;
          private int _Height = 150;
          private string _XML = "";
          private ImageFormat _ImageFormat = ImageFormat.Jpeg;
          private Font _LabelFont = new Font("Microsoft Sans Serif", 10, FontStyle.Bold);
          private AlignmentPositions _Alignment = AlignmentPositions.CENTER;
          private LabelPositions _LabelPosition = LabelPositions.BOTTOMCENTER;
          private RotateFlipType _RotateFlipType = RotateFlipType.RotateNoneFlipNone;
          #endregion
  
          #region Constructors
          /// <summary>
          /// Default constructor.  Does not populate the raw data.  MUST be done via the RawData property before encoding.
          /// </summary>
          public Barcode()
          {
              //constructor
          }//Barcode
          /// <summary>
          /// Constructor. Populates the raw data. No whitespace will be added before or after the barcode.
          /// </summary>
          /// <param name="data">String to be encoded.</param>
          public Barcode(string data)
          {
              //constructor
              this.Raw_Data = data;
          }//Barcode
          public Barcode(string data, TYPE iType)
          {
              this.Raw_Data = data;
              this.Encoded_Type = iType;
          }
          #endregion
  
          #region Properties
          /// <summary>
          /// Gets or sets the raw data to encode.
          /// </summary>
          public string RawData
          {
              get { return Raw_Data; }
              set { Raw_Data = value; }
          }//RawData
          /// <summary>
          /// Gets the encoded value.
          /// </summary>
          public string EncodedValue
          {
              get { return Encoded_Value; }
          }//EncodedValue
          /// <summary>
          /// Gets the Country that assigned the Manufacturer Code.
          /// </summary>
          public string Country_Assigning_Manufacturer_Code
          {
              get { return _Country_Assigning_Manufacturer_Code; }
          }//Country_Assigning_Manufacturer_Code
          /// <summary>
          /// Gets or sets the Encoded Type (ex. UPC-A, EAN-13 ... etc)
          /// </summary>
          public TYPE EncodedType
          {
              set { Encoded_Type = value; }
              get { return Encoded_Type;  }
          }//EncodedType
          /// <summary>
          /// Gets the Image of the generated barcode.
          /// </summary>
          public Image EncodedImage
          {
              get 
              {
                  return _Encoded_Image; 
              }
          }//EncodedImage
          /// <summary>
          /// Gets or sets the color of the bars. (Default is black)
          /// </summary>
          public Color ForeColor
          {
              get { return this._ForeColor; }
              set { this._ForeColor = value; }
          }//ForeColor
          /// <summary>
          /// Gets or sets the background color. (Default is white)
          /// </summary>
          public Color BackColor
          {
              get { return this._BackColor; }
              set { this._BackColor = value; }
          }//BackColor
          /// <summary>
          /// Gets or sets the label font. (Default is Microsoft Sans Serif, 10pt, Bold)
          /// </summary>
          public Font LabelFont
          {
              get { return this._LabelFont; }
              set { this._LabelFont = value; }
          }//LabelFont
          /// <summary>
          /// Gets or sets the location of the label in relation to the barcode. (BOTTOMCENTER is default)
          /// </summary>
          public LabelPositions LabelPosition
          {
              get { return _LabelPosition; }
              set { _LabelPosition = value; }
          }//LabelPosition
          /// <summary>
          /// Gets or sets the degree in which to rotate/flip the image.(No action is default)
          /// </summary>
          public RotateFlipType RotateFlipType
          {
              get { return _RotateFlipType; }
              set { _RotateFlipType = value; }
          }//RotatePosition
          /// <summary>
          /// Gets or sets the width of the image to be drawn. (Default is 300 pixels)
          /// </summary>
          public int Width
          {
              get { return _Width; }
              set { _Width = value; }
          }
          /// <summary>
          /// Gets or sets the height of the image to be drawn. (Default is 150 pixels)
          /// </summary>
          public int Height
          {
              get { return _Height; }
              set { _Height = value; }
          }
          /// <summary>
          /// Gets or sets whether a label should be drawn below the image. (Default is false)
          /// </summary>
          public bool IncludeLabel
          {
              get;
              set;
          }
          
          /// <summary>
          /// Alternate label to be displayed.  (IncludeLabel must be set to true as well)
          /// </summary>
          public String AlternateLabel 
          { 
              get; 
              set; 
          }
  
          /// <summary>
          /// Gets or sets the amount of time in milliseconds that it took to encode and draw the barcode.
          /// </summary>
          public double EncodingTime
          {
              get;
              set;
          }
          /// <summary>
          /// Gets the XML representation of the Barcode data and image.
          /// </summary>
          public string XML
          {
              get { return _XML; }
          }
          /// <summary>
          /// Gets or sets the image format to use when encoding and returning images. (Jpeg is default)
          /// </summary>
          public ImageFormat ImageFormat
          {
              get { return _ImageFormat; }
              set { _ImageFormat = value; }
          }
          /// <summary>
          /// Gets the list of errors encountered.
          /// </summary>
          public List<string> Errors
          {
              get { return this.ibarcode.Errors; }
          }
          /// <summary>
          /// Gets or sets the alignment of the barcode inside the image. (Not for Postnet or ITF-14)
          /// </summary>
          public AlignmentPositions Alignment
          {
              get;
              set;
          }//Alignment
          /// <summary>
          /// Gets a byte array representation of the encoded image. (Used for Crystal Reports)
          /// </summary>
          public byte[] Encoded_Image_Bytes
          {
              get
              {
                  if (_Encoded_Image == null)
                      return null;
                  
                  using (MemoryStream ms = new MemoryStream())
                  {
                      _Encoded_Image.Save(ms, _ImageFormat);
                      return ms.ToArray();
                  }//using
              }
          }
          /// <summary>
          /// Gets the assembly version information.
          /// </summary>
          public static Version Version
          {
              get { return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;}
          }
          #endregion
  
          /// <summary>
          /// Represents the size of an image in real world coordinates (millimeters or inches).
          /// </summary>
          public class ImageSize 
          {
              public ImageSize(double width, double height, bool metric)
              {
                  Width = width;
                  Height = height;
                  Metric = metric;
              }
  
              public double Width { get; set; }
              public double Height { get; set; }
              public bool Metric { get; set; }
          }
  
          #region Functions
          #region General Encode
          /// <summary>
          /// Encodes the raw data into binary form representing bars and spaces.  Also generates an Image of the barcode.
          /// </summary>
          /// <param name="iType">Type of encoding to use.</param>
          /// <param name="StringToEncode">Raw data to encode.</param>
          /// <param name="Width">Width of the resulting barcode.(pixels)</param>
          /// <param name="Height">Height of the resulting barcode.(pixels)</param>
          /// <returns>Image representing the barcode.</returns>
          public Image Encode(TYPE iType, string StringToEncode, int Width, int Height)
          {
              this.Width = Width;
              this.Height = Height;
              return Encode(iType, StringToEncode);
          }//Encode(TYPE, string, int, int)
          /// <summary>
          /// Encodes the raw data into binary form representing bars and spaces.  Also generates an Image of the barcode.
          /// </summary>
          /// <param name="iType">Type of encoding to use.</param>
          /// <param name="StringToEncode">Raw data to encode.</param>
          /// <param name="DrawColor">Foreground color</param>
          /// <param name="BackColor">Background color</param>
          /// <param name="Width">Width of the resulting barcode.(pixels)</param>
          /// <param name="Height">Height of the resulting barcode.(pixels)</param>
          /// <returns>Image representing the barcode.</returns>
          public Image Encode(TYPE iType, string StringToEncode, Color ForeColor, Color BackColor, int Width, int Height)
          {
              this.Width = Width;
              this.Height = Height;
              return Encode(iType, StringToEncode, ForeColor, BackColor);
          }//Encode(TYPE, string, Color, Color, int, int)
          /// <summary>
          /// Encodes the raw data into binary form representing bars and spaces.  Also generates an Image of the barcode.
          /// </summary>
          /// <param name="iType">Type of encoding to use.</param>
          /// <param name="StringToEncode">Raw data to encode.</param>
          /// <param name="DrawColor">Foreground color</param>
          /// <param name="BackColor">Background color</param>
          /// <returns>Image representing the barcode.</returns>
          public Image Encode(TYPE iType, string StringToEncode, Color ForeColor, Color BackColor)
          {
              this.BackColor = BackColor;
              this.ForeColor = ForeColor;
              return Encode(iType, StringToEncode);
          }//(Image)Encode(Type, string, Color, Color)
          /// <summary>
          /// Encodes the raw data into binary form representing bars and spaces.  Also generates an Image of the barcode.
          /// </summary>
          /// <param name="iType">Type of encoding to use.</param>
          /// <param name="StringToEncode">Raw data to encode.</param>
          /// <returns>Image representing the barcode.</returns>
          public Image Encode(TYPE iType, string StringToEncode)
          {
              Raw_Data = StringToEncode;
              return Encode(iType);
          }//(Image)Encode(TYPE, string)
          /// <summary>
          /// Encodes the raw data into binary form representing bars and spaces.  Also generates an Image of the barcode.
          /// </summary>
          /// <param name="iType">Type of encoding to use.</param>
          internal Image Encode(TYPE iType)
          {
              Encoded_Type = iType;
              return Encode();
          }//Encode()
          /// <summary>
          /// Encodes the raw data into binary form representing bars and spaces.
          /// </summary>
          internal Image Encode()
          {
              ibarcode.Errors.Clear();
  
              DateTime dtStartTime = DateTime.Now;
  
              //make sure there is something to encode
              if (Raw_Data.Trim() == "") 
                  throw new Exception("EENCODE-1: Input data not allowed to be blank.");
  
              if (this.EncodedType == TYPE.UNSPECIFIED) 
                  throw new Exception("EENCODE-2: Symbology type not allowed to be unspecified.");
  
              this.Encoded_Value = "";
              this._Country_Assigning_Manufacturer_Code = "N/A";
              
              switch (this.Encoded_Type)
              {
                  case TYPE.UCC12:
                  case TYPE.UPCA: //Encode_UPCA();
                      ibarcode = new UPCA(Raw_Data);
                      break;
                  case TYPE.UCC13:
                  case TYPE.EAN13: //Encode_EAN13();
                      ibarcode = new EAN13(Raw_Data);
                      break;
                  case TYPE.Interleaved2of5: //Encode_Interleaved2of5();
                      ibarcode = new Interleaved2of5(Raw_Data);
                      break;
                  case TYPE.Industrial2of5:
                  case TYPE.Standard2of5: //Encode_Standard2of5();
                      ibarcode = new Standard2of5(Raw_Data);
                      break;
                  case TYPE.LOGMARS:
                  case TYPE.CODE39: //Encode_Code39();
                      ibarcode = new Code39(Raw_Data);
                      break;
                  case TYPE.CODE39Extended:
                      ibarcode = new Code39(Raw_Data, true);
                      break;
                  case TYPE.CODE39_Mod43:
                      ibarcode = new Code39(Raw_Data, false, true);
                      break;
                  case TYPE.Codabar: //Encode_Codabar();
                      ibarcode = new Codabar(Raw_Data);
                      break;
                  case TYPE.PostNet: //Encode_PostNet();
                      ibarcode = new Postnet(Raw_Data);
                      break;
                  case TYPE.ISBN:
                  case TYPE.BOOKLAND: //Encode_ISBN_Bookland();
                      ibarcode = new ISBN(Raw_Data);
                      break;
                  case TYPE.JAN13: //Encode_JAN13();
                      ibarcode = new JAN13(Raw_Data);
                      break;
                  case TYPE.UPC_SUPPLEMENTAL_2DIGIT: //Encode_UPCSupplemental_2();
                      ibarcode = new UPCSupplement2(Raw_Data);
                      break;
                  case TYPE.MSI_Mod10:
                  case TYPE.MSI_2Mod10:
                  case TYPE.MSI_Mod11:
                  case TYPE.MSI_Mod11_Mod10:
                  case TYPE.Modified_Plessey: //Encode_MSI();
                      ibarcode = new MSI(Raw_Data, Encoded_Type);
                      break;
                  case TYPE.UPC_SUPPLEMENTAL_5DIGIT: //Encode_UPCSupplemental_5();
                      ibarcode = new UPCSupplement5(Raw_Data);
                      break;
                  case TYPE.UPCE: //Encode_UPCE();
                      ibarcode = new UPCE(Raw_Data);
                      break;
                  case TYPE.EAN8: //Encode_EAN8();
                      ibarcode = new EAN8(Raw_Data);
                      break;
                  case TYPE.USD8:
                  case TYPE.CODE11: //Encode_Code11();
                      ibarcode = new Code11(Raw_Data);
                      break;
                  case TYPE.CODE128: //Encode_Code128();
                      ibarcode = new Code128(Raw_Data);
                      break;
                  case TYPE.CODE128A:
                      ibarcode = new Code128(Raw_Data, Code128.TYPES.A);
                      break;
                  case TYPE.CODE128B:
                      ibarcode = new Code128(Raw_Data, Code128.TYPES.B);
                      break;
                  case TYPE.CODE128C:
                      ibarcode = new Code128(Raw_Data, Code128.TYPES.C);
                      break;
                  case TYPE.ITF14:
                      ibarcode = new ITF14(Raw_Data);
                      break;
                  case TYPE.CODE93:
                      ibarcode = new Code93(Raw_Data);
                      break;
                  case TYPE.TELEPEN:
                      ibarcode = new Telepen(Raw_Data);
                      break;
                  case TYPE.FIM:
                      ibarcode = new FIM(Raw_Data);
                      break;
                  case TYPE.PHARMACODE:
                      ibarcode = new Pharmacode(Raw_Data);
                      break;
  
                  default: throw new Exception("EENCODE-2: Unsupported encoding type specified.");
              }//switch
  
              this.Encoded_Value = ibarcode.Encoded_Value;
              this.Raw_Data = ibarcode.RawData;
  
              _Encoded_Image = (Image)Generate_Image();
  
              this.EncodedImage.RotateFlip(this.RotateFlipType);
  
              _XML = GetXML();
  
              this.EncodingTime = ((TimeSpan)(DateTime.Now - dtStartTime)).TotalMilliseconds;
              
              return EncodedImage;
          }//Encode
          #endregion
  
          #region Image Functions
          /// <summary>
          /// Gets a bitmap representation of the encoded data.
          /// </summary>
          /// <returns>Bitmap of encoded value.</returns>
          private Bitmap Generate_Image()
          {
              if (Encoded_Value == "") throw new Exception("EGENERATE_IMAGE-1: Must be encoded first.");
              Bitmap b = null;
  
              DateTime dtStartTime = DateTime.Now;
  
              switch (this.Encoded_Type)
              {
                  case TYPE.ITF14:
                      {
                          b = new Bitmap(Width, Height);
  
                          int bearerwidth = (int)((b.Width) / 12.05);
                          int iquietzone = Convert.ToInt32(b.Width * 0.05);
                          int iBarWidth = (b.Width - (bearerwidth * 2) - (iquietzone * 2)) / Encoded_Value.Length;
                          int shiftAdjustment = ((b.Width - (bearerwidth * 2) - (iquietzone * 2)) % Encoded_Value.Length) / 2;
  
                          if (iBarWidth <= 0 || iquietzone <= 0)
                              throw new Exception("EGENERATE_IMAGE-3: Image size specified not large enough to draw image. (Bar size determined to be less than 1 pixel or quiet zone determined to be less than 1 pixel)");
  
                          //draw image
                          int pos = 0;
  
                          using (Graphics g = Graphics.FromImage(b))
                          {
                              //fill background
                              g.Clear(BackColor);
  
                              //lines are fBarWidth wide so draw the appropriate color line vertically
                              using (Pen pen = new Pen(ForeColor, iBarWidth))
                              {
                                  pen.Alignment = PenAlignment.Right;
  
                                  while (pos < Encoded_Value.Length)
                                  {
                                      //draw the appropriate color line vertically
                                      if (Encoded_Value[pos] == '1')
                                          g.DrawLine(pen, new Point((pos * iBarWidth) + shiftAdjustment + bearerwidth + iquietzone, 0), new Point((pos * iBarWidth) + shiftAdjustment + bearerwidth + iquietzone, Height));
  
                                      pos++;
                                  }//while
                                  
                                  //bearer bars
                                  pen.Width = (float)b.Height / 8;
                                  pen.Color = ForeColor;
                                  pen.Alignment = PenAlignment.Center;
                                  g.DrawLine(pen, new Point(0, 0), new Point(b.Width, 0));//top
                                  g.DrawLine(pen, new Point(0, b.Height), new Point(b.Width, b.Height));//bottom
                                  g.DrawLine(pen, new Point(0, 0), new Point(0, b.Height));//left
                                  g.DrawLine(pen, new Point(b.Width, 0), new Point(b.Width, b.Height));//right                                
                              }//using
                          }//using
  
                          if (IncludeLabel)
                              Label_ITF14((Image)b);
  
                          break;
                      }//case
                  default:
                      {
                          b = new Bitmap(Width, Height);
                          int iBarWidth = Width / Encoded_Value.Length;
                          int shiftAdjustment = 0;
                          int iBarWidthModifier = 1;
  
                          if (this.Encoded_Type == TYPE.PostNet)
                              iBarWidthModifier = 2;
  
                          //set alignment
                          switch (Alignment)
                          {
                              case AlignmentPositions.CENTER: shiftAdjustment = (Width % Encoded_Value.Length) / 2;
                                  break;
                              case AlignmentPositions.LEFT: shiftAdjustment = 0;
                                  break;
                              case AlignmentPositions.RIGHT: shiftAdjustment = (Width % Encoded_Value.Length);
                                  break;
                              default: shiftAdjustment = (Width % Encoded_Value.Length) / 2;
                                  break;
                          }//switch
  
                          if (iBarWidth <= 0)
                              throw new Exception("EGENERATE_IMAGE-2: Image size specified not large enough to draw image. (Bar size determined to be less than 1 pixel)");
  
                          //draw image
                          int pos = 0;
                          int halfBarWidth = (int)(iBarWidth * 0.5);
  
                          using (Graphics g = Graphics.FromImage(b))
                          {
                              //clears the image and colors the entire background
                              g.Clear(BackColor);                            
  
                              //lines are fBarWidth wide so draw the appropriate color line vertically
                              using (Pen backpen = new Pen(BackColor, iBarWidth / iBarWidthModifier))
                              {
                                  using (Pen pen = new Pen(ForeColor, iBarWidth / iBarWidthModifier))
                                  {
                                      while (pos < Encoded_Value.Length)
                                      {
                                          if (this.Encoded_Type == TYPE.PostNet)
                                          {
                                              //draw half bars in postnet
                                              if (Encoded_Value[pos] == '0')
                                                  g.DrawLine(pen, new Point(pos * iBarWidth + shiftAdjustment + halfBarWidth, Height), new Point(pos * iBarWidth + shiftAdjustment + halfBarWidth, Height / 2));
                                              else
                                                  g.DrawLine(pen, new Point(pos * iBarWidth + shiftAdjustment + halfBarWidth, Height), new Point(pos * iBarWidth + shiftAdjustment + halfBarWidth, 0));
                                          }//if
                                          else
                                          {
                                              if (Encoded_Value[pos] == '1')
                                                  g.DrawLine(pen, new Point(pos * iBarWidth + shiftAdjustment + halfBarWidth, 0), new Point(pos * iBarWidth + shiftAdjustment + halfBarWidth, Height));
                                          }
                                          pos++;
                                      }//while
                                  }//using
                              }//using
                          }//using
                          if (IncludeLabel)
                          {
                              //if (this.EncodedType != TYPE.UPCA)
                                  Label_Generic((Image)b);
                              //else
                              //    Label_UPCA((Image)b);
                          }//if
                          
                          break;
                      }//case
              }//switch
  
              _Encoded_Image = (Image)b;
  
              this.EncodingTime += ((TimeSpan)(DateTime.Now - dtStartTime)).TotalMilliseconds;
  
              return b;
          }//Generate_Image
          /// <summary>
          /// Gets the bytes that represent the image.
          /// </summary>
          /// <param name="savetype">File type to put the data in before returning the bytes.</param>
          /// <returns>Bytes representing the encoded image.</returns>
          public byte[] GetImageData(SaveTypes savetype)
          {
              byte[] imageData = null;
                
              try
              {
                  if (_Encoded_Image != null)
                  {
                      //Save the image to a memory stream so that we can get a byte array!      
                      using (MemoryStream ms = new MemoryStream())
                      {
                          SaveImage(ms, savetype);
                          imageData = ms.ToArray();
                          ms.Flush();
                          ms.Close();
                      }//using
                  }//if
              }//try
              catch (Exception ex)
              {
                  throw new Exception("EGETIMAGEDATA-1: Could not retrieve image data. " + ex.Message);
              }//catch  
              return imageData;
          }
          /// <summary>
          /// Saves an encoded image to a specified file and type.
          /// </summary>
          /// <param name="Filename">Filename to save to.</param>
          /// <param name="FileType">Format to use.</param>
          public void SaveImage(string Filename, SaveTypes FileType)
          {
              try
              {
  
gt:                 if (_Encoded_Image != null)