Merge pull request #4 from gerzees/master

1234
pull/90/head
minsu4107 5 years ago committed by GitHub
commit 9458d17e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//java/src/main/java/io/nayuki/qrcodegen/QrCodeGeneratorDemo.java=UTF-8

@ -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);
}
}

@ -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.
* <p>Any text string can be converted to UTF-8 bytes ({@code
* s.getBytes(StandardCharsets.UTF_8)}) and encoded as a byte mode segment.</p>
* @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);
}
}

@ -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();
}
}

@ -0,0 +1,4 @@
public interface MakeSegment {
public QrSegment excute(String text);
}

@ -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;
}
}

@ -55,13 +55,13 @@ public final class QrCodeGeneratorDemo {
String text = "Hello, world!"; // User-supplied Unicode text String text = "Hello, world!"; // User-supplied Unicode text
Ecc errCorLvl = 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 File imgFile = new File("hello-world-QR.png"); // File path for output
ImageIO.write(img, "png", imgFile); // Write image to file 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 File svgFile = new File("hello-world-QR.svg"); // File path for output
Files.write(svgFile.toPath(), // Write image to file Files.write(svgFile.toPath(), // Write image to file
svg.getBytes(StandardCharsets.UTF_8)); svg.getBytes(StandardCharsets.UTF_8));
@ -70,22 +70,24 @@ public final class QrCodeGeneratorDemo {
// Creates a variety of QR Codes that exercise different features of the library, and writes each one to file. // 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 { private static void doVarietyDemo() throws IOException {
QrCode qr; QrCode qrCode;
// Numeric mode encoding (3.33 bits per digit) // Numeric mode encoding (3.33 bits per digit)
qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", 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) // Alphanumeric mode encoding (5.5 bits per character)
qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH); qrCode = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", Ecc.HIGH);
writePng(qr.toImage(10, 2), "alphanumeric-QR.png"); writePng(qrCode.toImage(10, 2), "alphanumeric-QR.png");
// Unicode text as UTF-8 // Unicode text as UTF-8
qr = QrCode.encodeText("こんにちwa、世界 αβγδ", Ecc.QUARTILE); qrCode = QrCode.encodeText("占쎄괭占쎄뎐占쎄쾽占쎄굶wa占쎄낌<EC8E84>닟占쎈르塋딉옙 <20>뀭汝뷸Ь<EBB7B8>걣", Ecc.QUARTILE);
writePng(qr.toImage(10, 3), "unicode-QR.png"); writePng(qrCode.toImage(10, 3), "unicode-QR.png");
// Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) // 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, " "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, " + "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 " + "but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice "
@ -93,74 +95,87 @@ public final class QrCodeGeneratorDemo {
+ "for the hot day made her feel very sleepy and stupid), whether the pleasure of making a " + "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 " + "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.", Ecc.HIGH); + "a White Rabbit with pink eyes ran close by her.", Ecc.HIGH);
writePng(qr.toImage(6, 10), "alice-wonderland-QR.png");
writePng(qrCode.toImage(6, 10), "alice-wonderland-QR.png");
} }
// Creates QR Codes with manually specified segments for better compactness. // Creates QR Codes with manually specified segments for better compactness.
private static void doSegmentDemo() throws IOException { private static void doSegmentDemo() throws IOException {
QrCode qr; QrCode qrCode;
List<QrSegment> segs; List<QrSegment> segments;
// Illustration "silver" // Illustration "silver"
String silver0 = "THE SQUARE ROOT OF 2 IS 1."; String silver0 = "THE SQUARE ROOT OF 2 IS 1.";
String silver1 = "41421356237309504880168872420969807856967187537694807317667973799"; String silver1 = "41421356237309504880168872420969807856967187537694807317667973799";
qr = QrCode.encodeText(silver0 + silver1, Ecc.LOW);
writePng(qr.toImage(10, 3), "sqrt2-monolithic-QR.png");
segs = Arrays.asList( qrCode = QrCode.encodeText(silver0 + silver1, Ecc.LOW);
writePng(qrCode.toImage(10, 3), "sqrt2-monolithic-QR.png");
segments = Arrays.asList(
QrSegment.makeAlphanumeric(silver0), QrSegment.makeAlphanumeric(silver0),
QrSegment.makeNumeric(silver1)); QrSegment.makeNumeric(silver1));
qr = QrCode.encodeSegments(segs, Ecc.LOW);
writePng(qr.toImage(10, 3), "sqrt2-segmented-QR.png"); qrCode = QrCode.encodeSegments(segments, Ecc.LOW);
writePng(qrCode.toImage(10, 3), "sqrt2-segmented-QR.png");
// Illustration "golden" // Illustration "golden"
String golden0 = "Golden ratio φ = 1."; String golden0 = "Golden ratio 占쏙옙 = 1.";
String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374"; String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374";
String golden2 = "......"; String golden2 = "......";
qr = QrCode.encodeText(golden0 + golden1 + golden2, Ecc.LOW);
writePng(qr.toImage(8, 5), "phi-monolithic-QR.png");
segs = Arrays.asList( qrCode = QrCode.encodeText(golden0 + golden1 + golden2, Ecc.LOW);
writePng(qrCode.toImage(8, 5), "phi-monolithic-QR.png");
segments = Arrays.asList(
QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)), QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)),
QrSegment.makeNumeric(golden1), QrSegment.makeNumeric(golden1),
QrSegment.makeAlphanumeric(golden2)); QrSegment.makeAlphanumeric(golden2));
qr = QrCode.encodeSegments(segs, Ecc.LOW);
writePng(qr.toImage(8, 5), "phi-segmented-QR.png"); qrCode = QrCode.encodeSegments(segments, Ecc.LOW);
writePng(qrCode.toImage(8, 5), "phi-segmented-QR.png");
// Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters
String madoka = "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?"; String madoka = "占쎈슞異몌쫲類앹빼阿잙뀍寃뀐옙寃묕옙嫄<EC9899>占쎌겳占쎄묻占쎄텤占쎄텠占쎈씞寃귨옙寃랃옙怨ο옙占쏙옙<EC8F99>꺂癒믪꼨占쏙옙影<EC9899>袁ы맀影<EBA780>蹂⑺맟占쏙옙鰲<EC9899><E9B0B2>뀭塋딉옙";
qr = QrCode.encodeText(madoka, Ecc.LOW); qrCode = QrCode.encodeText(madoka, Ecc.LOW);
writePng(qr.toImage(9, 4), "madoka-utf8-QR.png"); writePng(qrCode.toImage(9, 4), "madoka-utf8-QR.png");
segments = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka));
qrCode = QrCode.encodeSegments(segments, Ecc.LOW);
writePng(qrCode.toImage(9, 4), "madoka-kanji-QR.png");
segs = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka));
qr = QrCode.encodeSegments(segs, Ecc.LOW);
writePng(qr.toImage(9, 4), "madoka-kanji-QR.png");
} }
// Creates QR Codes with the same size and contents but different mask patterns. // Creates QR Codes with the same size and contents but different mask patterns.
private static void doMaskDemo() throws IOException { private static void doMaskDemo() throws IOException {
QrCode qr; QrCode qrCode;
List<QrSegment> segs; List<QrSegment> segments;
// Project Nayuki URL // Project Nayuki URL
segs = QrSegment.makeSegments("https://www.nayuki.io/");
qr = QrCode.encodeSegments(segs, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask segments = QrSegment.makeSegments("https://www.nayuki.io/");
writePng(qr.toImage(8, 6), "project-nayuki-automask-QR.png"); qrCode = QrCode.encodeSegments(segments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true); // Automatic mask
qr = QrCode.encodeSegments(segs, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3 writePng(qrCode.toImage(8, 6), "project-nayuki-automask-QR.png");
writePng(qr.toImage(8, 6), "project-nayuki-mask3-QR.png"); qrCode = QrCode.encodeSegments(segments, Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true); // Force mask 3
writePng(qrCode.toImage(8, 6), "project-nayuki-mask3-QR.png");
// Chinese text as UTF-8 // Chinese text as UTF-8
segs = QrSegment.makeSegments("維基百科Wikipedia聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫"); segments = QrSegment.makeSegments("力놂옙占쎌쓢占쎌뇥<EC8E8C>뇖臾뺥렩Wikipedia塋딅슜嫄앾옙寃켲/占쎈샆<EC8E88>뎚藥<EB8E9A>戮먮뒰i占쎈쫨i.占쏙옙/塋딅맚<EB9485>궦鼇앾옙占쎈뿨<EC8E88>닅占쎈뎨占쎈<E58DA0>諛ㅿ옙怨⑸<E680A8>띰옙堉<EC9899>歷뜯몼<EB9CAF>꽎鼇앸떱姨<EB96B1>亦껋쉮占쏙옙<EC8F99>돦力녠엽<EB85A0>윭占쎌뇥<EC8E8C>뇖臾덈<E887BE>뀐옙<EB8090>럱占쎈쐭俑앹뮂怡ワ옙鍮<EC9899>");
qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0 qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true); // Force mask 0
writePng(qr.toImage(10, 3), "unicode-mask0-QR.png"); writePng(qrCode.toImage(10, 3), "unicode-mask0-QR.png");
qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1 qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true); // Force mask 1
writePng(qr.toImage(10, 3), "unicode-mask1-QR.png"); writePng(qrCode.toImage(10, 3), "unicode-mask1-QR.png");
qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5 qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true); // Force mask 5
writePng(qr.toImage(10, 3), "unicode-mask5-QR.png"); writePng(qrCode.toImage(10, 3), "unicode-mask5-QR.png");
qr = QrCode.encodeSegments(segs, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7 qrCode = QrCode.encodeSegments(segments, Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true); // Force mask 7
writePng(qr.toImage(10, 3), "unicode-mask7-QR.png"); writePng(qrCode.toImage(10, 3), "unicode-mask7-QR.png");
} }

