// 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);
}
Exemplo n.º 2
0
/**
* Determines whether a segment contains a black point
*
* @param a          min value of the scanned coordinate
* @param b          max value of the scanned coordinate
* @param fixed      value of fixed coordinate
* @param horizontal set to true if scan must be horizontal, false if vertical
* @return true if a black point has been found, else false.
*/
static bool ContainsBlackPoint(const BitMatrix& image, int a, int b, int fixed, bool horizontal) {

	if (horizontal) {
		for (int x = a; x <= b; x++) {
			if (image.get(x, fixed)) {
				return true;
			}
		}
	}
	else {
		for (int y = a; y <= b; y++) {
			if (image.get(fixed, y)) {
				return true;
			}
		}
	}

	return false;
}
Exemplo n.º 3
0
/**
* <p>This method traces a line from a point in the image, in the direction towards another point.
* It begins in a black region, and keeps going until it finds white, then black, then white again.
* It reports the distance from the start to this point.</p>
*
* <p>This is used when figuring out how wide a finder pattern is, when the finder pattern
* may be skewed or rotated.</p>
*/
static float SizeOfBlackWhiteBlackRun(const BitMatrix& image, int fromX, int fromY, int toX, int toY) {
	// Mild variant of Bresenham's algorithm;
	// see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
	bool steep = std::abs(toY - fromY) > std::abs(toX - fromX);
	if (steep) {
		std::swap(fromX, fromY);
		std::swap(toX, toY);
	}

	int dx = std::abs(toX - fromX);
	int dy = std::abs(toY - fromY);
	int error = -dx / 2;
	int xstep = fromX < toX ? 1 : -1;
	int ystep = fromY < toY ? 1 : -1;

	// In black pixels, looking for white, first or second time.
	int state = 0;
	// Loop up until x == toX, but not beyond
	int xLimit = toX + xstep;
	for (int x = fromX, y = fromY; x != xLimit; x += xstep) {
		int realX = steep ? y : x;
		int realY = steep ? x : y;

		// Does current pixel mean we have moved white to black or vice versa?
		// Scanning black in state 0,2 and white in state 1, so if we find the wrong
		// color, advance to next state or end if we are in state 2 already
		if ((state == 1) == image.get(realX, realY)) {
			if (state == 2) {
				return ResultPoint::Distance(x, y, fromX, fromY);
			}
			state++;
		}

		error += dy;
		if (error > 0) {
			if (y == toY) {
				break;
			}
			y += ystep;
			error -= dx;
		}
	}
	// Found black-white-black; give the benefit of the doubt that the next pixel outside the image
	// is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a
	// small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.
	if (state == 2) {
		return ResultPoint::Distance(toX + xstep, toY, fromX, fromY);
	}
	// else we didn't find even black-white-black; no estimate is really possible
	return std::numeric_limits<float>::quiet_NaN();
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
static bool GetBlackPointOnSegment(const BitMatrix& image, int aX, int aY, int bX, int bY, ResultPoint& result) {
	int dist = RoundToNearest(ResultPoint::Distance(aX, aY, bX, bY));
	float xStep = static_cast<float>(bX - aX) / dist;
	float yStep = static_cast<float>(bY - aY) / dist;

	for (int i = 0; i < dist; i++) {
		int x = RoundToNearest(aX + i * xStep);
		int y = RoundToNearest(aY + i * yStep);
		if (image.get(x, y)) {
			result.set(static_cast<float>(x), static_cast<float>(y));
			return true;
		}
	}
	return false;
}
Exemplo n.º 6
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));
          }
        }

      }
    }

  }
}