private DmtxEncode(DmtxEncode src) { this._scheme = src._scheme; this._sizeIdxRequest = src._sizeIdxRequest; this._marginSize = src._marginSize; this._moduleSize = src._moduleSize; this._pixelPacking = src._pixelPacking; this._imageFlip = src._imageFlip; this._rowPadBytes = src._rowPadBytes; this._image = src._image; this._message = src._message; this._method = src._method; this._region = src._region; }
private List <string> DecodeImage(Bitmap image, int maxResultCount, TimeSpan timeOut, bool isMosaic) { List <string> result = new List <string>(); int stride; byte[] rawImg = ImageToByteArray(image, out stride); DmtxImage dmtxImg = new DmtxImage(rawImg, image.Width, image.Height, DmtxPackOrder.DmtxPack24bppRGB); dmtxImg.RowPadBytes = stride % 3; DmtxDecode decode = new DmtxDecode(dmtxImg, 1); TimeSpan timeLeft = new TimeSpan(timeOut.Ticks); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); while (true) { if (stopWatch.Elapsed > timeOut) { break; } DmtxRegion region = decode.RegionFindNext(timeOut); if (region != null) { DmtxMessage msg = isMosaic ? decode.MosaicRegion(region, -1) : decode.MatrixRegion(region, -1); string message = Encoding.ASCII.GetString(msg.Output); message = message.Substring(0, message.IndexOf('\0')); if (!result.Contains(message)) { result.Add(message); if (result.Count >= maxResultCount) { break; } } } else { break; } } return(result); }
internal DmtxMessage MosaicRegion(DmtxRegion reg, int fix) { DmtxMessage oMsg; int colorPlane = reg.FlowBegin.Plane; reg.FlowBegin.Plane = 0; /* kind of a hack */ DmtxMessage rMsg = MatrixRegion(reg, fix); reg.FlowBegin.Plane = 1; /* kind of a hack */ DmtxMessage gMsg = MatrixRegion(reg, fix); reg.FlowBegin.Plane = 2; /* kind of a hack */ DmtxMessage bMsg = MatrixRegion(reg, fix); reg.FlowBegin.Plane = colorPlane; oMsg = new DmtxMessage(reg.SizeIdx, DmtxFormat.Mosaic); List<byte> totalMessage = new List<byte>(); for (int i = 0; i < bMsg.OutputSize; i++) { if (bMsg.Output[i] == 0) { break; } totalMessage.Add(bMsg.Output[i]); } for (int i = 0; i < gMsg.OutputSize; i++) { if (gMsg.Output[i] == 0) { break; } totalMessage.Add(gMsg.Output[i]); } for (int i = 0; i < rMsg.OutputSize; i++) { if (rMsg.Output[i] == 0) { break; } totalMessage.Add(rMsg.Output[i]); } totalMessage.Add(0); oMsg.Output = totalMessage.ToArray(); return oMsg; }
internal DmtxMessage MatrixRegion(DmtxRegion reg, int fix) { DmtxMessage result = new DmtxMessage(reg.SizeIdx, DmtxFormat.Matrix); DmtxVector2 topLeft = new DmtxVector2(); DmtxVector2 topRight = new DmtxVector2(); DmtxVector2 bottomLeft = new DmtxVector2(); DmtxVector2 bottomRight = new DmtxVector2(); DmtxPixelLoc pxTopLeft = new DmtxPixelLoc(); DmtxPixelLoc pxTopRight = new DmtxPixelLoc(); DmtxPixelLoc pxBottomLeft = new DmtxPixelLoc(); DmtxPixelLoc pxBottomRight = new DmtxPixelLoc(); if (!PopulateArrayFromMatrix(reg, result)) { throw new Exception("Populating Array from matrix failed!"); } /* maybe place remaining logic into new dmtxDecodePopulatedArray() function so other people can pass in their own arrays */ ModulePlacementEcc200(result.Array, result.Code, reg.SizeIdx, DmtxConstants.DmtxModuleOnRed | DmtxConstants.DmtxModuleOnGreen | DmtxConstants.DmtxModuleOnBlue); if (DmtxCommon.DecodeCheckErrors(result.Code, 0, reg.SizeIdx, fix) != true) { return null; } topLeft.X = bottomLeft.X = topLeft.Y = topRight.Y = -0.1; topRight.X = bottomRight.X = bottomLeft.Y = bottomRight.Y = 1.1; topLeft *= reg.Fit2raw; topRight *= reg.Fit2raw; bottomLeft *= reg.Fit2raw; bottomLeft *= reg.Fit2raw; pxTopLeft.X = (int)(0.5 + topLeft.X); pxTopLeft.Y = (int)(0.5 + topLeft.Y); pxBottomLeft.X = (int)(0.5 + bottomLeft.X); pxBottomLeft.Y = (int)(0.5 + bottomLeft.Y); pxTopRight.X = (int)(0.5 + topRight.X); pxTopRight.Y = (int)(0.5 + topRight.Y); pxBottomRight.X = (int)(0.5 + bottomRight.X); pxBottomRight.Y = (int)(0.5 + bottomRight.Y); CacheFillQuad(pxTopLeft, pxTopRight, pxBottomRight, pxBottomLeft); result.DecodeDataStream(reg.SizeIdx, null); return result; }
private bool PopulateArrayFromMatrix(DmtxRegion reg, DmtxMessage msg) { /* Capture number of regions present in barcode */ int xRegionTotal = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribHorizDataRegions, reg.SizeIdx); int yRegionTotal = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribVertDataRegions, reg.SizeIdx); /* Capture region dimensions (not including border modules) */ int mapWidth = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribDataRegionCols, reg.SizeIdx); int mapHeight = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribDataRegionRows, reg.SizeIdx); int weightFactor = 2 * (mapHeight + mapWidth + 2); if (weightFactor <= 0) { throw new ArgumentException("PopulateArrayFromMatrix error: Weight Factor must be greater 0"); } /* Tally module changes for each region in each direction */ for (int yRegionCount = 0; yRegionCount < yRegionTotal; yRegionCount++) { /* Y location of mapping region origin in symbol coordinates */ int yOrigin = yRegionCount * (mapHeight + 2) + 1; for (int xRegionCount = 0; xRegionCount < xRegionTotal; xRegionCount++) { int[,] tally = new int[24, 24]; /* Large enough to map largest single region */ /* X location of mapping region origin in symbol coordinates */ int xOrigin = xRegionCount * (mapWidth + 2) + 1; for (int i = 0; i < 24; i++) { for (int j = 0; j < 24; j++) { tally[i, j] = 0; } } TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirUp); TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirLeft); TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirDown); TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirRight); /* Decide module status based on final tallies */ for (int mapRow = 0; mapRow < mapHeight; mapRow++) { for (int mapCol = 0; mapCol < mapWidth; mapCol++) { int rowTmp = (yRegionCount * mapHeight) + mapRow; rowTmp = yRegionTotal * mapHeight - rowTmp - 1; int colTmp = (xRegionCount * mapWidth) + mapCol; int idx = (rowTmp * xRegionTotal * mapWidth) + colTmp; if (tally[mapRow, mapCol] / (double)weightFactor >= 0.5) msg.Array[idx] = (byte)DmtxConstants.DmtxModuleOnRGB; else msg.Array[idx] = (byte)DmtxConstants.DmtxModuleOff; msg.Array[idx] |= (byte)DmtxConstants.DmtxModuleAssigned; } } } } return true; }
internal bool EncodeDataMatrix(Color? foreColor, Color? backColor, byte[] inputString) { int padCount; int width, height, bitsPerPixel; byte[] buf = new byte[4096]; byte[] pxl; /* Encode input string into data codewords */ DmtxSymbolSize sizeIdx = this._sizeIdxRequest; int dataWordCount = EncodeDataCodewords(buf, inputString, ref sizeIdx); if (dataWordCount <= 0) { return false; } /* EncodeDataCodewords() should have updated any auto sizeIdx to a real one */ if (sizeIdx == DmtxSymbolSize.DmtxSymbolSquareAuto || sizeIdx == DmtxSymbolSize.DmtxSymbolRectAuto) { throw new Exception("Invalid symbol size for encoding!"); } /* Add pad characters to match a standard symbol size (whether smallest or requested) */ padCount = AddPadChars(buf, ref dataWordCount, DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx)); /* XXX we can remove a lot of this redundant data */ this._region = new DmtxRegion(); this._region.SizeIdx = sizeIdx; this._region.SymbolRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolRows, sizeIdx); this._region.SymbolCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolCols, sizeIdx); this._region.MappingRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribMappingMatrixRows, sizeIdx); this._region.MappingCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribMappingMatrixCols, sizeIdx); /* Allocate memory for message and array */ this._message = new DmtxMessage(sizeIdx, DmtxFormat.Matrix); this._message.PadCount = padCount; for (int i = 0; i < dataWordCount; i++) { this._message.Code[i] = buf[i]; } /* Generate error correction codewords */ DmtxCommon.GenReedSolEcc(this._message, this._region.SizeIdx); /* Module placement in region */ DmtxDecode.ModulePlacementEcc200(this._message.Array, this._message.Code, this._region.SizeIdx, DmtxConstants.DmtxModuleOnRGB); width = 2 * this._marginSize + (this._region.SymbolCols * this._moduleSize); height = 2 * this._marginSize + (this._region.SymbolRows * this._moduleSize); bitsPerPixel = DmtxCommon.GetBitsPerPixel(this._pixelPacking); if (bitsPerPixel == DmtxConstants.DmtxUndefined) return false; if (bitsPerPixel % 8 != 0) { throw new Exception("Invalid color depth for encoding!"); } /* Allocate memory for the image to be generated */ // pxl = (unsigned char *)malloc(width * height * (bitsPerPixel/8) + enc->rowPadBytes); pxl = new byte[width * height * (bitsPerPixel / 8) + this._rowPadBytes]; this._image = new DmtxImage(pxl, width, height, this._pixelPacking); this._image.ImageFlip = this._imageFlip; this._image.RowPadBytes = this._rowPadBytes; /* Insert finder and aligment pattern modules */ PrintPattern(foreColor, backColor); return true; }
internal static void GenReedSolEcc(DmtxMessage message, DmtxSymbolSize sizeIdx) { byte[] g = new byte[69]; byte[] b = new byte[68]; int bIndex = 0;; 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); 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!"); } } }