How to Save the Barcode in 4 Bit/Pixel Format?

First generate the barcode in the default Pixel format (Format32bppArgb):

System.Drawing.Size optimalSize = myBarcode.CalculateOptimalBitmapSize(null, 2, 2);
myBarcode.BoundingRectangle = new Rectangle(0, 0, optimalSize.Width, optimalSize.Height);
Bitmap barcodeImage = myBarcode.DrawBitmap();

Then convert it to a bitmap with the Pixel format you need:

Bitmap converted = barcodeImage.Clone (new Rectangle(0, 0, barcodeImage.Width, barcodeImage.Height), PixelFormat.Format4bppIndexed);
// MessageBox.Show(converted.PixelFormat.ToString());

How to Encode Binary Data (2D Codes)

Even if you use an escape sequence for binary data the encoder will use code page conversion (example: \x88 leads to a different value in Data Matrix as desired).

Solution:

  • Switch off code page conversion (use encoding mode LowByte)
  • Force binary encoding mode if available (see PDF417 encoding mode, Data Matrix EnforceBinaryEncoding)
Relevant for DP Premium Address and other applications where you encode binary data in a 2D symbol (Data Matrix etc).

How Can I Create a Swiss QR Code V2?

The following sample code in C# .NET shows how to create the data format for Swiss QR Code 2.0.

public enum CurrencyCodes
{
  CHF,
  EUR
}

public enum ReferenceTypes
{
  NON,
  SCOR,
  QRR
}

private const string fldSep = "\n";

decimal? Amount = new decimal(99.01);
CurrencyCodes Currency = CurrencyCodes.CHF;
ReferenceTypes ReferenceType = ReferenceTypes.SCOR;

string QRIBAN            = "";
string CreditorIBAN      = "CH180024024037606600Q";
string CreditorName      = "Robert Schneider AG";
string CreditorAddress1  = "Rue du Lac 1268";
string CreditorAddress2  = "2501 Biel";
string CreditorCountry   = "CH";

string DebtorName        = "Max Mustermann";
string DebtorAddress1    = "Musterstrasse 2";
string DebtorAddress2    = "1234 Musterstadt";
string DebtorCountry     = "CH";
string QRReference       = "";
string CreditorReference = "RF18539007547034";
string Message           = "Optional";
string BillInfo          = "";
string Parameter1        = "";
string Parameter2        = "";


/// 
/// returns the Data string valid for Swiss QR-Code version 2
/// 
/// 
public string GetDataString()
{
  var sb = new StringBuilder();

  //initial
  sb.Append("SPC" + fldSep);
  sb.Append("0200" + fldSep);
  sb.Append("1" + fldSep);

  //creditor
  if (ReferenceType == ReferenceTypes.QRR)
    sb.Append(QRIBAN + fldSep);
  else
    sb.Append(CreditorIBAN + fldSep);

  sb.Append("K" + fldSep);
  sb.Append(CreditorName + fldSep);
  sb.Append(CreditorAddress1 + fldSep);
  sb.Append(CreditorAddress2 + fldSep);
  sb.Append(fldSep + fldSep);
  sb.Append(CreditorCountry + fldSep);

  //ultimate creditor
  sb.Append(fldSep + fldSep + fldSep + fldSep + fldSep + fldSep + fldSep);

  //amount
  if (Amount.HasValue)
    sb.Append(Amount.Value.ToString("#########.00", System.Globalization.CultureInfo.InvariantCulture) + fldSep);
  else
    sb.Append(fldSep);

  sb.Append(Currency + fldSep);

  //debtor
  if (DebtorName + DebtorAddress1 + DebtorAddress2 + DebtorCountry == string.Empty)
    sb.Append(fldSep + fldSep + fldSep + fldSep + fldSep + fldSep + fldSep);
  else
  {
    sb.Append("K" + fldSep);
    sb.Append(DebtorName + fldSep);
    sb.Append(DebtorAddress1 + fldSep);
    sb.Append(DebtorAddress2 + fldSep);
    sb.Append(fldSep + fldSep);
    sb.Append(DebtorCountry + fldSep);
  }

  //reference
  sb.Append(ReferenceType + fldSep);
  if (ReferenceType == ReferenceTypes.QRR)
    sb.Append(QRReference + fldSep);
  else if (ReferenceType == ReferenceTypes.SCOR)
    sb.Append(CreditorReference + fldSep);
  else
    sb.Append(fldSep);

  //additional
  sb.Append(Message + fldSep);
  sb.Append("EPD");
 
  // optional
  if (BillInfo != string.Empty || Parameter1 != string.Empty || Parameter2 != string.Empty)
  {
    sb.Append(fldSep); // close EPD line
    sb.Append(BillInfo + fldSep);
    sb.Append(Parameter1 + fldSep);
    sb.Append(Parameter2);
  }

  return sb.ToString(); // NOTE: last line does not end with fieldSeparator
}

How Can I Control the Bar Code Size?

You can chose between two size modes:

  • Size Mode Fit to Bounding Rectangle
    The barcode adapts to the bounding rectangle by auto-calculation of the module width. The module width property is just a Get/Set value and is not updated.
  • Size Mode Custom Module Width
    The barcode size depends on the module width property which is set in [mm]. The barcode still adapts to the bounding rectangle in the dimension where the module width is not relevant (like the height in a linear code).

The Bounding Rectangle must be supplied in [mm] for doing Size calculations like with CalculateModuleWidth or CalculateBarcodeSize.

The Bounding Rectangle must be supplied in [Pixel] for any bitmap or device context related drawing operations.

Recommended Workflow

For any operations first set the rectangle, then do the operation or calculation.

It is recommended to do all in [mm] first and in case you draw to a bitmap, convert the mm to Pixel considering also the DPI you have adjusted.

  • Set bar code and bar code data
  • Set bounding rectangle in [mm], set the size mode and if applicable the module width
  • Set the DPI if applicable
  • If you use a custom module width: Do size retrieval / calculation functions (returned values are in mm). This is required because your bounding rectangle may not reflect the real bar code size.
  • If you need a bitmap, convert the returned size to Pixel and set the bounding rectangle in Pixel
