// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) { int fromX = (int)from.x; int fromY = (int)from.y; int toX = (int)to.x; int toY = (int)to.y; bool steep = abs(toY - fromY) > abs(toX - fromX); if (steep) { int temp = fromX; fromX = fromY; fromY = temp; temp = toX; toX = toY; toY = temp; } int dx = abs(toX - fromX); int dy = abs(toY - fromY); int error = -dx >> 1; int ystep = fromY < toY ? -1 : 1; int xstep = fromX < toX ? -1 : 1; int state = 0; // In black pixels, looking for white, first or second time // In case there are no points, prepopulate to from int realX = fromX; int realY = fromY; for (int x = fromX, y = fromY; x != toX; x += xstep) { realX = steep ? y : x; realY = steep ? x : y; if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight()) break; if (state == 1) { // In white pixels, looking for black if (image.get(realX, realY)) { state++; } } else { if (!image.get(realX, realY)) { state++; } } if (state == 3) { // Found black, white, black, and stumbled back onto white; done return Point(realX, realY); } error += dy; if (error > 0) { y += ystep; error -= dx; } } // B-W-B run not found, return the last point visited. return Point(realX, realY); }
void findEdgePoints(std::vector<Point>& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation) { float xdist = end.x - start.x; float ydist = end.y - start.y; float length = sqrt(xdist * xdist + ydist * ydist); int var; if (abs(xdist) > abs(ydist)) { // Horizontal if (xdist < 0) skip = -skip; var = int(abs(deviation * length / xdist)); float dy = ydist / xdist * skip; bool left = (skip < 0) ^ invert; int x = int(start.x); int steps = int(xdist / skip); for (int i = 0; i < steps; i++) { x += skip; if (x < 0 || x >= (int)image.getWidth()) continue; // In case we start off the edge int my = int(start.y + dy * i); int ey = min(my + var + 1, (int)image.getHeight() - 1); int sy = max(my - var, 0); for (int y = sy + 1; y < ey; y++) { if (left) { if (image.get(x, y) && !image.get(x, y + 1)) { points.push_back(Point(x, y + 0.5f)); } } else { if (!image.get(x, y) && image.get(x, y + 1)) { points.push_back(Point(x, y + 0.5f)); } } } } } else { // Vertical if (ydist < 0) skip = -skip; var = int(abs(deviation * length / ydist)); float dx = xdist / ydist * skip; bool down = (skip > 0) ^ invert; int y = int(start.y); int steps = int(ydist / skip); for (int i = 0; i < steps; i++) { y += skip; if (y < 0 || y >= (int)image.getHeight()) continue; // In case we start off the edge int mx = int(start.x + dx * i); int ex = min(mx + var + 1, (int)image.getWidth() - 1); int sx = max(mx - var, 0); for (int x = sx + 1; x < ex; x++) { if (down) { if (image.get(x, y) && !image.get(x + 1, y)) { points.push_back(Point(x + 0.5f, y)); } } else { if (!image.get(x, y) && image.get(x + 1, y)) { points.push_back(Point(x + 0.5f, y)); } } } } } }