Moved {encodeText(), encodeBinary(), encodeSegments()} into class QrCode in Python and JavaScript implementations, for consistency with Java implementation.

This commit is contained in:
Nayuki Minase 2016-04-18 18:40:14 +00:00
parent de261ca62d
commit f325bfe638
4 changed files with 167 additions and 169 deletions

View File

@ -42,7 +42,7 @@ function redrawQrCode() {
var ecl = getInputErrorCorrectionLevel();
var text = document.getElementById("text-input").value;
var segs = qrcodegen.QrSegment.makeSegments(text);
var qr = qrcodegen.encodeSegments(segs, ecl);
var qr = qrcodegen.QrCode.encodeSegments(segs, ecl);
// Get scale and border
var scale = parseInt(document.getElementById("scale-input").value, 10);

View File

@ -27,11 +27,11 @@
/*
* Module "qrcodegen". Public members inside this namespace:
* - Class QrCode:
* - Function encodeText(str text, QrCode.Ecc ecl) -> QrCode
* - Function encodeBinary(list<int> data, QrCode.Ecc ecl) -> QrCode
* - Function encodeSegments(list<QrSegment> segs, QrCode.Ecc ecl,
* int minVersion=1, int maxVersion=40, mask=-1, boostEcl=true) -> QrCode
* - Class QrCode:
* - Constructor QrCode(QrCode qr, int mask)
* - Constructor QrCode(list<int> bytes, int mask, int version, QrCode.Ecc ecl)
* - Method getVersion() -> int
@ -60,87 +60,6 @@
*/
var qrcodegen = new function() {
/*---- Public static factory functions for QrCode ----*/
/*
* Returns a QR Code symbol representing the given Unicode text string at the given error correction level.
* As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode
* code points (not UTF-16 code units). The smallest possible QR Code version is automatically chosen for the output.
*/
this.encodeText = function(text, ecl) {
var segs = this.QrSegment.makeSegments(text);
return this.encodeSegments(segs, ecl);
};
/*
* Returns a QR Code symbol representing the given binary data string at the given error correction level.
* This function always encodes using the binary segment mode, not any text mode. The maximum number of
* bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
*/
this.encodeBinary = function(data, ecl) {
var seg = this.QrSegment.makeBytes(data);
return this.encodeSegments([seg], ecl);
};
/*
* Returns a QR Code symbol representing the specified data segments with the specified encoding parameters.
* The smallest possible QR Code version within the specified range is automatically chosen for the output.
* This function allows the user to create a custom sequence of segments that switches
* between modes (such as alphanumeric and binary) to encode text more efficiently.
* This function is considered to be lower level than simply encoding text or binary data.
*/
this.encodeSegments = function(segs, ecl, minVersion, maxVersion, mask, boostEcl) {
if (minVersion == undefined) minVersion = 1;
if (maxVersion == undefined) maxVersion = 40;
if (mask == undefined) mask = -1;
if (boostEcl == undefined) boostEcl = true;
if (!(1 <= minVersion && minVersion <= maxVersion && maxVersion <= 40) || mask < -1 || mask > 7)
throw "Invalid value";
// Find the minimal version number to use
var version, dataUsedBits;
for (version = minVersion; ; version++) {
var dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8; // Number of data bits available
dataUsedBits = this.QrSegment.getTotalBits(segs, version);
if (dataUsedBits != null && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable
if (version >= maxVersion) // All versions in the range could not fit the given data
throw "Data too long";
}
// Increase the error correction level while the data still fits in the current version number
[this.QrCode.Ecc.MEDIUM, this.QrCode.Ecc.QUARTILE, this.QrCode.Ecc.HIGH].forEach(function(newEcl) {
if (boostEcl && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
});
// Create the data bit string by concatenating all segments
var dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8;
var bb = new BitBuffer();
segs.forEach(function(seg) {
bb.appendBits(seg.getMode().getModeBits(), 4);
bb.appendBits(seg.getNumChars(), seg.getMode().numCharCountBits(version));
bb.appendData(seg);
});
// Add terminator and pad up to a byte if applicable
bb.appendBits(0, Math.min(4, dataCapacityBits - bb.bitLength()));
bb.appendBits(0, (8 - bb.bitLength() % 8) % 8);
// Pad with alternate bytes until data capacity is reached
for (var padByte = 0xEC; bb.bitLength() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
if (bb.bitLength() % 8 != 0)
throw "Assertion error";
// Create the QR Code symbol
return new this.QrCode(bb.getBytes(), mask, version, ecl);
};
/*---- QR Code symbol class ----*/
/*
@ -594,6 +513,85 @@ var qrcodegen = new function() {
};
/*---- Public static factory functions for QrCode ----*/
/*
* Returns a QR Code symbol representing the given Unicode text string at the given error correction level.
* As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode
* code points (not UTF-16 code units). The smallest possible QR Code version is automatically chosen for the output.
*/
this.QrCode.encodeText = function(text, ecl) {
var segs = qrcodegen.QrSegment.makeSegments(text);
return this.encodeSegments(segs, ecl);
};
/*
* Returns a QR Code symbol representing the given binary data string at the given error correction level.
* This function always encodes using the binary segment mode, not any text mode. The maximum number of
* bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
*/
this.QrCode.encodeBinary = function(data, ecl) {
var seg = qrcodegen.QrSegment.makeBytes(data);
return this.encodeSegments([seg], ecl);
};
/*
* Returns a QR Code symbol representing the specified data segments with the specified encoding parameters.
* The smallest possible QR Code version within the specified range is automatically chosen for the output.
* This function allows the user to create a custom sequence of segments that switches
* between modes (such as alphanumeric and binary) to encode text more efficiently.
* This function is considered to be lower level than simply encoding text or binary data.
*/
this.QrCode.encodeSegments = function(segs, ecl, minVersion, maxVersion, mask, boostEcl) {
if (minVersion == undefined) minVersion = 1;
if (maxVersion == undefined) maxVersion = 40;
if (mask == undefined) mask = -1;
if (boostEcl == undefined) boostEcl = true;
if (!(1 <= minVersion && minVersion <= maxVersion && maxVersion <= 40) || mask < -1 || mask > 7)
throw "Invalid value";
// Find the minimal version number to use
var version, dataUsedBits;
for (version = minVersion; ; version++) {
var dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8; // Number of data bits available
dataUsedBits = qrcodegen.QrSegment.getTotalBits(segs, version);
if (dataUsedBits != null && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable
if (version >= maxVersion) // All versions in the range could not fit the given data
throw "Data too long";
}
// Increase the error correction level while the data still fits in the current version number
[this.Ecc.MEDIUM, this.Ecc.QUARTILE, this.Ecc.HIGH].forEach(function(newEcl) {
if (boostEcl && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
});
// Create the data bit string by concatenating all segments
var dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8;
var bb = new BitBuffer();
segs.forEach(function(seg) {
bb.appendBits(seg.getMode().getModeBits(), 4);
bb.appendBits(seg.getNumChars(), seg.getMode().numCharCountBits(version));
bb.appendData(seg);
});
// Add terminator and pad up to a byte if applicable
bb.appendBits(0, Math.min(4, dataCapacityBits - bb.bitLength()));
bb.appendBits(0, (8 - bb.bitLength() % 8) % 8);
// Pad with alternate bytes until data capacity is reached
for (var padByte = 0xEC; bb.bitLength() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
if (bb.bitLength() % 8 != 0)
throw "Assertion error";
// Create the QR Code symbol
return new this(bb.getBytes(), mask, version, ecl);
};
/*---- Private static helper functions ----*/
var QrCode = {}; // Private object to assign properties to

View File

@ -39,7 +39,7 @@ def do_basic_demo():
"""Creates a single QR Code, then prints it to the console."""
text = u"Hello, world!" # User-supplied Unicode text
errcorlvl = qrcodegen.QrCode.Ecc.LOW # Error correction level
qr = qrcodegen.encode_text(text, errcorlvl)
qr = qrcodegen.QrCode.encode_text(text, errcorlvl)
print_qr(qr)
@ -47,27 +47,27 @@ def do_variety_demo():
"""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.encode_text("https://www.nayuki.io/", qrcodegen.QrCode.Ecc.HIGH)
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)
qr = qrcodegen.encode_text("314159265358979323846264338327950288419716939937510", qrcodegen.QrCode.Ecc.MEDIUM)
qr = qrcodegen.QrCode.encode_text("314159265358979323846264338327950288419716939937510", qrcodegen.QrCode.Ecc.MEDIUM)
print_qr(qr)
# Alphanumeric mode encoding (5.5 bits per character)
qr = qrcodegen.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)
# Unicode text as UTF-8, and different masks
qr = qrcodegen.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(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)
qr = qrcodegen.encode_text("Alice was beginning to get very tired of sitting by her sister on the bank, "
qr = qrcodegen.QrCode.encode_text("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, "
@ -83,27 +83,27 @@ def do_segment_demo():
# Illustration "silver"
silver0 = "THE SQUARE ROOT OF 2 IS 1."
silver1 = "41421356237309504880168872420969807856967187537694807317667973799"
qr = qrcodegen.encode_text(silver0 + silver1, qrcodegen.QrCode.Ecc.LOW)
qr = qrcodegen.QrCode.encode_text(silver0 + silver1, qrcodegen.QrCode.Ecc.LOW)
print_qr(qr)
segs = [
qrcodegen.QrSegment.make_alphanumeric(silver0),
qrcodegen.QrSegment.make_numeric(silver1)]
qr = qrcodegen.encode_segments(segs, qrcodegen.QrCode.Ecc.LOW)
qr = qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.LOW)
print_qr(qr)
# Illustration "golden"
golden0 = u"Golden ratio \u03C6 = 1."
golden1 = u"6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374"
golden2 = u"......"
qr = qrcodegen.encode_text(golden0 + golden1 + golden2, qrcodegen.QrCode.Ecc.LOW)
qr = qrcodegen.QrCode.encode_text(golden0 + golden1 + golden2, qrcodegen.QrCode.Ecc.LOW)
print_qr(qr)
segs = [
qrcodegen.QrSegment.make_bytes(golden0.encode("UTF-8")),
qrcodegen.QrSegment.make_numeric(golden1),
qrcodegen.QrSegment.make_alphanumeric(golden2)]
qr = qrcodegen.encode_segments(segs, qrcodegen.QrCode.Ecc.LOW)
qr = qrcodegen.QrCode.encode_segments(segs, qrcodegen.QrCode.Ecc.LOW)
print_qr(qr)

View File

@ -27,11 +27,11 @@ import itertools, re, sys
"""
Public members inside this module "qrcodegen":
- Class QrCode:
- Function encode_text(str text, QrCode.Ecc ecl) -> QrCode
- Function encode_binary(bytes data, QrCode.Ecc ecl) -> QrCode
- Function encode_segments(list<QrSegment> segs, QrCode.Ecc ecl,
int minversion=1, int maxversion=40, mask=-1, boostecl=true) -> QrCode
- Class QrCode:
- Constructor QrCode(QrCode qr, int mask)
- Constructor QrCode(bytes bytes, int mask, int version, QrCode.Ecc ecl)
- Method get_version() -> int
@ -59,14 +59,20 @@ Public members inside this module "qrcodegen":
"""
# ---- Public static factory functions for QrCode ----
# ---- QR Code symbol class ----
class QrCode(object):
"""Represents an immutable square grid of black or white cells for a QR Code symbol. This class covers the
QR Code model 2 specification, supporting all versions (sizes) from 1 to 40, all 4 error correction levels."""
# ---- Public static factory functions ----
def encode_text(text, ecl):
"""Returns a QR Code symbol representing the given Unicode text string at the given error correction level.
As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode
code points (not UTF-16 code units). The smallest possible QR Code version is automatically chosen for the output."""
segs = QrSegment.make_segments(text)
return encode_segments(segs, ecl)
return QrCode.encode_segments(segs, ecl)
def encode_binary(data, ecl):
@ -78,6 +84,7 @@ def encode_binary(data, ecl):
return QrCode.encode_segments([QrSegment.make_bytes(data)], ecl)
@staticmethod
def encode_segments(segs, ecl, minversion=1, maxversion=40, mask=-1, boostecl=True):
"""Returns a QR Code symbol representing the specified data segments with the specified encoding parameters.
The smallest possible QR Code version within the specified range is automatically chosen for the output.
@ -127,13 +134,6 @@ def encode_segments(segs, ecl, minversion=1, maxversion=40, mask=-1, boostecl=Tr
return QrCode(None, bb.get_bytes(), mask, version, ecl)
# ---- QR Code symbol class ----
class QrCode(object):
"""Represents an immutable square grid of black or white cells for a QR Code symbol. This class covers the
QR Code model 2 specification, supporting all versions (sizes) from 1 to 40, all 4 error correction levels."""
# ---- Constructor ----
def __init__(self, qrcode=None, datacodewords=None, mask=None, version=None, errcorlvl=None):