添加项目文件。

This commit is contained in:
akwkevin
2021-07-23 09:42:22 +08:00
commit f25a958797
2798 changed files with 352360 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.Datamatrix.Encoder
{
internal sealed class ASCIIEncoder : Encoder
{
public int EncodingMode
{
get { return Encodation.ASCII; }
}
public void encode(EncoderContext context)
{
//step B
int n = HighLevelEncoder.determineConsecutiveDigitCount(context.Message, context.Pos);
if (n >= 2)
{
context.writeCodeword(encodeASCIIDigits(context.Message[context.Pos],
context.Message[context.Pos + 1]));
context.Pos += 2;
}
else
{
char c = context.CurrentChar;
int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode);
if (newMode != EncodingMode)
{
switch (newMode)
{
case Encodation.BASE256:
context.writeCodeword(HighLevelEncoder.LATCH_TO_BASE256);
context.signalEncoderChange(Encodation.BASE256);
return;
case Encodation.C40:
context.writeCodeword(HighLevelEncoder.LATCH_TO_C40);
context.signalEncoderChange(Encodation.C40);
return;
case Encodation.X12:
context.writeCodeword(HighLevelEncoder.LATCH_TO_ANSIX12);
context.signalEncoderChange(Encodation.X12);
break;
case Encodation.TEXT:
context.writeCodeword(HighLevelEncoder.LATCH_TO_TEXT);
context.signalEncoderChange(Encodation.TEXT);
break;
case Encodation.EDIFACT:
context.writeCodeword(HighLevelEncoder.LATCH_TO_EDIFACT);
context.signalEncoderChange(Encodation.EDIFACT);
break;
default:
throw new InvalidOperationException("Illegal mode: " + newMode);
}
}
else if (HighLevelEncoder.isExtendedASCII(c))
{
context.writeCodeword(HighLevelEncoder.UPPER_SHIFT);
context.writeCodeword((char)(c - 128 + 1));
context.Pos++;
}
else
{
context.writeCodeword((char)(c + 1));
context.Pos++;
}
}
}
private static char encodeASCIIDigits(char digit1, char digit2)
{
if (HighLevelEncoder.isDigit(digit1) && HighLevelEncoder.isDigit(digit2))
{
int num = (digit1 - 48) * 10 + (digit2 - 48);
return (char)(num + 130);
}
throw new ArgumentException("not digits: " + digit1 + digit2);
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
internal sealed class Base256Encoder : Encoder
{
public int EncodingMode
{
get { return Encodation.BASE256; }
}
public void encode(EncoderContext context)
{
var buffer = new StringBuilder();
buffer.Append('\u0000'); //Initialize length field
while (context.HasMoreCharacters)
{
char c = context.CurrentChar;
buffer.Append(c);
context.Pos++;
int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode);
if (newMode != EncodingMode)
{
context.signalEncoderChange(newMode);
break;
}
}
int dataCount = buffer.Length - 1;
const int lengthFieldSize = 1;
int currentSize = context.CodewordCount + dataCount + lengthFieldSize;
context.updateSymbolInfo(currentSize);
bool mustPad = (context.SymbolInfo.dataCapacity - currentSize) > 0;
if (context.HasMoreCharacters || mustPad)
{
if (dataCount <= 249)
{
buffer[0] = (char)dataCount;
}
else if (dataCount > 249 && dataCount <= 1555)
{
buffer[0] = (char)((dataCount / 250) + 249);
buffer.Insert(1, new [] { (char)(dataCount % 250) });
}
else
{
throw new InvalidOperationException(
"Message length not in valid ranges: " + dataCount);
}
}
{
var c = buffer.Length;
for (int i = 0; i < c; i++)
{
context.writeCodeword(randomize255State(
buffer[i], context.CodewordCount + 1));
}
}
}
private static char randomize255State(char ch, int codewordPosition)
{
int pseudoRandom = ((149 * codewordPosition) % 255) + 1;
int tempVariable = ch + pseudoRandom;
if (tempVariable <= 255)
{
return (char)tempVariable;
}
return (char)(tempVariable - 256);
}
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
internal class C40Encoder : Encoder
{
virtual public int EncodingMode
{
get { return Encodation.C40; }
}
virtual public void encode(EncoderContext context)
{
//step C
var buffer = new StringBuilder();
while (context.HasMoreCharacters)
{
char c = context.CurrentChar;
context.Pos++;
int lastCharSize = encodeChar(c, buffer);
int unwritten = (buffer.Length / 3) * 2;
int curCodewordCount = context.CodewordCount + unwritten;
context.updateSymbolInfo(curCodewordCount);
int available = context.SymbolInfo.dataCapacity - curCodewordCount;
if (!context.HasMoreCharacters)
{
//Avoid having a single C40 value in the last triplet
var removed = new StringBuilder();
if ((buffer.Length % 3) == 2)
{
if (available < 2 || available > 2)
{
lastCharSize = backtrackOneCharacter(context, buffer, removed,
lastCharSize);
}
}
while ((buffer.Length % 3) == 1
&& ((lastCharSize <= 3 && available != 1) || lastCharSize > 3))
{
lastCharSize = backtrackOneCharacter(context, buffer, removed, lastCharSize);
}
break;
}
int count = buffer.Length;
if ((count % 3) == 0)
{
int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode);
if (newMode != EncodingMode)
{
context.signalEncoderChange(newMode);
break;
}
}
}
handleEOD(context, buffer);
}
private int backtrackOneCharacter(EncoderContext context,
StringBuilder buffer, StringBuilder removed, int lastCharSize)
{
int count = buffer.Length;
buffer.Remove(count - lastCharSize, lastCharSize);
context.Pos--;
char c = context.CurrentChar;
lastCharSize = encodeChar(c, removed);
context.resetSymbolInfo(); //Deal with possible reduction in symbol size
return lastCharSize;
}
internal static void writeNextTriplet(EncoderContext context, StringBuilder buffer)
{
context.writeCodewords(encodeToCodewords(buffer, 0));
buffer.Remove(0, 3);
}
/// <summary>
/// Handle "end of data" situations
/// </summary>
/// <param name="context">the encoder context</param>
/// <param name="buffer">the buffer with the remaining encoded characters</param>
virtual protected void handleEOD(EncoderContext context, StringBuilder buffer)
{
int unwritten = (buffer.Length / 3) * 2;
int rest = buffer.Length % 3;
int curCodewordCount = context.CodewordCount + unwritten;
context.updateSymbolInfo(curCodewordCount);
int available = context.SymbolInfo.dataCapacity - curCodewordCount;
if (rest == 2)
{
buffer.Append('\u0000'); //Shift 1
while (buffer.Length >= 3)
{
writeNextTriplet(context, buffer);
}
if (context.HasMoreCharacters)
{
context.writeCodeword(HighLevelEncoder.C40_UNLATCH);
}
}
else if (available == 1 && rest == 1)
{
while (buffer.Length >= 3)
{
writeNextTriplet(context, buffer);
}
if (context.HasMoreCharacters)
{
context.writeCodeword(HighLevelEncoder.C40_UNLATCH);
}
// else no unlatch
context.Pos--;
}
else if (rest == 0)
{
while (buffer.Length >= 3)
{
writeNextTriplet(context, buffer);
}
if (available > 0 || context.HasMoreCharacters)
{
context.writeCodeword(HighLevelEncoder.C40_UNLATCH);
}
}
else
{
throw new InvalidOperationException("Unexpected case. Please report!");
}
context.signalEncoderChange(Encodation.ASCII);
}
virtual protected int encodeChar(char c, StringBuilder sb)
{
if (c == ' ')
{
sb.Append('\u0003');
return 1;
}
if (c >= '0' && c <= '9')
{
sb.Append((char)(c - 48 + 4));
return 1;
}
if (c >= 'A' && c <= 'Z')
{
sb.Append((char)(c - 65 + 14));
return 1;
}
if (c >= '\u0000' && c <= '\u001f')
{
sb.Append('\u0000'); //Shift 1 Set
sb.Append(c);
return 2;
}
if (c >= '!' && c <= '/')
{
sb.Append('\u0001'); //Shift 2 Set
sb.Append((char)(c - 33));
return 2;
}
if (c >= ':' && c <= '@')
{
sb.Append('\u0001'); //Shift 2 Set
sb.Append((char)(c - 58 + 15));
return 2;
}
if (c >= '[' && c <= '_')
{
sb.Append('\u0001'); //Shift 2 Set
sb.Append((char)(c - 91 + 22));
return 2;
}
if (c >= '\u0060' && c <= '\u007f')
{
sb.Append('\u0002'); //Shift 3 Set
sb.Append((char)(c - 96));
return 2;
}
if (c >= '\u0080')
{
sb.Append("\u0001\u001e"); //Shift 2, Upper Shift
int len = 2;
len += encodeChar((char)(c - 128), sb);
return len;
}
throw new InvalidOperationException("Illegal character: " + c);
}
private static String encodeToCodewords(StringBuilder sb, int startPos)
{
char c1 = sb[startPos];
char c2 = sb[startPos + 1];
char c3 = sb[startPos + 2];
int v = (1600 * c1) + (40 * c2) + c3 + 1;
char cw1 = (char)(v / 256);
char cw2 = (char)(v % 256);
return new String(new char[] { cw1, cw2 });
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2006 Jeremias Maerki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace ZXing.Datamatrix.Encoder
{
internal sealed class DataMatrixSymbolInfo144 : SymbolInfo
{
public DataMatrixSymbolInfo144()
: base(false, 1558, 620, 22, 22, 36, -1, 62)
{
}
public override int getInterleavedBlockCount()
{
return 10;
}
public override int getDataLengthForInterleavedBlock(int index)
{
return (index <= 8) ? 156 : 155;
}
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright 2013 ZXing.Net authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using ZXing.Common;
using ZXing.Datamatrix.Encoder;
namespace ZXing.Datamatrix
{
/// <summary>
/// The class holds the available options for the DatamatrixWriter
/// </summary>
public class DatamatrixEncodingOptions : EncodingOptions
{
/// <summary>
/// Specifies the matrix shape for Data Matrix
/// </summary>
public SymbolShapeHint? SymbolShape
{
get
{
if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_SHAPE))
{
return (SymbolShapeHint)Hints[EncodeHintType.DATA_MATRIX_SHAPE];
}
return null;
}
set
{
if (value == null)
{
if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_SHAPE))
Hints.Remove(EncodeHintType.DATA_MATRIX_SHAPE);
}
else
{
Hints[EncodeHintType.DATA_MATRIX_SHAPE] = value;
}
}
}
/// <summary>
/// Specifies a minimum barcode size
/// </summary>
public Dimension MinSize
{
get
{
if (Hints.ContainsKey(EncodeHintType.MIN_SIZE))
{
return (Dimension)Hints[EncodeHintType.MIN_SIZE];
}
return null;
}
set
{
if (value == null)
{
if (Hints.ContainsKey(EncodeHintType.MIN_SIZE))
Hints.Remove(EncodeHintType.MIN_SIZE);
}
else
{
Hints[EncodeHintType.MIN_SIZE] = value;
}
}
}
/// <summary>
/// Specifies a maximum barcode size
/// </summary>
public Dimension MaxSize
{
get
{
if (Hints.ContainsKey(EncodeHintType.MAX_SIZE))
{
return (Dimension)Hints[EncodeHintType.MAX_SIZE];
}
return null;
}
set
{
if (value == null)
{
if (Hints.ContainsKey(EncodeHintType.MAX_SIZE))
Hints.Remove(EncodeHintType.MAX_SIZE);
}
else
{
Hints[EncodeHintType.MAX_SIZE] = value;
}
}
}
/// <summary>
/// Specifies the default encodation
/// Make sure that the content fits into the encodation value, otherwise there will be an exception thrown.
/// standard value: Encodation.ASCII
/// </summary>
public int? DefaultEncodation
{
get
{
if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION))
{
return (int)Hints[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION];
}
return null;
}
set
{
if (value == null)
{
if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION))
Hints.Remove(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION);
}
else
{
Hints[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION] = value;
}
}
}
}
}

