- Deleted constructors/functions/code for remasking existing QrCode object (due to doubtful real-world usefulness): C++, Java, JavaScript, Python, Rust.

- Tweaked code and comments due to feature removal: JavaScript, Python.
- Updated demo programs to reflect new API usage and add new example: C, C++, Java, Python, Rust.
pull/20/head
Project Nayuki 7 years ago
parent c4c8d6ba45
commit b86466ecd5

@ -36,6 +36,7 @@
static void doBasicDemo(void); static void doBasicDemo(void);
static void doVarietyDemo(void); static void doVarietyDemo(void);
static void doSegmentDemo(void); static void doSegmentDemo(void);
static void doMaskDemo(void);
static void printQr(const uint8_t qrcode[]); static void printQr(const uint8_t qrcode[]);
@ -45,6 +46,7 @@ int main(void) {
doBasicDemo(); doBasicDemo();
doVarietyDemo(); doVarietyDemo();
doSegmentDemo(); doSegmentDemo();
doMaskDemo();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -66,15 +68,6 @@ static void doBasicDemo(void) {
// Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console. // Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
static void doVarietyDemo(void) { static void doVarietyDemo(void) {
{ // Project Nayuki URL
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_3, true);
if (ok)
printQr(qrcode);
}
{ // Numeric mode encoding (3.33 bits per digit) { // Numeric mode encoding (3.33 bits per digit)
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
@ -93,29 +86,12 @@ static void doVarietyDemo(void) {
printQr(qrcode); printQr(qrcode);
} }
{ // Unicode text as UTF-8, and different masks { // Unicode text as UTF-8
const char *text = "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4"; const char *text = "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok; bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_0, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_1, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_5, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_7, true);
if (ok) if (ok)
printQr(qrcode); printQr(qrcode);
} }
@ -260,6 +236,60 @@ static void doSegmentDemo(void) {
} }
// Creates QR Codes with the same size and contents but different mask patterns.
static void doMaskDemo(void) {
{ // Project Nayuki URL
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
ok = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_3, true);
if (ok)
printQr(qrcode);
}
{ // Chinese text as UTF-8
const char *text =
"\xE7\xB6\xAD\xE5\x9F\xBA\xE7\x99\xBE\xE7\xA7\x91\xEF\xBC\x88\x57\x69\x6B\x69\x70"
"\x65\x64\x69\x61\xEF\xBC\x8C\xE8\x81\x86\xE8\x81\xBD\x69\x2F\xCB\x8C\x77\xC9\xAA"
"\x6B\xE1\xB5\xBB\xCB\x88\x70\x69\xCB\x90\x64\x69\x2E\xC9\x99\x2F\xEF\xBC\x89\xE6"
"\x98\xAF\xE4\xB8\x80\xE5\x80\x8B\xE8\x87\xAA\xE7\x94\xB1\xE5\x85\xA7\xE5\xAE\xB9"
"\xE3\x80\x81\xE5\x85\xAC\xE9\x96\x8B\xE7\xB7\xA8\xE8\xBC\xAF\xE4\xB8\x94\xE5\xA4"
"\x9A\xE8\xAA\x9E\xE8\xA8\x80\xE7\x9A\x84\xE7\xB6\xB2\xE8\xB7\xAF\xE7\x99\xBE\xE7"
"\xA7\x91\xE5\x85\xA8\xE6\x9B\xB8\xE5\x8D\x94\xE4\xBD\x9C\xE8\xA8\x88\xE7\x95\xAB";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_0, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_1, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_5, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_7, true);
if (ok)
printQr(qrcode);
}
}
// Prints the given QR Code to the console. // Prints the given QR Code to the console.
static void printQr(const uint8_t qrcode[]) { static void printQr(const uint8_t qrcode[]) {
int size = qrcodegen_getSize(qrcode); int size = qrcodegen_getSize(qrcode);

@ -139,25 +139,6 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int mask)
} }
QrCode::QrCode(const QrCode &qr, int mask) :
// Copy scalar fields
version(qr.version),
size(qr.size),
errorCorrectionLevel(qr.errorCorrectionLevel),
// Handle grid fields
modules(qr.modules),
isFunction(qr.isFunction) {
// Check arguments
if (mask < -1 || mask > 7)
throw "Mask value out of range";
// Handle masking
applyMask(qr.mask); // Undo old mask
this->mask = handleConstructorMasking(mask);
}
int QrCode::getVersion() const { int QrCode::getVersion() const {
return version; return version;
} }

