/** * A fast method to retrieve one row of data from the matrix as a BitArray. * * @param y The row to retrieve * @param row An optional caller-allocated BitArray, will be allocated if null or too small * @return The resulting BitArray - this reference should always be used even when passing * your own row */ public BitArray getRow(int y, BitArray row) { if (row == null || row.getSize() < width) { row = new BitArray(width); } else { row.clear(); } int offset = y * rowSize; for (int x = 0; x < rowSize; x++) { row.setBulk(x * 32, bits[offset + x]); } return row; }
public void appendBitArray(BitArray other) { int otherSize = other.getSize(); ensureCapacity(size + otherSize); for (int i = 0; i < otherSize; i++) { appendBit(other.get(i)); } }
public static void makeVersionInfoBits(int version, BitArray bits) throws WriterException { bits.appendBits(version, 6); int bchCode = calculateBCHCode(version, VERSION_INFO_POLY); bits.appendBits(bchCode, 12); if (bits.getSize() != 18) { // Just in case. throw new WriterException("should not happen but we got: " + bits.getSize()); } }
public void appendBitArray(BitArray other) { int otherSize = other.size; ensureCapacity(size + otherSize); for (int i = 0; i < otherSize; i++) { appendBit(other.get(i)); } }
static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits) throws WriterException { if (!QRCode.isValidMaskPattern(maskPattern)) { throw new WriterException("Invalid mask pattern"); } int typeInfo = (ecLevel.getBits() << 3) | maskPattern; bits.appendBits(typeInfo, 5); int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY); bits.appendBits(bchCode, 10); BitArray maskBits = new BitArray(); maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15); bits.xor(maskBits); if (bits.getSize() != 15) { // Just in case. throw new WriterException("should not happen but we got: " + bits.getSize()); } }
/** * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). */ static void terminateBits(int numDataBytes, BitArray bits) throws WriterException { int capacity = numDataBytes * 8; if (bits.getSize() > capacity) { throw new WriterException("data bits cannot fit in the QR Code" + bits.getSize() + " > " + capacity); } for (int i = 0; i < 4 && bits.getSize() < capacity; ++i) { bits.appendBit(false); } // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. // If the last byte isn't 8-bit aligned, we'll add padding bits. int numBitsInLastByte = bits.getSize() & 0x07; if (numBitsInLastByte > 0) { for (int i = numBitsInLastByte; i < 8; i++) { bits.appendBit(false); } } // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). int numPaddingBytes = numDataBytes - bits.getSizeInBytes(); for (int i = 0; i < numPaddingBytes; ++i) { bits.appendBits((i & 0x01) == 0 ? 0xEC : 0x11, 8); } if (bits.getSize() != capacity) { throw new WriterException("Bits size does not equal capacity"); } }
BitArray headerBits = new BitArray(); BitArray dataBits = new BitArray(); appendBytes(content, mode, dataBits, encoding); BitArray headerAndDataBits = new BitArray(); headerAndDataBits.appendBitArray(headerBits); int numLetters = mode == Mode.BYTE ? dataBits.getSizeInBytes() : content.length(); appendLengthInfo(numLetters, version, mode, headerAndDataBits); headerAndDataBits.appendBitArray(dataBits);
if (bits.getSizeInBytes() != numDataBytes) { throw new WriterException("Number of bits and data bytes does not match"); bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size); byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]); blocks.add(new BlockPair(dataBytes, ecBytes)); BitArray result = new BitArray(); byte[] dataBytes = block.getDataBytes(); if (i < dataBytes.length) { result.appendBits(dataBytes[i], 8); byte[] ecBytes = block.getErrorCorrectionBytes(); if (i < ecBytes.length) { result.appendBits(ecBytes[i], 8); if (numTotalBytes != result.getSizeInBytes()) { // Should be same. throw new WriterException("Interleaving error: " + numTotalBytes + " and " + result.getSizeInBytes() + " differ.");
static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix) throws WriterException { BitArray typeInfoBits = new BitArray(); makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits); for (int i = 0; i < typeInfoBits.getSize(); ++i) { // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in // "typeInfoBits". boolean bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i); // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). int[] coordinates = TYPE_INFO_COORDINATES[i]; int x1 = coordinates[0]; int y1 = coordinates[1]; matrix.set(x1, y1, bit); if (i < 8) { // Right top corner. int x2 = matrix.getWidth() - i - 1; int y2 = 8; matrix.set(x2, y2, bit); } else { // Left bottom corner. int x2 = 8; int y2 = matrix.getHeight() - 7 + (i - 8); matrix.set(x2, y2, bit); } } }
/** * A fast method to retrieve one row of data from the matrix as a BitArray. * * @param y The row to retrieve * @param row An optional caller-allocated BitArray, will be allocated if null or too small * @return The resulting BitArray - this reference should always be used even when passing * your own row */ public BitArray getRow(int y, BitArray row) { if (row == null || row.getSize() < width) { row = new BitArray(width); } int offset = y * rowSize; for (int x = 0; x < rowSize; x++) { row.setBulk(x << 5, bits[offset + x]); } return row; }
if (bits.getSizeInBytes() != numDataBytes) { throw new WriterException("Number of bits and data bytes does not match"); bits.toBytes(8*dataBytesOffset, dataBytes, 0, size); byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]); blocks.addElement(new BlockPair(dataBytes, ecBytes)); byte[] dataBytes = ((BlockPair) blocks.elementAt(j)).getDataBytes(); if (i < dataBytes.length) { result.appendBits(dataBytes[i], 8); byte[] ecBytes = ((BlockPair) blocks.elementAt(j)).getErrorCorrectionBytes(); if (i < ecBytes.length) { result.appendBits(ecBytes[i], 8); if (numTotalBytes != result.getSizeInBytes()) { // Should be same. throw new WriterException("Interleaving error: " + numTotalBytes + " and " + result.getSizeInBytes() + " differ.");
static void append8BitBytes(String content, BitArray bits, String encoding) throws WriterException { byte[] bytes; try { bytes = content.getBytes(encoding); } catch (UnsupportedEncodingException uee) { throw new WriterException(uee); } for (byte b : bytes) { bits.appendBits(b, 8); } }
/** * Appends the least-significant bits, from value, in order from most-significant to * least-significant. For example, appending 6 bits from 0x000001E will append the bits * 0, 1, 1, 1, 1, 0 in that order. */ public void appendBits(int value, int numBits) { if (numBits < 0 || numBits > 32) { throw new IllegalArgumentException("Num bits must be between 0 and 32"); } ensureCapacity(size + numBits); for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) { appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1); } }
public static void maybeEmbedVersionInfo(int version, ByteMatrix matrix) throws WriterException { if (version < 7) { // Version info is necessary if version >= 7. return; // Don't need version info. } BitArray versionInfoBits = new BitArray(); makeVersionInfoBits(version, versionInfoBits); int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0. for (int i = 0; i < 6; ++i) { for (int j = 0; j < 3; ++j) { // Place bits in LSB (least significant bit) to MSB order. boolean bit = versionInfoBits.get(bitIndex); bitIndex--; // Left bottom corner. matrix.set(i, matrix.getHeight() - 11 + j, bit); // Right bottom corner. matrix.set(matrix.getHeight() - 11 + j, i, bit); } } }
static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) { int value = 0; for (int i = 0; i < bits; ++i) { if (information.get(pos + i)) { value |= 1 << (bits - i - 1); } } return value; }
private static int getNextSecondBar(BitArray row, int initialPos) { int currentPos; if (row.get(initialPos)) { currentPos = row.getNextUnset(initialPos); currentPos = row.getNextSet(currentPos); } else { currentPos = row.getNextSet(initialPos); currentPos = row.getNextUnset(currentPos); } return currentPos; }
public BitArray(int size) { this.size = size; this.bits = makeArray(size); }
/** * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees */ public void rotate180() { int width = getWidth(); int height = getHeight(); BitArray topRow = new BitArray(width); BitArray bottomRow = new BitArray(width); for (int i = 0; i < (height + 1) / 2; i++) { topRow = getRow(i, topRow); bottomRow = getRow(height - 1 - i, bottomRow); topRow.reverse(); bottomRow.reverse(); setRow(i, bottomRow); setRow(height - 1 - i, topRow); } }