Use the BoundingRectangleF which is using "float" instead of integer.

For creating bitmaps where the barcode size is not predefined by any specific requirements there is also the function CalculateOptimalBitmapSize. This function avoids quantization errors and improves the quality.

barcode.Dpi = 100;
barcode.SizeMode = SizeMode.FitToBoundingRectangle;
Size optimalSize = barcode.CalculateOptimalBitmapSize(null, 1, 1);  // 1 Module = 1 Pixel
barcode.BoundingRectangle = new Rectangle(0, 0, optimalSize.Width,  optimalSize.Height);
barcode.Draw(filename, ImageType.Jpg);

How Can I Control the Bitmap Transparency

When creating a barcode in bitmap format, there are two possibilities to adjust the background:

  • IsBackgroundTransparent = TRUE → When drawing the barcode (DC, Graphics, Bitmap) only the bars are drawn, the rest remains free
  • IsBackgroundTransparent = FALSE → When drawing the barcode (DC, Graphics, Bitmap) the background is filled first, then the bars are drawn

Recommended Workflow

If you want to create a bitmap barcode with a transparent background, you have to set the transparency color separately. To do this, first draw into a bitmap, set the transparency and then save it. Try one of the two following options:

Option #1

Draw the barcode with a white background:

  • IsBackgroundTransparent := FALSE (→ the barcode library draws a white background)

Specify the transparency color:

  • bitmap.MakeTransparent( Color.White ); //make be background transparent - this will be an index (rather than an alpha) transparency

Sample code in C#:

Barcode BC = new Barcode();
int width = 300;
int height = 150;

BC.BarcodeType = BarcodeType.Code128;
BC.Data = "12345";
BC.IsBackgroundTransparent = false;
BC.BoundingRectangle = new Rectangle(0, 0, width, height); // Pixel

Bitmap bitmap = new Bitmap(width, height);
Graphics gfx = Graphics.FromImage(bitmap);
BC.Draw(gfx);
bitmap.MakeTransparent(Color.White);
bitmap.Save("c:\\temp\\test1a.png", System.Drawing.Imaging.ImageFormat.Png);

Variant without graphics object:

Barcode BC = new Barcode();

int width = 300;
int height = 150;

BC.BarcodeType = BarcodeType.Code128;
BC.Data = "12345";
BC.IsBackgroundTransparent = false;
BC.BoundingRectangle = new Rectangle(0, 0, width, height); // Pixel

Bitmap bitmap = BC.DrawBitmap();
bitmap.MakeTransparent(Color.White);
bitmap.Save("c:\\temp\\test1b.png", System.Drawing.Imaging.ImageFormat.Png);       

Option #2

Draw the barcode without background:

  • IsBackgroundTransparent := FALSE (→ the barcode library draws a white background)

Fill background with transparency:

  • gfx.Clear(Color.Transparent);

Sample Code in C#:

Barcode BC = new Barcode();

int width = 300;
int height = 150;

BC.BarcodeType = BarcodeType.Code128;
BC.Data = "12345";
BC.IsBackgroundTransparent = true;
BC.BoundingRectangle = new Rectangle(0, 0, width, height); // Pixel

Bitmap bitmap = new Bitmap(width, height);
Graphics gfx = Graphics.FromImage(bitmap);

gfx.Clear(Color.Transparent);
gfx.Flush();

BC.Draw(gfx);
bitmap.Save("c:\\temp\\test2.png", System.Drawing.Imaging.ImageFormat.Png); 

Notes

  • Please note that the example barcode is not pixel-optimized.
  • We recommend to use PNG images.
  • Further information about transparency can be found here.

How Can I Create an ITF-14 Bitmap Optimized for Thermal Printers?

The following sample code in C# .NET generates a barcode image optimized for thermal printer output (resolutions such as 203 dpi).

// Create an ITF-14 bar code for a label to be printed with 203 dpi
// Bearer bar width = 2 X (X = module width)
// We fine-tune the module width using AdjustModuleWidthToPixelRaster.

Barcode code = new Barcode ();
code.BarcodeType = TECIT.TBarCode.BarcodeType.ITF14;

code.Data = "1234567890123";

code.Font = new System.Drawing.Font("Arial", 15, System.Drawing.FontStyle.Bold, GraphicsUnit.Point);
code.TextDistance = 1.1F; // mm

// important: set printer resolution of thermal printer
code.Dpi = 203;

// 203 dpi --> Module Width = 0.5005 = 4 Pixel per Module
float moduleWidth = 0.5004926F; // use exact value!

code.SizeMode = TECIT.TBarCode.SizeMode.CustomModuleWidth;
code.ModuleWidth = moduleWidth + 0.001; // add delta to extend optimization range

code.AdjustModuleWidthToPixelRaster = true;

double modulesBearerBar = 2; // 2 X
code.BearerBarType = TECIT.TBarCode.BearerBarType.TopAndBottom;
code.BearerBarWidth = moduleWidth * modulesBearerBar;

// adjust quiet zone in [Modules] (recommended for bitmaps)
code.QuietZones.Unit = TECIT.TBarCode.QuietZoneUnit.Modules;
code.QuietZones.Left.Size = 10F;
code.QuietZones.Right.Size = 10F;

// for rectangular bearer bar having a width of 4.83 mm
// code.BearerBarWidth = 4.83F;
// double modulesBearerBar = Math.Round(code.BearerBarWidth / moduleWidth, MidpointRounding.AwayFromZero);
// code.QuietZones.Left.Size = 10F + modulesBearerBar;
// code.QuietZones.Right.Size = 10F + modulesBearerBar;

// size in [mm]
double width = code.CalculateBarcodeWidth(null);
double height = 35;

// convert size to [Pixels]
width = width / (25.4 / code.Dpi);
height = height / (25.4 / code.Dpi);

// adjust bitmap size
code.BoundingRectangleF = new RectangleF(0, 0, (float) width, (float) height);

// output to file
code.Draw("barcode-ITF-14-203dpi.bmp", TECIT.TBarCode.ImageType.Bmp);

How Can I Create a Readable PDF417 Bitmap with Constant Size?

The following sample code in C# ASP .NET generates a PDF417 image with constant size.