@ -132,14 +132,6 @@ class QrCode final {
public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int mask); public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int mask);
/*
* Creates a new QR Code symbol based on the given existing object, but with a potentially
* different mask pattern. The version, error correction level, codewords, etc. of the newly
* created object are all identical to the argument object; only the mask may differ.
*/
public: QrCode(const QrCode &qr, int mask);
/*---- Public instance methods ----*/ /*---- Public instance methods ----*/

@ -42,6 +42,7 @@ using qrcodegen::QrSegment;
static void doBasicDemo(); static void doBasicDemo();
static void doVarietyDemo(); static void doVarietyDemo();
static void doSegmentDemo(); static void doSegmentDemo();
static void doMaskDemo();
static void printQr(const QrCode &qr); static void printQr(const QrCode &qr);
@ -51,6 +52,7 @@ int main() {
doBasicDemo(); doBasicDemo();
doVarietyDemo(); doVarietyDemo();
doSegmentDemo(); doSegmentDemo();
doMaskDemo();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -69,10 +71,6 @@ static void doBasicDemo() {
// Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console. // Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
static void doVarietyDemo() { static void doVarietyDemo() {
// Project Nayuki URL
const QrCode qr0 = QrCode::encodeText("https://www.nayuki.io/", QrCode::Ecc::HIGH);
printQr(QrCode(qr0, 3)); // Change mask, forcing to mask #3
// Numeric mode encoding (3.33 bits per digit) // Numeric mode encoding (3.33 bits per digit)
const QrCode qr1 = QrCode::encodeText("314159265358979323846264338327950288419716939937510", QrCode::Ecc::MEDIUM); const QrCode qr1 = QrCode::encodeText("314159265358979323846264338327950288419716939937510", QrCode::Ecc::MEDIUM);
printQr(qr1); printQr(qr1);
@ -81,12 +79,9 @@ static void doVarietyDemo() {
const QrCode qr2 = QrCode::encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode::Ecc::HIGH); const QrCode qr2 = QrCode::encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode::Ecc::HIGH);
printQr(qr2); printQr(qr2);
// Unicode text as UTF-8, and different masks // Unicode text as UTF-8
const QrCode qr3 = QrCode::encodeText("\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4", QrCode::Ecc::QUARTILE); const QrCode qr3 = QrCode::encodeText("\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4", QrCode::Ecc::QUARTILE);
printQr(QrCode(qr3, 0)); printQr(qr3);
printQr(QrCode(qr3, 1));
printQr(QrCode(qr3, 5));
printQr(QrCode(qr3, 7));
// 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)
const QrCode qr4 = QrCode::encodeText( const QrCode qr4 = QrCode::encodeText(
@ -163,6 +158,29 @@ static void doSegmentDemo() {
} }
// Creates QR Codes with the same size and contents but different mask patterns.
static void doMaskDemo() {
// Project Nayuki URL
std::vector<QrSegment> segs0 = QrSegment::makeSegments("https://www.nayuki.io/");
printQr(QrCode::encodeSegments(segs0, QrCode::Ecc::HIGH, 1, 40, -1, true)); // Automatic mask
printQr(QrCode::encodeSegments(segs0, QrCode::Ecc::HIGH, 1, 40, 3, true)); // Force mask 3
// Chinese text as UTF-8
std::vector<QrSegment> segs1 = QrSegment::makeSegments(
"\xE7\xB6\xAD\xE5\x9F\xBA\xE7\x99\xBE\xE7\xA7\x91\xEF\xBC\x88\x57\x69\x6B\x69\x70"
"\x65\x64\x69\x61\xEF\xBC\x8C\xE8\x81\x86\xE8\x81\xBD\x69\x2F\xCB\x8C\x77\xC9\xAA"
"\x6B\xE1\xB5\xBB\xCB\x88\x70\x69\xCB\x90\x64\x69\x2E\xC9\x99\x2F\xEF\xBC\x89\xE6"
"\x98\xAF\xE4\xB8\x80\xE5\x80\x8B\xE8\x87\xAA\xE7\x94\xB1\xE5\x85\xA7\xE5\xAE\xB9"
"\xE3\x80\x81\xE5\x85\xAC\xE9\x96\x8B\xE7\xB7\xA8\xE8\xBC\xAF\xE4\xB8\x94\xE5\xA4"
"\x9A\xE8\xAA\x9E\xE8\xA8\x80\xE7\x9A\x84\xE7\xB6\xB2\xE8\xB7\xAF\xE7\x99\xBE\xE7"
"\xA7\x91\xE5\x85\xA8\xE6\x9B\xB8\xE5\x8D\x94\xE4\xBD\x9C\xE8\xA8\x88\xE7\x95\xAB");
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, 1, 40, 0, true)); // Force mask 0
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, 1, 40, 1, true)); // Force mask 1
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, 1, 40, 5, true)); // Force mask 5
printQr(QrCode::encodeSegments(segs1, QrCode::Ecc::MEDIUM, 1, 40, 7, true)); // Force mask 7
}
// Prints the given QR Code to the console. // Prints the given QR Code to the console.
static void printQr(const QrCode &qr) { static void printQr(const QrCode &qr) {
int border = 4; int border = 4;

@ -222,38 +222,6 @@ public final class QrCode {
} }
/**
* Creates a new QR Code symbol based on the specified existing object, but with a potentially
* different mask pattern. The version, error correction level, codewords, etc. of the newly
* created object are all identical to the argument object; only the mask may differ.
* @param qr the existing QR Code to copy and modify
* @param mask the new mask pattern, 0 to 7 to force a fixed choice or -1 for an automatic choice
* @throws NullPointerException if the QR Code is {@code null}
* @throws IllegalArgumentException if the mask value is out of range
*/
public QrCode(QrCode qr, int mask) {
// Check arguments
Objects.requireNonNull(qr);
if (mask < -1 || mask > 7)
throw new IllegalArgumentException("Mask value out of range");
// Copy scalar fields
version = qr.version;
size = qr.size;
errorCorrectionLevel = qr.errorCorrectionLevel;
// Handle grid fields
isFunction = qr.isFunction; // Shallow copy because the data is read-only
modules = qr.modules.clone(); // Deep copy
for (int i = 0; i < modules.length; i++)
modules[i] = modules[i].clone();
// Handle masking
applyMask(qr.mask); // Undo old mask
this.mask = handleConstructorMasking(mask);
}
/*---- Public instance methods ----*/ /*---- Public instance methods ----*/

@ -45,6 +45,7 @@ public final class QrCodeGeneratorDemo {
doBasicDemo(); doBasicDemo();
doVarietyDemo(); doVarietyDemo();
doSegmentDemo(); doSegmentDemo();
doMaskDemo();
} }
@ -72,11 +73,6 @@ public final class QrCodeGeneratorDemo {
private static void doVarietyDemo() throws IOException { private static void doVarietyDemo() throws IOException {
QrCode qr; QrCode qr;
// Project Nayuki URL
qr = QrCode.encodeText("https://www.nayuki.io/", QrCode.Ecc.HIGH);
qr = new QrCode(qr, 3); // Change mask, forcing to mask #3
writePng(qr.toImage(8, 6), "project-nayuki-QR.png");
// Numeric mode encoding (3.33 bits per digit) // Numeric mode encoding (3.33 bits per digit)
qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM); qr = QrCode.encodeText("314159265358979323846264338327950288419716939937510", QrCode.Ecc.MEDIUM);
writePng(qr.toImage(13, 1), "pi-digits-QR.png"); writePng(qr.toImage(13, 1), "pi-digits-QR.png");
@ -85,12 +81,9 @@ public final class QrCodeGeneratorDemo {
qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH); qr = QrCode.encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode.Ecc.HIGH);
writePng(qr.toImage(10, 2), "alphanumeric-QR.png"); writePng(qr.toImage(10, 2), "alphanumeric-QR.png");
// Unicode text as UTF-8, and different masks // Unicode text as UTF-8
qr = QrCode.encodeText("こんにちwa、世界 αβγδ", QrCode.Ecc.QUARTILE); qr = QrCode.encodeText("こんにちwa、世界 αβγδ", QrCode.Ecc.QUARTILE);
writePng(new QrCode(qr, 0).toImage(10, 3), "unicode-mask0-QR.png"); writePng(qr.toImage(10, 3), "unicode-QR.png");
writePng(new QrCode(qr, 1).toImage(10, 3), "unicode-mask1-QR.png");
writePng(new QrCode(qr, 5).toImage(10, 3), "unicode-mask5-QR.png");
writePng(new QrCode(qr, 7).toImage(10, 3), "unicode-mask7-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( qr = QrCode.encodeText(
@ -158,6 +151,31 @@ public final class QrCodeGeneratorDemo {
} }
// Creates QR Codes with the same size and contents but different mask patterns.
private static void doMaskDemo() throws IOException {
QrCode qr;
List<QrSegment> segs;
// Project Nayuki URL
segs = QrSegment.makeSegments("https://www.nayuki.io/");
qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, 1, 40, -1, true); // Automatic mask
writePng(qr.toImage(8, 6), "project-nayuki-automask-QR.png");
qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, 1, 40, 3, true); // Force mask 3
writePng(qr.toImage(8, 6), "project-nayuki-mask3-QR.png");
// Chinese text as UTF-8
segs = QrSegment.makeSegments("維基百科Wikipedia聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫");
qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, 1, 40, 0, true); // Force mask 0
writePng(qr.toImage(10, 3), "unicode-mask0-QR.png");
qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, 1, 40, 1, true); // Force mask 1
writePng(qr.toImage(10, 3), "unicode-mask1-QR.png");
qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, 1, 40, 5, true); // Force mask 5
writePng(qr.toImage(10, 3), "unicode-mask5-QR.png");
qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, 1, 40, 7, true); // Force mask 7
writePng(qr.toImage(10, 3), "unicode-mask7-QR.png");
}
// Helper function to reduce code duplication. // Helper function to reduce code duplication.
private static void writePng(BufferedImage img, String filepath) throws IOException { private static void writePng(BufferedImage img, String filepath) throws IOException {
ImageIO.write(img, "png", new File(filepath)); ImageIO.write(img, "png", new File(filepath));

@ -31,7 +31,6 @@
* - Function encodeBinary(list<byte> data, QrCode.Ecc ecl) -> QrCode * - Function encodeBinary(list<byte> data, QrCode.Ecc ecl) -> QrCode
* - Function encodeSegments(list<QrSegment> segs, QrCode.Ecc ecl, * - Function encodeSegments(list<QrSegment> segs, QrCode.Ecc ecl,
* int minVersion=1, int maxVersion=40, mask=-1, boostEcl=true) -> QrCode * int minVersion=1, int maxVersion=40, mask=-1, boostEcl=true) -> QrCode
* - Constructor QrCode(QrCode qr, int mask)
* - Constructor QrCode(list<int> datacodewords, int mask, int version, QrCode.Ecc ecl) * - Constructor QrCode(list<int> datacodewords, int mask, int version, QrCode.Ecc ecl)
* - Fields int version, size, mask * - Fields int version, size, mask
* - Field QrCode.Ecc errorCorrectionLevel * - Field QrCode.Ecc errorCorrectionLevel
@ -64,35 +63,19 @@ var qrcodegen = new function() {
* with associated static functions to create a QR Code from user-supplied textual or binary data. * with associated static functions to create a QR Code from user-supplied textual or binary data.
* This class covers the QR Code model 2 specification, supporting all versions (sizes) * This class covers the QR Code model 2 specification, supporting all versions (sizes)
* from 1 to 40, all 4 error correction levels. * from 1 to 40, all 4 error correction levels.
* * This constructor creates a new QR Code symbol with the given version number, error correction level, binary data array,
* This constructor can be called in one of two ways: * and mask number. mask = -1 is for automatic choice, or 0 to 7 for fixed choice. This is a cumbersome low-level constructor
* - new QrCode(datacodewords, mask, version, errCorLvl): * that should not be invoked directly by the user. To go one level up, see the QrCode.encodeSegments() function.
* Creates a new QR Code symbol with the given version number, error correction level, binary data array,
* and mask number. This is a cumbersome low-level constructor that should not be invoked directly by the user.
* To go one level up, see the QrCode.encodeSegments() function.
* - new QrCode(qr, mask):
* Creates a new QR Code symbol based on the given existing object, but with a potentially different
* mask pattern. The version, error correction level, codewords, etc. of the newly created object are
* all identical to the argument object; only the mask may differ.
* In both cases, mask = -1 is for automatic choice or 0 to 7 for fixed choice.
*/ */
this.QrCode = function(initData, mask, version, errCorLvl) { this.QrCode = function(datacodewords, mask, version, errCorLvl) {
/*---- Constructor ----*/ /*---- Constructor ----*/
// Check arguments and handle simple scalar fields // Check arguments and handle simple scalar fields
if (mask < -1 || mask > 7) if (mask < -1 || mask > 7)
throw "Mask value out of range"; throw "Mask value out of range";
if (initData instanceof Array) { if (version < 1 || version > 40)
if (version < 1 || version > 40) throw "Version value out of range";
throw "Version value out of range";
} else if (initData instanceof qrcodegen.QrCode) {
if (version != undefined || errCorLvl != undefined)
throw "Values must be undefined";
version = initData.version;
errCorLvl = initData.errorCorrectionLevel;
} else
throw "Invalid initial data";
var size = version * 4 + 17; var size = version * 4 + 17;
// Initialize both grids to be size*size arrays of Boolean false // Initialize both grids to be size*size arrays of Boolean false
@ -106,22 +89,10 @@ var qrcodegen = new function() {
isFunction.push(row.slice()); isFunction.push(row.slice());
} }
// Handle grid fields // Handle grid fields, draw function patterns, draw all codewords
if (initData instanceof Array) { drawFunctionPatterns();
// Draw function patterns, draw all codewords var allCodewords = appendErrorCorrection(datacodewords);
drawFunctionPatterns(); drawCodewords(allCodewords);
var allCodewords = appendErrorCorrection(initData);
drawCodewords(allCodewords);
} else if (initData instanceof qrcodegen.QrCode) {
for (var y = 0; y < size; y++) {
for (var x = 0; x < size; x++) {
modules[y][x] = initData.getModule(x, y);
isFunction[y][x] = initData.isFunctionModule(x, y);
}
}
applyMask(initData.mask); // Undo old mask
} else
throw "Invalid initial data";
// Handle masking // Handle masking
if (mask == -1) { // Automatically choose best mask if (mask == -1) { // Automatically choose best mask

@ -35,6 +35,7 @@ def main():
do_basic_demo() do_basic_demo()
do_variety_demo() do_variety_demo()
do_segment_demo() do_segment_demo()
do_mask_demo()
def do_basic_demo(): def do_basic_demo():
@ -51,11 +52,6 @@ def do_basic_demo():
def do_variety_demo(): def do_variety_demo():
"""Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.""" """Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console."""
# Project Nayuki URL
qr = qrcodegen.QrCode.encode_text("https://www.nayuki.io/", qrcodegen.QrCode.Ecc.HIGH)
qr = qrcodegen.QrCode(qrcode=qr, mask=3) # Change mask, forcing to mask #3
print_qr(qr)
# Numeric mode encoding (3.33 bits per digit) # Numeric mode encoding (3.33 bits per digit)
qr = qrcodegen.QrCode.encode_text("314159265358979323846264338327950288419716939937510", qrcodegen.QrCode.Ecc.MEDIUM) qr = qrcodegen.QrCode.encode_text("314159265358979323846264338327950288419716939937510", qrcodegen.QrCode.Ecc.MEDIUM)
print_qr(qr) print_qr(qr)
@ -64,12 +60,9 @@ def do_variety_demo():
qr = qrcodegen.QrCode.encode_text("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", qrcodegen.QrCode.Ecc.HIGH) qr = qrcodegen.QrCode.encode_text("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", qrcodegen.QrCode.Ecc.HIGH)
print_qr(qr) print_qr(qr)
# Unicode text as UTF-8, and different masks # Unicode text as UTF-8
qr = qrcodegen.QrCode.encode_text(u"\u3053\u3093\u306B\u3061\u0077\u0061\u3001\u4E16\u754C\uFF01\u0020\u03B1\u03B2\u03B3\u03B4", qrcodegen.QrCode.Ecc.QUARTILE) qr = qrcodegen.QrCode.encode_text(u"\u3053\u3093\u306B\u3061\u0077\u0061\u3001\u4E16\u754C\uFF01\u0020\u03B1\u03B2\u03B3\u03B4", qrcodegen.QrCode.Ecc.QUARTILE)
print_qr(qrcodegen.QrCode(qrcode=qr, mask=0)) print_qr(qr)
print_qr(qrcodegen.QrCode(qrcode=qr, mask=1))
print_qr(qrcodegen.QrCode(qrcode=qr, mask=5))
print_qr(qrcodegen.QrCode(qrcode=qr, mask=7))
# 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 = qrcodegen.QrCode.encode_text( qr = qrcodegen.QrCode.encode_text(
@ -153,6 +146,27 @@ def do_segment_demo():
print_qr(qr) print_qr(qr)
def do_mask_demo():
"""Creates QR Codes with the same size and contents but different mask patterns."""
# Project Nayuki URL
segs = qrcodegen.QrSegment.make_segments("https://www.nayuki.io/")
print_qr(qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.HIGH, mask=-1)) # Automatic mask
print_qr(qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.HIGH, mask=3)) # Force mask 3
# Chinese text as UTF-8
segs = qrcodegen.QrSegment.make_segments(
u"\u7DAD\u57FA\u767E\u79D1\uFF08\u0057\u0069\u006B\u0069\u0070\u0065\u0064\u0069\u0061\uFF0C"
"\u8046\u807D\u0069\u002F\u02CC\u0077\u026A\u006B\u1D7B\u02C8\u0070\u0069\u02D0\u0064\u0069"
"\u002E\u0259\u002F\uFF09\u662F\u4E00\u500B\u81EA\u7531\u5167\u5BB9\u3001\u516C\u958B\u7DE8"
"\u8F2F\u4E14\u591A\u8A9E\u8A00\u7684\u7DB2\u8DEF\u767E\u79D1\u5168\u66F8\u5354\u4F5C\u8A08"
"\u756B")
print_qr(qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.MEDIUM, mask=0)) # Force mask 0
print_qr(qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.MEDIUM, mask=1)) # Force mask 1
print_qr(qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.MEDIUM, mask=5)) # Force mask 5
print_qr(qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.MEDIUM, mask=7)) # Force mask 7
# ---- Utilities ---- # ---- Utilities ----

