/// <summary> This method detects a Data Matrix code in a "pure" image -- that is, pure monochrome image
        /// which contains only an unrotated, unskewed, image of a Data Matrix code, with some white border
        /// around it. This is a specialized method that works exceptionally fast in this special
        /// case.
        /// </summary>
        private static BitMatrix extractPureBits(BitMatrix image)
        {
            // Now need to determine module size in pixels

            int height = image.Height;
            int width = image.Width;
            int minDimension = System.Math.Min(height, width);

            // First, skip white border by tracking diagonally from the top left down and to the right:
            int borderWidth = 0;
            while (borderWidth < minDimension && !image.get_Renamed(borderWidth, borderWidth))
            {
                borderWidth++;
            }
            if (borderWidth == minDimension)
            {
                throw ReaderException.Instance;
            }

            // And then keep tracking across the top-left black module to determine module size
            int moduleEnd = borderWidth + 1;
            while (moduleEnd < width && image.get_Renamed(moduleEnd, borderWidth))
            {
                moduleEnd++;
            }
            if (moduleEnd == width)
            {
                throw ReaderException.Instance;
            }

            int moduleSize = moduleEnd - borderWidth;

            // And now find where the bottommost black module on the first column ends
            int columnEndOfSymbol = height - 1;
            while (columnEndOfSymbol >= 0 && !image.get_Renamed(borderWidth, columnEndOfSymbol))
            {
                columnEndOfSymbol--;
            }
            if (columnEndOfSymbol < 0)
            {
                throw ReaderException.Instance;
            }
            columnEndOfSymbol++;

            // Make sure width of barcode is a multiple of module size
            if ((columnEndOfSymbol - borderWidth) % moduleSize != 0)
            {
                throw ReaderException.Instance;
            }
            int dimension = (columnEndOfSymbol - borderWidth) / moduleSize;

            // Push in the "border" by half the module width so that we start
            // sampling in the middle of the module. Just in case the image is a
            // little off, this will help recover.
            borderWidth += (moduleSize >> 1);

            int sampleDimension = borderWidth + (dimension - 1) * moduleSize;
            if (sampleDimension >= width || sampleDimension >= height)
            {
                throw ReaderException.Instance;
            }

            // Now just read off the bits
            BitMatrix bits = new BitMatrix(dimension);
            for (int i = 0; i < dimension; i++)
            {
                int iOffset = borderWidth + i * moduleSize;
                for (int j = 0; j < dimension; j++)
                {
                    if (image.get_Renamed(borderWidth + j * moduleSize, iOffset))
                    {
                        bits.set_Renamed(j, i);
                    }
                }
            }
            return bits;
        }
Пример #2
0
        /// <summary> <p>Extracts the data region from a {@link BitMatrix} that contains
        /// alignment patterns.</p>
        /// 
        /// </summary>
        /// <param name="bitMatrix">Original {@link BitMatrix} with alignment patterns
        /// </param>
        /// <returns> BitMatrix that has the alignment patterns removed
        /// </returns>
        internal BitMatrix extractDataRegion(BitMatrix bitMatrix)
        {
            int symbolSizeRows = version.SymbolSizeRows;
            int symbolSizeColumns = version.SymbolSizeColumns;

            // TODO(bbrown): Make this work with rectangular codes
            if (bitMatrix.Dimension != symbolSizeRows)
            {
                throw new System.ArgumentException("Dimension of bitMarix must match the version size");
            }

            int dataRegionSizeRows = version.DataRegionSizeRows;
            int dataRegionSizeColumns = version.DataRegionSizeColumns;

            int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows;
            int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns;

            int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;
            //int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;

            // TODO(bbrown): Make this work with rectangular codes
            BitMatrix bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionRow);
            for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow)
            {
                int dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;
                for (int dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn)
                {
                    int dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;
                    for (int i = 0; i < dataRegionSizeRows; ++i)
                    {
                        int readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;
                        int writeRowOffset = dataRegionRowOffset + i;
                        for (int j = 0; j < dataRegionSizeColumns; ++j)
                        {
                            int readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;
                            if (bitMatrix.get_Renamed(readColumnOffset, readRowOffset))
                            {
                                int writeColumnOffset = dataRegionColumnOffset + j;
                                bitMatrixWithoutAlignment.set_Renamed(writeColumnOffset, writeRowOffset);
                            }
                        }
                    }
                }
            }
            return bitMatrixWithoutAlignment;
        }
Пример #3
0
        /// <param name="matrix">row of black/white values to search
        /// </param>
        /// <param name="column">x position to start search
        /// </param>
        /// <param name="row">y position to start search
        /// </param>
        /// <param name="width">the number of pixels to search on this row
        /// </param>
        /// <param name="pattern">pattern of counts of number of black and white pixels that are
        /// being searched for as a pattern
        /// </param>
        /// <returns> start/end horizontal offset of guard pattern, as an array of two ints.
        /// </returns>
        private static int[] findGuardPattern(BitMatrix matrix, int column, int row, int width, bool whiteFirst, int[] pattern)
        {
            int patternLength = pattern.Length;
            // TODO: Find a way to cache this array, as this method is called hundreds of times
            // per image, and we want to allocate as seldom as possible.
            int[] counters = new int[patternLength];
            bool isWhite = whiteFirst;

            int counterPosition = 0;
            int patternStart = column;
            for (int x = column; x < column + width; x++)
            {
                bool pixel = matrix.get_Renamed(x, row);
                if (pixel ^ isWhite)
                {
                    counters[counterPosition]++;
                }
                else
                {
                    if (counterPosition == patternLength - 1)
                    {
                        if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE)
                        {
                            return new int[]{patternStart, x};
                        }
                        patternStart += counters[0] + counters[1];
                        for (int y = 2; y < patternLength; y++)
                        {
                            counters[y - 2] = counters[y];
                        }
                        counters[patternLength - 2] = 0;
                        counters[patternLength - 1] = 0;
                        counterPosition--;
                    }
                    else
                    {
                        counterPosition++;
                    }
                    counters[counterPosition] = 1;
                    isWhite = !isWhite;
                }
            }
            return null;
        }