//PDF417
Barcode barcode = new Barcode();
barcode.Data = strMyData;
barcode.BarcodeType = BarcodeType.Pdf417;
barcode.Pdf417.EncodingMode = PdfEncodingMode.Binary;

// with dpi = 100 we get 1 Pixel = 0.254 mms
barcode.Dpi = 100;

 // we should specify the number of horizontal data columns
 // this inhibits the symbol to change its horizontal size regardless of data
 barcode.Pdf417.NumberOfColumns = 16; // use a value, which fits to your available space !!

 // now calculate optimal bitmap size for the bar code
 barcode.SizeMode = SizeMode.FitToBoundingRectangle;
 Size optimalSize = barcode.CalculateOptimalBitmapSize(null, 1, 1);

 // we already could use this optimal Size for saving the image
 // barcode.BoundingRectangle = new Rectangle(0, 0, optimalSize.Width,  optimalSize.Height);
 // barcode.Draw(filename, ImageType.Jpg);

 // but we want a constant bitmap size,
 // which fits exactly into your predefined space

 Size finalSize = new Size(350, 200); // final bitmap size in Pixel

 // so we have to add empty spaces around the symbol via adding a quiet zone
 barcode.QuietZoneUnit = QuietZoneUnit.Pixel;

 // calculate the required empty quiet zone we have to add

if (finalSize.Width > optimalSize.Width)
  barcode.QuietZoneRight = finalSize.Width - optimalSize.Width;
else
  // should not occur!! Reduce the Pdf417.NumberOfColumns
  finalSize.Width = optimalSize.Width;
            
if (finalSize.Height > optimalSize.Height)
  barcode.QuietZoneBottom = finalSize.Height - optimalSize.Height;
else
  // should not occur!! Increase final bitmap size
  finalSize.Height = optimalSize.Height;

barcode.BoundingRectangle = new Rectangle(0, 0, finalSize.Width, finalSize.Height);
barcode.Draw(filename, ImageType.Jpg);

How Can I Optimize PDF417 Symbols in my ASP.NET Web Control?

Option #1

Add the following attributes to your TBarCode .NET Web Control. This will generate an optimized symbol, which fits into a 120 x 120 pixel matrix. Increase both the Width/Height and the NumberOfColumns attribute if required.

<cc2:BarcodeControl id="BarcodeControl1"
  Width="120" Height="120"
  Barcode-Dpi="96" 
  Barcode-SizeMode="MinimalModuleWidth" 
  Barcode-Pdf417-NumberOfColumns="3"                        
  Barcode-MustFit="True" ErrorHandling="ShowMessage" 
  Barcode-BarcodeType="Pdf417" 

Option #2

In the Page Load event or after you have set the bar code data apply the following calculation. This code will use width/height ratio of 1:3 for the graphical modules.

Barcode barcode = BarcodeControl1.Barcode;
barcode.SizeMode = SizeMode.FitToBoundingRectangle;  
System.Drawing.Size optimalSize = barcode.CalculateOptimalBitmapSize(null, 1, 1);

BarcodeControl1.Width = new Unit(optimalSize.Width, UnitType.Pixel);
BarcodeControl1.Height = new Unit(optimalSize.Height, UnitType.Pixel);  

BarcodeControl1.Refresh();

How Can I Create a Readable Code 39 Bitmap?

The following sample code in ASP .NET generates a Code 39 image.

//Code 39
Barcode barcode = new Barcode();
barcode.Data = "10030000007611107871900002199908";
barcode.BarcodeType = BarcodeType.Code39;

// with dpi = 100 we get 1 Pixel = 0.254 mms
barcode.Dpi = 100;

// bar code size should adapt to bounding rectangle
barcode.SizeMode = SizeMode.FitToBoundingRectangle;

// set default size of symbol (define the default height)
barcode.BoundingRectangle = new Rectangle(0, 0, 254, 100 /* = 1 inch */);
                
// now calculate optimal bitmap size for the bar code
Size optimalSize = barcode.CalculateOptimalBitmapSize(null, 1, 1);

// update rectangle to optimized size
barcode.BoundingRectangle  = new Rectangle(0, 0, optimalSize.Width, optimalSize.Height);
barcode.Draw(filename, ImageType.Jpg);

How Can I Create a Bitmap with a Specific Bar Height?

The following sample code shows you how to create a bitmap with a particular bar height for EAN 13 (can be changed to other linear barcode types).

double dpi = 300;
double barHeightinMM = 23;
double symbolHeightinMM = 26;
double nominalNarrowBarWidthinMM = 0.33;

Graphics gfx = this.CreateGraphics(); // graphics of any screen DC

Barcode ean13 = new Barcode();
ean13.BarcodeType = BarcodeType.Ean13;
ean13.Data = "123456789012";
ean13.Dpi = dpi;

// 1 Pixel in mm
double PxtoMm = 25.4 / dpi; 

// how many Pixels are 0.33 mm => We have to round depending on DPI
int narrowBarinPx = (int) Math.Round (nominalNarrowBarWidthinMM / PxtoMm);
double narrowBarinMM = narrowBarinPx * PxtoMm;
System.Diagnostics.Debug.WriteLine("Narrow bar width in mm (rounded to full Pixels): " + narrowBarinMM);

// calculate width in pixels by using the number of "modules" in the barcode
int symbolWidthinPixels = ean13.CalculateNumberOfModules() * narrowBarinPx;

// set font size to an automatic size based upon module width
double fontSizePt = 10 * Math.Round(narrowBarinMM, 3) / 0.339;
ean13.Font = new Font("Consolas", (float) fontSizePt);

