public DataMatrixExtraction(Bitmap sourceImage, FinderPatternPair fpp) { this.fpp = fpp; PointF p1 = fpp.p1.X < fpp.p2.X ? fpp.p1.ToF() : fpp.p2.ToF(); PointF p2 = fpp.p1.X < fpp.p2.X ? fpp.p2.ToF() : fpp.p1.ToF(); PointF vect = PointOps.Mult(PointOps.Sub(p2, p1), 0.1f); float unit = (float)PointOps.Distance(vect); PointF normX = PointOps.Normalize(vect); angX = Math.Atan2(normX.Y, normX.X); double angY = angX - Math.PI / 2; PointF normY = new PointF((float)Math.Cos(angY), (float)Math.Sin(angY)); topLeft = PointOps.Add(p1, PointOps.Add(PointOps.Mult(normX, unit), PointOps.Mult(normY, unit))); bottomLeft = PointOps.Add(p1, PointOps.Sub(PointOps.Mult(normX, unit), PointOps.Mult(normY, unit))); topRight = PointOps.Add(p1, PointOps.Add(PointOps.Mult(normX, unit * 9), PointOps.Mult(normY, unit))); bottomRight = PointOps.Add(p1, PointOps.Sub(PointOps.Mult(normX, unit * 9), PointOps.Mult(normY, unit))); rotatedMatrix = new Bitmap((int)Math.Ceiling(unit * 8), (int)Math.Ceiling(unit * 2), PixelFormat.Format32bppArgb); Graphics rotG = Graphics.FromImage(rotatedMatrix); rotG.RotateTransform((float)(-angX * 180 / Math.PI)); float diagonal = (float)PointOps.Distance(p1, p2); rotG.DrawImage( sourceImage, new RectangleF(-diagonal, -diagonal, diagonal * 2, diagonal * 2), new RectangleF(topLeft.X - diagonal, topLeft.Y - diagonal, diagonal * 2, diagonal * 2), GraphicsUnit.Pixel); rotG.Dispose(); int[] cellSum = new int[DataMatrixDrawer.rowCount * DataMatrixDrawer.columnCount]; unsafe { BitmapData bd = rotatedMatrix.LockBits(ImageLockMode.ReadOnly); byte * ptr = (byte *)bd.Scan0.ToPointer(); for (int y = 0; y < rotatedMatrix.Height; y++) { for (int x = 0; x < rotatedMatrix.Width; x++) { int cx = (int)Math.Floor((float)x * DataMatrixDrawer.columnCount / rotatedMatrix.Width); int cy = (int)Math.Floor((float)y * DataMatrixDrawer.rowCount / rotatedMatrix.Height); cellSum[cy * DataMatrixDrawer.columnCount + cx] += *ptr; ptr += 4; } } rotatedMatrix.UnlockBits(bd); } double threshold = ValueClustering.DivThreshold(cellSum); extractedData = new bool[DataMatrixDrawer.rowCount * DataMatrixDrawer.columnCount]; for (int q = 0; q < DataMatrixDrawer.rowCount * DataMatrixDrawer.columnCount; q++) { extractedData[q] = cellSum[q] < threshold; } }
/* * Locates top-left cell corner at `x` column and `y` row. */ public PointF GetTopLeftCellCorner(int x, int y) { PointF p = origin; for (int q = 0; q < x; q++) { p = PointOps.Add(p, PointOps.Mult(horizontalNormal, columnWidths[q])); } for (int q = 0; q < y; q++) { p = PointOps.Add(p, PointOps.Mult(verticalNormal, rowHeights[q])); } return(p); }
/* * Draw a table on provided graphics canvas with provided pen. */ public void DrawTable(Graphics g, Pen p) { PointF row = PointOps.Mult(horizontalNormal, totalWidth); PointF r = origin; g.DrawLine(p, r, PointOps.Add(r, row)); for (int q = 0; q < rowHeights.Count; q++) { r = PointOps.Add(r, PointOps.Mult(verticalNormal, rowHeights[q])); g.DrawLine(p, r, PointOps.Add(r, row)); } PointF col = PointOps.Mult(verticalNormal, totalHeight); PointF c = origin; g.DrawLine(p, c, PointOps.Add(c, col)); for (int q = 0; q < columnWidths.Count; q++) { c = PointOps.Add(c, PointOps.Mult(horizontalNormal, columnWidths[q])); g.DrawLine(p, c, PointOps.Add(c, col)); } }