Added BitBuffer-based constructor to Java QrSegment class, updated existing library and demo code to use it.

pull/16/head
Project Nayuki 8 years ago
parent 7a2555816b
commit 05d470fcca

@ -141,14 +141,18 @@ public final class QrCodeGeneratorDemo {
qr = QrCode.encodeText(madoka, QrCode.Ecc.LOW); qr = QrCode.encodeText(madoka, QrCode.Ecc.LOW);
writePng(qr.toImage(9, 4), "madoka-utf8-QR.png"); writePng(qr.toImage(9, 4), "madoka-utf8-QR.png");
byte[] packedKanjiData = { // Kanji mode encoding (13 bits per character) int[] packedKanjiData = { // Kanji mode encoding (13 bits per character)
(byte)0x01, (byte)0xAC, (byte)0x00, (byte)0x9F, (byte)0x80, (byte)0xAE, (byte)0xD5, (byte)0x6B, (byte)0x85, (byte)0x70, 0x0035, 0x1002, 0x0FC0, 0x0AED, 0x0AD7,
(byte)0x28, (byte)0xE1, (byte)0x29, (byte)0x02, (byte)0xC8, (byte)0x6F, (byte)0x43, (byte)0x1A, (byte)0x18, (byte)0xA0, 0x015C, 0x0147, 0x0129, 0x0059, 0x01BD,
(byte)0x1B, (byte)0x05, (byte)0x04, (byte)0x28, (byte)0x80, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x92, (byte)0x44, 0x018D, 0x018A, 0x0036, 0x0141, 0x0144,
(byte)0x80, (byte)0x24, (byte)0x90, (byte)0x00, (byte)0x04, (byte)0x10, (byte)0x20, (byte)0xA1, (byte)0x13, (byte)0x08, 0x0001, 0x0000, 0x0249, 0x0240, 0x0249,
(byte)0xA8, (byte)0x00, (byte)0x04, (byte)0x10, (byte)0x1F, (byte)0xF0, (byte)0x04, (byte)0x00, 0x0000, 0x0104, 0x0105, 0x0113, 0x0115,
0x0000, 0x0208, 0x01FF, 0x0008,
}; };
segs = Arrays.asList(new QrSegment(QrSegment.Mode.KANJI, madoka.length(), packedKanjiData, madoka.length() * 13)); BitBuffer bb = new BitBuffer();
for (int c : packedKanjiData)
bb.appendBits(c, 13);
segs = Arrays.asList(new QrSegment(QrSegment.Mode.KANJI, madoka.length(), bb));
qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW); qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW);
writePng(qr.toImage(9, 4), "madoka-kanji-QR.png"); writePng(qr.toImage(9, 4), "madoka-kanji-QR.png");
} }

@ -51,7 +51,10 @@ public final class QrSegment {
*/ */
public static QrSegment makeBytes(byte[] data) { public static QrSegment makeBytes(byte[] data) {
Objects.requireNonNull(data); Objects.requireNonNull(data);
return new QrSegment(Mode.BYTE, data.length, data, data.length * 8); BitBuffer bb = new BitBuffer();
for (byte b : data)
bb.appendBits(b & 0xFF, 8);
return new QrSegment(Mode.BYTE, data.length, bb);
} }
@ -74,7 +77,7 @@ public final class QrSegment {
int rem = digits.length() - i; int rem = digits.length() - i;
if (rem > 0) // 1 or 2 digits remaining if (rem > 0) // 1 or 2 digits remaining
bb.appendBits(Integer.parseInt(digits.substring(i)), rem * 3 + 1); bb.appendBits(Integer.parseInt(digits.substring(i)), rem * 3 + 1);
return new QrSegment(Mode.NUMERIC, digits.length(), bb.getBytes(), bb.bitLength()); return new QrSegment(Mode.NUMERIC, digits.length(), bb);
} }
@ -100,7 +103,7 @@ public final class QrSegment {
} }
if (i < text.length()) // 1 character remaining if (i < text.length()) // 1 character remaining
bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6);
return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb.getBytes(), bb.bitLength()); return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb);
} }
@ -135,16 +138,18 @@ public final class QrSegment {
* @throws IllegalArgumentException if the value is outside the range [0, 10<sup>6</sup>) * @throws IllegalArgumentException if the value is outside the range [0, 10<sup>6</sup>)
*/ */
public static QrSegment makeEci(int assignVal) { public static QrSegment makeEci(int assignVal) {
byte[] data; BitBuffer bb = new BitBuffer();
if (0 <= assignVal && assignVal < (1 << 7)) if (0 <= assignVal && assignVal < (1 << 7))
data = new byte[]{(byte)assignVal}; bb.appendBits(assignVal, 8);
else if ((1 << 7) <= assignVal && assignVal < (1 << 14)) else if ((1 << 7) <= assignVal && assignVal < (1 << 14)) {
data = new byte[]{(byte)(0x80 | (assignVal >>> 8)), (byte)assignVal}; bb.appendBits(2, 2);
else if ((1 << 14) <= assignVal && assignVal < 999999) bb.appendBits(assignVal, 14);
data = new byte[]{(byte)(0xC0 | (assignVal >>> 16)), (byte)(assignVal >>> 8), (byte)assignVal}; } else if ((1 << 14) <= assignVal && assignVal < 999999) {
else bb.appendBits(6, 3);
bb.appendBits(assignVal, 21);
} else
throw new IllegalArgumentException("ECI assignment value out of range"); throw new IllegalArgumentException("ECI assignment value out of range");
return new QrSegment(Mode.ECI, 0, data, data.length * 8); return new QrSegment(Mode.ECI, 0, bb);
} }
@ -166,6 +171,19 @@ public final class QrSegment {
/*---- Constructor ----*/ /*---- Constructor ----*/
/**
* Creates a new QR Code data segment with the specified parameters and data.
* @param md the mode, which is not {@code null}
* @param numCh the data length in characters, which is non-negative
* @param data the data bits of this segment, which is not {@code null}
* @throws NullPointerException if the mode or bit buffer is {@code null}
* @throws IllegalArgumentException if the character count is negative
*/
public QrSegment(Mode md, int numCh, BitBuffer data) {
this(md, numCh, data.getBytes(), data.bitLength());
}
/** /**
* Creates a new QR Code data segment with the specified parameters and data. * Creates a new QR Code data segment with the specified parameters and data.
* @param md the mode, which is not {@code null} * @param md the mode, which is not {@code null}

@ -246,7 +246,7 @@ public final class QrSegmentAdvanced {
throw new IllegalArgumentException("String contains non-kanji-mode characters"); throw new IllegalArgumentException("String contains non-kanji-mode characters");
bb.appendBits(val, 13); bb.appendBits(val, 13);
} }
return new QrSegment(QrSegment.Mode.KANJI, text.length(), bb.getBytes(), bb.bitLength()); return new QrSegment(QrSegment.Mode.KANJI, text.length(), bb);
} }

Loading…
Cancel
Save