// Case A: desired bar height is 23 mm
{
    int barHeightinPx = (int) Math.Round(barHeightinMM / PxtoMm, 0);
    System.Diagnostics.Debug.WriteLine("Bar height in Pixels : " + barHeightinPx);

    // calculate actual text area height
    float textAreaHeightMM = ean13.CalculateTextAreaHeight(null);
    int textAreaHeightPx = (int) (0.5 + textAreaHeightMM / PxtoMm);
    System.Diagnostics.Debug.WriteLine("Text height in Pixels: " + textAreaHeightPx);

    int symbolHeightinPx = barHeightinPx + textAreaHeightPx;

     // set bounding rectangle in Pixels
    ean13.BoundingRectangle = new Rectangle(0,0, symbolWidthinPixels, symbolHeightinPx);

    // Draw directly to bitmap file
    ean13.Draw(AppDomain.CurrentDomain.BaseDirectory + @"\EAN13-caseA.BMP", ImageType.Bmp, gfx, 1);

    // Draw to Picture Box

    // Option A
    // scale font depending on DPI ratio (required if internal DC is used)
    ean13.FontHeight = (int) (fontSizePt * dpi / gfx.DpiY);
    pictureBoxEAN13.Image = ean13.DrawBitmap();

    // Option B
    // ignore DC resolution + use Pt font size
    ean13.IgnoreDpiFromDC = true;
    ean13.FontHeight = (int) fontSizePt;
    pictureBoxEAN13.Image = ean13.DrawBitmap();
}

// Case B: desired symbol height (incl. text) is 26 mm
{
    int symbolHeightinPx = (int) Math.Round (symbolHeightinMM / PxtoMm, 0);
    System.Diagnostics.Debug.WriteLine("Symbol height in Pixels : " + symbolHeightinPx);

     // set bounding rectangle in Pixels
    ean13.BoundingRectangle = new Rectangle(0, 0, symbolWidthinPixels, symbolHeightinPx);

    // Draw directly to bitmap file
    ean13.Draw(AppDomain.CurrentDomain.BaseDirectory + @"\EAN13-caseB.BMP", ImageType.Bmp, gfx, 1);
}

DrawBitmap Creates a Very Small Font Size

If you want to create a high resolution bitmap (DPI >= 300), you may encounter a very small font size of the HRT in the resulting bitmap.

The following C# sample code demonstrates the influence of the screen DC (96 dpi) when you use DrawBitmap(). You can solve this issue either by using the Draw() export function or with IgnoreDPIFromDC.

Barcode code128 = new Barcode();
code128.BarcodeType = BarcodeType.Code128;
code128.Data = "HELLO";
code128.Dpi = 600;

code128.BoundingRectangle = new Rectangle(0, 0, code128.CalculateNumberOfModules() * 6, 600); // one module = 6 Pixel
code128.Draw(@"C:\temp\Draw-OK.bmp", ImageType.Bmp); // HRT is scaled correctly

Bitmap test1 = code128.DrawBitmap();
test1.Save(@"C:\temp\DrawBitmap-NOK.bmp"); // HRT is very small (scaled to 96 dpi screen resolution instead of 600)

code128.IgnoreDpiFromDC = true;
Bitmap test2 = code128.DrawBitmap();
test2.Save(@"C:\temp\DrawBitmap-OK.bmp"); // HRT is scaled to 600 dpi (Screen DC is ignored).

How Can I Add Additional Text to the Control?

This is possible by changing the active text index programmatically. The following sample code assumes a Barcode Control, which is drawn on a Graphics (gfx) in Pixel units and shows how to add additional text on the right side.

Barcode tbc = barcodeControl1.Barcode;

Graphics gfx = this.CreateGraphics();
SizeF barcodeSizeMM = tbc.CalculateBarcodeSize(gfx);
double pixelSizeMM = 25.4F / gfx.DpiX;
int barcodeWidthPx = Convert.ToInt32(0.5 + barcodeSizeMM.Width / pixelSizeMM);
int barcodeHeightPx = Convert.ToInt32(0.5 + barcodeSizeMM.Height / pixelSizeMM);

// first add a quiet zone for our text area
tbc.QuietZones.Right.Size = 100;
tbc.QuietZones.Unit = QuietZoneUnit.Pixel;

// set barcode data (+ normal HRT) in text area #0
tbc.ActiveTextIndex = 0;
tbc.BarcodeType = BarcodeType.Code128;
tbc.Data = "1234567890";
tbc.IsTextVisible = false;

// change text index to (auxiliary) text area #1
tbc.ActiveTextIndex = 1;

// now adjust all settings for text area #1
tbc.HumanReadableText ="My Label Text";
tbc.Font = new Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point);
tbc.TextClipping = false;
tbc.IsTextVisible = true;
tbc.TextPositionTop = (barcodeHeightPx - (int) tbc.Font.GetHeight(gfx)) / 2 ;
tbc.TextPositionLeft = barcodeWidthPx - (int)tbc.QuietZones.Right.Size + 10;

// reset text index back to barcode text
tbc.ActiveTextIndex = 0;

The text area #1 can be set to any text, but also to your bar code data. You have to take care on the dimensions and need to center / align the text with your own coordinates.

How Can I Create a 26x26 Data Matrix for DP Premiumadress?

The following sample code for C# .NET shows you how to adjust the settings for Data Matrix:

Barcode barcode = new TECIT.TBarCode.Barcode();
      
barcode.BarcodeType = BarcodeType.DataMatrix;
barcode.DataMatrix.Size = DataMatrixSize.Square26x26;
barcode.DataMatrix.Format = DataMatrixFormat.Default;
barcode.DataMatrix.ShallEnforceBinaryEncoding = true;

barcode.SizeMode = SizeMode.CustomModuleWidth;
barcode.ModuleWidth = 0.423;

barcode.EncodingMode = EncodingMode.Hexadecimal;
// set preformatted data (Bytes = Hex codes)
barcode.Data = "444541080D02540BE3FF0052232D242D000065000000010100015A313031000000000000000000000000";

How Can I Create a Data Matrix with 1BPP and 1200 DPI?

The following sample code for C# .NET shows you how to create a TIFF with 1 bpp (B/W) and 1200 dpi.

Barcode barcode = new TECIT.TBarCode.Barcode();
//barcode.License(…)
barcode.BarcodeType = BarcodeType.DataMatrix;
barcode.Dpi = -1;  // Use DPI from screen DC
barcode.SizeMode = SizeMode.FitToBoundingRectangle;
barcode.Data = "TEST 1234";

