Added support for making Extended Channel Interpretation (ECI) segments - in Java, C++, JavaScript, and Python language versions.

This commit is contained in:
Project Nayuki 2017-05-08 18:04:10 +00:00
parent 0482a1ec5b
commit a610a3d8df
5 changed files with 87 additions and 3 deletions

View File

@ -53,6 +53,7 @@ const QrSegment::Mode QrSegment::Mode::NUMERIC (0x1, 10, 12, 14);
const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13); const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13);
const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16); const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16);
const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12); const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12);
const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0);
@ -127,6 +128,20 @@ vector<QrSegment> QrSegment::makeSegments(const char *text) {
} }
QrSegment QrSegment::makeEci(long assignVal) {
vector<uint8_t> data;
if (0 <= assignVal && assignVal < (1 << 7))
data = {static_cast<uint8_t>(assignVal)};
else if ((1 << 7) <= assignVal && assignVal < (1 << 14))
data = {static_cast<uint8_t>(0x80 | (assignVal >> 8)), static_cast<uint8_t>(assignVal)};
else if ((1 << 14) <= assignVal && assignVal < 999999L)
data = {static_cast<uint8_t>(0xC0 | (assignVal >> 16)), static_cast<uint8_t>(assignVal >> 8), static_cast<uint8_t>(assignVal)};
else
throw "ECI assignment value out of range";
return QrSegment(Mode::ECI, 0, data, data.size() * 8);
}
QrSegment::QrSegment(const Mode &md, int numCh, const vector<uint8_t> &b, int bitLen) : QrSegment::QrSegment(const Mode &md, int numCh, const vector<uint8_t> &b, int bitLen) :
mode(md), mode(md),
numChars(numCh), numChars(numCh),

View File

