PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Sat Nov 25, 2017 2:06 am

All times are UTC




Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: Barcode 128
PostPosted: Mon Mar 08, 2010 6:02 pm 
Offline

Joined: Mon Mar 08, 2010 5:46 pm
Posts: 5
I've been using your product and it's great. I was very impressed that you even included bar code capabilities which is what I was looking for. Up until recently, all I needed was 3 of 9 capabilities. Now, However, I need to be able to use a barcode that handles upper case, lower case, numeric, and some of the basic symbols (+(plus sign) and /(slash)). I believe what I would need is barcode 128. Is there any plans to add this in the near future or do you know a way I can incorporate this into the product.

With a little direction, I might be able to code it myself and I would be more than happy to share it so it could be included in a future release.

In the PdfSharp project under PdfSharp.Drawing.BarCodes, there's a missing text document: @BarCodes.txt. Is there any information in there that would help me move forward with my project? If so, could I be sent a copy of it?


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Tue Mar 09, 2010 12:15 pm 
Offline
empira Employee
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 2735
Location: Cologne, Germany
Hi!

Forget @BarCodes.txt - that's our TODO list.

I don't know how the PDFsharp barcodes are implemented.

Since there are three or four implementations already, it shouldn't be too difficult to add a new type.

Good luck if you try!
I'm afraid I can't tell you where to start and how to do it.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Mon Mar 15, 2010 7:40 pm 
Offline

Joined: Mon Mar 08, 2010 5:46 pm
Posts: 5
Here's my Code 128 implementation. I don't guarentee that all works perfectly, but it does work for my needs. I am using Code-B and it appears to be working.

The only changes that are needed is to add the following into the file: BcgSR.cs found in the PdfSharp.Drawing.BarCodes folder.

internal static string InvalidCode128(int code)
{
return String.Format("Contains an valid character for bar code 128 at index: {0}.", code);
}


Then add a new class into the same folder. I named mine Code128.cs. Replace the contents with the following:

using System;
using System.Collections.Generic;
using System.Text;

using PdfSharp.Drawing;
using PdfSharp.Drawing.BarCodes;