float dpi = 1200;
int nScale = 12; // 1 Dot = 12 Pixel  (at 1200 dpi, this is 0.254 mm)
// Calculate bounding rectangle using a scaled module width adapted to Pixel boundaries
Size sizePx = barcode.CalculateOptimalBitmapSize(null, nScale, nScale);
barcode.BoundingRectangleF = new RectangleF(0, 0, sizePx.Width, sizePx.Height);

Bitmap myBarcode = barcode.DrawBitmap();
//myBarcode.SetResolution(dpi, dpi);
//myBarcode.Save("c:\\temp\\ExportedFile.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Bitmap converted = myBarcode.Clone(new Rectangle(0, 0, myBarcode.Width, myBarcode.Height), System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
converted.SetResolution(dpi, dpi);
converted.Save("c:\\temp\\ExportedFile.tif", System.Drawing.Imaging.ImageFormat.Tiff);

How Can I Create a 2D Mailmark Type 7?

The following sample code for VB .NET shows you how to adjust the settings for 2D Mailmark Type 7 bitmap file:

' 2D Mailmark Type 7 - 24x24 matrix size
' Module size 0.508 mm (300 dpi), total size 12.2 x 12.2 mm

Dim myBarcode As New TECIT.TBarCode.Barcode
myBarcode.BarcodeType = TECIT.TBarCode.BarcodeType.Mailmark_2D
myBarcode.DataMatrix.Size = TECIT.TBarCode.DataMatrixSize.Square24x24

myBarcode.SizeMode = TECIT.TBarCode.SizeMode.CustomModuleWidth
myBarcode.ModuleWidth = 0.508F
myBarcode.Dpi = 300

myBarcode.Data = "JGB 012100123412345678AB19XY1A 0             123456"

' retrieve final size in [mm]
Dim finalSizeMM As SizeF
finalSizeMM = myBarcode.CalculateBarcodeSize(Nothing) ' will return [mm]

Dim widthPx As Integer
Dim heightPx As Integer

' convert to Pixel
widthPx = finalSizeMM.Width * myBarcode.Dpi / 25.4
heightPx = finalSizeMM.Height * myBarcode.Dpi / 25.4

' adjust bitmap size and save as BMP
myBarcode.BoundingRectangleF = New RectangleF(0, 0, widthPx, heightPx)
myBarcode.Draw("C:\temp\2DMailmark.bmp", TECIT.TBarCode.ImageType.Bmp)

How to Convert an Image to Base64?

This can be realized by creating a byte array and then converting it to Base64 encoding:

public Byte[] GenerateBarcodeStream2D(String data)
{
  TECIT.TBarCode.Barcode barcode = new TECIT.TBarCode.Barcode();
  barcode.BarcodeType = TECIT.TBarCode.BarcodeType.DataMatrix;
  barcode.Data = data;
  barcode.Dpi = 100;
  Size optimalSize = barcode.CalculateOptimalBitmapSize(null, 2, 2);
  barcode.BoundingRectangle = new Rectangle(0, 0, optimalSize.Width, optimalSize.Height);
  using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
  {
    Bitmap bitmap = barcode.DrawBitmap();
    bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    /* 
     * // or save as 24 bit JPG
     *  ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(codec => codec.FormatID.Equals(ImageFormat.Jpeg.Guid)).FirstOrDefault(); 
     *  System.Drawing.Imaging.EncoderParameters parameters = new System.Drawing.Imaging.EncoderParameters(); 
     *  parameters.Param[0] = new EncoderParameter (System.Drawing.Imaging.Encoder.ColorDepth, 24); 
     *  bitmap.Save(ms, jpgCodec, parameters);
    */
    ms.Position = 0; 
    return ms.ToArray();
  }
}

Once you created the Byte array you can convert the array to Base64. For embedding the image into html, prefix the image with the mime type:

Byte[] barcodeImageStream = GenerateBarcodeStream2D ("12345"); 
String myBase64Barcode = Convert.ToBase64String(barcodeImageStream);
String imgSrc = "data:image/png;base64, " + myBase64Barcode;

How To Create a Linear Barcode in C/AL (Dynamics NAV)?

Import the Assemblies in dotnet.al:

dotnet
{
  assembly(TECIT.TBarCode)
  {
    type(TECIT.TBarCode.Barcode; barcode) { }
    type(TECIT.TBarCode.BarcodeType; barcodeType) { }
    type(TECIT.TBarCode.CodePage; codePage) { }
    type(TECIT.TBarCode.CheckdigitMethod; checkDigitMethod) { }
  }
  assembly(System.Drawing)
  {
    type(System.Drawing.Rectangle; barcodeRectangle) { }
    type(System.Drawing.Bitmap; barcodeBitmap) { }
  }
}

Use them as follows:

  barcode := barcode.Barcode;
  //barcode.License(your license data);

  barcode.BarcodeType := barcodeType.Code128;
  barcode.Dpi := 300;
  barcode.Data := yourDataToEncode;
  // barcode.TranslateEscapeSequences := TRUE; // optional

  // calculate optimal width in Pixel with scaling factor (1 Module = 3 Pixels)
  optimalWidthPx := 3 * barcode.CalculateNumberOfModules();
  // set optimal width for the bitmap (works for linear codes)
  barcode.BoundingRectangle := barcodeRectangle.Rectangle(0, 0, optimalWidthPx, 300);  

  FileNameBmp := Filemanagement.ServerTempFileName('bmp');
  barcode.Draw(FileNameBmp, 0);  // save as BMP format (0 = BMP)

Click here for more information: Call .NET Framework Types From C/AL Code in Dynamics NAV

Example function for Nav 2017

This function returns a BMP image in a TempBlob record:

PROCEDURE CreateCode128 (Data2Encode : Text[100]; ScaleX: Integer, HeightPx : Integer; VAR TempBlob : TEMPORARY Record 99008535);
VAR
  barcode : DotNet "'TECIT.TBarCode, Version=11.10.0.0, Culture=neutral, PublicKeyToken=1b5f4306b234b83d'.TECIT.TBarCode.Barcode";
  bctype : DotNet "'TECIT.TBarCode, Version=11.10.0.0, Culture=neutral, PublicKeyToken=1b5f4306b234b83d'.TECIT.TBarCode.BarcodeType";
  rectangle : DotNet "'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Drawing.Rectangle";
  widthPx : Integer;