@ -52,6 +52,7 @@ class QrSegment final {
public: static const Mode ALPHANUMERIC; public: static const Mode ALPHANUMERIC;
public: static const Mode BYTE; public: static const Mode BYTE;
public: static const Mode KANJI; public: static const Mode KANJI;
public: static const Mode ECI;
/*-- Fields --*/ /*-- Fields --*/
@ -106,6 +107,12 @@ class QrSegment final {
public: static std::vector<QrSegment> makeSegments(const char *text); public: static std::vector<QrSegment> makeSegments(const char *text);
/*
* Returns a segment representing an Extended Channel Interpretation (ECI) designator with the given assignment value.
*/
public: static QrSegment makeEci(long assignVal);
/*---- Public static helper functions ----*/ /*---- Public static helper functions ----*/
/* /*

View File

@ -128,6 +128,26 @@ public final class QrSegment {
} }
/**
* Returns a segment representing an Extended Channel Interpretation (ECI) designator with the specified assignment value.
* @param assignVal the ECI assignment number (see the AIM ECI specification)
* @return a segment containing the data
* @throws IllegalArgumentException if the value is outside the range [0, 10<sup>6</sup>)
*/
public static QrSegment makeEci(int assignVal) {
byte[] data;
if (0 <= assignVal && assignVal < (1 << 7))
data = new byte[]{(byte)assignVal};
else if ((1 << 7) <= assignVal && assignVal < (1 << 14))
data = new byte[]{(byte)(0x80 | (assignVal >>> 8)), (byte)assignVal};
else if ((1 << 14) <= assignVal && assignVal < 999999)
data = new byte[]{(byte)(0xC0 | (assignVal >>> 16)), (byte)(assignVal >>> 8), (byte)assignVal};
else
throw new IllegalArgumentException("ECI assignment value out of range");
return new QrSegment(Mode.ECI, 0, data, data.length * 8);
}
/*---- Instance fields ----*/ /*---- Instance fields ----*/
@ -228,7 +248,8 @@ public final class QrSegment {
NUMERIC (0x1, 10, 12, 14), NUMERIC (0x1, 10, 12, 14),
ALPHANUMERIC(0x2, 9, 11, 13), ALPHANUMERIC(0x2, 9, 11, 13),
BYTE (0x4, 8, 16, 16), BYTE (0x4, 8, 16, 16),
KANJI (0x8, 8, 10, 12); KANJI (0x8, 8, 10, 12),
ECI (0x7, 0, 0, 0);
/*-- Fields --*/ /*-- Fields --*/

View File

@ -46,13 +46,14 @@
* - Function makeNumeric(str data) -> QrSegment * - Function makeNumeric(str data) -> QrSegment
* - Function makeAlphanumeric(str data) -> QrSegment * - Function makeAlphanumeric(str data) -> QrSegment
* - Function makeSegments(str text) -> list<QrSegment> * - Function makeSegments(str text) -> list<QrSegment>
* - Function makeEci(int assignVal) -> QrSegment
* - Constructor QrSegment(QrSegment.Mode mode, int numChars, list<int> bitData) * - Constructor QrSegment(QrSegment.Mode mode, int numChars, list<int> bitData)
* - Field QrSegment.Mode mode * - Field QrSegment.Mode mode
* - Field int numChars * - Field int numChars
* - Method getBits() -> list<int> * - Method getBits() -> list<int>
* - Constants RegExp NUMERIC_REGEX, ALPHANUMERIC_REGEX * - Constants RegExp NUMERIC_REGEX, ALPHANUMERIC_REGEX
* - Enum Mode: * - Enum Mode:
* - Constants NUMERIC, ALPHANUMERIC, BYTE, KANJI * - Constants NUMERIC, ALPHANUMERIC, BYTE, KANJI, ECI
*/ */
var qrcodegen = new function() { var qrcodegen = new function() {
@ -815,6 +816,25 @@ var qrcodegen = new function() {
}; };
/*
* Returns a segment representing an Extended Channel Interpretation (ECI) designator with the given assignment value.
*/
this.QrSegment.makeEci = function(assignVal) {
var bb = new BitBuffer();
if (0 <= assignVal && assignVal < (1 << 7))
bb.appendBits(assignVal, 8);
else if ((1 << 7) <= assignVal && assignVal < (1 << 14)) {
bb.appendBits(2, 2);
bb.appendBits(assignVal, 14);
} else if ((1 << 14) <= assignVal && assignVal < 999999) {
bb.appendBits(6, 3);
bb.appendBits(assignVal, 21);
} else
throw "ECI assignment value out of range";
return new this(this.Mode.ECI, 0, bb.getBits());
};
// Package-private helper function. // Package-private helper function.
this.QrSegment.getTotalBits = function(segs, version) { this.QrSegment.getTotalBits = function(segs, version) {
if (version < 1 || version > 40) if (version < 1 || version > 40)
@ -856,6 +876,7 @@ var qrcodegen = new function() {
ALPHANUMERIC: new Mode(0x2, [ 9, 11, 13]), ALPHANUMERIC: new Mode(0x2, [ 9, 11, 13]),
BYTE : new Mode(0x4, [ 8, 16, 16]), BYTE : new Mode(0x4, [ 8, 16, 16]),
KANJI : new Mode(0x8, [ 8, 10, 12]), KANJI : new Mode(0x8, [ 8, 10, 12]),
ECI : new Mode(0x7, [ 0, 0, 0]),
}; };

View File

@ -47,13 +47,14 @@ This module "qrcodegen", public members:
- Function make_numeric(str digits) -> QrSegment - Function make_numeric(str digits) -> QrSegment
- Function make_alphanumeric(str text) -> QrSegment - Function make_alphanumeric(str text) -> QrSegment
- Function make_segments(str text) -> list<QrSegment> - Function make_segments(str text) -> list<QrSegment>
- Function make_eci(int assignval) -> QrSegment
- Constructor QrSegment(QrSegment.Mode mode, int numch, list<int> bitdata) - Constructor QrSegment(QrSegment.Mode mode, int numch, list<int> bitdata)
- Method get_mode() -> QrSegment.Mode - Method get_mode() -> QrSegment.Mode
- Method get_num_chars() -> int - Method get_num_chars() -> int
- Method get_bits() -> list<int> - Method get_bits() -> list<int>
- Constants regex NUMERIC_REGEX, ALPHANUMERIC_REGEX - Constants regex NUMERIC_REGEX, ALPHANUMERIC_REGEX
- Enum Mode: - Enum Mode:
- Constants NUMERIC, ALPHANUMERIC, BYTE, KANJI - Constants NUMERIC, ALPHANUMERIC, BYTE, KANJI, ECI
""" """
@ -669,6 +670,24 @@ class QrSegment(object):
return [QrSegment.make_bytes(text.encode("UTF-8"))] return [QrSegment.make_bytes(text.encode("UTF-8"))]
@staticmethod
def make_eci(assignval):
"""Returns a segment representing an Extended Channel Interpretation
(ECI) designator with the given assignment value."""
bb = _BitBuffer()
if 0 <= assignval < (1 << 7):
bb.append_bits(assignval, 8)
elif (1 << 7) <= assignval < (1 << 14):
bb.append_bits(2, 2)
bb.append_bits(assignval, 14)
elif (1 << 14) <= assignval < 999999:
bb.append_bits(6, 3)
bb.append_bits(assignval, 21)
else:
raise ValueError("ECI assignment value out of range")
return QrSegment(QrSegment.Mode.ECI, 0, bb.get_bits())
# ---- Constructor ---- # ---- Constructor ----
def __init__(self, mode, numch, bitdata): def __init__(self, mode, numch, bitdata):
@ -746,6 +765,7 @@ class QrSegment(object):
Mode.ALPHANUMERIC = Mode(0x2, ( 9, 11, 13)) Mode.ALPHANUMERIC = Mode(0x2, ( 9, 11, 13))
Mode.BYTE = Mode(0x4, ( 8, 16, 16)) Mode.BYTE = Mode(0x4, ( 8, 16, 16))
Mode.KANJI = Mode(0x8, ( 8, 10, 12)) Mode.KANJI = Mode(0x8, ( 8, 10, 12))
Mode.ECI = Mode(0x7, ( 0, 0, 0))