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::BYTE (0x4, 8, 16, 16);
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) :
mode(md),
numChars(numCh),

View File

@ -52,6 +52,7 @@ class QrSegment final {
public: static const Mode ALPHANUMERIC;
public: static const Mode BYTE;
public: static const Mode KANJI;
public: static const Mode ECI;
/*-- Fields --*/
@ -106,6 +107,12 @@ class QrSegment final {
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 ----*/
/*

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 ----*/
@ -228,7 +248,8 @@ public final class QrSegment {
NUMERIC (0x1, 10, 12, 14),
ALPHANUMERIC(0x2, 9, 11, 13),
BYTE (0x4, 8, 16, 16),
KANJI (0x8, 8, 10, 12);
KANJI (0x8, 8, 10, 12),
ECI (0x7, 0, 0, 0);
/*-- Fields --*/

View File

@ -46,13 +46,14 @@
* - Function makeNumeric(str data) -> QrSegment
* - Function makeAlphanumeric(str data) -> QrSegment
* - Function makeSegments(str text) -> list<QrSegment>
* - Function makeEci(int assignVal) -> QrSegment
* - Constructor QrSegment(QrSegment.Mode mode, int numChars, list<int> bitData)
* - Field QrSegment.Mode mode
* - Field int numChars
* - Method getBits() -> list<int>
* - Constants RegExp NUMERIC_REGEX, ALPHANUMERIC_REGEX
* - Enum Mode:
* - Constants NUMERIC, ALPHANUMERIC, BYTE, KANJI
* - Constants NUMERIC, ALPHANUMERIC, BYTE, KANJI, ECI
*/
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.
this.QrSegment.getTotalBits = function(segs, version) {
if (version < 1 || version > 40)
@ -856,6 +876,7 @@ var qrcodegen = new function() {
ALPHANUMERIC: new Mode(0x2, [ 9, 11, 13]),
BYTE : new Mode(0x4, [ 8, 16, 16]),
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_alphanumeric(str text) -> QrSegment
- Function make_segments(str text) -> list<QrSegment>
- Function make_eci(int assignval) -> QrSegment
- Constructor QrSegment(QrSegment.Mode mode, int numch, list<int> bitdata)
- Method get_mode() -> QrSegment.Mode
- Method get_num_chars() -> int
- Method get_bits() -> list<int>
- Constants regex NUMERIC_REGEX, ALPHANUMERIC_REGEX
- 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"))]
@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 ----
def __init__(self, mode, numch, bitdata):
@ -746,6 +765,7 @@ class QrSegment(object):
Mode.ALPHANUMERIC = Mode(0x2, ( 9, 11, 13))
Mode.BYTE = Mode(0x4, ( 8, 16, 16))
Mode.KANJI = Mode(0x8, ( 8, 10, 12))
Mode.ECI = Mode(0x7, ( 0, 0, 0))