BEGIN
  FileNameBmp := FileManagement.ServerTempFileName('bmp');

  barcode := barcode.Barcode;
  //barcode.License(your license data);

  barcode.BarcodeType := bctype.Code128;
  barcode.Dpi := 300;
  barcode.Data := Data2Encode;
  // barcode.TranslateEscapeSequences := TRUE; // optional

  // calculate optimal width in Pixel with scaling factor (ScaleX =3 -> 1 Module = 3 Pixels)
  widthPx := ScaleX * barcode.CalculateNumberOfModules();
  // set optimal width for the bitmap (works for linear codes)
  barcode.BoundingRectangle := rectangle.Rectangle(0, 0, widthPx, HeightPx);
  barcode.Draw(FileNameBmp, 0);  // save as BMP format (0 = BMP)

  CLEAR(TempBlob);
  IF TempBlob.INSERT THEN;
  FileManagement.BLOBImportFromServerFile(TempBlob, FileNameBmp);
  TempBlob.MODIFY;
END;

2D Code

For a 2D Matrix Code change the size calculation as follows:

  widthPx := Scale * barcode.CalculateXColumnsOf2DBarcode ();
  heightPx := Scale * barcode.CalculateXRowsOf2DBarcode ();
  barcode.BoundingRectangle := rectangle.Rectangle(0, 0, widthPx, heightPx);
  • Scale is a factor that determines how many pixels a matrix point in the QR code should consist of.
  • A module width of 0.423 mm is achieved with 300 dpi and Scale=5. A module width of 0.381 mm is achieved with 600 dpi and Scale=9.
  • If necessary, the matrix can be fixed to a specific QR code version (but then the capacity would also be limited).
  • If UTF-8 is required as encoding (instead of Latin-1), you can set the code page in the barcode to UTF-8 (must be supported by the reader!):barcode.CodePage := codePage.Utf_8;

How Can I Use TBarCode .NET within Powershell?

You can use TBarCode .NET within Microsoft PowerShell like any other .NET class. Below is a sample with default bar code type (Code-128):

Add-Type -Path 'C:\Program Files\Common Files\TEC-IT\TBarCode\11.15\TECIT.TBarCode.dll'
$tbc = New-Object -TypeName TECIT.TBarCode.Barcode
$tbc.Data="12345"
$tbc.BoundingRectangle = New-Object -TypeName System.Drawing.Rectangle (0, 0, 138, 75) 
$tbc.Draw('c:\\temp\\test.bmp', [TECIT.TBarCode.ImageType]::Bmp)
$tbc.CopyToClipboard(138, 75)
For saving bitmaps, the code above can be extended with the CalculateNumberOfModules function to determine the optimal bitmap width. For static size bar codes (like EAN 13 P2) you can use a precalculated size.

Why I See a Different Font in EPS and AI Export?

TBarCode SDK does not embed the fonts into EPS and AI. It just references the font by specifying the font name. So it depends on the output device or graphics suite if the font is available and how the font is rendered.

For EPS only font names which are standard in PostScript or font names, which do not contain any blanks/spaces in the referenced font name are allowed.

Helvetica is a standard PostScript font but it may not be included in Illustrator (Helvetica Font missing in Illustrator).

EPS: In order to avoid problems on printers, which do not have Arial installed, we convert references to Arial always to Helvetica, which looks similar and is a standard PS font (available in all printers). If this is not desired, you have an option, which controls if there is a font replacement applied or not. This is the UseDeviceFonts option.

Here is sample code for EAN13 SC2 – 100%:

Export to EPS with Standard Postscript Fonts (Arial ⇒ Helvetica)

Barcode barcode = new Barcode();
barcode.BarcodeType = BarcodeType.Ean13;

barcode.BoundingRectangleF = new RectangleF(0, 0, 37.29F, 25.91F); // SC2 size
barcode.SizeMode = SizeMode.CustomModuleWidth;
barcode.ModuleWidth = 0.330F; // SC2 module width

barcode.Data = "123456789012";
barcode.Font = new Font("Arial", 9);
barcode.UseDeviceFonts = true;

barcode.Draw("c:\\temp\\TestFile.eps", ImageType.Eps);
barcode.Draw("c:\\temp\\TestFile.ai", ImageType.Ai);

If you open the exported EPS file with a text editor, you see Helvetica instead of Arial:

/Helvetica findfont
9.0000 scalefont setfont

This is how it looks if you open the EPS file with a PostScript viewer (like GSView):

EPS Barcode Export

If you open the exported AI file with a text editor, you see:

