/** * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of * a finder pattern by looking for a black-white-black run from the center in the direction * of another point (another finder pattern center), and in the opposite direction too. */ static float SizeOfBlackWhiteBlackRunBothWays(const BitMatrix& image, int fromX, int fromY, int toX, int toY) { float result = SizeOfBlackWhiteBlackRun(image, fromX, fromY, toX, toY); // Now count other way -- don't run off image though of course float scale = 1.0f; int otherToX = fromX - (toX - fromX); if (otherToX < 0) { scale = (float)fromX / (float)(fromX - otherToX); otherToX = 0; } else if (otherToX >= image.width()) { scale = (float)(image.width() - 1 - fromX) / (float)(otherToX - fromX); otherToX = image.width() - 1; } int otherToY = (int)(fromY - (toY - fromY) * scale); scale = 1.0f; if (otherToY < 0) { scale = (float)fromY / (float)(fromY - otherToY); otherToY = 0; } else if (otherToY >= image.height()) { scale = (float)(image.height() - 1 - fromY) / (float)(otherToY - fromY); otherToY = image.height() - 1; } otherToX = (int)(fromX + (otherToX - fromX) * scale); result += SizeOfBlackWhiteBlackRun(image, fromX, fromY, otherToX, otherToY); // Middle pixel is double-counted this way; subtract 1 return result - 1.0f; }
TEST(QRWriterTest, OverSize) { // The QR should be multiplied up to fit, with extra padding if necessary int bigEnough = 256; Writer writer; BitMatrix matrix = writer.encode(L"http://www.google.com/", bigEnough, bigEnough); EXPECT_EQ(matrix.width(), bigEnough); EXPECT_EQ(matrix.height(), bigEnough); // The QR will not fit in this size, so the matrix should come back bigger int tooSmall = 20; matrix = writer.encode(L"http://www.google.com/", tooSmall, tooSmall); EXPECT_GT(matrix.width(), tooSmall); EXPECT_GT(matrix.height(), tooSmall); // We should also be able to handle non-square requests by padding them int strangeWidth = 500; int strangeHeight = 100; matrix = writer.encode(L"http://www.google.com/", strangeWidth, strangeHeight); EXPECT_EQ(matrix.width(), strangeWidth); EXPECT_EQ(matrix.height(), strangeHeight); }
ByteArray BitMatrixParser::ReadCodewords(const BitMatrix& image) { ByteArray result(144); int height = image.height(); int width = image.width(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int bit = BITNR[y][x]; if (bit >= 0 && image.get(x, y)) { result[bit / 6] |= static_cast<uint8_t>(1 << (5 - (bit % 6))); } } } return result; }
/** * <p>Attempts to locate an alignment pattern in a limited region of the image, which is * guessed to contain it. This method uses {@link AlignmentPattern}.</p> * * @param overallEstModuleSize estimated module size so far * @param estAlignmentX x coordinate of center of area probably containing alignment pattern * @param estAlignmentY y coordinate of above * @param allowanceFactor number of pixels in all directions to search from the center * @return {@link AlignmentPattern} if found, or null otherwise * @throws NotFoundException if an unexpected error occurs during detection */ AlignmentPattern FindAlignmentInRegion(const BitMatrix& image, float overallEstModuleSize, int estAlignmentX, int estAlignmentY, float allowanceFactor) { // Look for an alignment pattern (3 modules in size) around where it // should be int allowance = (int)(allowanceFactor * overallEstModuleSize); int alignmentAreaLeftX = std::max(0, estAlignmentX - allowance); int alignmentAreaRightX = std::min(image.width() - 1, estAlignmentX + allowance); if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) { return {}; } int alignmentAreaTopY = std::max(0, estAlignmentY - allowance); int alignmentAreaBottomY = std::min(image.height() - 1, estAlignmentY + allowance); if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) { return {}; } return AlignmentPatternFinder::Find(image, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize); }
bool WhiteRectDetector::Detect(const BitMatrix& image, ResultPoint& p0, ResultPoint& p1, ResultPoint& p2, ResultPoint& p3) { return Detect(image, INIT_SIZE, image.width() / 2, image.height() / 2, p0, p1, p2, p3); }
/** * <p> * Detects a candidate barcode-like rectangular region within an image. It * starts around the center of the image, increases the size of the candidate * region until it finds a white rectangular region. * </p> * * @return {@link ResultPoint}[] describing the corners of the rectangular * region. The first and last points are opposed on the diagonal, as * are the second and third. The first point will be the topmost * point and the last, the bottommost. The second point will be * leftmost and the third, the rightmost * @throws NotFoundException if no Data Matrix Code can be found */ bool WhiteRectDetector::Detect(const BitMatrix& image, int initSize, int x, int y, ResultPoint& p0, ResultPoint& p1, ResultPoint& p2, ResultPoint& p3) { int height = image.height(); int width = image.width(); int halfsize = initSize / 2; int left = x - halfsize; int right = x + halfsize; int up = y - halfsize; int down = y + halfsize; if (up < 0 || left < 0 || down >= height || right >= width) { return false; } bool sizeExceeded = false; bool aBlackPointFoundOnBorder = true; bool atLeastOneBlackPointFoundOnBorder = false; bool atLeastOneBlackPointFoundOnRight = false; bool atLeastOneBlackPointFoundOnBottom = false; bool atLeastOneBlackPointFoundOnLeft = false; bool atLeastOneBlackPointFoundOnTop = false; while (aBlackPointFoundOnBorder) { aBlackPointFoundOnBorder = false; // ..... // . | // ..... bool rightBorderNotWhite = true; while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) { rightBorderNotWhite = ContainsBlackPoint(image, up, down, right, false); if (rightBorderNotWhite) { right++; aBlackPointFoundOnBorder = true; atLeastOneBlackPointFoundOnRight = true; } else if (!atLeastOneBlackPointFoundOnRight) { right++; } } if (right >= width) { sizeExceeded = true; break; } // ..... // . . // .___. bool bottomBorderNotWhite = true; while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) { bottomBorderNotWhite = ContainsBlackPoint(image, left, right, down, true); if (bottomBorderNotWhite) { down++; aBlackPointFoundOnBorder = true; atLeastOneBlackPointFoundOnBottom = true; } else if (!atLeastOneBlackPointFoundOnBottom) { down++; } } if (down >= height) { sizeExceeded = true; break; } // ..... // | . // ..... bool leftBorderNotWhite = true; while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) { leftBorderNotWhite = ContainsBlackPoint(image, up, down, left, false); if (leftBorderNotWhite) { left--; aBlackPointFoundOnBorder = true; atLeastOneBlackPointFoundOnLeft = true; } else if (!atLeastOneBlackPointFoundOnLeft) { left--; } } if (left < 0) { sizeExceeded = true; break; } // .___. // . . // ..... bool topBorderNotWhite = true; while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) { topBorderNotWhite = ContainsBlackPoint(image, left, right, up, true); if (topBorderNotWhite) { up--; aBlackPointFoundOnBorder = true; atLeastOneBlackPointFoundOnTop = true; } else if (!atLeastOneBlackPointFoundOnTop) { up--; } } if (up < 0) { sizeExceeded = true; break; } if (aBlackPointFoundOnBorder) { atLeastOneBlackPointFoundOnBorder = true; } } if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) { int maxSize = right - left; ResultPoint z; bool found = false; for (int i = 1; !found && i < maxSize; i++) { found = GetBlackPointOnSegment(image, left, down - i, left + i, down, z); } if (!found) { return false; } ResultPoint t; found = false; //go down right for (int i = 1; !found && i < maxSize; i++) { found = GetBlackPointOnSegment(image, left, up + i, left + i, up, t); } if (!found) { return false; } ResultPoint x; found = false; //go down left for (int i = 1; !found && i < maxSize; i++) { found = GetBlackPointOnSegment(image, right, up + i, right - i, up, x); } if (!found) { return false; } ResultPoint y; found = false; //go up left for (int i = 1; !found && i < maxSize; i++) { found = GetBlackPointOnSegment(image, right, down - i, right - i, down, y); } if (!found) { return false; } CenterEdges(y, z, x, t, width, p0, p1, p2, p3); return true; } else { return false; } }