namespace PdfSharp.Drawing.BarCodes
{
/// <summary>A Class to be able to render a Code 128 bar code</summary>
/// <remarks>For a more detailed explanation of the Code 128, please visit the following
/// web site: http://www.barcodeman.com/info/c128.php3
/// or
/// http://www.adams1.com/128code.html
/// </remarks>
public class Code128 : BarCode
{
/// <summary>A static place holder for the patterns to draw the code 128 barcode</summary>
public static Dictionary<Byte, Byte[]> Patterns = null;
private Code_128_Code_Types Code128Code = Code_128_Code_Types.CodeB;
private Byte[] Values = null;
private const int CODE128_STOPCODE = 106;

/// <summary>Constructor</summary>
/// <param name="text">String - The text to be coded</param>
/// <param name="size">XSize - The size of the bar code</param>
/// <param name="direction">CodeDirection - Indicates the direction to draw the bar code</param>
public Code128(string text, XSize size, CodeDirection direction)
: this(text, size, direction, Code_128_Code_Types.CodeB)
{
}

/// <summary>Constructor</summary>
/// <param name="text">String - The text to be coded</param>
/// <param name="size">XSize - The size of the bar code</param>
/// <param name="direction">CodeDirection - Indicates the direction to draw the bar code</param>
/// <param name="code128Code">Code_128_Code_Types - Indicates which of the codes to use when rendering the bar code.
/// The options are A, B, or buffer.</param>
public Code128(string text, XSize size, CodeDirection direction, Code_128_Code_Types code128Code)
: this((byte[])null, size, direction, code128Code)
{
this.Text = text;


// Create the array to hold the values to be rendered
if (Code128Code == Code_128_Code_Types.CodeC)
{
// Ensure that the text is an even length
if ((text.Length % 2) == 1) throw new ArgumentOutOfRangeException("Parameter text (string) must have an even length for Code 128 - Code C");
Values = new byte[text.Length / 2];
}
else
{
Values = new byte[text.Length];
}


String buffer = "";
for (int x = 0; x < text.Length; x++)
{
switch (Code128Code)
{
case Code_128_Code_Types.CodeA:
if (text[x] < 32)
{
Values[x] = (byte)(text[x] + 64);
}
else if ((text[x] >= 32) && (text[x] < 64))
{
Values[x] = (byte)(text[x] - 32);
}
else
{
Values[x] = (byte)text[x];
}
break;

case Code_128_Code_Types.CodeB:
Values[x] = (byte)(text[x] - 32);
break;

case Code_128_Code_Types.CodeC:
if ((text[x] >= '0') && (text[x] <= '9'))
{
buffer += text[x];
if (buffer.Length == 2)
{
Values[x / 2] = byte.Parse(buffer);
buffer = "";
}
}
else
{
throw new ArgumentOutOfRangeException("Parameter text (string) can only contain numeric characters for Code 128 - Code C");
}
break;
}
}
CheckValues();
}


private void CheckValues()
{
if (Values == null) throw new InvalidOperationException("Text or Values must be set");
if (Values.Length == 0) throw new InvalidOperationException("Text or Values must have content");

for (int x = 0; x < Values.Length; x++)
{
if (Values[x] > 102) throw new ArgumentOutOfRangeException(BcgSR.InvalidCode128(x));
}
}

/// <summary>Constructor</summary>
/// <param name="values">byte[] - The values to be rendered</param>
/// <param name="size">XSize - The size of the bar code</param>
/// <param name="direction">CodeDirection - Indicates the direction to draw the bar code</param>
/// <param name="code128Code">Code_128_Code_Types - Indicates which of the codes to use when rendering the bar code.
/// The options are A, B, or buffer.</param>
public Code128(byte[] values, XSize size, CodeDirection direction, Code_128_Code_Types code128Code)
: base(null, size, direction)
{
if (!Enum.IsDefined(typeof(Code_128_Code_Types), code128Code)) throw new ArgumentOutOfRangeException("Parameter code128Code (Code_128_Code_Types) is invalid");
if (Patterns == null) Load();
Code128Code = code128Code;
Values = values;
}

/// <summary>Creates a new instance of the Patterns field and populates it with the appropriate
/// pattern to draw a code 128 bar code</summary>
private void Load()
{
Patterns = new Dictionary<byte, byte[]>();
Patterns.Add(0, new Byte[] { 2, 1, 2, 2, 2, 2 });
Patterns.Add(1, new Byte[] { 2, 2, 2, 1, 2, 2 });
Patterns.Add(2, new Byte[] { 2, 2, 2, 2, 2, 1 });
Patterns.Add(3, new Byte[] { 1, 2, 1, 2, 2, 3 });
Patterns.Add(4, new Byte[] { 1, 2, 1, 3, 2, 2 });
Patterns.Add(5, new Byte[] { 1, 3, 1, 2, 2, 2 });
Patterns.Add(6, new Byte[] { 1, 2, 2, 2, 1, 3 });
Patterns.Add(7, new Byte[] { 1, 2, 2, 3, 1, 2 });
Patterns.Add(8, new Byte[] { 1, 3, 2, 2, 1, 2 });
Patterns.Add(9, new Byte[] { 2, 2, 1, 2, 1, 3 });
Patterns.Add(10, new Byte[] { 2, 2, 1, 3, 1, 2 });
Patterns.Add(11, new Byte[] { 2, 3, 1, 2, 1, 2 });
Patterns.Add(12, new Byte[] { 1, 1, 2, 2, 3, 2 });
Patterns.Add(13, new Byte[] { 1, 2, 2, 1, 3, 2 });
Patterns.Add(14, new Byte[] { 1, 2, 2, 2, 3, 1 });
Patterns.Add(15, new Byte[] { 1, 1, 3, 2, 2, 2 });
Patterns.Add(16, new Byte[] { 1, 2, 3, 1, 2, 2 });
Patterns.Add(17, new Byte[] { 1, 2, 3, 2, 2, 1 });
Patterns.Add(18, new Byte[] { 2, 2, 3, 2, 1, 1 });
Patterns.Add(19, new Byte[] { 2, 2, 1, 1, 3, 2 });
Patterns.Add(20, new Byte[] { 2, 2, 1, 2, 3, 1 });
Patterns.Add(21, new Byte[] { 2, 1, 3, 2, 1, 2 });
Patterns.Add(22, new Byte[] { 2, 2, 3, 1, 1, 2 });
Patterns.Add(23, new Byte[] { 3, 1, 2, 1, 3, 1 });
Patterns.Add(24, new Byte[] { 3, 1, 1, 2, 2, 2 });
Patterns.Add(25, new Byte[] { 3, 2, 1, 1, 2, 2 });
Patterns.Add(26, new Byte[] { 3, 2, 1, 2, 2, 1 });
Patterns.Add(27, new Byte[] { 3, 1, 2, 2, 1, 2 });
Patterns.Add(28, new Byte[] { 3, 2, 2, 1, 1, 2 });
Patterns.Add(29, new Byte[] { 3, 2, 2, 2, 1, 1 });
Patterns.Add(30, new Byte[] { 2, 1, 2, 1, 2, 3 });
Patterns.Add(31, new Byte[] { 2, 1, 2, 3, 2, 1 });
Patterns.Add(32, new Byte[] { 2, 3, 2, 1, 2, 1 });
Patterns.Add(33, new Byte[] { 1, 1, 1, 3, 2, 3 });
Patterns.Add(34, new Byte[] { 1, 3, 1, 1, 2, 3 });
Patterns.Add(35, new Byte[] { 1, 3, 1, 3, 2, 1 });
Patterns.Add(36, new Byte[] { 1, 1, 2, 3, 1, 3 });
Patterns.Add(37, new Byte[] { 1, 3, 2, 1, 1, 3 });
Patterns.Add(38, new Byte[] { 1, 3, 2, 3, 1, 1 });
Patterns.Add(39, new Byte[] { 2, 1, 1, 3, 1, 3 });
Patterns.Add(40, new Byte[] { 2, 3, 1, 1, 1, 3 });
Patterns.Add(41, new Byte[] { 2, 3, 1, 3, 1, 1 });
Patterns.Add(42, new Byte[] { 1, 1, 2, 1, 3, 3 });
Patterns.Add(43, new Byte[] { 1, 1, 2, 3, 3, 1 });
Patterns.Add(44, new Byte[] { 1, 3, 2, 1, 3, 1 });
Patterns.Add(45, new Byte[] { 1, 1, 3, 1, 2, 3 });
Patterns.Add(46, new Byte[] { 1, 1, 3, 3, 2, 1 });
Patterns.Add(47, new Byte[] { 1, 3, 3, 1, 2, 1 });
Patterns.Add(48, new Byte[] { 3, 1, 3, 1, 2, 1 });
Patterns.Add(49, new Byte[] { 2, 1, 1, 3, 3, 1 });
Patterns.Add(50, new Byte[] { 2, 3, 1, 1, 3, 1 });
Patterns.Add(51, new Byte[] { 2, 1, 3, 1, 1, 3 });
Patterns.Add(52, new Byte[] { 2, 1, 3, 3, 1, 1 });
Patterns.Add(53, new Byte[] { 2, 1, 3, 1, 3, 1 });
Patterns.Add(54, new Byte[] { 3, 1, 1, 1, 2, 3 });
Patterns.Add(55, new Byte[] { 3, 1, 1, 3, 2, 1 });
Patterns.Add(56, new Byte[] { 3, 3, 1, 1, 2, 1 });
Patterns.Add(57, new Byte[] { 3, 1, 2, 1, 1, 3 });
Patterns.Add(58, new Byte[] { 3, 1, 2, 3, 1, 1 });
Patterns.Add(59, new Byte[] { 3, 3, 2, 1, 1, 1 });
Patterns.Add(60, new Byte[] { 3, 1, 4, 1, 1, 1 });
Patterns.Add(61, new Byte[] { 2, 2, 1, 4, 1, 1 });
Patterns.Add(62, new Byte[] { 4, 3, 1, 1, 1, 1 });
Patterns.Add(63, new Byte[] { 1, 1, 1, 2, 2, 4 });
Patterns.Add(64, new Byte[] { 1, 1, 1, 4, 2, 2 });
Patterns.Add(65, new Byte[] { 1, 2, 1, 1, 2, 4 });
Patterns.Add(66, new Byte[] { 1, 2, 1, 4, 2, 1 });
Patterns.Add(67, new Byte[] { 1, 4, 1, 1, 2, 2 });
Patterns.Add(68, new Byte[] { 1, 4, 1, 2, 2, 1 });
Patterns.Add(69, new Byte[] { 1, 1, 2, 2, 1, 4 });
Patterns.Add(70, new Byte[] { 1, 1, 2, 4, 1, 2 });
Patterns.Add(71, new Byte[] { 1, 2, 2, 1, 1, 4 });
Patterns.Add(72, new Byte[] { 1, 2, 2, 4, 1, 1 });
Patterns.Add(73, new Byte[] { 1, 4, 2, 1, 1, 2 });
Patterns.Add(74, new Byte[] { 1, 4, 2, 2, 1, 1 });
Patterns.Add(75, new Byte[] { 2, 4, 1, 2, 1, 1 });
Patterns.Add(76, new Byte[] { 2, 2, 1, 1, 1, 4 });
Patterns.Add(77, new Byte[] { 4, 1, 3, 1, 1, 1 });
Patterns.Add(78, new Byte[] { 2, 4, 1, 1, 1, 2 });
Patterns.Add(79, new Byte[] { 1, 3, 4, 1, 1, 1 });
Patterns.Add(80, new Byte[] { 1, 1, 1, 2, 4, 2 });
Patterns.Add(81, new Byte[] { 1, 2, 1, 1, 4, 2 });
Patterns.Add(82, new Byte[] { 1, 2, 1, 2, 4, 1 });
Patterns.Add(83, new Byte[] { 1, 1, 4, 2, 1, 2 });
Patterns.Add(84, new Byte[] { 1, 2, 4, 1, 1, 2 });
Patterns.Add(85, new Byte[] { 1, 2, 4, 2, 1, 1 });
Patterns.Add(86, new Byte[] { 4, 1, 1, 2, 1, 2 });
Patterns.Add(87, new Byte[] { 4, 2, 1, 1, 1, 2 });
Patterns.Add(88, new Byte[] { 4, 2, 1, 2, 1, 1 });
Patterns.Add(89, new Byte[] { 2, 1, 2, 1, 4, 1 });
Patterns.Add(90, new Byte[] { 2, 1, 4, 1, 2, 1 });
Patterns.Add(91, new Byte[] { 4, 1, 2, 1, 2, 1 });
Patterns.Add(92, new Byte[] { 1, 1, 1, 1, 4, 3 });
Patterns.Add(93, new Byte[] { 1, 1, 1, 3, 4, 1 });
Patterns.Add(94, new Byte[] { 1, 3, 1, 1, 4, 1 });
Patterns.Add(95, new Byte[] { 1, 1, 4, 1, 1, 3 });
Patterns.Add(96, new Byte[] { 1, 1, 4, 3, 1, 1 });
Patterns.Add(97, new Byte[] { 4, 1, 1, 1, 1, 3 });
Patterns.Add(98, new Byte[] { 4, 1, 1, 3, 1, 1 });
Patterns.Add(99, new Byte[] { 1, 1, 3, 1, 4, 1 });
Patterns.Add(100, new Byte[] { 1, 1, 4, 1, 3, 1 });
Patterns.Add(101, new Byte[] { 3, 1, 1, 1, 4, 1 });
Patterns.Add(102, new Byte[] { 4, 1, 1, 1, 3, 1 });
Patterns.Add(103, new Byte[] { 2, 1, 1, 4, 1, 2 });
Patterns.Add(104, new Byte[] { 2, 1, 1, 2, 1, 4 });
Patterns.Add(105, new Byte[] { 2, 1, 1, 2, 3, 2 });
Patterns.Add(106, new Byte[] { 2, 3, 3, 1, 1, 1, 2 });
}

/// <summary>Validates the text string to be coded</summary>
/// <param name="text">String - The text string to be coded</param>
protected override void CheckCode(string text)
{
if (text == null) throw new ArgumentNullException("Parameter text (string) can not be null");
if (text.Length == 0) throw new ArgumentException("Parameter text (string) can not be empty");
}

/// <summary>Renders the content found in Text</summary>
/// <param name="gfx">XGraphics - Instance of the drawing surface </param>
/// <param name="brush">XBrush - Line and Color to draw the bar code</param>
/// <param name="font">XFont - Font to use to draw the text string</param>
/// <param name="position">XPoint - Location to render the bar code</param>
protected internal override void Render(XGraphics gfx, XBrush brush, XFont font, XPoint position)
{
XGraphicsState state = gfx.Save();

BarCodeRenderInfo info = new BarCodeRenderInfo(gfx, brush, font, position);
InitRendering(info);
info.CurrPosInString = 0;
info.CurrPos = position - CodeBase.CalcDistance(AnchorType.TopLeft, this.anchor, this.size);

RenderStart(info);
foreach (byte c in Values)
{
RenderValue(info, (int)c);
}
RenderStop(info);
if (TextLocation != TextLocation.None) RenderText(info);

gfx.Restore(state);
}

private void RenderStart(BarCodeRenderInfo info)
{
RenderValue(info, (int)Code128Code);
}

private void RenderStop(BarCodeRenderInfo info)
{
RenderValue(info, CalculateParity());
RenderValue(info, CODE128_STOPCODE);
}

private void RenderValue(BarCodeRenderInfo info, int chVal)
{
byte[] pattern = GetPattern(chVal);
XBrush space = XBrushes.White;
for (int idx = 0; idx < pattern.Length; idx++)
{
if ((idx % 2) == 0)
{
RenderBar(info, info.ThinBarWidth * pattern[idx]);
}
else
{
RenderBar(info, info.ThinBarWidth * pattern[idx], space);
}
}
}

private void RenderText(BarCodeRenderInfo info)
{
if (info.Font == null) info.Font = new XFont("Courier New", Size.Height / 6);
XPoint center = info.Position + CodeBase.CalcDistance(this.anchor, AnchorType.TopLeft, this.size);
if (TextLocation == TextLocation.Above)
{
info.Gfx.DrawString(this.text, info.Font, info.Brush, new XRect(center, Size), XStringFormat.TopCenter);
}
else if (TextLocation == TextLocation.AboveEmbedded)
{
XSize textSize = info.Gfx.MeasureString(this.text, info.Font);
textSize.Width += this.Size.Width * .15;
XPoint point = info.Position;
point.X += (this.Size.Width - textSize.Width) / 2;
XRect rect = new XRect(point, textSize);
info.Gfx.DrawRectangle(XBrushes.White, rect);
info.Gfx.DrawString(this.text, info.Font, info.Brush, new XRect(center, Size), XStringFormat.TopCenter);
}
else if (TextLocation == TextLocation.Below)
{
info.Gfx.DrawString(this.text, info.Font, info.Brush, new XRect(center, Size), XStringFormat.BottomCenter);
}
else if (TextLocation == TextLocation.BelowEmbedded)
{
XSize textSize = info.Gfx.MeasureString(this.text, info.Font);
textSize.Width += this.Size.Width * .15;
XPoint point = info.Position;
point.X += (this.Size.Width - textSize.Width) / 2;
point.Y += Size.Height - textSize.height;
XRect rect = new XRect(point, textSize);
info.Gfx.DrawRectangle(XBrushes.White, rect);
info.Gfx.DrawString(this.text, info.Font, info.Brush, new XRect(center, Size), XStringFormat.BottomCenter);
}
}

private byte[] GetPattern(int codeValue)
{
if (codeValue < 0) throw new ArgumentOutOfRangeException("Parameter ch (int) can not be less than 32 (space).");
if (codeValue > 106) throw new ArgumentOutOfRangeException("Parameter ch (int) can not be greater than 138.");
return Patterns[(byte)codeValue];
}

private int CalculateParity()
{
long parityValue = (int)Code128Code;
for (int x = 1; x <= Values.Length; x++)
{
parityValue += ((Values[x - 1]) * x);
}
parityValue %= 103;
return (int)parityValue;
}

/// <summary>Renders a single line of the character. Each character has three lines and three spaces</summary>
/// <param name="info"></param>
/// <param name="barWidth">Indicates the thickness of the line/bar to be rendered.</param>
internal void RenderBar(BarCodeRenderInfo info, double barWidth)
{
RenderBar(info, barWidth, info.Brush);
}

/// <summary>Renders a single line of the character. Each character has three lines and three spaces</summary>
/// <param name="info"></param>
/// <param name="barWidth">Indicates the thickness of the line/bar to be rendered.</param>
/// <param name="brush">Indicates the brush to use to render the line/bar.</param>
private void RenderBar(BarCodeRenderInfo info, double barWidth, XBrush brush)
{
double height = Size.Height;
double yPos = info.CurrPos.Y;

switch (TextLocation)
{
case TextLocation.Above:
yPos = info.CurrPos.Y + (height / 5);
height *= 4.0 / 5;
break;
case TextLocation.Below:
height *= 4.0 / 5;
break;
case TextLocation.AboveEmbedded:
case TextLocation.BelowEmbedded:
case TextLocation.None:
break;
}
XRect rect = new XRect(info.CurrPos.X, yPos, barWidth, height);
info.Gfx.DrawRectangle(brush, rect);
info.CurrPos.X += barWidth;
}

internal override void InitRendering(BarCodeRenderInfo info)
{
if (Values == null) throw new InvalidOperationException(BcgSR.BarCodeNotSet);
if (Values.Length == 0) throw new InvalidOperationException(BcgSR.EmptyBarCodeSize);

int numberOfBars = Values.Length + 3; // The length of the string plus the start, stop, and parity value
numberOfBars *= 11; // Each character has 11 bars
numberOfBars += 2; // Add two more because the stop bit has two extra bars

// Calculating the width of a bar
info.ThinBarWidth = ((double)this.Size.Width / (double)numberOfBars);
}
}


/// <summary>Code types for Code 128 bar code</summary>
public enum Code_128_Code_Types
{
/// <summary>Code A</summary>
CodeA = 103,
/// <summary>Code B</summary>
CodeB = 104,
/// <summary>Code buffer</summary>
CodeC = 105,
}
}