%%IncludeResource: font ArialMT
%AI3_BeginEncoding: _ArialMT ArialMT
[/_ArialMT/ArialMT 0 0 1 TZ
For AI export we use ArialMT as standard font (if Arial has been adjusted).

Export to EPS and Keep the Adjusted Font (Arial ⇒ Arial)

The printer or the graphics software must support “Arial”! Font names must not contain blanks/spaces!

Barcode barcode = new Barcode();
barcode.BarcodeType = BarcodeType.Ean13;

barcode.BoundingRectangleF = new RectangleF(0, 0, 37.29F, 25.91F);
barcode.SizeMode = SizeMode.CustomModuleWidth;
barcode.ModuleWidth = 0.330F;

barcode.Data = "123456789012";
barcode.Font = new Font("Arial", 9);
barcode.UseDeviceFonts = false;

barcode.Draw("c:\\temp\\TestFile.eps", ImageType.Eps);
barcode.Draw("c:\\temp\\TestFile.ai", ImageType.Ai);

If you open the exported EPS file with a text editor, you see:

/Arial findfont
9.0000 scalefont setfont

If you open the exported AI file with a text editor you see:

%%IncludeResource: font Arial
%AI3_BeginEncoding: _Arial Arial
[/_Arial/Arial 0 0 1 TZ

Summary

In order to use the adjusted font for the export, you can set UseDeviceFonts = false. It depends also what you want to do with the EPS file. If you want to send the file just “as is” to a printer or printing system, it is maybe better to use Helvetica with UseDeviceFonts = true. We recommend to try printing first before you make a decision about DeviceFonts.

PDF Export without HRT

For PDF export, there is no font rendering included in the TBarCode SDK - that is why you don’t get any font or text output if you chose PDF export format.

If you need PDF export with font embedding, you may use our TFORMer Label Printing SDK. The TFORMer SDK supports the same barcodes as the TBarCode SDK. Or - you can also use Barcode Studio in command line mode – you call BCStudio.exe from your own program code and pass the barcode data and file name to BCStudio (for the available command line parameters see the BCStudio user manual). Alternatively - if you want to use PDF libraries from third party vendors, you may use the Callback drawing mechanism of TBarCode SDK – here you get the coordinates of the bars and of the text and with these coordinates you implement the barcode with the drawing and font / text rendering functions of the PDF library. Samples for how to use the Callback drawing are included in the SDK.

Deployment Issues and Library Dependencies

The TBarCode SDK installs these two libraries:

32-bit: C:\Program Files (x86)\Common Files\TEC-IT\TBarCode\11.15
64-bit: C:\Program Files\Common Files\TEC-IT\TBarCode\11.15

The .NET Library "TECIT.TBarCode.dll" is also installed into the Global Assembly Cache (GAC), so they are always available system wide. When loading it automatically switches from 32 to 64 bit depending on the process - this has advantages.

The TECIT.TBarCode.dll wants to reload certain DLLs (the TBarCode11.dll / TBarCode11_x64.dll) - the Lib Loader finds these either in the same directory or via the PATH variable, which points to the above path in the Common Files directory. Directly after the SDK installation a server reboot or service restart may be necessary, some services (IIS) read the PATH variable only at startup.

During development, Visual Studio compilations often start in the debugger as 32 bit processes, but server processes usually run as 64 bit.

The TBarCode Library needs the Visual Studio Runtime (version dependent), which can be deployed also from here.

SQL Server Deployment

What makes it sometimes tricky are the security features of SQL Server. You can only see what exactly is missing during deployment. In most cases it does not load external DLLs or does not allow file access to reload the other DLLs we need. You have to copy all DLLs (TBarCode*.dll) into a specific SQL Server directory and allow file access in the rssrvpolicy.config file (Full Trust) - see links:

If you don’t want to deal with DLL security issues, there is an alternative: You can move the bar code generator into a separate barcode web service and load the bar codes during report runtime 'on-the-fly' from an URL. We deliver the bar code web service with the TBarCode SDK and also a guide how to install and use it:

C:\ProgramData\TEC-IT\TBarCode\11.15\Examples\Visual Studio .NET\Barcode Service

Bad Image Format Exception After Deployment of a Web Application

The following applies to TBarCode .NET versions before 11.15.

You get a System.BadImageFormatException (an attempt was made to load a program with an incorrect format) after you have deployed your ASP. NET project to your IIS web server. During development there was no such problem.

Reason: Visual Studio is a 32 Bit application and the development server usually runs as 32 Bit process. Therefore the 32 Bit version of TECIT.TBarCode.DLL has been embedded into your project and is now part of your ./bin folder. But your IIS runs the worker thread as 64 Bit process and now loads the wrong format.

Option #1: Deploy the 64-Bit version of the Assembly

Use the version from the C:\Program Files\Common Files\TEC-IT\TBarCode\[version] folder (this is the x64 version). Exchange the ../bin/TECIT.TBarCode.dll file on your target system with that version.

Option #2: Let the GAC do the work

Remove the TECIT.TBarCode.dll completely from your bin folder. In that case the TECIT.TBarCode.dll from the global assembly cache (GAC) will be loaded. The common language runtime loads the correct version automatically because the GAC holds both versions, 32 and 64 Bit. Prerequisite: The setup of TBarCode SDK must be executed on the target server, the setup installs the DLLs in the GAC for you.

If you don't see an effect immediately, restart your application pool or perform an "iisreset" on the command line (take care, this restarts ALL and sessions will be lost).

Bad Image Format Exception After Deployment of a Desktop Application

The following applies to TBarCode .NET versions before 11.15.

You get the following exception after you have deployed your Windows Desktop application.

System.BadImageFormatException: Could not load file or assembly 'TECIT.TBarCode, Version=11.10.0.0, Culture=neutral, PublicKeyToken=1b5f4306b234b83d' or one of its dependencies. An attempt was made to load a program with an incorrect format.

Reason for the problem: During development you referenced the 32 bit version of the DLL. Now at deployment, the EXE is executed as 64 bit process and cannot load the TECIT.TBarCode.dll (which is 32 bit).

Background information:

Because of loading native libraries, the TECIT.TBarCode.dll is platform specific and not marked as CPU=Any. On the development computer you usually execute the program as 32 bit process, because Visual Studio is a 32 bit application. But also if the process runs as 64 bit (either with CPU=Any or CPU=x64) it still can load the required DLLs from the GAC and from the program files/common files folder. Our setup installs both versions (32 bit + 64 bit) and extends also the search path. So it will always find the DLLs.

Then when moving to the target system, because of managed code, the executable can run either as 32 bit or 64 bit. In some cases the process cannot find the correct DLLs because it switches from 32 to 64 bit automatically, or the DLLs are not in the search path or GAC or just not installed.

Our DLL is a combination of managed code and native precompiled DLLs, so you have to decide if it should run as 32 bit or 64 bit. This decision must be made at compile time when you build the target platform (x86 or x64). If you want to use target CPU=Any, you have to install all DLLs into the GAC (done by our setup). This makes sure that both versions, x86 (32 bit) and x64 (64 bit) are available in parallel.

Proceed as follows – chose one of the options below:

Build your EXE with target CPU x86

Reference the TECIT.TBarcode.dll in the “C:\Program Files (x86)\Common Files\TEC-IT\TBarCode\11*” folder and copy the TECIT.TBarcode.dll + TBarCode11.dll + zlib1.dll to your deployment folder. The zlib1.dll is only needed if you use gzip compression with 2D codes. Install the x86 VCRedist from Microsoft (2015 U3 RC or the newer 2015-2019 edition).

Build your EXE with target CPU x64 (64 bit)

Reference the TECIT.TBarcode.dll in the “C:\Program Files\Common Files\TEC-IT\TBarCode\11*” folder and copy the TECIT.TBarcode.dll + TBarCode11_x64.dll + zlib1.dll to your deployment folder. The zlib1.dll is only needed if you use gzip compression with 2D codes. Install the x64 VCRedist from Microsoft (2015 U3 RC or the newer 2015-2019 edition).

Build your EXE with target CPU Any

For programming, reference the TECIT.TBarcode.dll in the “C:\Program Files (x86)\Common Files\TEC-IT\TBarCode\11*” folder. For deployment don’t copy any TEC-IT DLLs along with your EXE. Remove the TECIT.TBarCode.dll from your deployment folder. Instead install the TBarCode SDK Setup and select only the TBarCode .NET component from the features list – this will install x86 and x64 versions parallel into the GAC and extends the PATH variable with the DLL path. The TBarCode Assembly will be loaded automatically in the correct version because it is in the GAC for 32 and 64 bit. If you don’t want to execute the TBarCode Setup manually, it can be also automated by applying command line switches (silent setup). Install both the x86 and x64 VCRedist from Microsoft (2015-2019 edition).

Error "Catastrophic Failure" During Licensing

On specific systems (e.g. W2012R2, IIS8.5) you may encounter an error if you apply the license key immediately after creating an instance of the bar code object. This occurs because the underlying (native) TBarCode DLL has not been initialized at this point - possibly due to delayed loading of dependency DLLs or another timing issue.

As a workaround try to set any property before applying the license - see below:

TECIT.TBarCode.Barcode oBC = new TECIT.TBarCode.Barcode();
oBC.BarcodeType = TECIT.TBarCode.BarcodeType.Code128; // set a property of the object
oBC.License("Licensee", TECIT.TBarCode.LicenseType.DeveloperOrWeb, 1, "Key", TECIT.TBarCode.TBarCodeProduct.Barcode2D);

Lack of Barcode After Deployment to Microsoft Azure

TBarCode employs Windows GDI API calls for drawing lines and rendering text output. However, a problem arises on Azure due to the Web App sandbox's blocking of GDI. This blockage is implemented for security reasons, as Microsoft restricts calls to the video/screen driver owing to security concerns. Consequently, the barcode is either drawn in a fragmented manner or is entirely absent. The complete functionality of GDI functions is only achievable with a server hosted on-premise.

Solution: Utilize the Custom Drawing Callback interface as an alternative to GDI API calls.

  • Download the QR Code Web App Sample for .NET 6 (see folder ASPNETCoreWebApp).
  • Refer to BarcodeController.cs: GetQRCodeImgNoGDI, which utilizes .NET functions through the Callback interface to draw the barcode. This method is suitable for Azure Services where GDI is inaccessible.
  • If you are utilizing the SDK's precompiled Barcode Service (WebDeploy package), update to the latest version and set the UseGDI=false parameter.

Callback drawing is not operational in demo mode. Kindly request a temporary license from sales@tec-it.com. You can implement the licensing in the constructor of BarcodeNoGDI or license through a barcode.ini file.

Issues with Font Size on Azure

If your intention involves creating a linear barcode with human-readable text, text output via the Callback interface is also necessary (code is included in the ASP.NET Core sample linked above). Sometimes we saw an unwanted font scaling on Azure, in this case you have to use a font, which is installed and set the size.

barcode.Font = new System.Drawing.Font("Microsoft Sans Serif", 10, System.Drawing.FontStyle.Regular, GraphicsUnit.Point);
barcode.Font = new System.Drawing.Font("Microsoft Sans Serif", 12, System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel);

Performance: Caching Barcode Images in ASP.NET Applications

File Based Caching

The CacheDirectory property only accepts virtual paths from the web server. It is not possible to use a physical path such as c:\temp. Temporary barcode images should be created within the local (virtual) application directory (where you can find the *.aspx files) or in a subdirectory.

Cache="Harddisk" 
CacheDirectory="." or CacheDirectory="barcodefiles"

Memory Based Caching

With the following setting all barcode images will be stored in the web server's cache memory:

Cache="Memory"

In order to use memory caching you must include a custom HTTP handler BarcodeHttpHandler in the <httpHandlers> section of your web.config file (you might need to create this section first, if it does not exist). It should look similar to this:

 <system.web>
  ...
  <httpHandlers>
    ...
    <add verb="GET" path="BarcodeHttpHandler.axd" 
               type="TECIT.TBarCode.Web.BarcodeHttpHandler,
               TECIT.TBarCode, 
               Version=9.0.1.0, Culture=neutral, 
               PublicKeyToken=1B5F4306B234B83D" />
    ...
  </httpHandlers>
  ...
 </system.web>

Based on the example shown above, you probably need to change the version number depending on your package. Under c:\windows\assembly, look for TECIT.TBarCode to find the correct version.

If you need more detailed instructions go to:

> Start Menu > TEC-IT TBarCode 9.0 > Developer Manuals >TBarCode .NET Developer Reference (BarcodeHttpHandler Class)

Using TBarCode ASP.NET in Web Farms (IIS 7.0)

If you use TBarCode ASP.NET Web Control in a Web Farm you may encounter the following exception:

Exception Type: System.ApplicationException
Message: The requested image is no longer cached.

The TBarCode .NET Web Control uses the HttpContext.Cache object to store the generated barcode image. Since http requests are load balanced within a web farm it can occur that a specific Web Control receives a request for an image, which has been generated on a different application server (and therefore is not available in its local cache).

To overcome this problem you could

  • Synchronize the HttpContext.Cache object on all servers in the web farm (="distributed caches"). This could be done with extra programming or additional third party software.
  • or simply use Client Affinity in IIS 7.0 (recommended)

Having client affinity enabled all requests are tagged with a cookie so that subsequent requests (from the same client) are routed to the same server in the web farm.

See Application Request Routing (Step 3 – Configure client affinity)

Application Request Routing provides a client affinity feature that maps a client to a content server behind Application Request Routing for the duration of a client session. When this feature is enabled, the load balancing algorithm is applied only for the very first request from the client.