View File

@@ -0,0 +1,222 @@
/*
* Copyright 2006 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.Datamatrix.Encoder
{
/// <summary>
/// Symbol Character Placement Program. Adapted from Annex M.1 in ISO/IEC 16022:2000(E).
/// </summary>
public class DefaultPlacement
{
private readonly String codewords;
private readonly int numrows;
private readonly int numcols;
private readonly byte[] bits;
/// <summary>
/// Main constructor
/// </summary>
/// <param name="codewords">the codewords to place</param>
/// <param name="numcols">the number of columns</param>
/// <param name="numrows">the number of rows</param>
public DefaultPlacement(String codewords, int numcols, int numrows)
{
this.codewords = codewords;
this.numcols = numcols;
this.numrows = numrows;
this.bits = new byte[numcols * numrows];
SupportClass.Fill(this.bits, (byte)2); //Initialize with "not set" value
}
public int Numrows
{
get { return numrows; }
}
public int Numcols
{
get { return numcols; }
}
public byte[] Bits
{
get { return bits; }
}
public bool getBit(int col, int row)
{
return bits[row * numcols + col] == 1;
}
public void setBit(int col, int row, bool bit)
{
bits[row * numcols + col] = bit ? (byte)1 : (byte)0;
}
public bool hasBit(int col, int row)
{
return bits[row * numcols + col] < 2;
}
public void place()
{
int pos = 0;
int row = 4;
int col = 0;
do
{
/* repeatedly first check for one of the special corner cases, then... */
if ((row == numrows) && (col == 0))
{
corner1(pos++);
}
if ((row == numrows - 2) && (col == 0) && ((numcols % 4) != 0))
{
corner2(pos++);
}
if ((row == numrows - 2) && (col == 0) && (numcols % 8 == 4))
{
corner3(pos++);
}
if ((row == numrows + 4) && (col == 2) && ((numcols % 8) == 0))
{
corner4(pos++);
}
/* sweep upward diagonally, inserting successive characters... */
do
{
if ((row < numrows) && (col >= 0) && !hasBit(col, row))
{
utah(row, col, pos++);
}
row -= 2;
col += 2;
} while (row >= 0 && (col < numcols));
row++;
col += 3;
/* and then sweep downward diagonally, inserting successive characters, ... */
do
{
if ((row >= 0) && (col < numcols) && !hasBit(col, row))
{
utah(row, col, pos++);
}
row += 2;
col -= 2;
} while ((row < numrows) && (col >= 0));
row += 3;
col++;
/* ...until the entire array is scanned */
} while ((row < numrows) || (col < numcols));
/* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */
if (!hasBit(numcols - 1, numrows - 1))
{
setBit(numcols - 1, numrows - 1, true);
setBit(numcols - 2, numrows - 2, true);
}
}
private void module(int row, int col, int pos, int bit)
{
if (row < 0)
{
row += numrows;
col += 4 - ((numrows + 4) % 8);
}
if (col < 0)
{
col += numcols;
row += 4 - ((numcols + 4) % 8);
}
// Note the conversion:
int v = codewords[pos];
v &= 1 << (8 - bit);
setBit(col, row, v != 0);
}
/// <summary>
/// Places the 8 bits of a utah-shaped symbol character in ECC200.
/// </summary>
/// <param name="row">The row.</param>
/// <param name="col">The col.</param>
/// <param name="pos">character position</param>
private void utah(int row, int col, int pos)
{
module(row - 2, col - 2, pos, 1);
module(row - 2, col - 1, pos, 2);
module(row - 1, col - 2, pos, 3);
module(row - 1, col - 1, pos, 4);
module(row - 1, col, pos, 5);
module(row, col - 2, pos, 6);
module(row, col - 1, pos, 7);
module(row, col, pos, 8);
}
private void corner1(int pos)
{
module(numrows - 1, 0, pos, 1);
module(numrows - 1, 1, pos, 2);
module(numrows - 1, 2, pos, 3);
module(0, numcols - 2, pos, 4);
module(0, numcols - 1, pos, 5);
module(1, numcols - 1, pos, 6);
module(2, numcols - 1, pos, 7);
module(3, numcols - 1, pos, 8);
}
private void corner2(int pos)
{
module(numrows - 3, 0, pos, 1);
module(numrows - 2, 0, pos, 2);
module(numrows - 1, 0, pos, 3);
module(0, numcols - 4, pos, 4);
module(0, numcols - 3, pos, 5);
module(0, numcols - 2, pos, 6);
module(0, numcols - 1, pos, 7);
module(1, numcols - 1, pos, 8);
}
private void corner3(int pos)
{
module(numrows - 3, 0, pos, 1);
module(numrows - 2, 0, pos, 2);
module(numrows - 1, 0, pos, 3);
module(0, numcols - 2, pos, 4);
module(0, numcols - 1, pos, 5);
module(1, numcols - 1, pos, 6);
module(2, numcols - 1, pos, 7);
module(3, numcols - 1, pos, 8);
}
private void corner4(int pos)
{
module(numrows - 1, 0, pos, 1);
module(numrows - 1, numcols - 1, pos, 2);
module(0, numcols - 3, pos, 3);
module(0, numcols - 2, pos, 4);
module(0, numcols - 1, pos, 5);
module(1, numcols - 3, pos, 6);
module(1, numcols - 2, pos, 7);
module(1, numcols - 1, pos, 8);
}
}
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
internal sealed class EdifactEncoder : Encoder
{
public int EncodingMode
{
get { return Encodation.EDIFACT; }
}
public void encode(EncoderContext context)
{
//step F
var buffer = new StringBuilder();
while (context.HasMoreCharacters)
{
char c = context.CurrentChar;
encodeChar(c, buffer);
context.Pos++;
int count = buffer.Length;
if (count >= 4)
{
context.writeCodewords(encodeToCodewords(buffer, 0));
buffer.Remove(0, 4);
int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode);
if (newMode != EncodingMode)
{
context.signalEncoderChange(Encodation.ASCII);
break;
}
}
}
buffer.Append((char)31); //Unlatch
handleEOD(context, buffer);
}
/// <summary>
/// Handle "end of data" situations
/// </summary>
/// <param name="context">the encoder context</param>
/// <param name="buffer">the buffer with the remaining encoded characters</param>
private static void handleEOD(EncoderContext context, StringBuilder buffer)
{
try
{
int count = buffer.Length;
if (count == 0)
{
return; //Already finished
}
if (count == 1)
{
//Only an unlatch at the end
context.updateSymbolInfo();
int available = context.SymbolInfo.dataCapacity - context.CodewordCount;
int remaining = context.RemainingCharacters;
if (remaining == 0 && available <= 2)
{
return; //No unlatch
}
}
if (count > 4)
{
throw new InvalidOperationException("Count must not exceed 4");
}
int restChars = count - 1;
String encoded = encodeToCodewords(buffer, 0);
bool endOfSymbolReached = !context.HasMoreCharacters;
bool restInAscii = endOfSymbolReached && restChars <= 2;
if (restChars <= 2)
{
context.updateSymbolInfo(context.CodewordCount + restChars);
int available = context.SymbolInfo.dataCapacity - context.CodewordCount;
if (available >= 3)
{
restInAscii = false;
context.updateSymbolInfo(context.CodewordCount + encoded.Length);
//available = context.symbolInfo.dataCapacity - context.getCodewordCount();
}
}
if (restInAscii)
{
context.resetSymbolInfo();
context.Pos -= restChars;
}
else
{
context.writeCodewords(encoded);
}
}
finally
{
context.signalEncoderChange(Encodation.ASCII);
}
}
private static void encodeChar(char c, StringBuilder sb)
{
if (c >= ' ' && c <= '?')
{
sb.Append(c);
}
else if (c >= '@' && c <= '^')
{
sb.Append((char)(c - 64));
}
else
{
HighLevelEncoder.illegalCharacter(c);
}
}
private static String encodeToCodewords(StringBuilder sb, int startPos)
{
int len = sb.Length - startPos;
if (len == 0)
{
throw new InvalidOperationException("StringBuilder must not be empty");
}
char c1 = sb[startPos];
char c2 = len >= 2 ? sb[startPos + 1] : (char)0;
char c3 = len >= 3 ? sb[startPos + 2] : (char)0;
char c4 = len >= 4 ? sb[startPos + 3] : (char)0;
int v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4;
char cw1 = (char)((v >> 16) & 255);
char cw2 = (char)((v >> 8) & 255);
char cw3 = (char)(v & 255);
var res = new StringBuilder(3);
res.Append(cw1);
if (len >= 2)
{
res.Append(cw2);
}
if (len >= 3)
{
res.Append(cw3);
}
return res.ToString();
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace ZXing.Datamatrix.Encoder
{
/// <summary>
/// Enumeration for encodation types
/// </summary>
public sealed class Encodation
{
public const int ASCII = 0;
public const int C40 = 1;
public const int TEXT = 2;
public const int X12 = 3;
public const int EDIFACT = 4;
public const int BASE256 = 5;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace ZXing.Datamatrix.Encoder
{
internal interface Encoder
{
int EncodingMode { get; }
void encode(EncoderContext context);
}
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
internal sealed class EncoderContext
{
private readonly String msg;
private SymbolShapeHint shape;
private Dimension minSize;
private Dimension maxSize;
private readonly StringBuilder codewords;
private int pos;
private int newEncoding;
private SymbolInfo symbolInfo;
private int skipAtEnd;
private static readonly Encoding encoding;
static EncoderContext()
{
#if !(WindowsCE || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE)
encoding = Encoding.GetEncoding("ISO-8859-1");
#elif WindowsCE
try
{
encoding = Encoding.GetEncoding("ISO-8859-1");
}
catch (PlatformNotSupportedException)
{
encoding = Encoding.GetEncoding(1252);
}
#else
// not fully correct but what else
encoding = Encoding.GetEncoding("UTF-8");
#endif
}
public EncoderContext(String msg)
{
//From this point on Strings are not Unicode anymore!
var msgBinary = encoding.GetBytes(msg);
var sb = new StringBuilder(msgBinary.Length);
var c = msgBinary.Length;
for (int i = 0; i < c; i++)
{
// TODO: does it works in .Net the same way?
var ch = (char)(msgBinary[i] & 0xff);
if (ch == '?' && msg[i] != '?')
{
throw new ArgumentException("Message contains characters outside " + encoding.WebName + " encoding.");
}
sb.Append(ch);
}
this.msg = sb.ToString(); //Not Unicode here!
shape = SymbolShapeHint.FORCE_NONE;
this.codewords = new StringBuilder(msg.Length);
newEncoding = -1;
}
public void setSymbolShape(SymbolShapeHint shape)
{
this.shape = shape;
}
public void setSizeConstraints(Dimension minSize, Dimension maxSize)
{
this.minSize = minSize;
this.maxSize = maxSize;
}
public void setSkipAtEnd(int count)
{
this.skipAtEnd = count;
}
public char CurrentChar
{
get { return msg[pos]; }
}
public char Current
{
get { return msg[pos]; }
}
public void writeCodewords(String codewords)
{
this.codewords.Append(codewords);
}
public void writeCodeword(char codeword)
{
this.codewords.Append(codeword);
}
public int CodewordCount
{
get { return this.codewords.Length; }
}
public void signalEncoderChange(int encoding)
{
this.newEncoding = encoding;
}
public void resetEncoderSignal()
{
this.newEncoding = -1;
}
public bool HasMoreCharacters
{
get { return pos < TotalMessageCharCount; }
}
private int TotalMessageCharCount
{
get { return msg.Length - skipAtEnd; }
}
public int RemainingCharacters
{
get { return TotalMessageCharCount - pos; }
}
public void updateSymbolInfo()
{
updateSymbolInfo(CodewordCount);
}
public void updateSymbolInfo(int len)
{
if (this.symbolInfo == null || len > this.symbolInfo.dataCapacity)
{
this.symbolInfo = SymbolInfo.lookup(len, shape, minSize, maxSize, true);
}
}
public void resetSymbolInfo()
{
this.symbolInfo = null;
}
public int Pos
{
get { return pos; }
set { pos = value; }
}
public StringBuilder Codewords
{
get { return codewords; }
}
public SymbolInfo SymbolInfo
{
get { return symbolInfo; }
}
public int NewEncoding
{
get { return newEncoding; }
}
public String Message
{
get { return msg; }
}
}
}

View File

@@ -0,0 +1,283 @@
/*
* Copyright 2006 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
/// <summary>
/// Error Correction Code for ECC200.
/// </summary>
public static class ErrorCorrection
{
/// <summary>
/// Lookup table which factors to use for which number of error correction codewords.
/// See FACTORS.
/// </summary>
private static readonly int[] FACTOR_SETS
= { 5, 7, 10, 11, 12, 14, 18, 20, 24, 28, 36, 42, 48, 56, 62, 68 };
/// <summary>
/// Precomputed polynomial factors for ECC 200.
/// </summary>
private static readonly int[][] FACTORS = {
new[] {228, 48, 15, 111, 62},
new[] {23, 68, 144, 134, 240, 92, 254},
new[] {28, 24, 185, 166, 223, 248, 116, 255, 110, 61},
new[] {175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120},
new[] {41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242},
new[] {156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185}
,
new[]
{
83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254,
225,
48, 90, 188
},
new[]
{
15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79,
108,
82, 27, 174, 186, 172
},
new[]
{
52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21
, 5
, 172,
254, 124, 12, 181, 184, 96, 50, 193
},
new[]
{
211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34,
249,
121,
17, 138, 110, 213, 141, 136, 120, 151, 233, 168, 93, 255
},
new[]
{
245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220,
251, 80, 182,
229, 18, 2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59
,
25,
225, 98, 81, 112
},
new[]
{
77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133,
242
, 8,
175, 95, 100, 9, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57,
54,
101,
248, 202, 69, 50, 150, 177, 226, 5, 9, 5
},
new[]
{
245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205,
188,
237, 87,
191, 106, 16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100
,
66, 138,
186, 240, 82, 44, 176, 87, 187, 147, 160, 175, 69, 213, 92, 253
,
225, 19
},
new[]
{
175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192
,
215, 235,
150, 159, 36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117,
203,
29, 232,
144, 238, 22, 150, 201, 117, 62, 207, 164, 13, 137, 245, 127,
67,
247, 28,
155, 43, 203, 107, 233, 53, 143, 46
},
new[]
{
242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143,
108,
196, 37,
185, 112, 134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175,
64
, 114, 71,
161, 44, 147, 6, 27, 218, 51, 63, 87, 10, 40, 130, 188, 17, 163
,
31,
176, 170, 4, 107, 232, 7, 94, 166, 224, 124, 86, 47, 11, 204
},
new[]
{
220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36
,
73, 127,
213, 136, 248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15,
160,
227, 236,
66, 139, 153, 185, 202, 167, 179, 25, 220, 232, 96, 210, 231,
136,
223, 239,
181, 241, 59, 52, 172, 25, 49, 232, 211, 189, 64, 54, 108, 153,
132, 63,
96, 103, 82, 186
}
};
private const int MODULO_VALUE = 0x12D;
private static readonly int[] LOG;
private static readonly int[] ALOG;
static ErrorCorrection()
{
//Create log and antilog table
LOG = new int[256];
ALOG = new int[255];
int p = 1;
for (int i = 0; i < 255; i++)
{
ALOG[i] = p;
LOG[p] = i;
p <<= 1;
if (p >= 256)
{
p ^= MODULO_VALUE;
}
}
}
/// <summary>
/// Creates the ECC200 error correction for an encoded message.
/// </summary>
/// <param name="codewords">The codewords.</param>
/// <param name="symbolInfo">information about the symbol to be encoded</param>
/// <returns>the codewords with interleaved error correction.</returns>
public static String encodeECC200(String codewords, SymbolInfo symbolInfo)
{
if (codewords.Length != symbolInfo.dataCapacity)
{
throw new ArgumentException(
"The number of codewords does not match the selected symbol");
}
var sb = new StringBuilder(symbolInfo.dataCapacity + symbolInfo.errorCodewords);
sb.Append(codewords);
int blockCount = symbolInfo.getInterleavedBlockCount();
if (blockCount == 1)
{
String ecc = createECCBlock(codewords, symbolInfo.errorCodewords);
sb.Append(ecc);
}
else
{
sb.Length = sb.Capacity;
int[] dataSizes = new int[blockCount];
int[] errorSizes = new int[blockCount];
int[] startPos = new int[blockCount];
for (int i = 0; i < blockCount; i++)
{
dataSizes[i] = symbolInfo.getDataLengthForInterleavedBlock(i + 1);
errorSizes[i] = symbolInfo.getErrorLengthForInterleavedBlock(i + 1);
startPos[i] = 0;
if (i > 0)
{
startPos[i] = startPos[i - 1] + dataSizes[i];
}
}
for (int block = 0; block < blockCount; block++)
{
var temp = new StringBuilder(dataSizes[block]);
for (int d = block; d < symbolInfo.dataCapacity; d += blockCount)
{
temp.Append(codewords[d]);
}
String ecc = createECCBlock(temp.ToString(), errorSizes[block]);
int pos = 0;
for (int e = block; e < errorSizes[block] * blockCount; e += blockCount)
{
sb[symbolInfo.dataCapacity + e] = ecc[pos++];
}
}
}
return sb.ToString();
}
private static String createECCBlock(String codewords, int numECWords)
{
return createECCBlock(codewords, 0, codewords.Length, numECWords);
}
private static String createECCBlock(String codewords, int start, int len, int numECWords)
{
int table = -1;
for (int i = 0; i < FACTOR_SETS.Length; i++)
{
if (FACTOR_SETS[i] == numECWords)
{
table = i;
break;
}
}
if (table < 0)
{
throw new ArgumentException(
"Illegal number of error correction codewords specified: " + numECWords);
}
int[] poly = FACTORS[table];
char[] ecc = new char[numECWords];
for (int i = 0; i < numECWords; i++)
{
ecc[i] = (char)0;
}
for (int i = start; i < start + len; i++)
{
int m = ecc[numECWords - 1] ^ codewords[i];
for (int k = numECWords - 1; k > 0; k--)
{
if (m != 0 && poly[k] != 0)
{
ecc[k] = (char)(ecc[k - 1] ^ ALOG[(LOG[m] + LOG[poly[k]]) % 255]);
}
else
{
ecc[k] = ecc[k - 1];
}
}
if (m != 0 && poly[0] != 0)
{
ecc[0] = (char)ALOG[(LOG[m] + LOG[poly[0]]) % 255];
}
else
{
ecc[0] = (char)0;
}
}
char[] eccReversed = new char[numECWords];
for (int i = 0; i < numECWords; i++)
{
eccReversed[i] = ecc[numECWords - i - 1];
}
return new String(eccReversed);
}
}
}

View File

@@ -0,0 +1,537 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
/// <summary>
/// DataMatrix ECC 200 data encoder following the algorithm described in ISO/IEC 16022:200(E) in
/// annex S.
/// </summary>
internal static class HighLevelEncoder
{
/// <summary>
/// Padding character
/// </summary>
public const char PAD = (char)129;
/// <summary>
/// mode latch to C40 encodation mode
/// </summary>
public const char LATCH_TO_C40 = (char)230;
/// <summary>
/// mode latch to Base 256 encodation mode
/// </summary>
public const char LATCH_TO_BASE256 = (char)231;
/// <summary>
/// FNC1 Codeword
/// </summary>
public const char FNC1 = (char)232;
/// <summary>
/// Structured Append Codeword
/// </summary>
public const char STRUCTURED_APPEND = (char)233;
/// <summary>
/// Reader Programming
/// </summary>
public const char READER_PROGRAMMING = (char)234;
/// <summary>
/// Upper Shift
/// </summary>
public const char UPPER_SHIFT = (char)235;
/// <summary>
/// 05 Macro
/// </summary>
public const char MACRO_05 = (char)236;
/// <summary>
/// 06 Macro
/// </summary>
public const char MACRO_06 = (char)237;
/// <summary>
/// mode latch to ANSI X.12 encodation mode
/// </summary>
public const char LATCH_TO_ANSIX12 = (char)238;
/// <summary>
/// mode latch to Text encodation mode
/// </summary>
public const char LATCH_TO_TEXT = (char)239;
/// <summary>
/// mode latch to EDIFACT encodation mode
/// </summary>
public const char LATCH_TO_EDIFACT = (char)240;
/// <summary>
/// ECI character (Extended Channel Interpretation)
/// </summary>
public const char ECI = (char)241;
/// <summary>
/// Unlatch from C40 encodation
/// </summary>
public const char C40_UNLATCH = (char)254;
/// <summary>
/// Unlatch from X12 encodation
/// </summary>
public const char X12_UNLATCH = (char)254;
/// <summary>
/// 05 Macro header
/// </summary>
public const String MACRO_05_HEADER = "[)>\u001E05\u001D";
/// <summary>
/// 06 Macro header
/// </summary>
public const String MACRO_06_HEADER = "[)>\u001E06\u001D";
/// <summary>
/// Macro trailer
/// </summary>
public const String MACRO_TRAILER = "\u001E\u0004";
/*
/// <summary>
/// Converts the message to a byte array using the default encoding (cp437) as defined by the
/// specification
/// </summary>
/// <param name="msg">the message</param>
/// <returns>the byte array of the message</returns>
public static byte[] getBytesForMessage(String msg)
{
return Encoding.GetEncoding("CP437").GetBytes(msg); //See 4.4.3 and annex B of ISO/IEC 15438:2001(E)
}
*/
private static char randomize253State(char ch, int codewordPosition)
{
int pseudoRandom = ((149 * codewordPosition) % 253) + 1;
int tempVariable = ch + pseudoRandom;
return tempVariable <= 254 ? (char)tempVariable : (char)(tempVariable - 254);
}
/// <summary>
/// Performs message encoding of a DataMatrix message using the algorithm described in annex P
/// of ISO/IEC 16022:2000(E).
/// </summary>
/// <param name="msg">the message</param>
/// <returns>the encoded message (the char values range from 0 to 255)</returns>
public static String encodeHighLevel(String msg)
{
return encodeHighLevel(msg, SymbolShapeHint.FORCE_NONE, null, null, Encodation.ASCII);
}
/// <summary>
/// Performs message encoding of a DataMatrix message using the algorithm described in annex P
/// of ISO/IEC 16022:2000(E).
/// </summary>
/// <param name="msg">the message</param>
/// <param name="shape">requested shape. May be {@code SymbolShapeHint.FORCE_NONE},{@code SymbolShapeHint.FORCE_SQUARE} or {@code SymbolShapeHint.FORCE_RECTANGLE}.</param>
/// <param name="minSize">the minimum symbol size constraint or null for no constraint</param>
/// <param name="maxSize">the maximum symbol size constraint or null for no constraint</param>
/// <returns>the encoded message (the char values range from 0 to 255)</returns>
public static String encodeHighLevel(String msg,
SymbolShapeHint shape,
Dimension minSize,
Dimension maxSize,
int defaultEncodation)
{
//the codewords 0..255 are encoded as Unicode characters
Encoder[] encoders =
{
new ASCIIEncoder(), new C40Encoder(), new TextEncoder(),
new X12Encoder(), new EdifactEncoder(), new Base256Encoder()
};
var context = new EncoderContext(msg);
context.setSymbolShape(shape);
context.setSizeConstraints(minSize, maxSize);
if (msg.StartsWith(MACRO_05_HEADER) && msg.EndsWith(MACRO_TRAILER))
{
context.writeCodeword(MACRO_05);
context.setSkipAtEnd(2);
context.Pos += MACRO_05_HEADER.Length;
}
else if (msg.StartsWith(MACRO_06_HEADER) && msg.EndsWith(MACRO_TRAILER))
{
context.writeCodeword(MACRO_06);
context.setSkipAtEnd(2);
context.Pos += MACRO_06_HEADER.Length;
}
int encodingMode = defaultEncodation; //Default mode
switch (encodingMode)
{
case Encodation.BASE256:
context.writeCodeword(HighLevelEncoder.LATCH_TO_BASE256);
break;
case Encodation.C40:
context.writeCodeword(HighLevelEncoder.LATCH_TO_C40);
break;
case Encodation.X12:
context.writeCodeword(HighLevelEncoder.LATCH_TO_ANSIX12);
break;
case Encodation.TEXT:
context.writeCodeword(HighLevelEncoder.LATCH_TO_TEXT);
break;
case Encodation.EDIFACT:
context.writeCodeword(HighLevelEncoder.LATCH_TO_EDIFACT);
break;
case Encodation.ASCII:
break;
default:
throw new InvalidOperationException("Illegal mode: " + encodingMode);
}
while (context.HasMoreCharacters)
{
encoders[encodingMode].encode(context);
if (context.NewEncoding >= 0)
{
encodingMode = context.NewEncoding;
context.resetEncoderSignal();
}
}
int len = context.Codewords.Length;
context.updateSymbolInfo();
int capacity = context.SymbolInfo.dataCapacity;
if (len < capacity)
{
if (encodingMode != Encodation.ASCII && encodingMode != Encodation.BASE256)
{
context.writeCodeword('\u00fe'); //Unlatch (254)
}
}
//Padding
StringBuilder codewords = context.Codewords;
if (codewords.Length < capacity)
{
codewords.Append(PAD);
}
while (codewords.Length < capacity)
{
codewords.Append(randomize253State(PAD, codewords.Length + 1));
}
return context.Codewords.ToString();
}
internal static int lookAheadTest(String msg, int startpos, int currentMode)
{
if (startpos >= msg.Length)
{
return currentMode;
}
float[] charCounts;
//step J
if (currentMode == Encodation.ASCII)
{
charCounts = new [] { 0, 1, 1, 1, 1, 1.25f };
}
else
{
charCounts = new [] { 1, 2, 2, 2, 2, 2.25f };
charCounts[currentMode] = 0;
}
int charsProcessed = 0;
while (true)
{
//step K
if ((startpos + charsProcessed) == msg.Length)
{
var min = Int32.MaxValue;
var mins = new byte[6];
var intCharCounts = new int[6];
min = findMinimums(charCounts, intCharCounts, min, mins);
var minCount = getMinimumCount(mins);
if (intCharCounts[Encodation.ASCII] == min)
{
return Encodation.ASCII;
}
if (minCount == 1 && mins[Encodation.BASE256] > 0)
{
return Encodation.BASE256;
}
if (minCount == 1 && mins[Encodation.EDIFACT] > 0)
{
return Encodation.EDIFACT;
}
if (minCount == 1 && mins[Encodation.TEXT] > 0)
{
return Encodation.TEXT;
}
if (minCount == 1 && mins[Encodation.X12] > 0)
{
return Encodation.X12;
}
return Encodation.C40;
}
char c = msg[startpos + charsProcessed];
charsProcessed++;
//step L
if (isDigit(c))
{
charCounts[Encodation.ASCII] += 0.5f;
}
else if (isExtendedASCII(c))
{
charCounts[Encodation.ASCII] = (int)Math.Ceiling(charCounts[Encodation.ASCII]);
charCounts[Encodation.ASCII] += 2;
}
else
{
charCounts[Encodation.ASCII] = (int)Math.Ceiling(charCounts[Encodation.ASCII]);
charCounts[Encodation.ASCII]++;
}
//step M
if (isNativeC40(c))
{
charCounts[Encodation.C40] += 2.0f / 3.0f;
}
else if (isExtendedASCII(c))
{
charCounts[Encodation.C40] += 8.0f / 3.0f;
}
else
{
charCounts[Encodation.C40] += 4.0f / 3.0f;
}
//step N
if (isNativeText(c))
{
charCounts[Encodation.TEXT] += 2.0f / 3.0f;
}
else if (isExtendedASCII(c))
{
charCounts[Encodation.TEXT] += 8.0f / 3.0f;
}
else
{
charCounts[Encodation.TEXT] += 4.0f / 3.0f;
}
//step O
if (isNativeX12(c))
{
charCounts[Encodation.X12] += 2.0f / 3.0f;
}
else if (isExtendedASCII(c))
{
charCounts[Encodation.X12] += 13.0f / 3.0f;
}
else
{
charCounts[Encodation.X12] += 10.0f / 3.0f;
}
//step P
if (isNativeEDIFACT(c))
{
charCounts[Encodation.EDIFACT] += 3.0f / 4.0f;
}
else if (isExtendedASCII(c))
{
charCounts[Encodation.EDIFACT] += 17.0f / 4.0f;
}
else
{
charCounts[Encodation.EDIFACT] += 13.0f / 4.0f;
}
// step Q
if (isSpecialB256(c))
{
charCounts[Encodation.BASE256] += 4;
}
else
{
charCounts[Encodation.BASE256]++;
}
//step R
if (charsProcessed >= 4)
{
var intCharCounts = new int[6];
var mins = new byte[6];
findMinimums(charCounts, intCharCounts, Int32.MaxValue, mins);
int minCount = getMinimumCount(mins);
if (intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.BASE256]
&& intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.C40]
&& intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.TEXT]
&& intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.X12]
&& intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.EDIFACT])
{
return Encodation.ASCII;
}
if (intCharCounts[Encodation.BASE256] < intCharCounts[Encodation.ASCII]
|| (mins[Encodation.C40] + mins[Encodation.TEXT] + mins[Encodation.X12] + mins[Encodation.EDIFACT]) == 0)
{
return Encodation.BASE256;
}
if (minCount == 1 && mins[Encodation.EDIFACT] > 0)
{
return Encodation.EDIFACT;
}
if (minCount == 1 && mins[Encodation.TEXT] > 0)
{
return Encodation.TEXT;
}
if (minCount == 1 && mins[Encodation.X12] > 0)
{
return Encodation.X12;
}
if (intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.ASCII]
&& intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.BASE256]
&& intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.EDIFACT]
&& intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.TEXT])
{
if (intCharCounts[Encodation.C40] < intCharCounts[Encodation.X12])
{
return Encodation.C40;
}
if (intCharCounts[Encodation.C40] == intCharCounts[Encodation.X12])
{
int p = startpos + charsProcessed + 1;
while (p < msg.Length)
{
char tc = msg[p];
if (isX12TermSep(tc))
{
return Encodation.X12;
}
if (!isNativeX12(tc))
{
break;
}
p++;
}
return Encodation.C40;
}
}
}
}
}
private static int findMinimums(float[] charCounts, int[] intCharCounts, int min, byte[] mins)
{
SupportClass.Fill(mins, (byte)0);
for (int i = 0; i < 6; i++)
{
intCharCounts[i] = (int)Math.Ceiling(charCounts[i]);
int current = intCharCounts[i];
if (min > current)
{
min = current;
SupportClass.Fill(mins, (byte)0);
}
if (min == current)
{
mins[i]++;
}
}
return min;
}
private static int getMinimumCount(byte[] mins)
{
int minCount = 0;
for (int i = 0; i < 6; i++)
{
minCount += mins[i];
}
return minCount;
}
internal static bool isDigit(char ch)
{
return ch >= '0' && ch <= '9';
}
internal static bool isExtendedASCII(char ch)
{
return ch >= 128 && ch <= 255;
}
internal static bool isNativeC40(char ch)
{
return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z');
}
internal static bool isNativeText(char ch)
{
return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z');
}
internal static bool isNativeX12(char ch)
{
return isX12TermSep(ch) || (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z');
}
internal static bool isX12TermSep(char ch)
{
return (ch == '\r') //CR
|| (ch == '*')
|| (ch == '>');
}
internal static bool isNativeEDIFACT(char ch)
{
return ch >= ' ' && ch <= '^';
}
internal static bool isSpecialB256(char ch)
{
return false; //TODO NOT IMPLEMENTED YET!!!
}
/// <summary>
/// Determines the number of consecutive characters that are encodable using numeric compaction.
/// </summary>
/// <param name="msg">the message</param>
/// <param name="startpos">the start position within the message</param>
/// <returns>the requested character count</returns>
public static int determineConsecutiveDigitCount(String msg, int startpos)
{
int count = 0;
int len = msg.Length;
int idx = startpos;
if (idx < len)
{
char ch = msg[idx];
while (isDigit(ch) && idx < len)
{
count++;
idx++;
if (idx < len)
{
ch = msg[idx];
}
}
}
return count;
}
internal static void illegalCharacter(char c)
{
throw new ArgumentException(String.Format("Illegal character: {0} (0x{1:X})", c, (int)c));
}
}
}

