private static bool TryFindStartingAngleAndSegmentSize(TagImage tagImage) { double startingAngle = -1; const double angleStepSize = Math.PI / 360.0 / 2.0; const int radiusOffset = 2; double currentAngle = 0.0; for (int step = 0; currentAngle < Math.PI * 2; step++) { currentAngle = angleStepSize * step; CalculateCoords(tagImage, currentAngle, tagImage.CodeRadius + radiusOffset, out int x, out int y); _debugImage?.WriteColor(x, y, 0xff0000ff); if (x < 0 || y < 0 || x > tagImage.Width || y > tagImage.Width) { continue; } bool hasPixel = tagImage.CheckPixel(x, y); // Find the first pixel in the notch of the first layer if (startingAngle < 0 && !hasPixel) { startingAngle = currentAngle - angleStepSize; _debugImage?.WriteColor(x, y, 0xffff00ff); } // Find the last pixel in the notch of the first layer if (startingAngle > 0 && hasPixel) { tagImage.CodeStartingAngle = startingAngle; tagImage.CodeSegmentSize = currentAngle - startingAngle; _debugImage?.WriteColor(x, y, 0xff00ffff); return(true); } } return(false); }
private static bool TryCalculateDistances(TagImage tagImage, int originX, int originY, out int left, out int right, out int down, out int up) { left = -1; right = -1; down = -1; up = -1; int size = tagImage.Width / 2; uint diff = 0; for (int i = 1; i < size; i++) { int x = originX - i; int y = originY; if (x >= 0 && x < tagImage.Width) { if (left < 0 && tagImage.CheckPixel(x, y, out diff)) { left = x + 1; } _debugImage?.WriteColor(x, y, diff | 0xff000000); } x = originX + i; if (x >= 0 && x < tagImage.Width) { if (right < 0 && tagImage.CheckPixel(x, y, out diff)) { right = x - 1; } _debugImage?.WriteColor(x, y, diff | 0xff000000); } x = originX; y = originY - i; if (y >= 0 && y < tagImage.Height) { if (down < 0 && tagImage.CheckPixel(x, y, out diff)) { down = y + 1; } _debugImage?.WriteColor(x, y, diff | 0xff000000); } y = originY + i; if (y >= 0 && y < tagImage.Height) { if (up < 0 && tagImage.CheckPixel(x, y, out diff)) { up = y - 1; } _debugImage?.WriteColor(x, y, diff | 0xff000000); } if (left >= 0 && right >= 0 && down >= 0 && up >= 0) { return(true); } } return(false); }
private static bool TryReadData(TagImage tagImage, out byte[] bytes) { bytes = null; int segments = CalculateSegmentCount(tagImage.CodeSegmentSize); if (segments <= 0) { return(false); } double halfSegment = tagImage.CodeSegmentSize / 2.0; int byteIndex = 0; byte currentBit = 1; byte currentByte = 0; byte sizeByte = 0; for (int layer = 0; layer < tagImage.CodeLayerCount; layer++) { for (int segment = 1; segment < segments; segment++) { // Calculate coordinates double angle = tagImage.CodeStartingAngle + segment * tagImage.CodeSegmentSize + halfSegment; int distance = tagImage.CodeRadius + tagImage.CodeLayerSize + layer * tagImage.CodeLayerSize + tagImage.CodeLayerSize / 2; CalculateCoords(tagImage, angle, distance, out int x, out int y); // Read bit if (tagImage.CheckPixel(x, y)) { currentByte |= currentBit; } // Advance bit and check if there are more bits currentBit <<= 1; if (currentBit > 0) { continue; } // No more bits, handle byte currentBit = 1; if (sizeByte == 0) { // Size not read yet, use the current byte value as data size and continue reading sizeByte = currentByte; currentByte = 0; bytes = new byte[sizeByte]; continue; } if (byteIndex == sizeByte) { // We have read all bytes, check hash byte and return byte hash = CalculateHash(bytes); return(hash == currentByte); } // Push the current byte to the byte array and continue reading bytes[byteIndex] = currentByte; currentByte = 0; byteIndex++; } } return(false); }