Skip to content

Commit bc5649a

Browse files
committed
add text encoder/decoder options
1 parent 7afbeba commit bc5649a

3 files changed

Lines changed: 19 additions & 7 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const larger = encodeQR(txt, 'gif', { scale: 4 });
6565
// type QrOpts = {
6666
// ecc?: 'low' | 'medium' | 'quartile' | 'high';
6767
// encoding?: 'numeric' | 'alphanumeric' | 'byte' | 'kanji' | 'eci';
68+
// textEncoder?: (text: string) => Uint8Array;
6869
// version?: number; // 1..40, QR code version
6970
// mask?: number; // 0..7, mask number
7071
// border?: number; // Border size, default 2.

src/decode.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -738,8 +738,11 @@ function parseInfo(b: Bitmap) {
738738
// Global symbols in both browsers and Node.js since v11
739739
// See https://github.com/microsoft/TypeScript/issues/31535
740740
declare const TextDecoder: any;
741+
function bytesToUtf8(bytes: Uint8Array): string {
742+
return new TextDecoder().decode(new Uint8Array(bytes));
743+
}
741744

742-
function decodeBitmap(b: Bitmap): string {
745+
function decodeBitmap(b: Bitmap, decoder: (bytes: Uint8Array) => string = bytesToUtf8): string {
743746
const size = b.height;
744747
if (size < 21 || (size & 0b11) !== 1 || size !== b.width)
745748
throw new Error(`decode: invalid size=${size}`);
@@ -815,14 +818,15 @@ function decodeBitmap(b: Bitmap): string {
815818
} else if (mode === 'byte') {
816819
let utf8 = [];
817820
for (let i = 0; i < count; i++) utf8.push(Number(`0b${readBits(8)}`));
818-
res += new TextDecoder().decode(new Uint8Array(utf8));
821+
res += decoder(new Uint8Array(utf8));
819822
} else throw new Error(`Unknown mode=${mode}`);
820823
}
821824
return res;
822825
}
823826

824827
export type DecodeOpts = {
825828
cropToSquare?: boolean;
829+
textDecoder?: (bytes: Uint8Array) => string;
826830
pointsOnDetect?: (points: FinderPoints) => void;
827831
imageOnBitmap?: (img: Image) => void;
828832
imageOnDetect?: (img: Image) => void;
@@ -876,7 +880,7 @@ export function decodeQR(img: Image, opts: DecodeOpts = {}): string {
876880
opts.pointsOnDetect(p);
877881
}
878882
if (opts.imageOnDetect) opts.imageOnDetect(bits.toImage());
879-
const res = decodeBitmap(bits);
883+
const res = decodeBitmap(bits, opts.textDecoder);
880884
if (opts.imageOnResult) opts.imageOnResult(bits.toImage());
881885
return res;
882886
}

src/index.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,13 @@ export function utf8ToBytes(str: string): Uint8Array {
901901
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
902902
}
903903

904-
function encode(ver: Version, ecc: ErrorCorrection, data: string, type: EncodingType): Uint8Array {
904+
function encode(
905+
ver: Version,
906+
ecc: ErrorCorrection,
907+
data: string,
908+
type: EncodingType,
909+
encoder: (value: string) => Uint8Array = utf8ToBytes
910+
): Uint8Array {
905911
let encoded = '';
906912
let dataLen = data.length;
907913
if (type === 'numeric') {
@@ -919,7 +925,7 @@ function encode(ver: Version, ecc: ErrorCorrection, data: string, type: Encoding
919925
for (let i = 0; i < n - 1; i += 2) encoded += bin(t[i] * 45 + t[i + 1], 11);
920926
if (n % 2 == 1) encoded += bin(t[n - 1], 6); // pad if odd number of chars
921927
} else if (type === 'byte') {
922-
const utf8 = utf8ToBytes(data);
928+
const utf8 = encoder(data);
923929
dataLen = utf8.length;
924930
encoded = Array.from(utf8)
925931
.map((i) => bin(i, 8))
@@ -1041,6 +1047,7 @@ function drawQRBest(ver: Version, ecc: ErrorCorrection, data: Uint8Array, maskId
10411047
export type QrOpts = {
10421048
ecc?: ErrorCorrection | undefined;
10431049
encoding?: EncodingType | undefined;
1050+
textEncoder?: (text: string) => Uint8Array;
10441051
version?: Version | undefined;
10451052
mask?: number | undefined;
10461053
border?: number | undefined;
@@ -1112,13 +1119,13 @@ export function encodeQR(text: string, output: Output = 'raw', opts: QrOpts & Sv
11121119
err = new Error('Unknown error');
11131120
if (ver !== undefined) {
11141121
validateVersion(ver);
1115-
data = encode(ver, ecc, text, encoding);
1122+
data = encode(ver, ecc, text, encoding, opts.textEncoder);
11161123
} else {
11171124
// If no version is provided, try to find smallest one which fits
11181125
// Currently just scans all version, can be significantly speedup if needed
11191126
for (let i = 1; i <= 40; i++) {
11201127
try {
1121-
data = encode(i, ecc, text, encoding);
1128+
data = encode(i, ecc, text, encoding, opts.textEncoder);
11221129
ver = i;
11231130
break;
11241131
} catch (e) {

0 commit comments

Comments
 (0)