View File

@@ -0,0 +1,258 @@
/*
* Copyright 2006 Jeremias Maerki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
/// <summary>
/// Symbol info table for DataMatrix.
/// </summary>
public class SymbolInfo
{
internal static readonly SymbolInfo[] PROD_SYMBOLS = {
new SymbolInfo(false, 3, 5, 8, 8, 1),
new SymbolInfo(false, 5, 7, 10, 10, 1),
/*rect*/new SymbolInfo(true, 5, 7, 16, 6, 1),
new SymbolInfo(false, 8, 10, 12, 12, 1),
/*rect*/new SymbolInfo(true, 10, 11, 14, 6, 2),
new SymbolInfo(false, 12, 12, 14, 14, 1),
/*rect*/new SymbolInfo(true, 16, 14, 24, 10, 1),
new SymbolInfo(false, 18, 14, 16, 16, 1),
new SymbolInfo(false, 22, 18, 18, 18, 1),
/*rect*/new SymbolInfo(true, 22, 18, 16, 10, 2),
new SymbolInfo(false, 30, 20, 20, 20, 1),
/*rect*/new SymbolInfo(true, 32, 24, 16, 14, 2),
new SymbolInfo(false, 36, 24, 22, 22, 1),
new SymbolInfo(false, 44, 28, 24, 24, 1),
/*rect*/new SymbolInfo(true, 49, 28, 22, 14, 2),
new SymbolInfo(false, 62, 36, 14, 14, 4),
new SymbolInfo(false, 86, 42, 16, 16, 4),
new SymbolInfo(false, 114, 48, 18, 18, 4),
new SymbolInfo(false, 144, 56, 20, 20, 4),
new SymbolInfo(false, 174, 68, 22, 22, 4),
new SymbolInfo(false, 204, 84, 24, 24, 4, 102, 42),
new SymbolInfo(false, 280, 112, 14, 14, 16, 140, 56),
new SymbolInfo(false, 368, 144, 16, 16, 16, 92, 36),
new SymbolInfo(false, 456, 192, 18, 18, 16, 114, 48),
new SymbolInfo(false, 576, 224, 20, 20, 16, 144, 56),
new SymbolInfo(false, 696, 272, 22, 22, 16, 174, 68),
new SymbolInfo(false, 816, 336, 24, 24, 16, 136, 56),
new SymbolInfo(false, 1050, 408, 18, 18, 36, 175, 68),
new SymbolInfo(false, 1304, 496, 20, 20, 36, 163, 62),
new DataMatrixSymbolInfo144(),
};
private static SymbolInfo[] symbols = PROD_SYMBOLS;
/**
* Overrides the symbol info set used by this class. Used for testing purposes.
*
* @param override the symbol info set to use
*/
public static void overrideSymbolSet(SymbolInfo[] @override)
{
symbols = @override;
}
private readonly bool rectangular;
internal readonly int dataCapacity;
internal readonly int errorCodewords;
public readonly int matrixWidth;
public readonly int matrixHeight;
private readonly int dataRegions;
private readonly int rsBlockData;
private readonly int rsBlockError;
public SymbolInfo(bool rectangular, int dataCapacity, int errorCodewords,
int matrixWidth, int matrixHeight, int dataRegions)
: this(rectangular, dataCapacity, errorCodewords, matrixWidth, matrixHeight, dataRegions,
dataCapacity, errorCodewords)
{
}
internal SymbolInfo(bool rectangular, int dataCapacity, int errorCodewords,
int matrixWidth, int matrixHeight, int dataRegions,
int rsBlockData, int rsBlockError)
{
this.rectangular = rectangular;
this.dataCapacity = dataCapacity;
this.errorCodewords = errorCodewords;
this.matrixWidth = matrixWidth;
this.matrixHeight = matrixHeight;
this.dataRegions = dataRegions;
this.rsBlockData = rsBlockData;
this.rsBlockError = rsBlockError;
}
public static SymbolInfo lookup(int dataCodewords)
{
return lookup(dataCodewords, SymbolShapeHint.FORCE_NONE, true);
}
public static SymbolInfo lookup(int dataCodewords, SymbolShapeHint shape)
{
return lookup(dataCodewords, shape, true);
}
public static SymbolInfo lookup(int dataCodewords, bool allowRectangular, bool fail)
{
SymbolShapeHint shape = allowRectangular
? SymbolShapeHint.FORCE_NONE : SymbolShapeHint.FORCE_SQUARE;
return lookup(dataCodewords, shape, fail);
}
private static SymbolInfo lookup(int dataCodewords, SymbolShapeHint shape, bool fail)
{
return lookup(dataCodewords, shape, null, null, fail);
}
public static SymbolInfo lookup(int dataCodewords,
SymbolShapeHint shape,
Dimension minSize,
Dimension maxSize,
bool fail)
{
foreach (SymbolInfo symbol in symbols)
{
if (shape == SymbolShapeHint.FORCE_SQUARE && symbol.rectangular)
{
continue;
}
if (shape == SymbolShapeHint.FORCE_RECTANGLE && !symbol.rectangular)
{
continue;
}
if (minSize != null
&& (symbol.getSymbolWidth() < minSize.Width
|| symbol.getSymbolHeight() < minSize.Height))
{
continue;
}
if (maxSize != null
&& (symbol.getSymbolWidth() > maxSize.Width
|| symbol.getSymbolHeight() > maxSize.Height))
{
continue;
}
if (dataCodewords <= symbol.dataCapacity)
{
return symbol;
}
}
if (fail)
{
throw new ArgumentException(
"Can't find a symbol arrangement that matches the message. Data codewords: "
+ dataCodewords);
}
return null;
}
int getHorizontalDataRegions()
{
switch (dataRegions)
{
case 1:
return 1;
case 2:
return 2;
case 4:
return 2;
case 16:
return 4;
case 36:
return 6;
default:
throw new InvalidOperationException("Cannot handle this number of data regions");
}
}
int getVerticalDataRegions()
{
switch (dataRegions)
{
case 1:
return 1;
case 2:
return 1;
case 4:
return 2;
case 16:
return 4;
case 36:
return 6;
default:
throw new InvalidOperationException("Cannot handle this number of data regions");
}
}
public int getSymbolDataWidth()
{
return getHorizontalDataRegions() * matrixWidth;
}
public int getSymbolDataHeight()
{
return getVerticalDataRegions() * matrixHeight;
}
public int getSymbolWidth()
{
return getSymbolDataWidth() + (getHorizontalDataRegions() * 2);
}
public int getSymbolHeight()
{
return getSymbolDataHeight() + (getVerticalDataRegions() * 2);
}
public int getCodewordCount()
{
return dataCapacity + errorCodewords;
}
virtual public int getInterleavedBlockCount()
{
return dataCapacity / rsBlockData;
}
virtual public int getDataLengthForInterleavedBlock(int index)
{
return rsBlockData;
}
public int getErrorLengthForInterleavedBlock(int index)
{
return rsBlockError;
}
public override String ToString()
{
var sb = new StringBuilder();
sb.Append(rectangular ? "Rectangular Symbol:" : "Square Symbol:");
sb.Append(" data region ").Append(matrixWidth).Append('x').Append(matrixHeight);
sb.Append(", symbol size ").Append(getSymbolWidth()).Append('x').Append(getSymbolHeight());
sb.Append(", symbol data size ").Append(getSymbolDataWidth()).Append('x').Append(getSymbolDataHeight());
sb.Append(", codewords ").Append(dataCapacity).Append('+').Append(errorCodewords);
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace ZXing.Datamatrix.Encoder
{
/// <summary>
/// Enumeration for DataMatrix symbol shape hint. It can be used to force square or rectangular
/// symbols.
/// </summary>
public enum SymbolShapeHint
{
FORCE_NONE,
FORCE_SQUARE,
FORCE_RECTANGLE,
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
internal sealed class TextEncoder : C40Encoder
{
override public int EncodingMode
{
get { return Encodation.TEXT; }
}
override protected int encodeChar(char c, StringBuilder sb)
{
if (c == ' ')
{
sb.Append('\u0003');
return 1;
}
if (c >= '0' && c <= '9')
{
sb.Append((char)(c - 48 + 4));
return 1;
}
if (c >= 'a' && c <= 'z')
{
sb.Append((char)(c - 97 + 14));
return 1;
}
if (c >= '\u0000' && c <= '\u001f')
{
sb.Append('\u0000'); //Shift 1 Set
sb.Append(c);
return 2;
}
if (c >= '!' && c <= '/')
{
sb.Append('\u0001'); //Shift 2 Set
sb.Append((char)(c - 33));
return 2;
}
if (c >= ':' && c <= '@')
{
sb.Append('\u0001'); //Shift 2 Set
sb.Append((char)(c - 58 + 15));
return 2;
}
if (c >= '[' && c <= '_')
{
sb.Append('\u0001'); //Shift 2 Set
sb.Append((char)(c - 91 + 22));
return 2;
}
if (c == '\u0060')
{
sb.Append('\u0002'); //Shift 3 Set
sb.Append((char)(c - 96));
return 2;
}
if (c >= 'A' && c <= 'Z')
{
sb.Append('\u0002'); //Shift 3 Set
sb.Append((char)(c - 65 + 1));
return 2;
}
if (c >= '{' && c <= '\u007f')
{
sb.Append('\u0002'); //Shift 3 Set
sb.Append((char)(c - 123 + 27));
return 2;
}
if (c >= '\u0080')
{
sb.Append("\u0001\u001e"); //Shift 2, Upper Shift
int len = 2;
len += encodeChar((char)(c - 128), sb);
return len;
}
HighLevelEncoder.illegalCharacter(c);
return -1;
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2006-2007 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Text;
namespace ZXing.Datamatrix.Encoder
{
internal sealed class X12Encoder : C40Encoder
{
public override int EncodingMode
{
get { return Encodation.X12; }
}
public override void encode(EncoderContext context)
{
//step C
var buffer = new StringBuilder();
int currentMode = EncodingMode;
while (context.HasMoreCharacters)
{
char c = context.CurrentChar;
context.Pos++;
encodeChar(c, buffer);
int count = buffer.Length;
if ((count%3) == 0)
{
writeNextTriplet(context, buffer);
int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, currentMode);
if (newMode != currentMode)
{
context.signalEncoderChange(newMode);
break;
}
}
}
handleEOD(context, buffer);
}
protected override int encodeChar(char c, StringBuilder sb)
{
if (c == '\r')
{
sb.Append('\u0000');
}
else if (c == '*')
{
sb.Append('\u0001');
}
else if (c == '>')
{
sb.Append('\u0002');
}
else if (c == ' ')
{
sb.Append('\u0003');
}
else if (c >= '0' && c <= '9')
{
sb.Append((char) (c - 48 + 4));
}
else if (c >= 'A' && c <= 'Z')
{
sb.Append((char) (c - 65 + 14));
}
else
{
HighLevelEncoder.illegalCharacter(c);
}
return 1;
}
protected override void handleEOD(EncoderContext context, StringBuilder buffer)
{
context.updateSymbolInfo();
int available = context.SymbolInfo.dataCapacity - context.CodewordCount;
int count = buffer.Length;
context.Pos -= count;
if (context.RemainingCharacters > 1 || available > 1 ||
context.RemainingCharacters != available)
context.writeCodeword(HighLevelEncoder.X12_UNLATCH);
if (context.NewEncoding < 0)
context.signalEncoderChange(Encodation.ASCII);
}
}
}