Page 1 of 1

ECI in DataMatrix

Posted: Wed May 15, 2013 11:28 am
by i.patalas

I'm currently evaluating your component and I have something I can't do. I need a way to properly encode extended characters from different encodings (not only default iso-8859-1). Basing on one of the posts here I was able to do that with Base256 encoding and proper ECI codes. However according to specs there is another way of doing the same using Text/ASCII mode. Does your component support this feature?
I figured out it somehow does, because it detects ECI codes properly. I tried with a string like "Ã<ECI000007>Д<ECI000004>ą". I don't know if it displays properly here, but the first char is in iso-8859-1, then it switches to iso-8859-5 with one character and finally to iso-8859-2 with another character. If I try it with Text/C40 I get "Value does not fall within the expected range". In ASCII mode it works, but the results are strange for me:
First character was encoded properly, but it uses default encoding. The rest is read as some numeric values which doesn't even make much sense to me. I thought it might be the problem with your reader, but I've also checked it with our hardware barcode verifier and it shows the same numeric values following the ECI codes. Am I doing it wrong?

Best regards,
Ireneusz Patalas

Re: ECI in DataMatrix

Posted: Wed May 15, 2013 4:01 pm
by Alex
Hello Ireneusz,

Our barcode writer does not encode text, you need encode text by yourself, i.e. you should create a sequence of value items (ValueItemBase) from your text and pass the value items to the barcode writer.

Our barcode reader also does not decode text, you need decode text by yourself, i.e. you should get a sequence of value items from barcode reader and create the text from value items.

Best regards, Alexander

Re: ECI in DataMatrix

Posted: Fri May 17, 2013 3:25 pm
by i.patalas

Do you mean something like this?

Code: Select all

var items = new List<ValueItemBase>();

items.Add(new BinaryValueItem(iso88592.GetBytes("ążśźęćń󳥯ŚŹĘĆŃÓŁ")));

items.Add(new BinaryValueItem(iso88595.GetBytes("АБВГДЕЖЗИЙКЛМНОП")));

items.Add(new BinaryValueItem(big5.GetBytes("分切刈勻勾勿化匹午升卅卞厄友及反")));

dm.Settings.ValueItems = items.ToArray();
This way it works, but it's all encoded as Base256, which is not optimal, because it encodes 1 character on 1 byte. Text modes use 2 bytes for 3 characters, so it takes less space. We rather don't expect many special characters so it would be better to encode it as Text. According to Datamatrix specs it's possible to change default encoding with proper ECI codeword and then use normal ASCII/Text encoding to encode extended characters. Depending on the mode it will require a special codeword preceding the actual extended character, so each special character will actually take 2 codewords, but there should be only quite a few of them. The text we encode might be up to about 500 characters so it seems that we can have save some bytes by prefering Text over Base256 encodation of diacritics. This is especially important as our customers have strict requirements for the barcodes we generate and we cannot exceed specified sizes.
I wonder if such thing can be achieved by your component and how.

Best regards,
Ireneusz Patalas

Re: ECI in DataMatrix

Posted: Mon May 20, 2013 9:45 am
by Alex
Hello Ireneusz,

Example below shows how encode and decode 3 text strings (strings have different code pages) in text mode in one barcode.

Code: Select all

public static void Test()
    Encoding iso88591 = Encoding.GetEncoding(28591);
    Encoding iso88595 = Encoding.GetEncoding(28595);
    Encoding iso88592 = Encoding.GetEncoding(28592);
    Encoding big5 = Encoding.GetEncoding(950);

    // create the barcode value
    List<ValueItemBase> items = new List<ValueItemBase>();
    EncodeText(items, "ążśźęćń󳥯ŚŹĘĆŃÓŁ", iso88592);
    EncodeText(items, "АБВГДЕЖЗИЙКЛМНОП", iso88595);
    EncodeText(items, "分切刈勻勾勿化匹午升卅卞厄友及反", big5);
    EncodeText(items, "test!", iso88591);

    // write the barcode
    BarcodeWriter writer = new BarcodeWriter();
    writer.Settings.Barcode = BarcodeType.DataMatrix;
    writer.Settings.ValueItems = items.ToArray();
    Bitmap bmp = writer.GetBarcodeAsBitmap();

    // read the barcode
    BarcodeReader reader = new BarcodeReader();
    reader.Settings.ScanBarcodeTypes = BarcodeType.DataMatrix;
    ValueItemBase[] readItems = reader.ReadBarcodes(bmp)[0].ValueItems;

    // parse the barcode value
    string value = ParseBarcodeValue(readItems);

    // check the barcode value
    if (value != 
        "ążśźęćń󳥯ŚŹĘĆŃÓŁ" + 
        "分切刈勻勾勿化匹午升卅卞厄友及反" + 
        throw new ApplicationException();

// Encodes text using specified encoding.
private static void EncodeText(List<ValueItemBase> items, string value, Encoding encoding)
    int eciNumber = GetEciNumber(encoding);

    // add ECI character

    // string -> bytes
    byte[] bytes = encoding.GetBytes(value);

    // bytes -> text
    char[] textChars = new char[bytes.Length];
    for (int i = 0; i < textChars.Length; i++)
        textChars[i] = (char)bytes[i];

    // create and add text value item
    items.Add(new TextValueItem(new string(textChars)));

// Parses the barcode value with ECI characters.
private static string ParseBarcodeValue(ValueItemBase[] items)
    StringBuilder result = new StringBuilder();
    // default encoding
    Encoding currentEncoding = GetEncoding(3);
    // for each value item
    for (int i = 0; i < items.Length; i++)
        if (items[i] is ECICharacterValueItem)
            // change current encoding
            currentEncoding = GetEncoding(((ECICharacterValueItem)items[i]).ECIAssignmentNumber);
        // decode text value item
        string text = ((TextValueItem)items[i]).Value;
        byte[] bytes = new byte[text.Length];
        for (int j = 0; j < text.Length; j++)
            bytes[j] = (byte)text[j];
    return result.ToString();

// Gets the ECI number for specified encoding.
private static int GetEciNumber(Encoding encoding)
    switch (encoding.CodePage)
        case 28591:
            return 3;
        case 28592:
            return 4;
        case 28595: 
            return 7;
        case 950: 
            return 28;
    throw new NotImplementedException();

// Gets the Encoding for specified ECI number.
private static Encoding GetEncoding(int eciNumber)
    switch (eciNumber)
        case 3:
            return Encoding.GetEncoding(28591);
        case 4:
            return Encoding.GetEncoding(28592);
        case 7:
            return Encoding.GetEncoding(28595);
        case 28:
            return Encoding.GetEncoding(950);
    throw new NotImplementedException();
Best regards, Alexander

Re: ECI in DataMatrix

Posted: Tue May 21, 2013 10:37 am
by i.patalas
Thank you very much! It's exactly what I was looking for.