272 lines
10 KiB
C#
272 lines
10 KiB
C#
|
|
using System;
|
|||
|
|
|
|||
|
|
namespace DataMatrix4Net
|
|||
|
|
{
|
|||
|
|
public class DataMatrix
|
|||
|
|
{
|
|||
|
|
///
|
|||
|
|
/// Public interface
|
|||
|
|
///
|
|||
|
|
public bool isContainMatrix { get { return Matrix != null; } }
|
|||
|
|
public Gma.QrCodeNet.Encoding.BitMatrix Matrix;
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Internal member variables
|
|||
|
|
///
|
|||
|
|
readonly SymbolSize chosenSize;
|
|||
|
|
readonly bool[,] visited;
|
|||
|
|
int width { get { return isContainMatrix ? Matrix.Width : 0; } }
|
|||
|
|
int height { get { return isContainMatrix ? Matrix.Height : 0; } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Data matrix constructor
|
|||
|
|
/// Data matrix size up to 26x26 supported, one data region.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="content">Content of the data matrix (ASCII characters only)</param>
|
|||
|
|
/// <param name="symbolSize">Chosen data matrix size</param>
|
|||
|
|
public DataMatrix(string content, SymbolSize symbolSize = SymbolSize.SquareAuto)
|
|||
|
|
{
|
|||
|
|
byte[] contentBytes = Utils.MakeByteArray(content);
|
|||
|
|
|
|||
|
|
if (symbolSize >= 0)
|
|||
|
|
{
|
|||
|
|
chosenSize = symbolSize;
|
|||
|
|
}
|
|||
|
|
else if (symbolSize == SymbolSize.SquareAuto)
|
|||
|
|
{
|
|||
|
|
for (SymbolSize ss = 0; ss < Symbol.SymbolSquareCount; ss++)
|
|||
|
|
{
|
|||
|
|
if (contentBytes.Length <= Symbol.GetSymbolAttribute(SymbolAttribute.SymbolDataWords, ss))
|
|||
|
|
{
|
|||
|
|
chosenSize = ss;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int w = Symbol.GetSymbolAttribute(SymbolAttribute.SymbolCols, chosenSize);
|
|||
|
|
int h = Symbol.GetSymbolAttribute(SymbolAttribute.SymbolRows, chosenSize);
|
|||
|
|
if (w == -1 || h == -1)
|
|||
|
|
{
|
|||
|
|
throw new ArgumentOutOfRangeException("symboSize");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Add padding and Reed-Solomon error correction bytes to the content
|
|||
|
|
byte[] data = ReedSolomon.Encode(contentBytes, chosenSize);
|
|||
|
|
|
|||
|
|
/// Create matrix, fill in frame cells
|
|||
|
|
Matrix = new MyBitMatrix(w, h);
|
|||
|
|
visited = new bool[w - 2, h - 2];
|
|||
|
|
MakeFrame(chosenSize);
|
|||
|
|
|
|||
|
|
int ix = 0;
|
|||
|
|
int x = 0; /// inside data region in the range 0 .. width-2 (x coordinate, frame excluded)
|
|||
|
|
int y = 4; /// inside data region in the range 0 .. height-2 (y coordinate, frame excluded)
|
|||
|
|
|
|||
|
|
/// Walk through the data matrix area and fill in data bytes
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (x == 0 && y == height - 2)
|
|||
|
|
{
|
|||
|
|
PlaceByteSpecial1(data[ix++], width, height);
|
|||
|
|
}
|
|||
|
|
else if (x == 0 && y == height - 4 && (height - 2) % 4 != 0)
|
|||
|
|
{
|
|||
|
|
PlaceByteSpecial2(data[ix++], width, height);
|
|||
|
|
}
|
|||
|
|
else if (x == 0 && y == height - 4 && (height - 2) % 8 == 4)
|
|||
|
|
{
|
|||
|
|
PlaceByteSpecial3(data[ix++], width, height);
|
|||
|
|
}
|
|||
|
|
else if (x == 2 && y == height + 2 && (height - 2) % 8 == 0)
|
|||
|
|
{
|
|||
|
|
PlaceByteSpecial4(data[ix++], width, height);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (x >= 0 && y < height - 2 && !visited[x, y])
|
|||
|
|
{
|
|||
|
|
PlaceByteStandard(data[ix++], x, y, width, height);
|
|||
|
|
visited[x, y] = true;
|
|||
|
|
}
|
|||
|
|
x += 2;
|
|||
|
|
y -= 2;
|
|||
|
|
}
|
|||
|
|
while (x < width - 2 && y >= 0);
|
|||
|
|
x += 3;
|
|||
|
|
y += 1;
|
|||
|
|
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
if (x < width - 2 && y >= 0 && !visited[x, y])
|
|||
|
|
{
|
|||
|
|
PlaceByteStandard(data[ix++], x, y, width, height);
|
|||
|
|
visited[x, y] = true;
|
|||
|
|
}
|
|||
|
|
x -= 2;
|
|||
|
|
y += 2;
|
|||
|
|
}
|
|||
|
|
while (x >= 0 && y < height - 2);
|
|||
|
|
x += 1;
|
|||
|
|
y += 3;
|
|||
|
|
}
|
|||
|
|
while (ix < data.Length);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// All matrix sizes
|
|||
|
|
void PlaceByteSpecial1(byte dataByte, int width, int height)
|
|||
|
|
{
|
|||
|
|
Matrix[width - 2, 4] = (dataByte & 0x01) != 0;
|
|||
|
|
Matrix[width - 2, 3] = (dataByte & 0x02) != 0;
|
|||
|
|
Matrix[width - 2, 2] = (dataByte & 0x04) != 0;
|
|||
|
|
Matrix[width - 2, 1] = (dataByte & 0x08) != 0;
|
|||
|
|
Matrix[width - 3, 1] = (dataByte & 0x10) != 0;
|
|||
|
|
Matrix[3, height - 2] = (dataByte & 0x20) != 0;
|
|||
|
|
Matrix[2, height - 2] = (dataByte & 0x40) != 0;
|
|||
|
|
Matrix[1, height - 2] = (dataByte & 0x80) != 0;
|
|||
|
|
|
|||
|
|
visited[width - 3, 3] = true;
|
|||
|
|
visited[width - 3, 2] = true;
|
|||
|
|
visited[width - 3, 1] = true;
|
|||
|
|
visited[width - 3, 0] = true;
|
|||
|
|
visited[width - 4, 0] = true;
|
|||
|
|
visited[2, height - 3] = true;
|
|||
|
|
visited[1, height - 3] = true;
|
|||
|
|
visited[0, height - 3] = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PlaceByteSpecial2(byte dataByte, int width, int height)
|
|||
|
|
{
|
|||
|
|
Matrix[width - 2, 2] = (dataByte & 0x01) != 0;
|
|||
|
|
Matrix[width - 2, 1] = (dataByte & 0x02) != 0;
|
|||
|
|
Matrix[width - 3, 1] = (dataByte & 0x04) != 0;
|
|||
|
|
Matrix[width - 4, 1] = (dataByte & 0x08) != 0;
|
|||
|
|
Matrix[width - 5, 1] = (dataByte & 0x10) != 0;
|
|||
|
|
Matrix[1, height - 2] = (dataByte & 0x20) != 0;
|
|||
|
|
Matrix[1, height - 3] = (dataByte & 0x40) != 0;
|
|||
|
|
Matrix[1, height - 4] = (dataByte & 0x80) != 0;
|
|||
|
|
|
|||
|
|
visited[width - 3, 1] = true;
|
|||
|
|
visited[width - 3, 0] = true;
|
|||
|
|
visited[width - 4, 0] = true;
|
|||
|
|
visited[width - 5, 0] = true;
|
|||
|
|
visited[width - 6, 0] = true;
|
|||
|
|
visited[0, height - 3] = true;
|
|||
|
|
visited[0, height - 4] = true;
|
|||
|
|
visited[0, height - 5] = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PlaceByteSpecial3(byte dataByte, int width, int height)
|
|||
|
|
{
|
|||
|
|
Matrix[width - 2, 2] = (dataByte & 0x01) != 0;
|
|||
|
|
Matrix[width - 3, 2] = (dataByte & 0x02) != 0;
|
|||
|
|
Matrix[width - 4, 2] = (dataByte & 0x04) != 0;
|
|||
|
|
Matrix[width - 2, 1] = (dataByte & 0x08) != 0;
|
|||
|
|
Matrix[width - 3, 1] = (dataByte & 0x10) != 0;
|
|||
|
|
Matrix[width - 4, 1] = (dataByte & 0x20) != 0;
|
|||
|
|
Matrix[width - 2, height - 2] = (dataByte & 0x40) != 0;
|
|||
|
|
Matrix[1, height - 2] = (dataByte & 0x80) != 0;
|
|||
|
|
|
|||
|
|
visited[width - 3, 1] = true;
|
|||
|
|
visited[width - 4, 1] = true;
|
|||
|
|
visited[width - 5, 1] = true;
|
|||
|
|
visited[width - 3, 0] = true;
|
|||
|
|
visited[width - 4, 0] = true;
|
|||
|
|
visited[width - 5, 0] = true;
|
|||
|
|
visited[width - 3, height - 3] = true;
|
|||
|
|
visited[0, height - 3] = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PlaceByteSpecial4(byte dataByte, int width, int height)
|
|||
|
|
{
|
|||
|
|
Matrix[width - 2, 4] = (dataByte & 0x01) != 0;
|
|||
|
|
Matrix[width - 2, 3] = (dataByte & 0x02) != 0;
|
|||
|
|
Matrix[width - 2, 2] = (dataByte & 0x04) != 0;
|
|||
|
|
Matrix[width - 2, 1] = (dataByte & 0x08) != 0;
|
|||
|
|
Matrix[width - 3, 1] = (dataByte & 0x10) != 0;
|
|||
|
|
Matrix[1, height - 2] = (dataByte & 0x20) != 0;
|
|||
|
|
Matrix[1, height - 3] = (dataByte & 0x40) != 0;
|
|||
|
|
Matrix[1, height - 4] = (dataByte & 0x80) != 0;
|
|||
|
|
|
|||
|
|
visited[width - 3, 3] = true;
|
|||
|
|
visited[width - 3, 2] = true;
|
|||
|
|
visited[width - 3, 1] = true;
|
|||
|
|
visited[width - 3, 0] = true;
|
|||
|
|
visited[width - 4, 0] = true;
|
|||
|
|
visited[0, height - 3] = true;
|
|||
|
|
visited[0, height - 4] = true;
|
|||
|
|
visited[0, height - 5] = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
///
|
|||
|
|
/// Standard bit positioning (all matrix sizes)
|
|||
|
|
///
|
|||
|
|
int[] xOffs = new int[8] { 1, 0, -1, 1, 0, -1, 0, -1 };
|
|||
|
|
int[] yOffs = new int[8] { 1, 1, 1, 0, 0, 0, -1, -1 };
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Standard placemnt of a byte into a matrix
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="dataByte">Data byte</param>
|
|||
|
|
/// <param name="x">X-coordinate in range 0..width-2 (from left, frame excluded)</param>
|
|||
|
|
/// <param name="y">Y-coordinate in range 0..height-2 (from top, frame excluded)</param>
|
|||
|
|
/// <param name="width">Matrix width incl. frame</param>
|
|||
|
|
/// <param name="height">Matrix height incl. frame</param>
|
|||
|
|
void PlaceByteStandard(byte dataByte, int x, int y, int width, int height)
|
|||
|
|
{
|
|||
|
|
int mask = 1;
|
|||
|
|
for (int i = 0; i < 8; i++)
|
|||
|
|
{
|
|||
|
|
int xx = x + xOffs[i];
|
|||
|
|
int yy = y + yOffs[i];
|
|||
|
|
if (xx < 1)
|
|||
|
|
{
|
|||
|
|
xx += width - 2;
|
|||
|
|
yy += 4 - (width + 4) % 8;
|
|||
|
|
}
|
|||
|
|
else if (yy < 1)
|
|||
|
|
{
|
|||
|
|
xx += 4 - (height + 4) % 8;
|
|||
|
|
yy += height - 2;
|
|||
|
|
}
|
|||
|
|
Matrix[xx, yy] = (dataByte & mask) != 0;
|
|||
|
|
mask = mask << 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Crate data matrix frame.
|
|||
|
|
/// All square data matrix sizes supported (incl. 4, 16 and 36 data regions).
|
|||
|
|
/// </summary>
|
|||
|
|
void MakeFrame(SymbolSize size)
|
|||
|
|
{
|
|||
|
|
int drw = Symbol.GetSymbolAttribute(SymbolAttribute.DataRegionCols, size);
|
|||
|
|
int drh = Symbol.GetSymbolAttribute(SymbolAttribute.DataRegionRows, size);
|
|||
|
|
int totalhdr = Symbol.GetSymbolAttribute(SymbolAttribute.HorizDataRegions, size);
|
|||
|
|
int totalvdr = Symbol.GetSymbolAttribute(SymbolAttribute.VertDataRegions, size);
|
|||
|
|
|
|||
|
|
for (int hdr = 0; hdr < totalhdr; hdr++)
|
|||
|
|
{
|
|||
|
|
for (int vdr = 0; vdr < totalvdr; vdr++)
|
|||
|
|
{
|
|||
|
|
int offsx = hdr * (drw + 2);
|
|||
|
|
int offsy = vdr * (drh + 2);
|
|||
|
|
|
|||
|
|
for (int i = 0; i < drw + 2; i++)
|
|||
|
|
{
|
|||
|
|
Matrix[offsx + i, offsy + drh + 1] = true;
|
|||
|
|
if (i % 2 == 0) Matrix[offsx + i, offsy] = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (int j = 0; j < drh + 2; j++)
|
|||
|
|
{
|
|||
|
|
Matrix[offsx, offsy + j] = true;
|
|||
|
|
if (j % 2 == 1) Matrix[offsx + drw + 1, offsy + j] = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|