You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
12 KiB

/*
DataMatrix.Net
DataMatrix.Net - .net library for decoding DataMatrix codes.
Copyright (C) 2009/2010 Michael Faschinger
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
You can also redistribute and/or modify it under the terms of the
GNU Lesser General Public License as published by the Free Software
Foundation; either version 3.0 of the License or (at your option)
any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License or the GNU Lesser General Public License
for more details.
You should have received a copy of the GNU General Public
License and the GNU Lesser General Public License along with this
library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Contact: Michael Faschinger - michfasch@gmx.at
*/
using System;
namespace DataMatrix.net
{
internal static class DmtxCommon
{
internal static void GenReedSolEcc(DmtxMessage message, DmtxSymbolSize sizeIdx)
{
byte[] g = new byte[69];
byte[] b = new byte[68];
int symbolDataWords = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx);
int symbolErrorWords = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolErrorWords, sizeIdx);
int symbolTotalWords = symbolDataWords + symbolErrorWords;
int blockErrorWords = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribBlockErrorWords, sizeIdx);
int step = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribInterleavedBlocks, sizeIdx);
if (blockErrorWords != symbolErrorWords / step)
{
throw new Exception("Error generation reed solomon error correction");
}
for (int gI = 0; gI < g.Length; gI++)
{
g[gI] = 0x01;
}
// Generate ECC polynomia
for (int i = 1; i <= blockErrorWords; i++)
{
for (int j = i - 1; j >= 0; j--)
{
g[j] = GfDoublify(g[j], i); // g[j] *= 2**i
if (j > 0)
g[j] = GfSum(g[j], g[j - 1]); // g[j] += g[j-1]
}
}
// Populate error codeword array
for (int block = 0; block < step; block++)
{
for (int bI = 0; bI < b.Length; bI++)
{
b[bI] = 0;
}
for (int i = block; i < symbolDataWords; i += step)
{
int val = GfSum(b[blockErrorWords - 1], message.Code[i]);
for (int j = blockErrorWords - 1; j > 0; j--)
{
b[j] = GfSum(b[j - 1], GfProduct(g[j], val));
}
b[0] = GfProduct(g[0], val);
}
int blockDataWords = GetBlockDataSize(sizeIdx, block);
int bIndex = blockErrorWords;
for (int i = block + (step * blockDataWords); i < symbolTotalWords; i += step)
{
message.Code[i] = b[--bIndex];
}
if (bIndex != 0)
{
throw new Exception("Error generation error correction code!");
}
}
}
private static byte GfProduct(byte a, int b)
{
if (a == 0 || b == 0)
return 0;
return (byte)DmtxConstants.aLogVal[(DmtxConstants.logVal[a] + DmtxConstants.logVal[b]) % 255];
}
private static byte GfSum(byte a, byte b)
{
return (byte)(a ^ b);
}
private static byte GfDoublify(byte a, int b)
{
if (a == 0) /* XXX this is right, right? */
return 0;
if (b == 0)
return a; /* XXX this is right, right? */
return (byte)DmtxConstants.aLogVal[(DmtxConstants.logVal[a] + b) % 255];
}
internal static int GetSymbolAttribute(DmtxSymAttribute attribute, DmtxSymbolSize sizeIdx)
{
if (sizeIdx < 0 || (int)sizeIdx >= DmtxConstants.DmtxSymbolSquareCount + DmtxConstants.DmtxSymbolRectCount)
return DmtxConstants.DmtxUndefined;
switch (attribute)
{
case DmtxSymAttribute.DmtxSymAttribSymbolRows:
return DmtxConstants.SymbolRows[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribSymbolCols:
return DmtxConstants.SymbolCols[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribDataRegionRows:
return DmtxConstants.DataRegionRows[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribDataRegionCols:
return DmtxConstants.DataRegionCols[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribHorizDataRegions:
return DmtxConstants.HorizDataRegions[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribVertDataRegions:
return ((int)sizeIdx < DmtxConstants.DmtxSymbolSquareCount) ? DmtxConstants.HorizDataRegions[(int)sizeIdx] : 1;
case DmtxSymAttribute.DmtxSymAttribMappingMatrixRows:
return DmtxConstants.DataRegionRows[(int)sizeIdx] *
GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribVertDataRegions, sizeIdx);
case DmtxSymAttribute.DmtxSymAttribMappingMatrixCols:
return DmtxConstants.DataRegionCols[(int)sizeIdx] * DmtxConstants.HorizDataRegions[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribInterleavedBlocks:
return DmtxConstants.InterleavedBlocks[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribBlockErrorWords:
return DmtxConstants.BlockErrorWords[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribBlockMaxCorrectable:
return DmtxConstants.BlockMaxCorrectable[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribSymbolDataWords:
return DmtxConstants.SymbolDataWords[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribSymbolErrorWords:
return DmtxConstants.BlockErrorWords[(int)sizeIdx] * DmtxConstants.InterleavedBlocks[(int)sizeIdx];
case DmtxSymAttribute.DmtxSymAttribSymbolMaxCorrectable:
return DmtxConstants.BlockMaxCorrectable[(int)sizeIdx] * DmtxConstants.InterleavedBlocks[(int)sizeIdx];
}
return DmtxConstants.DmtxUndefined;
}
internal static int GetBlockDataSize(DmtxSymbolSize sizeIdx, int blockIdx)
{
int symbolDataWords = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx);
int interleavedBlocks = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribInterleavedBlocks, sizeIdx);
int count = symbolDataWords / interleavedBlocks;
if (symbolDataWords < 1 || interleavedBlocks < 1)
return DmtxConstants.DmtxUndefined;
return (sizeIdx == DmtxSymbolSize.DmtxSymbol144x144 && blockIdx < 8) ? count + 1 : count;
}
internal static DmtxSymbolSize FindCorrectSymbolSize(int dataWords, DmtxSymbolSize sizeIdxRequest)
{
DmtxSymbolSize sizeIdx;
if (dataWords <= 0)
{
return DmtxSymbolSize.DmtxSymbolShapeAuto;
}
if (sizeIdxRequest == DmtxSymbolSize.DmtxSymbolSquareAuto || sizeIdxRequest == DmtxSymbolSize.DmtxSymbolRectAuto)
{
DmtxSymbolSize idxBeg;
DmtxSymbolSize idxEnd;
if (sizeIdxRequest == DmtxSymbolSize.DmtxSymbolSquareAuto)
{
idxBeg = 0;
idxEnd = (DmtxSymbolSize)DmtxConstants.DmtxSymbolSquareCount;
}
else
{
idxBeg = (DmtxSymbolSize)DmtxConstants.DmtxSymbolSquareCount;
idxEnd = (DmtxSymbolSize)(DmtxConstants.DmtxSymbolSquareCount + DmtxConstants.DmtxSymbolRectCount);
}
for (sizeIdx = idxBeg; sizeIdx < idxEnd; sizeIdx++)
{
if (GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx) >= dataWords)
break;
}
if (sizeIdx == idxEnd)
{
return DmtxSymbolSize.DmtxSymbolShapeAuto;
}
}
else
{
sizeIdx = sizeIdxRequest;
}
if (dataWords > GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx))
{
return DmtxSymbolSize.DmtxSymbolShapeAuto;
}
return sizeIdx;
}
internal static int GetBitsPerPixel(DmtxPackOrder pack)
{
switch (pack)
{
case DmtxPackOrder.DmtxPack1bppK:
return 1;
case DmtxPackOrder.DmtxPack8bppK:
return 8;
case DmtxPackOrder.DmtxPack16bppRGB:
case DmtxPackOrder.DmtxPack16bppRGBX:
case DmtxPackOrder.DmtxPack16bppXRGB:
case DmtxPackOrder.DmtxPack16bppBGR:
case DmtxPackOrder.DmtxPack16bppBGRX:
case DmtxPackOrder.DmtxPack16bppXBGR:
case DmtxPackOrder.DmtxPack16bppYCbCr:
return 16;
case DmtxPackOrder.DmtxPack24bppRGB:
case DmtxPackOrder.DmtxPack24bppBGR:
case DmtxPackOrder.DmtxPack24bppYCbCr:
return 24;
case DmtxPackOrder.DmtxPack32bppRGBX:
case DmtxPackOrder.DmtxPack32bppXRGB:
case DmtxPackOrder.DmtxPack32bppBGRX:
case DmtxPackOrder.DmtxPack32bppXBGR:
case DmtxPackOrder.DmtxPack32bppCMYK:
return 32;
}
return DmtxConstants.DmtxUndefined;
}
internal static T Min<T>(T x, T y) where T : IComparable<T>
{
return x.CompareTo(y) < 0 ? x : y;
}
internal static T Max<T>(T x, T y) where T : IComparable<T>
{
return x.CompareTo(y) < 0 ? y : x;
}
internal static bool DecodeCheckErrors(byte[] code, int codeIndex, DmtxSymbolSize sizeIdx, int fix)
{
byte[] data = new byte[255];
int interleavedBlocks = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribInterleavedBlocks, sizeIdx);
int blockErrorWords = GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribBlockErrorWords, sizeIdx);
const int fixedErr = 0;
int fixedErrSum = 0;
for (int i = 0; i < interleavedBlocks; i++)
{
int blockTotalWords = blockErrorWords + GetBlockDataSize(sizeIdx, i);
int j;
for (j = 0; j < blockTotalWords; j++)
data[j] = code[j * interleavedBlocks + i];
fixedErrSum += fixedErr;
for (j = 0; j < blockTotalWords; j++)
code[j * interleavedBlocks + i] = data[j];
}
if (fix != DmtxConstants.DmtxUndefined && fix >= 0 && fix < fixedErrSum)
{
return false;
}
return true;
}
internal static double RightAngleTrueness(DmtxVector2 c0, DmtxVector2 c1, DmtxVector2 c2, double angle)
{
DmtxVector2 vA = (c0 - c1);
DmtxVector2 vB = (c2 - c1);
vA.Norm();
vB.Norm();
DmtxMatrix3 m = DmtxMatrix3.Rotate(angle);
vB *= m;
return vA.Dot(vB);
}
}
}