diff --git a/java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java b/java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java new file mode 100644 index 0000000..f0d59ba --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/AlphanumericMode.java @@ -0,0 +1,25 @@ +package io.nayuki.qrcodegen; + +import java.nio.charset.StandardCharsets; + +public class AlphanumericMode extends QrMode { + protected AlphanumericMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected AlphanumericMode() { + modeBits = 0x2; + numBitsCharCount[0] = 9; + numBitsCharCount[1] = 11; + numBitsCharCount[2] = 13; + } + + public int getcost(int pre, int codePoint) { + return pre + 33; + } + + public QrSegment making(String str) { + return QrSegment.makeAlphanumeric(str); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/ByteMode.java b/java/src/main/java/io/nayuki/qrcodegen/ByteMode.java new file mode 100644 index 0000000..1270381 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/ByteMode.java @@ -0,0 +1,25 @@ +package io.nayuki.qrcodegen; + +import java.nio.charset.StandardCharsets; + +public class ByteMode extends QrMode { + protected ByteMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected ByteMode() { + modeBits = 0x4; + numBitsCharCount[0] = 8; + numBitsCharCount[1] = 16; + numBitsCharCount[2] = 16; + } + + public int getcost(int pre, int codePoint) { + return pre + QrSegmentAdvanced.countUtf8Bytes(codePoint) * 8 * 6; + } + + public QrSegment making(String str) { + return QrSegment.makeBytes(str.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/Ecc.java b/java/src/main/java/io/nayuki/qrcodegen/Ecc.java new file mode 100644 index 0000000..e6f21a9 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/Ecc.java @@ -0,0 +1,61 @@ +package io.nayuki.qrcodegen; + +/** + * The error correction level in a QR Code symbol. + */ +public class Ecc { + /** The QR Code can tolerate about 7% erroneous codewords. */ + public static final Ecc LOW = new Ecc(1, + new byte[] { -1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, + 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + new byte[] { -1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25 }); + /** The QR Code can tolerate about 15% erroneous codewords. */ + public static final Ecc MEDIUM = new Ecc(0, + new byte[] { -1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28 }, + new byte[] { -1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, + 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49 }); + /** The QR Code can tolerate about 25% erroneous codewords. */ + public static final Ecc QUARTILE = new Ecc(3, + new byte[] { -1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, + 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + new byte[] { -1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, + 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68 }); + /** The QR Code can tolerate about 30% erroneous codewords. */ + public static final Ecc HIGH = new Ecc(2, + new byte[] { -1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + new byte[] { -1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, + 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81 }); + + private final int formatBits; + private final byte[] blockLength; + private final byte[] numberOfBlocks; + + // For formatBits and blockLength, array index is Version: (note that index 0 is + // for padding, and is set to an illegal value) + private Ecc(int formatBits, byte[] blockLength, byte[] numberOfBlocks) { + this.formatBits = formatBits; + this.blockLength = blockLength; + this.numberOfBlocks = numberOfBlocks; + } + + public int getFormatBits() { + return formatBits; + } + + public byte getBlockLength(int version) { + return blockLength[version]; + } + + public byte getNumberOfBlock(int version) { + return numberOfBlocks[version]; + } + + // Must in ascending order of error protection + // so that values() work properly + public static Ecc[] values() { + return new Ecc[] { LOW, MEDIUM, QUARTILE, HIGH }; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/EciMode.java b/java/src/main/java/io/nayuki/qrcodegen/EciMode.java new file mode 100644 index 0000000..ce33fa9 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/EciMode.java @@ -0,0 +1,23 @@ +package io.nayuki.qrcodegen; + +public class EciMode extends QrMode { + protected EciMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected EciMode() { + modeBits = 0x7; + numBitsCharCount[0] = 0; + numBitsCharCount[1] = 0; + numBitsCharCount[2] = 0; + } + + public QrSegment making(int prmt) { + return QrSegment.makeEci(prmt); + } + + public int getcost(int pre, int codePoint) { + return pre; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java b/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java new file mode 100644 index 0000000..9729f93 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/KanjiMode.java @@ -0,0 +1,23 @@ +package io.nayuki.qrcodegen; + +public class KanjiMode extends QrMode { + protected KanjiMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected KanjiMode() { + modeBits = 0x8; + numBitsCharCount[0] = 8; + numBitsCharCount[1] = 10; + numBitsCharCount[2] = 12; + } + + public int getcost(int pre, int codePoint) { + return pre + 78; + } + + public QrSegment making(String str) { + return QrSegmentAdvanced.makeKanji(str); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java new file mode 100644 index 0000000..2ed2f40 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeAlphaNumericToSegment.java @@ -0,0 +1,34 @@ +import java.util.Objects; + +public class MakeAlphaNumericToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + * @param text the text (not {@code null}), with only certain characters allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-encodable characters + */ + public QrSegment excute(String text) { + Objects.requireNonNull(text); + if (!QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) + throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode"); + + BitBuffer bitBuffer = new BitBuffer(); + changeAlphaNumericStringToSegment(text, bitBuffer); + return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length(), bitBuffer); + } + + public static void changeAlphaNumericStringToSegment(String text, BitBuffer bitBuffer) { + int i; + for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2 + int temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; + temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); + bitBuffer.appendBits(temp, 11); + } + if (i < text.length()) // 1 character remaining + bitBuffer.appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java new file mode 100644 index 0000000..2b3660c --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeBytesToSegment.java @@ -0,0 +1,36 @@ +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +public class MakeBytesToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified binary data + * encoded in byte mode. All input byte arrays are acceptable. + *
Any text string can be converted to UTF-8 bytes ({@code + * s.getBytes(StandardCharsets.UTF_8)}) and encoded as a byte mode segment.
+ * @param data the binary data (not {@code null}) + * @return a segment (not {@code null}) containing the data + * @throws NullPointerException if the array is {@code null} + */ + public QrSegment excute(String text) { + byte[] data = text.getBytes(StandardCharsets.UTF_8)); + + Objects.requireNonNull(data); + BitBuffer bitBuffer = new BitBuffer(); + for (byte bits : data) + changeByteToSegment(bitBuffer, bits); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); + } + + public QrSegment excuteForBytedata(byte[] data) { + Objects.requireNonNull(data); + BitBuffer bitBuffer = new BitBuffer(); + for (byte bits : data) + changeByteToSegment(bitBuffer, bits); + return new QrSegment(QrSegment.Mode.BYTE, data.length, bitBuffer); + } + + public static void changeByteToSegment(BitBuffer bitBuffer, byte bits) { + bitBuffer.appendBits(bits & 0xFF, 8); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java new file mode 100644 index 0000000..929a6b7 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeNumericToSegment.java @@ -0,0 +1,33 @@ +import java.util.Objects; + +public class MakeNumericToSegment implements MakeSegment { + + /** + * Returns a segment representing the specified string of decimal digits encoded in numeric mode. + * @param digits the text (not {@code null}), with only digits from 0 to 9 allowed + * @return a segment (not {@code null}) containing the text + * @throws NullPointerException if the string is {@code null} + * @throws IllegalArgumentException if the string contains non-digit characters + */ + public QrSegment excute(String digits) { + Objects.requireNonNull(digits); + if (containNonNumericCharaters(digits)) + throw new IllegalArgumentException("String contains non-numeric characters"); + + BitBuffer bitBuffer = new BitBuffer(); + changeNumericToSegment(digits, bitBuffer); + return new QrSegment(QrSegment.Mode.NUMERIC, digits.length(), bitBuffer); + } + + public static void changeNumericToSegment(String digits, BitBuffer bitBuffer) { + for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration + int n = Math.min(digits.length() - i, 3); + bitBuffer.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1); + i += n; + } + } + + public static boolean containNonNumericCharaters(String digits) { + return !QrSegment.NUMERIC_REGEX.matcher(digits).matches(); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java b/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java new file mode 100644 index 0000000..cfda06d --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeSegment.java @@ -0,0 +1,4 @@ + +public interface MakeSegment { + public QrSegment excute(String text); +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java b/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java new file mode 100644 index 0000000..6a45f5c --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/MakeSegmentFactory.java @@ -0,0 +1,15 @@ +public class MakeSegmentFactory { + public static MakeSegment getMakeSegment(String text) { + MakeSegment makeSegment = null; + + if (text.equals("")); // Leave result empty + else if (QrSegment.NUMERIC_REGEX.matcher(text).matches()) + makeSegment = new MakeNumericToSegment(); + else if (QrSegment.ALPHANUMERIC_REGEX.matcher(text).matches()) + makeSegment = new MakeAlphaNumericToSegment(); + else + makeSegment = new MakeBytesToSegment(); + + return makeSegment; + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/NumericMode.java b/java/src/main/java/io/nayuki/qrcodegen/NumericMode.java new file mode 100644 index 0000000..a8af039 --- /dev/null +++ b/java/src/main/java/io/nayuki/qrcodegen/NumericMode.java @@ -0,0 +1,23 @@ +package io.nayuki.qrcodegen; + +public class NumericMode extends QrMode { + protected NumericMode(int mode, int... ccbits) { + modeBits = mode; + numBitsCharCount = ccbits; + } + + protected NumericMode() { + modeBits = 0x1; + numBitsCharCount[0] = 10; + numBitsCharCount[1] = 12; + numBitsCharCount[2] = 1; + } + + public int getcost(int pre, int codePoint) { + return pre + 20; + } + + public QrSegment making(String str) { + return QrSegment.makeNumeric(str); + } +} diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCode.java b/java/src/main/java/io/nayuki/qrcodegen/QrCode.java index dcb8b6b..5ade16c 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCode.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCode.java @@ -421,7 +421,7 @@ public final class QrCode { // based on the given mask and this object's error correction level field. private void drawFormatBits(int msk) { // Calculate error correction code and pack bits - int data = errorCorrectionLevel.formatBits << 3 | msk; // errCorrLvl is uint2, mask is uint3 + int data = errorCorrectionLevel.getFormatBits() << 3 | msk; // errCorrLvl is uint2, mask is uint3 int rem = data; for (int i = 0; i < 10; i++) rem = (rem << 1) ^ ((rem >>> 9) * 0x537); @@ -512,8 +512,8 @@ public final class QrCode { throw new IllegalArgumentException(); // Calculate parameter numbers - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.ordinal()][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [errorCorrectionLevel.ordinal()][version]; + int numBlocks = errorCorrectionLevel.getNumberOfBlock(version); + int blockEccLen = errorCorrectionLevel.getBlockLength(version); int rawCodewords = getNumRawDataModules(version) / 8; int numShortBlocks = numBlocks - rawCodewords % numBlocks; int shortBlockLen = rawCodewords / numBlocks; @@ -830,9 +830,9 @@ public final class QrCode { // QR Code of the given version number and error correction level, with remainder bits discarded. // This stateless pure function could be implemented as a (40*4)-cell lookup table. static int getNumDataCodewords(int ver, Ecc ecl) { - return getNumRawDataModules(ver) / 8 - - ECC_CODEWORDS_PER_BLOCK [ecl.ordinal()][ver] - * NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal()][ver]; + return getNumRawDataModules(ver) / 8 + - ecl.getBlockLength(ver) + * ecl.getNumberOfBlock(ver); } @@ -889,47 +889,4 @@ public final class QrCode { private static final int PENALTY_N3 = 40; private static final int PENALTY_N4 = 10; - - private static final byte[][] ECC_CODEWORDS_PER_BLOCK = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High - }; - - private static final byte[][] NUM_ERROR_CORRECTION_BLOCKS = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High - }; - - - - /*---- Public helper enumeration ----*/ - - /** - * The error correction level in a QR Code symbol. - */ - public enum Ecc { - // Must be declared in ascending order of error protection - // so that the implicit ordinal() and values() work properly - /** The QR Code can tolerate about 7% erroneous codewords. */ LOW(1), - /** The QR Code can tolerate about 15% erroneous codewords. */ MEDIUM(0), - /** The QR Code can tolerate about 25% erroneous codewords. */ QUARTILE(3), - /** The QR Code can tolerate about 30% erroneous codewords. */ HIGH(2); - - // In the range 0 to 3 (unsigned 2-bit integer). - final int formatBits; - - // Constructor. - private Ecc(int fb) { - formatBits = fb; - } - } - } \ No newline at end of file diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java index 3c50bda..0e25584 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java @@ -53,15 +53,15 @@ public final class QrCodeGeneratorDemo { // Creates a single QR Code, then writes it to a PNG file and an SVG file. private static void doBasicDemo() throws IOException { String text = "Hello, world!"; // User-supplied Unicode text - QrCode.Ecc errCorLvl = QrCode.Ecc.LOW; // Error correction level + Ecc errCorLvl = Ecc.LOW; // Error correction level - QrCode qr = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol + QrCode qrCode = QrCode.encodeText(text, errCorLvl); // Make the QR Code symbol - BufferedImage img = qr.toImage(10, 4); // Convert to bitmap image + BufferedImage img = qrCode.toImage(10, 4); // Convert to bitmap image File imgFile = new File("hello-world-QR.png"); // File path for output ImageIO.write(img, "png", imgFile); // Write image to file - String svg = qr.toSvgString(4); // Convert to SVG XML code + String svg = qrCode.toSvgString(4); // Convert to SVG XML code File svgFile = new File("hello-world-QR.svg"); // File path for output Files.write(svgFile.toPath(), // Write image to file svg.getBytes(StandardCharsets.UTF_8)); @@ -70,97 +70,112 @@ public final class QrCodeGeneratorDemo { // Creates a variety of QR Codes that exercise different features of the library, and writes each one to file. private static void doVarietyDemo() throws IOException { - QrCode qr; + QrCode qrCode; // Numeric mode encoding (3.33 bits per digit) - qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM); - writePng(qr.toImage(13, 1), "pi-digits-QR.png"); + + qrCode = QrCode.encodeText("314159265358979323846264338327950288419716939937510", Ecc.MEDIUM); + writePng(qrCode.toImage(13, 1), "pi-digits-QR.png"); // Alphanumeric mode encoding (5.5 bits per character) - qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH); - writePng(qr.toImage(10, 2), "alphanumeric-QR.png"); + qrCode = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH); + writePng(qrCode.toImage(10, 2), "alphanumeric-QR.png"); // Unicode text as UTF-8 - qr = QrCode.encodeText("こんにちwa、世界! αβγδ", QrCode.Ecc.QUARTILE); - writePng(qr.toImage(10, 3), "unicode-QR.png"); + qrCode = QrCode.encodeText("占쎄괭占쎄뎐占쎄쾽占쎄굶wa占쎄낌�닟占쎈르塋딉옙 �뀭汝뷸Ь�걣", Ecc.QUARTILE); + writePng(qrCode.toImage(10, 3), "unicode-QR.png"); + // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) - qr = QrCode.encodeText( + qrCode = QrCode.encodeText( "Alice was beginning to get very tired of sitting by her sister on the bank, " + "and of having nothing to do: once or twice she had peeped into the book her sister was reading, " + "but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice " + "'without pictures or conversations?' So she was considering in her own mind (as well as she could, " + "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a " + "daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly " - + "a White Rabbit with pink eyes ran close by her.", QrCode.Ecc.HIGH); - writePng(qr.toImage(6, 10), "alice-wonderland-QR.png"); + + "a White Rabbit with pink eyes ran close by her.", Ecc.HIGH); + + writePng(qrCode.toImage(6, 10), "alice-wonderland-QR.png"); + } // Creates QR Codes with manually specified segments for better compactness. private static void doSegmentDemo() throws IOException { - QrCode qr; - List