@li0ard/wsq 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/const.js +3 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +38 -37
- package/package.json +1 -1
package/dist/const.js
CHANGED
|
@@ -208,8 +208,8 @@ const buildWTree = (token, wtreelen, width, height) => {
|
|
|
208
208
|
token.wtree[19].leny = (token.wtree[15].leny + 1) / 2;
|
|
209
209
|
};
|
|
210
210
|
const wtree4 = (token, start1, start2, lenx, leny, x, y, stop1) => {
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
const p1 = start1, p2 = start2;
|
|
212
|
+
const evenx = lenx % 2, eveny = leny % 2;
|
|
213
213
|
if (!token.wtree)
|
|
214
214
|
return;
|
|
215
215
|
token.wtree[p1].x = x;
|
|
@@ -408,7 +408,7 @@ const qtree16 = (token, start, lenx, leny, x, y, rw, cl) => {
|
|
|
408
408
|
token.qtree[p + 15].leny = token.qtree[p + 10].leny;
|
|
409
409
|
};
|
|
410
410
|
const qtree4 = (token, start, lenx, leny, x, y) => {
|
|
411
|
-
|
|
411
|
+
const p = start, evenx = lenx % 2, eveny = leny % 2;
|
|
412
412
|
if (!token.qtree)
|
|
413
413
|
return;
|
|
414
414
|
token.qtree[p].x = x;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { BitmapWithMetadata } from "./bitmap.js";
|
|
2
|
+
export declare const wsqToRAW: (data: Uint8Array) => BitmapWithMetadata;
|
|
1
3
|
/**
|
|
2
4
|
* Convert Wavelet Scalar Quantization (`.wsq`) to PNG
|
|
3
5
|
* @param data WSQ buffer
|
|
4
6
|
*/
|
|
5
7
|
export declare const wsqToPNG: (data: Uint8Array) => Uint8Array;
|
|
8
|
+
export { BitmapWithMetadata } from "./bitmap.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BitmapWithMetadata } from "./bitmap";
|
|
2
|
-
import { ANY_WSQ, BITMASK, buildWSQTrees, COM_WSQ, DHT_WSQ, DQT_WSQ, DTT_WSQ, EOI_WSQ, HeaderFrm, HuffCode, HuffmanTable, MAX_HUFFBITS, MAX_HUFFCOUNTS_WSQ, NCM_COLORSPACE, NCM_COMPRESSION, NCM_HEADER, NCM_LOSSY, NCM_PIX_DEPTH, NCM_PIX_HEIGHT, NCM_PIX_WIDTH, NCM_PPI, NUM_SUBBANDS, Ref, SOB_WSQ, SOF_WSQ, SOI_WSQ, Table_DQT, TBLS_N_SOB, TBLS_N_SOF, Token, W_TREELEN } from "./const";
|
|
1
|
+
import { BitmapWithMetadata } from "./bitmap.js";
|
|
2
|
+
import { ANY_WSQ, BITMASK, buildWSQTrees, COM_WSQ, DHT_WSQ, DQT_WSQ, DTT_WSQ, EOI_WSQ, HeaderFrm, HuffCode, HuffmanTable, MAX_HUFFBITS, MAX_HUFFCOUNTS_WSQ, NCM_COLORSPACE, NCM_COMPRESSION, NCM_HEADER, NCM_LOSSY, NCM_PIX_DEPTH, NCM_PIX_HEIGHT, NCM_PIX_WIDTH, NCM_PPI, NUM_SUBBANDS, Ref, SOB_WSQ, SOF_WSQ, SOI_WSQ, Table_DQT, TBLS_N_SOB, TBLS_N_SOF, Token, W_TREELEN } from "./const.js";
|
|
3
3
|
import UPNG from "@pdf-lib/upng";
|
|
4
4
|
class WSQDecoder {
|
|
5
5
|
offset = 0;
|
|
@@ -12,22 +12,21 @@ class WSQDecoder {
|
|
|
12
12
|
this.getCTableWSQ(dataInput, token, marker);
|
|
13
13
|
marker = this.getCMarkerWSQ(dataInput, TBLS_N_SOF);
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const frmHeaderWSQ = this.getCFrameHeaderWSQ(dataInput);
|
|
16
|
+
const width = frmHeaderWSQ.width;
|
|
17
|
+
const height = frmHeaderWSQ.height;
|
|
18
18
|
buildWSQTrees(token, width, height);
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const qdata = this.huffmanDecodeDataMem(dataInput, token, width * height);
|
|
20
|
+
const fdata = this.unquantize(token, qdata, width, height);
|
|
21
21
|
this.wsqReconstruct(token, fdata, width, height);
|
|
22
|
-
|
|
22
|
+
const cdata = this.convertImageToByte(fdata, width, height, frmHeaderWSQ.mShift, frmHeaderWSQ.rScale);
|
|
23
23
|
const nistcom = new Map();
|
|
24
24
|
const comments = [];
|
|
25
25
|
for (const comment of token.comments) {
|
|
26
26
|
try {
|
|
27
27
|
const parsed = this.stringToFet(comment);
|
|
28
|
-
for (const [k, v] of parsed)
|
|
28
|
+
for (const [k, v] of parsed)
|
|
29
29
|
nistcom.set(k, v);
|
|
30
|
-
}
|
|
31
30
|
}
|
|
32
31
|
catch (e) {
|
|
33
32
|
comments.push(comment);
|
|
@@ -69,7 +68,7 @@ class WSQDecoder {
|
|
|
69
68
|
return result;
|
|
70
69
|
}
|
|
71
70
|
convertImageToByte(img, width, height, mShift, rScale) {
|
|
72
|
-
|
|
71
|
+
const data = new Uint8Array(width * height);
|
|
73
72
|
let idx = 0;
|
|
74
73
|
for (let r = 0; r < height; r++) {
|
|
75
74
|
for (let c = 0; c < width; c++) {
|
|
@@ -94,10 +93,10 @@ class WSQDecoder {
|
|
|
94
93
|
throw new Error("ERROR: wsq_reconstruct : Lopass filter coefficients not defined");
|
|
95
94
|
if (token.tableDTT.hidef != 1)
|
|
96
95
|
throw new Error("ERROR: wsq_reconstruct : Hipass filter coefficients not defined");
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
const numPix = width * height;
|
|
97
|
+
const fdataTemp = new Float32Array(numPix);
|
|
99
98
|
for (let node = W_TREELEN - 1; node >= 0; node--) {
|
|
100
|
-
|
|
99
|
+
const fdataBse = (token.wtree[node].y * width) + token.wtree[node].x;
|
|
101
100
|
this.joinLets(fdataTemp, fdata, 0, fdataBse, token.wtree[node].lenx, token.wtree[node].leny, 1, width, token.tableDTT.hifilt, token.tableDTT.hisz, token.tableDTT.lofilt, token.tableDTT.losz, token.wtree[node].invcl);
|
|
102
101
|
this.joinLets(fdata, fdataTemp, fdataBse, 0, token.wtree[node].leny, token.wtree[node].lenx, width, 1, token.tableDTT.hifilt, token.tableDTT.hisz, token.tableDTT.lofilt, token.tableDTT.losz, token.wtree[node].invrw);
|
|
103
102
|
}
|
|
@@ -409,10 +408,10 @@ class WSQDecoder {
|
|
|
409
408
|
}
|
|
410
409
|
}
|
|
411
410
|
unquantize(token, sip, width, height) {
|
|
412
|
-
|
|
411
|
+
const fip = new Float32Array(width * height);
|
|
413
412
|
if (token.tableDQT.dqtDef != 1)
|
|
414
413
|
throw new Error("ERROR: unquantize : quantization table parameters not defined!");
|
|
415
|
-
|
|
414
|
+
const binCenter = token.tableDQT.binCenter;
|
|
416
415
|
let sptr = 0;
|
|
417
416
|
for (let cnt = 0; cnt < NUM_SUBBANDS; cnt++) {
|
|
418
417
|
if (token.tableDQT.qBin[cnt] == 0.0)
|
|
@@ -436,13 +435,13 @@ class WSQDecoder {
|
|
|
436
435
|
return fip;
|
|
437
436
|
}
|
|
438
437
|
huffmanDecodeDataMem(dataInput, token, size) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
438
|
+
const qdata = new Array(size);
|
|
439
|
+
const maxcode = new Array(MAX_HUFFBITS + 1);
|
|
440
|
+
const mincode = new Array(MAX_HUFFBITS + 1);
|
|
441
|
+
const valptr = new Array(MAX_HUFFBITS + 1);
|
|
442
|
+
const marker = new Ref(this.getCMarkerWSQ(dataInput, TBLS_N_SOB));
|
|
443
|
+
const bitCount = new Ref(0);
|
|
444
|
+
const nextByte = new Ref(0);
|
|
446
445
|
let hufftableId = 0;
|
|
447
446
|
let ip = 0;
|
|
448
447
|
let isPrematureEOF = false;
|
|
@@ -455,14 +454,14 @@ class WSQDecoder {
|
|
|
455
454
|
hufftableId = this.getCBlockHeader(dataInput);
|
|
456
455
|
if (token.tableDHT[hufftableId].tabdef != 1)
|
|
457
456
|
throw new Error("ERROR : huffmanDecodeDataMem : huffman table undefined.");
|
|
458
|
-
|
|
457
|
+
const hufftable = this.buildHuffsizes(token.tableDHT[hufftableId].huffbits, MAX_HUFFCOUNTS_WSQ);
|
|
459
458
|
this.buildHuffcodes(hufftable);
|
|
460
459
|
this.genDecodeTable(hufftable, maxcode, mincode, valptr, token.tableDHT[hufftableId].huffbits);
|
|
461
460
|
bitCount.value = 0;
|
|
462
461
|
marker.value = 0;
|
|
463
462
|
}
|
|
464
463
|
try {
|
|
465
|
-
|
|
464
|
+
const nodeptr = this.decodeDataMem(dataInput, mincode, maxcode, valptr, token.tableDHT[hufftableId].huffvalues, bitCount, marker, nextByte);
|
|
466
465
|
if (nodeptr == -1)
|
|
467
466
|
continue;
|
|
468
467
|
if (nodeptr > 0 && nodeptr <= 100) {
|
|
@@ -510,7 +509,7 @@ class WSQDecoder {
|
|
|
510
509
|
if (marker.value != 0)
|
|
511
510
|
return -1;
|
|
512
511
|
}
|
|
513
|
-
|
|
512
|
+
const inx2 = valptr[inx] + code - mincode[inx];
|
|
514
513
|
return huffvalues[inx2];
|
|
515
514
|
}
|
|
516
515
|
getCNextbitsWSQ(dataInput, marker, bitCount, bitsReq, nextByte) {
|
|
@@ -519,7 +518,7 @@ class WSQDecoder {
|
|
|
519
518
|
this.offset += 1;
|
|
520
519
|
bitCount.value = 8;
|
|
521
520
|
if (nextByte.value == 0xFF) {
|
|
522
|
-
|
|
521
|
+
const code2 = dataInput.getUint8(this.offset);
|
|
523
522
|
this.offset += 1;
|
|
524
523
|
if (code2 != 0x00 && bitsReq == 1) {
|
|
525
524
|
marker.value = (nextByte.value << 8) | code2;
|
|
@@ -566,7 +565,7 @@ class WSQDecoder {
|
|
|
566
565
|
}
|
|
567
566
|
buildHuffsizes(huffbits, maxHuffcounts) {
|
|
568
567
|
let numberOfCodes = 1;
|
|
569
|
-
|
|
568
|
+
const huffcodeTable = new Array(maxHuffcounts + 1);
|
|
570
569
|
let tempSize = 0;
|
|
571
570
|
for (let codeSize = 1; codeSize <= MAX_HUFFBITS; codeSize++) {
|
|
572
571
|
while (numberOfCodes <= huffbits[codeSize - 1]) {
|
|
@@ -604,12 +603,12 @@ class WSQDecoder {
|
|
|
604
603
|
getCBlockHeader(dataInput) {
|
|
605
604
|
dataInput.getUint16(this.offset);
|
|
606
605
|
this.offset += 2;
|
|
607
|
-
|
|
606
|
+
const value = dataInput.getUint8(this.offset);
|
|
608
607
|
this.offset += 1;
|
|
609
608
|
return value;
|
|
610
609
|
}
|
|
611
610
|
getCFrameHeaderWSQ(dataInput) {
|
|
612
|
-
|
|
611
|
+
const headerFrm = new HeaderFrm();
|
|
613
612
|
dataInput.getUint16(this.offset);
|
|
614
613
|
this.offset += 2;
|
|
615
614
|
headerFrm.black = dataInput.getUint8(this.offset);
|
|
@@ -689,7 +688,7 @@ class WSQDecoder {
|
|
|
689
688
|
}
|
|
690
689
|
}
|
|
691
690
|
getCHuffmanTableWSQ(dataInput, token) {
|
|
692
|
-
|
|
691
|
+
const firstHuffmanTable = this.getCHuffmanTable(dataInput, token, MAX_HUFFCOUNTS_WSQ, 0, true);
|
|
693
692
|
let tableId = firstHuffmanTable.tableId;
|
|
694
693
|
token.tableDHT[tableId].huffbits = firstHuffmanTable.huffbits.slice();
|
|
695
694
|
token.tableDHT[tableId].huffvalues = firstHuffmanTable.huffvalues.slice();
|
|
@@ -707,7 +706,7 @@ class WSQDecoder {
|
|
|
707
706
|
}
|
|
708
707
|
}
|
|
709
708
|
getCHuffmanTable(dataInput, token, maxHuffcounts, bytesLeft, readTableLen) {
|
|
710
|
-
|
|
709
|
+
const huffmanTable = new HuffmanTable();
|
|
711
710
|
if (readTableLen) {
|
|
712
711
|
huffmanTable.tableLen = dataInput.getUint16(this.offset);
|
|
713
712
|
this.offset += 2;
|
|
@@ -797,11 +796,11 @@ class WSQDecoder {
|
|
|
797
796
|
const aLofilt = new Float32Array(aSize);
|
|
798
797
|
aSize--;
|
|
799
798
|
for (let cnt = 0; cnt <= aSize; cnt++) {
|
|
800
|
-
|
|
799
|
+
const sign = dataInput.getUint8(this.offset);
|
|
801
800
|
this.offset += 1;
|
|
802
801
|
let scale = dataInput.getUint8(this.offset);
|
|
803
802
|
this.offset += 1;
|
|
804
|
-
|
|
803
|
+
const shrtDat = (dataInput.getInt32(this.offset) & 0xFFFFFFFF) >>> 0;
|
|
805
804
|
this.offset += 4;
|
|
806
805
|
aLofilt[cnt] = shrtDat;
|
|
807
806
|
while (scale > 0) {
|
|
@@ -827,11 +826,11 @@ class WSQDecoder {
|
|
|
827
826
|
const aHifilt = new Float32Array(aSize);
|
|
828
827
|
aSize--;
|
|
829
828
|
for (let cnt = 0; cnt <= aSize; cnt++) {
|
|
830
|
-
|
|
829
|
+
const sign = dataInput.getUint8(this.offset);
|
|
831
830
|
this.offset += 1;
|
|
832
831
|
let scale = dataInput.getUint8(this.offset);
|
|
833
832
|
this.offset += 1;
|
|
834
|
-
|
|
833
|
+
const shrtDat = (dataInput.getInt32(this.offset) & 0xFFFFFFFF) >>> 0;
|
|
835
834
|
this.offset += 4;
|
|
836
835
|
aHifilt[cnt] = shrtDat;
|
|
837
836
|
while (scale > 0) {
|
|
@@ -862,12 +861,13 @@ class WSQDecoder {
|
|
|
862
861
|
return num;
|
|
863
862
|
}
|
|
864
863
|
}
|
|
864
|
+
export const wsqToRAW = (data) => new WSQDecoder().decode(data);
|
|
865
865
|
/**
|
|
866
866
|
* Convert Wavelet Scalar Quantization (`.wsq`) to PNG
|
|
867
867
|
* @param data WSQ buffer
|
|
868
868
|
*/
|
|
869
869
|
export const wsqToPNG = (data) => {
|
|
870
|
-
const grayscale =
|
|
870
|
+
const grayscale = wsqToRAW(data);
|
|
871
871
|
const rgba = new Uint8Array(grayscale.width * grayscale.height * 4);
|
|
872
872
|
for (let i = 0; i < grayscale.width * grayscale.height; i++) {
|
|
873
873
|
rgba[i * 4 + 0] = grayscale.pixels[i];
|
|
@@ -877,3 +877,4 @@ export const wsqToPNG = (data) => {
|
|
|
877
877
|
}
|
|
878
878
|
return new Uint8Array(UPNG.encode([rgba.buffer], grayscale.width, grayscale.height, 0));
|
|
879
879
|
};
|
|
880
|
+
export { BitmapWithMetadata } from "./bitmap.js";
|