@ -31,7 +31,6 @@ This module "qrcodegen", public members:
- Function encode_binary(bytes data, QrCode.Ecc ecl) -> QrCode - Function encode_binary(bytes data, QrCode.Ecc ecl) -> QrCode
- Function encode_segments(list<QrSegment> segs, QrCode.Ecc ecl, - Function encode_segments(list<QrSegment> segs, QrCode.Ecc ecl,
int minversion=1, int maxversion=40, mask=-1, boostecl=true) -> QrCode int minversion=1, int maxversion=40, mask=-1, boostecl=true) -> QrCode
- Constructor QrCode(QrCode qr, int mask)
- Constructor QrCode(bytes datacodewords, int mask, int version, QrCode.Ecc ecl) - Constructor QrCode(bytes datacodewords, int mask, int version, QrCode.Ecc ecl)
- Method get_version() -> int - Method get_version() -> int
- Method get_size() -> int - Method get_size() -> int
@ -135,56 +134,36 @@ class QrCode(object):
assert len(bb) % 8 == 0 assert len(bb) % 8 == 0
# Create the QR Code symbol # Create the QR Code symbol
return QrCode(None, bb.get_bytes(), mask, version, ecl) return QrCode(bb.get_bytes(), mask, version, ecl)
# ---- Constructor ---- # ---- Constructor ----
def __init__(self, qrcode=None, datacodewords=None, mask=None, version=None, errcorlvl=None): def __init__(self, datacodewords, mask, version, errcorlvl):
"""This constructor can be called in one of two ways: """Creates a new QR Code symbol with the given version number, error correction level, binary data array,
- QrCode(datacodewords=list<int>, mask=int, version=int, errcorlvl=QrCode.Ecc): and mask number. mask = -1 is for automatic choice, or 0 to 7 for fixed choice. This is a cumbersome low-level constructor
Creates a new QR Code symbol with the given version number, error correction level, binary data array, that should not be invoked directly by the user. To go one level up, see the QrCode.encode_segments() function."""
and mask number. This is a cumbersome low-level constructor that should not be invoked directly by the user.
To go one level up, see the QrCode.encode_segments() function.
- QrCode(qrcode=QrCode, mask=int):
Creates a new QR Code symbol based on the given existing object, but with a potentially different
mask pattern. The version, error correction level, codewords, etc. of the newly created object are
all identical to the argument object; only the mask may differ.
In both cases, mask = -1 is for automatic choice or 0 to 7 for fixed choice."""
# Check arguments and handle simple scalar fields # Check arguments and handle simple scalar fields
if not (-1 <= mask <= 7): if not (-1 <= mask <= 7):
raise ValueError("Mask value out of range") raise ValueError("Mask value out of range")
if datacodewords is not None and qrcode is None: if not (1 <= version <= 40):
if not (1 <= version <= 40): raise ValueError("Version value out of range")
raise ValueError("Version value out of range") if not isinstance(errcorlvl, QrCode.Ecc):
if not isinstance(errcorlvl, QrCode.Ecc): raise TypeError("QrCode.Ecc expected")
raise TypeError("QrCode.Ecc expected")
elif qrcode is not None and datacodewords is None:
if version is not None or errcorlvl is not None:
raise ValueError("Values must be None")
version = qrcode._version
errcorlvl = qrcode._errcorlvl
else:
raise ValueError("Exactly one of datacodewords or qrcode must be not None")
self._version = version self._version = version
self._errcorlvl = errcorlvl self._errcorlvl = errcorlvl
self._size = version * 4 + 17 self._size = version * 4 + 17
if datacodewords is not None: # Render from scratch a QR Code based on data codewords if len(datacodewords) != QrCode._get_num_data_codewords(version, errcorlvl):
if len(datacodewords) != QrCode._get_num_data_codewords(version, errcorlvl): raise ValueError("Invalid array length")
raise ValueError("Invalid array length") # Initialize grids of modules
# Initialize grids of modules self._modules = [[False] * self._size for _ in range(self._size)] # The modules of the QR symbol; start with entirely white grid
self._modules = [[False] * self._size for _ in range(self._size)] # The modules of the QR symbol; start with entirely white grid self._isfunction = [[False] * self._size for _ in range(self._size)] # Indicates function modules that are not subjected to masking
self._isfunction = [[False] * self._size for _ in range(self._size)] # Indicates function modules that are not subjected to masking # Draw function patterns, draw all codewords
# Draw function patterns, draw all codewords self._draw_function_patterns()
self._draw_function_patterns() allcodewords = self._append_error_correction(datacodewords)
allcodewords = self._append_error_correction(datacodewords) self._draw_codewords(allcodewords)
self._draw_codewords(allcodewords)
elif qrcode is not None: # Modify the mask of an existing QR Code
self._modules = [list(row) for row in qrcode._modules] # Deep copy
self._isfunction = qrcode._isfunction # Shallow copy because the data is read-only
self._apply_mask(qrcode._mask) # Undo existing mask
# Handle masking # Handle masking
if mask == -1: # Automatically choose best mask if mask == -1: # Automatically choose best mask