@ -57,11 +57,11 @@ public final class QrCodeGeneratorWorker {
boolean isAscii = true; boolean isAscii = true;
byte[] data = new byte[length]; byte[] data = new byte[length];
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
int b = input.nextInt(); int one_byte = input.nextInt();
if (b < 0 || b > 255) if (one_byte < 0 || one_byte > 255)
throw new RuntimeException(); throw new RuntimeException();
data[i] = (byte)b; data[i] = (byte)one_byte;
isAscii &= b < 128; isAscii &= one_byte < 128;
} }
// Read encoding parameters // Read encoding parameters
@ -75,14 +75,15 @@ public final class QrCodeGeneratorWorker {
throw new RuntimeException(); throw new RuntimeException();
// Make segments for encoding // Make segments for encoding
List<QrSegment> segs; List<QrSegment> segments;
if (isAscii) if (isAscii)
segs = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII)); segments = QrSegment.makeSegments(new String(data, StandardCharsets.US_ASCII));
else else
segs = Arrays.asList(QrSegment.makeBytes(data)); segments = Arrays.asList(QrSegment.makeBytes(data));
try { // Try to make QR Code symbol try { // Try to make QR Code symbol
QrCode qr = QrCode.encodeSegments(segs, Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0); QrCode qr = QrCode.encodeSegments(segments, Ecc.values()[errCorLvl], minVersion, maxVersion, mask, boostEcl != 0);
// Print grid of modules // Print grid of modules
System.out.println(qr.version); System.out.println(qr.version);
for (int y = 0; y < qr.size; y++) { for (int y = 0; y < qr.size; y++) {

@ -29,6 +29,8 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import QrSegment.Mode;
/** /**
* A segment of character/binary/control data in a QR Code symbol. * A segment of character/binary/control data in a QR Code symbol.
@ -46,7 +48,6 @@ import java.util.regex.Pattern;
public final class QrSegment { public final class QrSegment {
/*---- Static factory functions (mid level) ----*/ /*---- Static factory functions (mid level) ----*/
/** /**
* Returns a segment representing the specified binary data * Returns a segment representing the specified binary data
* encoded in byte mode. All input byte arrays are acceptable. * encoded in byte mode. All input byte arrays are acceptable.
@ -57,11 +58,9 @@ public final class QrSegment {
* @throws NullPointerException if the array is {@code null} * @throws NullPointerException if the array is {@code null}
*/ */
public static QrSegment makeBytes(byte[] data) { public static QrSegment makeBytes(byte[] data) {
Objects.requireNonNull(data); MakeBytesToSegment makeBytesToSegment = new MakeBytesToSegment();
BitBuffer bb = new BitBuffer();
for (byte b : data) return makeBytesToSegment.excuteForBytedata(data);
bb.appendBits(b & 0xFF, 8);
return new QrSegment(Mode.BYTE, data.length, bb);
} }
@ -73,17 +72,9 @@ public final class QrSegment {
* @throws IllegalArgumentException if the string contains non-digit characters * @throws IllegalArgumentException if the string contains non-digit characters
*/ */
public static QrSegment makeNumeric(String digits) { public static QrSegment makeNumeric(String digits) {
Objects.requireNonNull(digits); MakeSegment makeSegment = new MakeNumericToSegment();
if (!NUMERIC_REGEX.matcher(digits).matches())
throw new IllegalArgumentException("String contains non-numeric characters"); return makeSegment.excute(digits);
BitBuffer bb = new BitBuffer();
for (int i = 0; i < digits.length(); ) { // Consume up to 3 digits per iteration
int n = Math.min(digits.length() - i, 3);
bb.appendBits(Integer.parseInt(digits.substring(i, i + n)), n * 3 + 1);
i += n;
}
return new QrSegment(Mode.NUMERIC, digits.length(), bb);
} }
@ -97,23 +88,10 @@ public final class QrSegment {
* @throws IllegalArgumentException if the string contains non-encodable characters * @throws IllegalArgumentException if the string contains non-encodable characters
*/ */
public static QrSegment makeAlphanumeric(String text) { public static QrSegment makeAlphanumeric(String text) {
Objects.requireNonNull(text); MakeSegment makeSegment = new MakeAlphaNumericToSegment();
if (!ALPHANUMERIC_REGEX.matcher(text).matches())
throw new IllegalArgumentException("String contains unencodable characters in alphanumeric mode");
BitBuffer bb = new BitBuffer();
int i;
for (i = 0; i <= text.length() - 2; i += 2) { // Process groups of 2
int temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
bb.appendBits(temp, 11);
}
if (i < text.length()) // 1 character remaining
bb.appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6);
return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb);
}
return makeSegment.excute(text);
}
/** /**
* Returns a list of zero or more segments to represent the specified Unicode text string. * Returns a list of zero or more segments to represent the specified Unicode text string.
* The result may use various segment modes and switch modes to optimize the length of the bit stream. * The result may use various segment modes and switch modes to optimize the length of the bit stream.
@ -121,22 +99,18 @@ public final class QrSegment {
* @return a new mutable list (not {@code null}) of segments (not {@code null}) containing the text * @return a new mutable list (not {@code null}) of segments (not {@code null}) containing the text
* @throws NullPointerException if the text is {@code null} * @throws NullPointerException if the text is {@code null}
*/ */
public static List<QrSegment> makeSegments(String text) { public static List<QrSegment> makeSegments(String text) {
Objects.requireNonNull(text); Objects.requireNonNull(text);
// Select the most efficient segment encoding automatically // Select the most efficient segment encoding automatically
List<QrSegment> result = new ArrayList<>(); List<QrSegment> segments = new ArrayList<>();
if (text.equals("")); // Leave result empty
else if (NUMERIC_REGEX.matcher(text).matches())
result.add(makeNumeric(text));
else if (ALPHANUMERIC_REGEX.matcher(text).matches())
result.add(makeAlphanumeric(text));
else
result.add(makeBytes(text.getBytes(StandardCharsets.UTF_8)));
return result;
}
MakeSegment makeSegment = MakeSegmentFactory.getMakeSegment(text);
segments.add(makeSegment.excute(text));
return segments;
}
/** /**
* Returns a segment representing an Extended Channel Interpretation * Returns a segment representing an Extended Channel Interpretation
* (ECI) designator with the specified assignment value. * (ECI) designator with the specified assignment value.
@ -144,21 +118,21 @@ public final class QrSegment {
* @return a segment (not {@code null}) containing the data * @return a segment (not {@code null}) containing the data
* @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 assignValue) {
BitBuffer bb = new BitBuffer(); BitBuffer bitBuffer = new BitBuffer();
if (assignVal < 0) if (assignValue < 0)
throw new IllegalArgumentException("ECI assignment value out of range"); throw new IllegalArgumentException("ECI assignment value out of range");
else if (assignVal < (1 << 7)) else if (assignValue < (1 << 7))
bb.appendBits(assignVal, 8); bitBuffer.appendBits(assignValue, 8);
else if (assignVal < (1 << 14)) { else if (assignValue < (1 << 14)) {
bb.appendBits(2, 2); bitBuffer.appendBits(2, 2);
bb.appendBits(assignVal, 14); bitBuffer.appendBits(assignValue, 14);
} else if (assignVal < 1_000_000) { } else if (assignValue < 1_000_000) {
bb.appendBits(6, 3); bitBuffer.appendBits(6, 3);
bb.appendBits(assignVal, 21); bitBuffer.appendBits(assignValue, 21);
} else } 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, bb); return new QrSegment(Mode.ECI, 0, bitBuffer);
} }
@ -189,16 +163,15 @@ public final class QrSegment {
* @throws NullPointerException if the mode or data is {@code null} * @throws NullPointerException if the mode or data is {@code null}
* @throws IllegalArgumentException if the character count is negative * @throws IllegalArgumentException if the character count is negative
*/ */
public QrSegment(Mode md, int numCh, BitBuffer data) { public QrSegment(Mode _mode, int _numberOfCharacters, BitBuffer data) {
mode = Objects.requireNonNull(md); mode = Objects.requireNonNull(_mode);
Objects.requireNonNull(data); Objects.requireNonNull(data);
if (numCh < 0) if (_numberOfCharacters < 0)
throw new IllegalArgumentException("Invalid value"); throw new IllegalArgumentException("Invalid value");
numChars = numCh; numberOfCharacters = _numberOfCharacters;
this.data = data.clone(); // Make defensive copy this.data = data.clone(); // Make defensive copy
} }
/*---- Methods ----*/ /*---- Methods ----*/
/** /**
@ -213,22 +186,21 @@ public final class QrSegment {
// Calculates the number of bits needed to encode the given segments at the given version. // Calculates the number of bits needed to encode the given segments at the given version.
// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too // Returns a non-negative number if successful. Otherwise returns -1 if a segment has too
// many characters to fit its length field, or the total bits exceeds Integer.MAX_VALUE. // many characters to fit its length field, or the total bits exceeds Integer.MAX_VALUE.
static int getTotalBits(List<QrSegment> segs, int version) { static int getTotalBits(List<QrSegment> segments, int version) {
Objects.requireNonNull(segs); Objects.requireNonNull(segments);
long result = 0; long TotalBits = 0;
for (QrSegment seg : segs) { for (QrSegment segment : segments) {
Objects.requireNonNull(seg); Objects.requireNonNull(segment);
int ccbits = seg.mode.numCharCountBits(version); int characterCountBits = segment.mode.numCharCountBits(version);
if (seg.numChars >= (1 << ccbits)) if (segment.numberOfCharacters >= (1 << characterCountBits))
return -1; // The segment's length doesn't fit the field's bit width return -1; // The segment's length doesn't fit the field's bit width
result += 4L + ccbits + seg.data.bitLength(); TotalBits += 4L + characterCountBits + segment.data.bitLength();
if (result > Integer.MAX_VALUE) if (TotalBits > Integer.MAX_VALUE)
return -1; // The sum will overflow an int type return -1; // The sum will overflow an int type
} }
return (int)result; return (int)TotalBits;
} }
/*---- Constants ----*/ /*---- Constants ----*/
/** Describes precisely all strings that are encodable in numeric mode. To test whether a /** Describes precisely all strings that are encodable in numeric mode. To test whether a

Loading…
Cancel
Save