// 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);
}
예제 #2
0
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));
          }
        }

      }
    }

  }
}