/* 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 struct DmtxScanGrid { #region Fields int _minExtent; int _maxExtent; int _xOffset; int _yOffset; int _xMin; int _xMax; int _yMin; int _yMax; int _total; int _extent; int _jumpSize; int _pixelTotal; int _startPos; int _pixelCount; int _xCenter; int _yCenter; #endregion #region Constructors internal DmtxScanGrid(DmtxDecode dec) { int smallestFeature = dec.ScanGap; this._xMin = dec.XMin; this._xMax = dec.XMax; this._yMin = dec.YMin; this._yMax = dec.YMax; /* Values that get set once */ int xExtent = this._xMax - this._xMin; int yExtent = this._yMax - this._yMin; int maxExtent = (xExtent > yExtent) ? xExtent : yExtent; if (maxExtent < 1) { throw new ArgumentException("Invalid max extent for Scan Grid: Must be greater than 0"); } int extent = 1; this._minExtent = extent; for (; extent < maxExtent; extent = ((extent + 1) * 2) - 1) { if (extent <= smallestFeature) { _minExtent = extent; } } this._maxExtent = extent ; this._xOffset = (this._xMin + this._xMax - this._maxExtent) / 2; this._yOffset = (this._yMin + this._yMax - this._maxExtent) / 2; /* Values that get reset for every level */ this._total = 1; this._extent = this._maxExtent; this._jumpSize = this._extent + 1; this._pixelTotal = 2 * this._extent - 1; this._startPos = this._extent / 2; this._pixelCount = 0; this._xCenter = this._yCenter = this._startPos; SetDerivedFields(); } #endregion #region Methods internal DmtxRange PopGridLocation(ref DmtxPixelLoc loc) { DmtxRange locStatus; do { locStatus = GetGridCoordinates(ref loc); /* Always leave grid pointing at next available location */ this._pixelCount++; } while (locStatus == DmtxRange.DmtxRangeBad); return locStatus; } private DmtxRange GetGridCoordinates(ref DmtxPixelLoc locRef) { /* Initially pixelCount may fall beyond acceptable limits. Update grid * state before testing coordinates */ /* Jump to next cross pattern horizontally if current column is done */ if (this._pixelCount >= this._pixelTotal) { this._pixelCount = 0; this._xCenter += this._jumpSize; } /* Jump to next cross pattern vertically if current row is done */ if (this._xCenter > this._maxExtent) { this._xCenter = this._startPos; this._yCenter += this._jumpSize; } /* Increment level when vertical step goes too far */ if (this._yCenter > this._maxExtent) { this._total *= 4; this._extent /= 2; SetDerivedFields(); } if (this._extent == 0 || this._extent < this._minExtent) { locRef.X = locRef.Y = -1; return DmtxRange.DmtxRangeEnd; } int count = this._pixelCount; if (count >= this._pixelTotal) { throw new Exception("Scangrid is beyong image limits!"); } DmtxPixelLoc loc = new DmtxPixelLoc(); if (count == this._pixelTotal - 1) { /* center pixel */ loc.X = this._xCenter; loc.Y = this._yCenter; } else { int half = this._pixelTotal / 2; int quarter = half / 2; /* horizontal portion */ if (count < half) { loc.X = this._xCenter + ((count < quarter) ? (count - quarter) : (half - count)); loc.Y = this._yCenter; } /* vertical portion */ else { count -= half; loc.X = this._xCenter; loc.Y = this._yCenter + ((count < quarter) ? (count - quarter) : (half - count)); } } loc.X += this._xOffset; loc.Y += this._yOffset; locRef.X = loc.X; locRef.Y = loc.Y; if (loc.X < this._xMin || loc.X > this._xMax || loc.Y < this._yMin || loc.Y > this._yMax) { return DmtxRange.DmtxRangeBad; } return DmtxRange.DmtxRangeGood; } /// /// Update derived fields based on current state /// private void SetDerivedFields() { this._jumpSize = this._extent + 1; this._pixelTotal = 2 * this._extent - 1; this._startPos = this._extent / 2; this._pixelCount = 0; this._xCenter = this._yCenter = this._startPos; } #endregion #region Properties /// /// Smallest cross size used in scan /// internal int MinExtent { get { return _minExtent; } set { _minExtent = value; } } /// /// Size of bounding grid region (2^N - 1) /// internal int MaxExtent { get { return _maxExtent; } set { _maxExtent = value; } } /// /// Offset to obtain image X coordinate /// internal int XOffset { get { return _xOffset; } set { _xOffset = value; } } /// /// Offset to obtain image Y coordinate /// internal int YOffset { get { return _yOffset; } set { _yOffset = value; } } /// /// Minimum X in image coordinate system /// internal int XMin { get { return _xMin; } set { _xMin = value; } } /// /// Maximum X in image coordinate system /// internal int XMax { get { return _xMax; } set { _xMax = value; } } /// /// Minimum Y in image coordinate system /// internal int YMin { get { return _yMin; } set { _yMin = value; } } /// /// Maximum Y in image coordinate system /// internal int YMax { get { return _yMax; } set { _yMax = value; } } /// /// Total number of crosses at this size /// internal int Total { get { return _total; } set { _total = value; } } /// /// Length/width of cross in pixels /// internal int Extent { get { return _extent; } set { _extent = value; } } /// /// Distance in pixels between cross centers /// internal int JumpSize { get { return _jumpSize; } set { _jumpSize = value; } } /// /// Total pixel count within an individual cross path /// internal int PixelTotal { get { return _pixelTotal; } set { _pixelTotal = value; } } /// /// X and Y coordinate of first cross center in pattern /// internal int StartPos { get { return _startPos; } set { _startPos = value; } } /// /// Progress (pixel count) within current cross pattern /// internal int PixelCount { get { return _pixelCount; } set { _pixelCount = value; } } /// /// X center of current cross pattern /// internal int XCenter { get { return _xCenter; } set { _xCenter = value; } } /// /// Y center of current cross pattern /// internal int YCenter { get { return _yCenter; } set { _yCenter = value; } } #endregion } }