Here's a quick example on how to use it.
1. Create a console application in visual studio
2. Add your new PdfSharp library as a reference
3. Replace the contents of your 'program.cs' file with the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using PdfSharp;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using PdfSharp.Drawing.Layout;
using PdfSharp.Drawing.BarCodes;

namespace Sample_PDF
{
class Program
{
static void Main(string[] args)
{
PdfDocument document = new PdfDocument();
document.Info.Title = "Sample Code128 Barcode";
document.Info.Author = "Rod Spencer";
document.Info.Subject = "Sample Code128 Barcode";

PdfPage page = document.AddPage();
page.Width = XUnit.FromPoint(500);
page.Height = XUnit.FromMillimeter(145);

XGraphics gfx = XGraphics.FromPdfPage(page);

Code128 c128 = new Code128("Rod.Spencer@segway.com", new XSize(200, 50), CodeDirection.LeftToRight);
c128.TextLocation = TextLocation.BelowEmbedded;
gfx.DrawBarCode(c128, XBrushes.Navy, new XPoint(10, 10));

document.Save("TestPDF.pdf");
}
}
}

4. Build
5. Run - It creates a PDF document in the folder in which you are running called: "TestPDF.pdf"
6. Enjoy


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Tue Mar 16, 2010 2:53 pm 
Offline