@ -35,6 +35,7 @@ fn main() {
do_basic_demo(); do_basic_demo();
do_variety_demo(); do_variety_demo();
do_segment_demo(); do_segment_demo();
do_mask_demo();
} }
@ -52,11 +53,6 @@ fn do_basic_demo() {
// Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console. // Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
fn do_variety_demo() { fn do_variety_demo() {
// Project Nayuki URL
let qr = QrCode::encode_text("https://www.nayuki.io/", QrCodeEcc::High).unwrap();
let qr = QrCode::remask(&qr, Some(3)); // Change mask, forcing to mask #3
print_qr(&qr);
// Numeric mode encoding (3.33 bits per digit) // Numeric mode encoding (3.33 bits per digit)
let qr = QrCode::encode_text("314159265358979323846264338327950288419716939937510", QrCodeEcc::Medium).unwrap(); let qr = QrCode::encode_text("314159265358979323846264338327950288419716939937510", QrCodeEcc::Medium).unwrap();
print_qr(&qr); print_qr(&qr);
@ -65,12 +61,9 @@ fn do_variety_demo() {
let qr = QrCode::encode_text("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCodeEcc::High).unwrap(); let qr = QrCode::encode_text("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCodeEcc::High).unwrap();
print_qr(&qr); print_qr(&qr);
// Unicode text as UTF-8, and different masks // Unicode text as UTF-8
let qr = QrCode::encode_text("こんにちwa、世界 αβγδ", QrCodeEcc::Quartile).unwrap(); let qr = QrCode::encode_text("こんにちwa、世界 αβγδ", QrCodeEcc::Quartile).unwrap();
print_qr(&QrCode::remask(&qr, Some(0))); print_qr(&qr);
print_qr(&QrCode::remask(&qr, Some(1)));
print_qr(&QrCode::remask(&qr, Some(5)));
print_qr(&QrCode::remask(&qr, Some(7)));
// 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)
let qr = QrCode::encode_text(concat!( let qr = QrCode::encode_text(concat!(
@ -140,6 +133,28 @@ fn do_segment_demo() {
} }
// Creates QR Codes with the same size and contents but different mask patterns.
fn do_mask_demo() {
// Project Nayuki URL
let segs = QrSegment::make_segments(&to_chars("https://www.nayuki.io/"));
let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::High, 1, 40, None, true).unwrap(); // Automatic mask
print_qr(&qr);
let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::High, 1, 40, Some(3), true).unwrap(); // Force mask 3
print_qr(&qr);
// Chinese text as UTF-8
let segs = QrSegment::make_segments(&to_chars("維基百科Wikipedia聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫"));
let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::Medium, 1, 40, Some(0), true).unwrap(); // Force mask 0
print_qr(&qr);
let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::Medium, 1, 40, Some(1), true).unwrap(); // Force mask 1
print_qr(&qr);
let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::Medium, 1, 40, Some(5), true).unwrap(); // Force mask 5
print_qr(&qr);
let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::Medium, 1, 40, Some(7), true).unwrap(); // Force mask 7
print_qr(&qr);
}
/*---- Utilities ----*/ /*---- Utilities ----*/
// Prints the given QrCode object to the console. // Prints the given QrCode object to the console.

@ -193,30 +193,6 @@ impl QrCode {
} }
// Creates a new QR Code symbol based on the given existing object, but with a potentially
// different mask pattern. The version, error correction level, codewords, etc. of the newly
// created object are all identical to the argument object; only the mask may differ.
pub fn remask(qr: &QrCode, mask: Option<u8>) -> QrCode {
// Check arguments
assert!(mask == None || mask.unwrap() <= 7, "Mask out of range");
// Copy fields
let mut result = QrCode {
version: qr.version,
size: qr.size,
mask: 0, // Dummy value
errorcorrectionlevel: qr.errorcorrectionlevel,
modules: qr.modules.clone(),
isfunction: qr.isfunction.clone(),
};
// Handle masking
result.apply_mask(qr.mask); // Undo old mask
result.handle_constructor_masking(mask);
result
}
// Returns this QR Code's version, in the range [1, 40]. // Returns this QR Code's version, in the range [1, 40].
pub fn version(&self) -> u8 { pub fn version(&self) -> u8 {
self.version self.version

Loading…
Cancel
Save