Joined: Mon Jan 04, 2010 2:44 pm
Posts: 23
rodspencer wrote:
throw new ArgumentOutOfRangeException("Parameter text (string) must have an even length for Code 128 - Code C");
...
throw new ArgumentOutOfRangeException("Parameter text (string) can only contain numeric characters for Code 128 - Code C");

These are both invalid, and I suspect several of your other throws are invalid too. Code128 can encode all 128 low-ASCII characters, and it's the encoder's responsibility to shift/switch between A, B, and C as necessary to make that happen; you seem to be ignoring this entirely.

For example, if I pass "1234567890123456789" (19 digits), the resultant barcode should contain the following entities (assuming I calculated the check digit correctly):
105 12 34 56 78 90 12 34 56 78 101 25 49 106
or
105 12 34 56 78 90 12 34 56 78 100 25 39 106

To produce the shortest possible barcode:
Switch to 128C (or start in 128C) when you encounter four consecutive digits. (There are situations where using 128C for two digits, or 128A/B for four digits, will produce an equally short barcode, but neither can ever produce a shorter barcode.)
Start A/B, Switch A/B, and Shift A/B are more complicated.
Temporarily drop all characters that can be encoded in both 128A and 128B.
If no characters remain, pick one at random.
If you are switching from C to A/B, look at the first remaining character and use the subcode that can encode it.
If you are considering switching A<->B, look all the remaining characters and seek forward until you find two or three (I haven't figured that one out yet) consecutive characters (remember that these consecutive characters may not be consecutive in the original string) that are both 128A-only or 128B-only. Use that subcode until there, shifting (entity 98) as necessary
If you are starting in A or B, do as above, but it's definitely two consecutive characters.


Last edited by DaleStan on Tue Mar 16, 2010 3:35 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Tue Mar 16, 2010 3:16 pm 
Offline

Joined: Mon Mar 08, 2010 5:46 pm
Posts: 5
Thanks for the update. I originally wrote this to handle strictly Code-B using text strings and with no switching or shifting. I noticed a few places where I didn't update the throw messages.


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Tue Mar 16, 2010 3:50 pm 
Offline

Joined: Mon Jan 04, 2010 2:44 pm
Posts: 23
I thought some more about 128A/128B; the results I came up with are above.

Verifying them yourself is probably a good plan.


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Fri Apr 27, 2012 8:12 am 
Offline

Joined: Wed Apr 25, 2012 9:30 am
Posts: 6
For those who want to use Barcodes128 in Migradoc.

First, apply this patch viewtopic.php?p=3332#p3332

After in the file Migradoc.Rendering.BarcodeRenderer.cs you have to replace function Render() with following:

Code:
internal override void Render()
        {
            RenderFilling();

            BarcodeFormatInfo formatInfo = (BarcodeFormatInfo)this.renderInfo.FormatInfo;
            Area contentArea = this.renderInfo.LayoutInfo.ContentArea;
            XRect destRect = new XRect(contentArea.X, contentArea.Y, formatInfo.Width, formatInfo.Height);

            BarCode gfxBarcode = null;
            Code128 c128 = null;

            switch (this.barcode.Type)
            {
                case BarcodeType.Barcode128:
                    c128 = new Code128("123123", new XSize(200, 50), CodeDirection.LeftToRight);
                    c128.TextLocation = TextLocation.BelowEmbedded;
                    gfxBarcode = c128;
                    break;
                case BarcodeType.Barcode25i:
                    gfxBarcode = new Code2of5Interleaved();
                    break;
                case BarcodeType.Barcode39:
                    gfxBarcode = new Code3of9Standard();
                    break;
                default:
                    break;
            }

            // if gfxBarcode is null, the barcode type is not supported
            if (gfxBarcode != null )
            {
                gfxBarcode.Text = this.barcode.Code;
                gfxBarcode.Direction = CodeDirection.LeftToRight;
                gfxBarcode.Size = new XSize(ShapeWidth, ShapeHeight);
                this.gfx.DrawBarCode(gfxBarcode, XBrushes.Black, destRect.Location);
            }

            RenderLine();
        }


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Fri Sep 28, 2012 2:48 pm 
Offline

Joined: Fri Sep 28, 2012 2:17 pm
Posts: 2
Location: Warszawa, Polska
Hello, I have issue with that solution. I've added this patch, but unfortunately when I'm trying to add barcode (128) it appears with embedded text (which is correct and as expected), but code after scanning is "123123". Constructor in BarcodeRenderer.cs contains this value - but as far I have no idea how to fix it.

Any help would be appreciated :)

[Edit:] Of course it was matter of constructor in render method in BarcodeRenderer.cs - I should have look more carefully. Great solution for Barcode 128, thanks :)

_________________
Regards, Piotr Sońta


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Mon Nov 10, 2014 10:53 am 
Offline

Joined: Mon Nov 10, 2014 9:42 am
Posts: 1
rodspencer wrote:
Here's my Code 128 implementation. [...]
6. Enjoy

Good job,i try your Code 128 implementation,it works perfectly,thank you for solving my problem.


Top
 Profile  
Reply with quote  
 Post subject: Re: Barcode 128
PostPosted: Mon Apr 13, 2015 7:09 am 
Offline

Joined: Fri Dec 19, 2014 1:46 am
Posts: 8
DaleStan wrote:
These are both invalid, and I suspect several of your other throws are invalid too. Code128 can encode all 128 low-ASCII characters, and it's the encoder's responsibility to shift/switch between A, B, and C as necessary to make that happen; you seem to be ignoring this entirely.

Yes, and I remember some bar code need to be added with *, otherwise this bar code cannot be encoded correctly.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group