@intactfile/engines 0.1.0
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/README.md +68 -0
- package/dist/archive/diagnose.d.ts +37 -0
- package/dist/archive/diagnose.d.ts.map +1 -0
- package/dist/archive/diagnose.js +165 -0
- package/dist/archive/diagnose.js.map +1 -0
- package/dist/archive/format.d.ts +52 -0
- package/dist/archive/format.d.ts.map +1 -0
- package/dist/archive/format.js +87 -0
- package/dist/archive/format.js.map +1 -0
- package/dist/archive/host.d.ts +83 -0
- package/dist/archive/host.d.ts.map +1 -0
- package/dist/archive/host.js +92 -0
- package/dist/archive/host.js.map +1 -0
- package/dist/archive/index.d.ts +22 -0
- package/dist/archive/index.d.ts.map +1 -0
- package/dist/archive/index.js +19 -0
- package/dist/archive/index.js.map +1 -0
- package/dist/archive/salvage.d.ts +73 -0
- package/dist/archive/salvage.d.ts.map +1 -0
- package/dist/archive/salvage.js +210 -0
- package/dist/archive/salvage.js.map +1 -0
- package/dist/byte-source.d.ts +19 -0
- package/dist/byte-source.d.ts.map +1 -0
- package/dist/byte-source.js +16 -0
- package/dist/byte-source.js.map +1 -0
- package/dist/bytesource/blob.d.ts +14 -0
- package/dist/bytesource/blob.d.ts.map +1 -0
- package/dist/bytesource/blob.js +23 -0
- package/dist/bytesource/blob.js.map +1 -0
- package/dist/crc32.d.ts +2 -0
- package/dist/crc32.d.ts.map +1 -0
- package/dist/crc32.js +18 -0
- package/dist/crc32.js.map +1 -0
- package/dist/detect/index.d.ts +16 -0
- package/dist/detect/index.d.ts.map +1 -0
- package/dist/detect/index.js +159 -0
- package/dist/detect/index.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/jpeg/browser-loader.d.ts +21 -0
- package/dist/jpeg/browser-loader.d.ts.map +1 -0
- package/dist/jpeg/browser-loader.js +28 -0
- package/dist/jpeg/browser-loader.js.map +1 -0
- package/dist/jpeg/diagnose.d.ts +50 -0
- package/dist/jpeg/diagnose.d.ts.map +1 -0
- package/dist/jpeg/diagnose.js +124 -0
- package/dist/jpeg/diagnose.js.map +1 -0
- package/dist/jpeg/exif.d.ts +11 -0
- package/dist/jpeg/exif.d.ts.map +1 -0
- package/dist/jpeg/exif.js +50 -0
- package/dist/jpeg/exif.js.map +1 -0
- package/dist/jpeg/format.d.ts +106 -0
- package/dist/jpeg/format.d.ts.map +1 -0
- package/dist/jpeg/format.js +248 -0
- package/dist/jpeg/format.js.map +1 -0
- package/dist/jpeg/index.d.ts +18 -0
- package/dist/jpeg/index.d.ts.map +1 -0
- package/dist/jpeg/index.js +14 -0
- package/dist/jpeg/index.js.map +1 -0
- package/dist/jpeg/mozjpeg-host.d.ts +60 -0
- package/dist/jpeg/mozjpeg-host.d.ts.map +1 -0
- package/dist/jpeg/mozjpeg-host.js +138 -0
- package/dist/jpeg/mozjpeg-host.js.map +1 -0
- package/dist/jpeg/repair.d.ts +89 -0
- package/dist/jpeg/repair.d.ts.map +1 -0
- package/dist/jpeg/repair.js +216 -0
- package/dist/jpeg/repair.js.map +1 -0
- package/dist/node.d.ts +11 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +29 -0
- package/dist/node.js.map +1 -0
- package/dist/pdf/browser-loader.d.ts +30 -0
- package/dist/pdf/browser-loader.d.ts.map +1 -0
- package/dist/pdf/browser-loader.js +21 -0
- package/dist/pdf/browser-loader.js.map +1 -0
- package/dist/pdf/diagnose.d.ts +23 -0
- package/dist/pdf/diagnose.d.ts.map +1 -0
- package/dist/pdf/diagnose.js +113 -0
- package/dist/pdf/diagnose.js.map +1 -0
- package/dist/pdf/format.d.ts +61 -0
- package/dist/pdf/format.d.ts.map +1 -0
- package/dist/pdf/format.js +150 -0
- package/dist/pdf/format.js.map +1 -0
- package/dist/pdf/index.d.ts +17 -0
- package/dist/pdf/index.d.ts.map +1 -0
- package/dist/pdf/index.js +12 -0
- package/dist/pdf/index.js.map +1 -0
- package/dist/pdf/qpdf-host.d.ts +66 -0
- package/dist/pdf/qpdf-host.d.ts.map +1 -0
- package/dist/pdf/qpdf-host.js +149 -0
- package/dist/pdf/qpdf-host.js.map +1 -0
- package/dist/pdf/rebuild.d.ts +32 -0
- package/dist/pdf/rebuild.d.ts.map +1 -0
- package/dist/pdf/rebuild.js +90 -0
- package/dist/pdf/rebuild.js.map +1 -0
- package/dist/pdf/repair.d.ts +61 -0
- package/dist/pdf/repair.d.ts.map +1 -0
- package/dist/pdf/repair.js +167 -0
- package/dist/pdf/repair.js.map +1 -0
- package/dist/png/diagnose.d.ts +50 -0
- package/dist/png/diagnose.d.ts.map +1 -0
- package/dist/png/diagnose.js +261 -0
- package/dist/png/diagnose.js.map +1 -0
- package/dist/png/format.d.ts +133 -0
- package/dist/png/format.d.ts.map +1 -0
- package/dist/png/format.js +350 -0
- package/dist/png/format.js.map +1 -0
- package/dist/png/index.d.ts +13 -0
- package/dist/png/index.d.ts.map +1 -0
- package/dist/png/index.js +10 -0
- package/dist/png/index.js.map +1 -0
- package/dist/png/repair.d.ts +31 -0
- package/dist/png/repair.d.ts.map +1 -0
- package/dist/png/repair.js +335 -0
- package/dist/png/repair.js.map +1 -0
- package/dist/sqlite/diagnose.d.ts +31 -0
- package/dist/sqlite/diagnose.d.ts.map +1 -0
- package/dist/sqlite/diagnose.js +169 -0
- package/dist/sqlite/diagnose.js.map +1 -0
- package/dist/sqlite/format.d.ts +103 -0
- package/dist/sqlite/format.d.ts.map +1 -0
- package/dist/sqlite/format.js +237 -0
- package/dist/sqlite/format.js.map +1 -0
- package/dist/sqlite/index.d.ts +24 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +19 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite/recover.d.ts +66 -0
- package/dist/sqlite/recover.d.ts.map +1 -0
- package/dist/sqlite/recover.js +305 -0
- package/dist/sqlite/recover.js.map +1 -0
- package/dist/sqlite/scan.d.ts +94 -0
- package/dist/sqlite/scan.d.ts.map +1 -0
- package/dist/sqlite/scan.js +356 -0
- package/dist/sqlite/scan.js.map +1 -0
- package/dist/sqlite/sqlite-host.d.ts +37 -0
- package/dist/sqlite/sqlite-host.d.ts.map +1 -0
- package/dist/sqlite/sqlite-host.js +80 -0
- package/dist/sqlite/sqlite-host.js.map +1 -0
- package/dist/sqlite/wal.d.ts +14 -0
- package/dist/sqlite/wal.d.ts.map +1 -0
- package/dist/sqlite/wal.js +79 -0
- package/dist/sqlite/wal.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/video/diagnose.d.ts +41 -0
- package/dist/video/diagnose.d.ts.map +1 -0
- package/dist/video/diagnose.js +188 -0
- package/dist/video/diagnose.js.map +1 -0
- package/dist/video/format.d.ts +87 -0
- package/dist/video/format.d.ts.map +1 -0
- package/dist/video/format.js +273 -0
- package/dist/video/format.js.map +1 -0
- package/dist/video/index.d.ts +21 -0
- package/dist/video/index.d.ts.map +1 -0
- package/dist/video/index.js +17 -0
- package/dist/video/index.js.map +1 -0
- package/dist/video/libav-host.d.ts +88 -0
- package/dist/video/libav-host.d.ts.map +1 -0
- package/dist/video/libav-host.js +66 -0
- package/dist/video/libav-host.js.map +1 -0
- package/dist/video/mp4-rebuild.d.ts +167 -0
- package/dist/video/mp4-rebuild.d.ts.map +1 -0
- package/dist/video/mp4-rebuild.js +270 -0
- package/dist/video/mp4-rebuild.js.map +1 -0
- package/dist/video/mp4box-host.d.ts +62 -0
- package/dist/video/mp4box-host.d.ts.map +1 -0
- package/dist/video/mp4box-host.js +209 -0
- package/dist/video/mp4box-host.js.map +1 -0
- package/dist/video/reconstruct.d.ts +97 -0
- package/dist/video/reconstruct.d.ts.map +1 -0
- package/dist/video/reconstruct.js +271 -0
- package/dist/video/reconstruct.js.map +1 -0
- package/dist/video/remux.d.ts +85 -0
- package/dist/video/remux.d.ts.map +1 -0
- package/dist/video/remux.js +350 -0
- package/dist/video/remux.js.map +1 -0
- package/dist/zip/diagnose.d.ts +22 -0
- package/dist/zip/diagnose.d.ts.map +1 -0
- package/dist/zip/diagnose.js +126 -0
- package/dist/zip/diagnose.js.map +1 -0
- package/dist/zip/format.d.ts +79 -0
- package/dist/zip/format.d.ts.map +1 -0
- package/dist/zip/format.js +129 -0
- package/dist/zip/format.js.map +1 -0
- package/dist/zip/repair.d.ts +32 -0
- package/dist/zip/repair.d.ts.map +1 -0
- package/dist/zip/repair.js +82 -0
- package/dist/zip/repair.js.map +1 -0
- package/dist/zip/salvage.d.ts +23 -0
- package/dist/zip/salvage.d.ts.map +1 -0
- package/dist/zip/salvage.js +140 -0
- package/dist/zip/salvage.js.map +1 -0
- package/dist/zip/scan.d.ts +64 -0
- package/dist/zip/scan.d.ts.map +1 -0
- package/dist/zip/scan.js +386 -0
- package/dist/zip/scan.js.map +1 -0
- package/dist/zip/writer.d.ts +14 -0
- package/dist/zip/writer.d.ts.map +1 -0
- package/dist/zip/writer.js +131 -0
- package/dist/zip/writer.js.map +1 -0
- package/package.json +71 -0
- package/src/archive/LICENSE-unrar.txt +53 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure JPEG marker-scan primitives — no wasm, no third-party deps, so this
|
|
3
|
+
* module is safe to pull into the browser-facing diagnosis path.
|
|
4
|
+
*
|
|
5
|
+
* A JPEG is a sequence of marker segments framed by 0xFF <marker> bytes.
|
|
6
|
+
* Standalone markers (SOI, EOI, RSTn, TEM) carry no payload; every other
|
|
7
|
+
* marker is followed by a big-endian 2-byte length that INCLUDES those two
|
|
8
|
+
* length bytes. After SOS the entropy-coded scan data runs raw until the next
|
|
9
|
+
* real marker (0xFF followed by a non-0x00, non-RSTn byte), typically EOI.
|
|
10
|
+
*
|
|
11
|
+
* Two views are offered: a strict sequential walk (order, overflow, structural
|
|
12
|
+
* corruption) and a robust presence scan (which markers exist *anywhere*, so a
|
|
13
|
+
* destroyed header whose SOS+scan survived is still recognisable — the case
|
|
14
|
+
* donor transplant exists for).
|
|
15
|
+
*/
|
|
16
|
+
export declare const M_SOI = 216;
|
|
17
|
+
export declare const M_EOI = 217;
|
|
18
|
+
export declare const M_TEM = 1;
|
|
19
|
+
export declare const M_RST0 = 208;
|
|
20
|
+
export declare const M_RST7 = 215;
|
|
21
|
+
export declare const M_SOS = 218;
|
|
22
|
+
export declare const M_DQT = 219;
|
|
23
|
+
export declare const M_DHT = 196;
|
|
24
|
+
export declare const M_DRI = 221;
|
|
25
|
+
export declare const M_APP0 = 224;
|
|
26
|
+
export declare const M_APP15 = 239;
|
|
27
|
+
export declare const M_COM = 254;
|
|
28
|
+
/** SOF markers are 0xC0..0xCF except 0xC4 (DHT), 0xC8 (JPG), 0xCC (DAC). */
|
|
29
|
+
export declare function isSofMarker(m: number): boolean;
|
|
30
|
+
export declare function isAppMarker(m: number): boolean;
|
|
31
|
+
export declare function isStandaloneMarker(m: number): boolean;
|
|
32
|
+
export declare function markerName(m: number): string;
|
|
33
|
+
export declare function readU16BE(b: Uint8Array, off: number): number;
|
|
34
|
+
/** Locate the first SOI (0xFFD8) within [0, window). Returns -1 if absent. */
|
|
35
|
+
export declare function findSoi(bytes: Uint8Array, window?: number): number;
|
|
36
|
+
export interface MarkerSegment {
|
|
37
|
+
marker: number;
|
|
38
|
+
name: string;
|
|
39
|
+
/** Offset of the 0xFF byte. */
|
|
40
|
+
offset: number;
|
|
41
|
+
/** Declared segment length (payload+2), or 0 for standalone markers. */
|
|
42
|
+
length: number;
|
|
43
|
+
}
|
|
44
|
+
export interface MarkerScan {
|
|
45
|
+
soiOffset: number;
|
|
46
|
+
segments: MarkerSegment[];
|
|
47
|
+
/** Offset of the SOS 0xFF byte, or -1. */
|
|
48
|
+
sosOffset: number;
|
|
49
|
+
/** First byte of entropy-coded scan data, or -1. */
|
|
50
|
+
scanStart: number;
|
|
51
|
+
/** One past the last scan byte (EOI offset or EOF), or -1. */
|
|
52
|
+
scanEnd: number;
|
|
53
|
+
/** Offset of the trailing EOI 0xFF byte, or -1. */
|
|
54
|
+
eoiOffset: number;
|
|
55
|
+
hasEoi: boolean;
|
|
56
|
+
/** A segment length ran past EOF (structural corruption or truncation). */
|
|
57
|
+
overflow: boolean;
|
|
58
|
+
/** Expected a 0xFF marker lead but found something else before SOS. */
|
|
59
|
+
badMarker: boolean;
|
|
60
|
+
/** Ran out of bytes while still walking the header (before SOS resolved). */
|
|
61
|
+
truncatedHeader: boolean;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Strict sequential walk from SOI. Stops at SOS (recording where the scan
|
|
65
|
+
* begins) or at the first structural problem. Never throws.
|
|
66
|
+
*/
|
|
67
|
+
export declare function scanMarkers(bytes: Uint8Array, soiOffset: number): MarkerScan;
|
|
68
|
+
/** Find the trailing EOI (0xFFD9) scanning forward from `from`. */
|
|
69
|
+
export declare function findEoiFrom(bytes: Uint8Array, from: number): number;
|
|
70
|
+
export interface MarkerPresence {
|
|
71
|
+
hasDqt: boolean;
|
|
72
|
+
hasDht: boolean;
|
|
73
|
+
hasSof: boolean;
|
|
74
|
+
hasSos: boolean;
|
|
75
|
+
hasEoi: boolean;
|
|
76
|
+
/** Offset of the first SOS 0xFF byte, or -1. */
|
|
77
|
+
sosOffset: number;
|
|
78
|
+
/** Offset of the last EOI 0xFF byte, or -1. */
|
|
79
|
+
eoiOffset: number;
|
|
80
|
+
/** Offset of the first SOF 0xFF byte, or -1. */
|
|
81
|
+
sofOffset: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Robust presence scan: look for each key marker anywhere in [start, end),
|
|
85
|
+
* independent of sequence. Survives a zeroed/garbled header as long as the
|
|
86
|
+
* marker bytes themselves are intact — how we recognise "header destroyed but
|
|
87
|
+
* scan alive". Skips 0xFF00 byte-stuffing and 0xFFFF fill.
|
|
88
|
+
*/
|
|
89
|
+
export declare function scanMarkerPresence(bytes: Uint8Array, start: number, end?: number): MarkerPresence;
|
|
90
|
+
/**
|
|
91
|
+
* Read the frame dimensions from a SOF segment at `sofOffset` (the 0xFF byte).
|
|
92
|
+
* SOF layout: FF Cx | len(2) | precision(1) | height(2) | width(2) | ...
|
|
93
|
+
* Returns null when the segment is not fully present.
|
|
94
|
+
*/
|
|
95
|
+
export declare function readSofDimensions(bytes: Uint8Array, sofOffset: number): {
|
|
96
|
+
width: number;
|
|
97
|
+
height: number;
|
|
98
|
+
} | null;
|
|
99
|
+
/**
|
|
100
|
+
* Shannon entropy (bits/byte, 0..8) over [start, end). A healthy JPEG scan is
|
|
101
|
+
* high (~7.3–8.0); a zeroed or overwritten scan collapses toward 0 — a cheap
|
|
102
|
+
* triage hint for "structure looks fine but the pixels were destroyed". For
|
|
103
|
+
* large ranges the data is strided to cap cost. Returns null for empty ranges.
|
|
104
|
+
*/
|
|
105
|
+
export declare function shannonEntropy(bytes: Uint8Array, start: number, end: number): number | null;
|
|
106
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/jpeg/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure JPEG marker-scan primitives — no wasm, no third-party deps, so this
|
|
3
|
+
* module is safe to pull into the browser-facing diagnosis path.
|
|
4
|
+
*
|
|
5
|
+
* A JPEG is a sequence of marker segments framed by 0xFF <marker> bytes.
|
|
6
|
+
* Standalone markers (SOI, EOI, RSTn, TEM) carry no payload; every other
|
|
7
|
+
* marker is followed by a big-endian 2-byte length that INCLUDES those two
|
|
8
|
+
* length bytes. After SOS the entropy-coded scan data runs raw until the next
|
|
9
|
+
* real marker (0xFF followed by a non-0x00, non-RSTn byte), typically EOI.
|
|
10
|
+
*
|
|
11
|
+
* Two views are offered: a strict sequential walk (order, overflow, structural
|
|
12
|
+
* corruption) and a robust presence scan (which markers exist *anywhere*, so a
|
|
13
|
+
* destroyed header whose SOS+scan survived is still recognisable — the case
|
|
14
|
+
* donor transplant exists for).
|
|
15
|
+
*/
|
|
16
|
+
// Standalone markers (no length field).
|
|
17
|
+
export const M_SOI = 0xd8;
|
|
18
|
+
export const M_EOI = 0xd9;
|
|
19
|
+
export const M_TEM = 0x01;
|
|
20
|
+
export const M_RST0 = 0xd0;
|
|
21
|
+
export const M_RST7 = 0xd7;
|
|
22
|
+
// Segment markers we care about.
|
|
23
|
+
export const M_SOS = 0xda;
|
|
24
|
+
export const M_DQT = 0xdb;
|
|
25
|
+
export const M_DHT = 0xc4;
|
|
26
|
+
export const M_DRI = 0xdd;
|
|
27
|
+
export const M_APP0 = 0xe0;
|
|
28
|
+
export const M_APP15 = 0xef;
|
|
29
|
+
export const M_COM = 0xfe;
|
|
30
|
+
/** SOF markers are 0xC0..0xCF except 0xC4 (DHT), 0xC8 (JPG), 0xCC (DAC). */
|
|
31
|
+
export function isSofMarker(m) {
|
|
32
|
+
return m >= 0xc0 && m <= 0xcf && m !== 0xc4 && m !== 0xc8 && m !== 0xcc;
|
|
33
|
+
}
|
|
34
|
+
export function isAppMarker(m) {
|
|
35
|
+
return m >= M_APP0 && m <= M_APP15;
|
|
36
|
+
}
|
|
37
|
+
export function isStandaloneMarker(m) {
|
|
38
|
+
return m === M_SOI || m === M_EOI || m === M_TEM || (m >= M_RST0 && m <= M_RST7);
|
|
39
|
+
}
|
|
40
|
+
export function markerName(m) {
|
|
41
|
+
switch (m) {
|
|
42
|
+
case M_SOI:
|
|
43
|
+
return 'SOI';
|
|
44
|
+
case M_EOI:
|
|
45
|
+
return 'EOI';
|
|
46
|
+
case M_SOS:
|
|
47
|
+
return 'SOS';
|
|
48
|
+
case M_DQT:
|
|
49
|
+
return 'DQT';
|
|
50
|
+
case M_DHT:
|
|
51
|
+
return 'DHT';
|
|
52
|
+
case M_DRI:
|
|
53
|
+
return 'DRI';
|
|
54
|
+
case M_COM:
|
|
55
|
+
return 'COM';
|
|
56
|
+
case M_TEM:
|
|
57
|
+
return 'TEM';
|
|
58
|
+
default:
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
if (isSofMarker(m))
|
|
62
|
+
return `SOF${m - 0xc0}`;
|
|
63
|
+
if (isAppMarker(m))
|
|
64
|
+
return `APP${m - M_APP0}`;
|
|
65
|
+
if (m >= M_RST0 && m <= M_RST7)
|
|
66
|
+
return `RST${m - M_RST0}`;
|
|
67
|
+
return `0x${m.toString(16).padStart(2, '0')}`;
|
|
68
|
+
}
|
|
69
|
+
export function readU16BE(b, off) {
|
|
70
|
+
return ((b[off] ?? 0) << 8) | (b[off + 1] ?? 0);
|
|
71
|
+
}
|
|
72
|
+
/** Locate the first SOI (0xFFD8) within [0, window). Returns -1 if absent. */
|
|
73
|
+
export function findSoi(bytes, window = bytes.length) {
|
|
74
|
+
const limit = Math.min(bytes.length - 1, window);
|
|
75
|
+
for (let i = 0; i <= limit; i++) {
|
|
76
|
+
if (bytes[i] === 0xff && bytes[i + 1] === M_SOI)
|
|
77
|
+
return i;
|
|
78
|
+
}
|
|
79
|
+
return -1;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Strict sequential walk from SOI. Stops at SOS (recording where the scan
|
|
83
|
+
* begins) or at the first structural problem. Never throws.
|
|
84
|
+
*/
|
|
85
|
+
export function scanMarkers(bytes, soiOffset) {
|
|
86
|
+
const scan = {
|
|
87
|
+
soiOffset,
|
|
88
|
+
segments: [],
|
|
89
|
+
sosOffset: -1,
|
|
90
|
+
scanStart: -1,
|
|
91
|
+
scanEnd: -1,
|
|
92
|
+
eoiOffset: -1,
|
|
93
|
+
hasEoi: false,
|
|
94
|
+
overflow: false,
|
|
95
|
+
badMarker: false,
|
|
96
|
+
truncatedHeader: false,
|
|
97
|
+
};
|
|
98
|
+
const len = bytes.length;
|
|
99
|
+
let i = soiOffset + 2;
|
|
100
|
+
while (i < len) {
|
|
101
|
+
// 0xFF fill bytes are permitted before a marker.
|
|
102
|
+
while (i < len && bytes[i] === 0xff && bytes[i + 1] === 0xff)
|
|
103
|
+
i++;
|
|
104
|
+
if (i + 1 >= len) {
|
|
105
|
+
scan.truncatedHeader = true;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
if (bytes[i] !== 0xff) {
|
|
109
|
+
scan.badMarker = true;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
const m = bytes[i + 1];
|
|
113
|
+
if (m === M_EOI) {
|
|
114
|
+
scan.hasEoi = true;
|
|
115
|
+
scan.eoiOffset = i;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
if (isStandaloneMarker(m)) {
|
|
119
|
+
i += 2;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (i + 3 >= len) {
|
|
123
|
+
scan.truncatedHeader = true;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
const segLen = readU16BE(bytes, i + 2);
|
|
127
|
+
scan.segments.push({ marker: m, name: markerName(m), offset: i, length: segLen });
|
|
128
|
+
if (m === M_SOS) {
|
|
129
|
+
scan.sosOffset = i;
|
|
130
|
+
scan.scanStart = i + 2 + segLen;
|
|
131
|
+
// Scan data ends at the trailing EOI, else EOF.
|
|
132
|
+
const eoi = findEoiFrom(bytes, scan.scanStart);
|
|
133
|
+
scan.eoiOffset = eoi;
|
|
134
|
+
scan.hasEoi = eoi !== -1;
|
|
135
|
+
scan.scanEnd = eoi === -1 ? len : eoi;
|
|
136
|
+
if (scan.scanStart > len)
|
|
137
|
+
scan.overflow = true;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
const segEnd = i + 2 + segLen;
|
|
141
|
+
if (segLen < 2 || segEnd > len) {
|
|
142
|
+
scan.overflow = true;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
i = segEnd;
|
|
146
|
+
}
|
|
147
|
+
return scan;
|
|
148
|
+
}
|
|
149
|
+
/** Find the trailing EOI (0xFFD9) scanning forward from `from`. */
|
|
150
|
+
export function findEoiFrom(bytes, from) {
|
|
151
|
+
for (let i = Math.max(0, from); i + 1 < bytes.length; i++) {
|
|
152
|
+
if (bytes[i] === 0xff && bytes[i + 1] === M_EOI)
|
|
153
|
+
return i;
|
|
154
|
+
}
|
|
155
|
+
return -1;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Robust presence scan: look for each key marker anywhere in [start, end),
|
|
159
|
+
* independent of sequence. Survives a zeroed/garbled header as long as the
|
|
160
|
+
* marker bytes themselves are intact — how we recognise "header destroyed but
|
|
161
|
+
* scan alive". Skips 0xFF00 byte-stuffing and 0xFFFF fill.
|
|
162
|
+
*/
|
|
163
|
+
export function scanMarkerPresence(bytes, start, end = bytes.length) {
|
|
164
|
+
const p = {
|
|
165
|
+
hasDqt: false,
|
|
166
|
+
hasDht: false,
|
|
167
|
+
hasSof: false,
|
|
168
|
+
hasSos: false,
|
|
169
|
+
hasEoi: false,
|
|
170
|
+
sosOffset: -1,
|
|
171
|
+
eoiOffset: -1,
|
|
172
|
+
sofOffset: -1,
|
|
173
|
+
};
|
|
174
|
+
const limit = Math.min(end, bytes.length) - 1;
|
|
175
|
+
for (let i = Math.max(0, start); i <= limit; i++) {
|
|
176
|
+
if (bytes[i] !== 0xff)
|
|
177
|
+
continue;
|
|
178
|
+
const m = bytes[i + 1];
|
|
179
|
+
if (m === 0x00 || m === 0xff)
|
|
180
|
+
continue; // stuffing / fill
|
|
181
|
+
if (m === M_DQT)
|
|
182
|
+
p.hasDqt = true;
|
|
183
|
+
else if (m === M_DHT)
|
|
184
|
+
p.hasDht = true;
|
|
185
|
+
else if (isSofMarker(m)) {
|
|
186
|
+
p.hasSof = true;
|
|
187
|
+
if (p.sofOffset === -1)
|
|
188
|
+
p.sofOffset = i;
|
|
189
|
+
}
|
|
190
|
+
else if (m === M_SOS) {
|
|
191
|
+
p.hasSos = true;
|
|
192
|
+
if (p.sosOffset === -1)
|
|
193
|
+
p.sosOffset = i;
|
|
194
|
+
}
|
|
195
|
+
else if (m === M_EOI) {
|
|
196
|
+
p.hasEoi = true;
|
|
197
|
+
p.eoiOffset = i;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return p;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Read the frame dimensions from a SOF segment at `sofOffset` (the 0xFF byte).
|
|
204
|
+
* SOF layout: FF Cx | len(2) | precision(1) | height(2) | width(2) | ...
|
|
205
|
+
* Returns null when the segment is not fully present.
|
|
206
|
+
*/
|
|
207
|
+
export function readSofDimensions(bytes, sofOffset) {
|
|
208
|
+
if (sofOffset < 0 || sofOffset + 9 > bytes.length)
|
|
209
|
+
return null;
|
|
210
|
+
const height = readU16BE(bytes, sofOffset + 5);
|
|
211
|
+
const width = readU16BE(bytes, sofOffset + 7);
|
|
212
|
+
if (width === 0 || height === 0)
|
|
213
|
+
return null;
|
|
214
|
+
return { width, height };
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Shannon entropy (bits/byte, 0..8) over [start, end). A healthy JPEG scan is
|
|
218
|
+
* high (~7.3–8.0); a zeroed or overwritten scan collapses toward 0 — a cheap
|
|
219
|
+
* triage hint for "structure looks fine but the pixels were destroyed". For
|
|
220
|
+
* large ranges the data is strided to cap cost. Returns null for empty ranges.
|
|
221
|
+
*/
|
|
222
|
+
export function shannonEntropy(bytes, start, end) {
|
|
223
|
+
const lo = Math.max(0, start);
|
|
224
|
+
const hi = Math.min(bytes.length, end);
|
|
225
|
+
const span = hi - lo;
|
|
226
|
+
if (span <= 0)
|
|
227
|
+
return null;
|
|
228
|
+
const stride = span > 65536 ? Math.ceil(span / 65536) : 1;
|
|
229
|
+
const hist = new Uint32Array(256);
|
|
230
|
+
let n = 0;
|
|
231
|
+
for (let i = lo; i < hi; i += stride) {
|
|
232
|
+
const b = bytes[i];
|
|
233
|
+
hist[b] = (hist[b] ?? 0) + 1;
|
|
234
|
+
n++;
|
|
235
|
+
}
|
|
236
|
+
if (n === 0)
|
|
237
|
+
return null;
|
|
238
|
+
let h = 0;
|
|
239
|
+
for (let v = 0; v < 256; v++) {
|
|
240
|
+
const c = hist[v];
|
|
241
|
+
if (c === 0)
|
|
242
|
+
continue;
|
|
243
|
+
const pr = c / n;
|
|
244
|
+
h -= pr * Math.log2(pr);
|
|
245
|
+
}
|
|
246
|
+
return h;
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/jpeg/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JPEG engine subpath export (`@intactfile/engines/jpeg`). Kept out of the
|
|
3
|
+
* root export so browser bundles that never touch JPEGs never pull in the
|
|
4
|
+
* @jsquash codec wasm or exifr; even here, the codec wasm only loads on the
|
|
5
|
+
* first repairJpeg call. diagnoseJpeg is pure marker-scanning and safe to call
|
|
6
|
+
* eagerly.
|
|
7
|
+
*/
|
|
8
|
+
export { diagnoseJpeg, LOW_SCAN_ENTROPY, SOI_SCAN_WINDOW } from './diagnose.js';
|
|
9
|
+
export type { JpegDiagnosis, JpegDamageClass } from './diagnose.js';
|
|
10
|
+
export { repairJpeg, buildRepairCandidates, transplantHeader } from './repair.js';
|
|
11
|
+
export type { JpegRepairResult, JpegRepairReport, JpegRepairOptions, JpegRepairOutcome, JpegRepairStrategy, JpegRepairAttempt, } from './repair.js';
|
|
12
|
+
export { extractExifThumbnail, extractExifOrientation } from './exif.js';
|
|
13
|
+
export { decodeJpeg, encodeJpeg, setJpegLoader, resetJpegHost, SALVAGE_ENCODE_OPTIONS, } from './mozjpeg-host.js';
|
|
14
|
+
export type { DecodedImage, DecodeResult, JpegCodecLoader, JpegEncodeOptions } from './mozjpeg-host.js';
|
|
15
|
+
export { createBrowserJpegLoader, DEFAULT_JPEG_BASE_URL } from './browser-loader.js';
|
|
16
|
+
export { markerName, isSofMarker, isAppMarker, scanMarkers, scanMarkerPresence, findSoi, findEoiFrom, readSofDimensions, shannonEntropy, } from './format.js';
|
|
17
|
+
export type { MarkerScan, MarkerSegment, MarkerPresence } from './format.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jpeg/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChF,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEzE,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExG,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAErF,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JPEG engine subpath export (`@intactfile/engines/jpeg`). Kept out of the
|
|
3
|
+
* root export so browser bundles that never touch JPEGs never pull in the
|
|
4
|
+
* @jsquash codec wasm or exifr; even here, the codec wasm only loads on the
|
|
5
|
+
* first repairJpeg call. diagnoseJpeg is pure marker-scanning and safe to call
|
|
6
|
+
* eagerly.
|
|
7
|
+
*/
|
|
8
|
+
export { diagnoseJpeg, LOW_SCAN_ENTROPY, SOI_SCAN_WINDOW } from './diagnose.js';
|
|
9
|
+
export { repairJpeg, buildRepairCandidates, transplantHeader } from './repair.js';
|
|
10
|
+
export { extractExifThumbnail, extractExifOrientation } from './exif.js';
|
|
11
|
+
export { decodeJpeg, encodeJpeg, setJpegLoader, resetJpegHost, SALVAGE_ENCODE_OPTIONS, } from './mozjpeg-host.js';
|
|
12
|
+
export { createBrowserJpegLoader, DEFAULT_JPEG_BASE_URL } from './browser-loader.js';
|
|
13
|
+
export { markerName, isSofMarker, isAppMarker, scanMarkers, scanMarkerPresence, findSoi, findEoiFrom, readSofDimensions, shannonEntropy, } from './format.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jpeg/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhF,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUlF,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEzE,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAErF,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,cAAc,GACf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isolated host for the MozJPEG (libjpeg-turbo lineage) wasm codec shipped by
|
|
3
|
+
* @jsquash/jpeg 1.6.0 (Apache-2.0). Two wasm modules: the decoder
|
|
4
|
+
* (mozjpeg_dec.wasm, ~163 KB) and the encoder (mozjpeg_enc.wasm, ~246 KB).
|
|
5
|
+
* Everything that touches the codec lives here; nothing else in the package
|
|
6
|
+
* imports @jsquash/jpeg, and the wasm is only compiled on first use.
|
|
7
|
+
*
|
|
8
|
+
* Loading is injectable, same shape as pdf/qpdf-host.ts and video/libav-host.ts:
|
|
9
|
+
* the Node default loader reads the two .wasm files from node_modules and
|
|
10
|
+
* compiles them; a browser host calls setJpegLoader() with a loader that
|
|
11
|
+
* fetches+compiles them from a same-origin URL (see browser-loader.ts). This
|
|
12
|
+
* matters because @jsquash's default codec path uses fetch(import.meta.url)
|
|
13
|
+
* to locate the wasm, which does not work in Node.
|
|
14
|
+
*
|
|
15
|
+
* Why a warning-capturing decoder matters: libjpeg emits "Premature end of
|
|
16
|
+
* JPEG file" / "Corrupt JPEG data" to stderr but STILL returns the rows it
|
|
17
|
+
* managed to decode (the rest filled grey). Capturing that stderr is how we
|
|
18
|
+
* honestly tell a full decode from a partial salvage.
|
|
19
|
+
*/
|
|
20
|
+
import decodeWasmDefault from '@jsquash/jpeg/decode.js';
|
|
21
|
+
import encodeWasmDefault from '@jsquash/jpeg/encode.js';
|
|
22
|
+
import type { EncodeOptions } from '@jsquash/jpeg/meta.js';
|
|
23
|
+
export interface DecodedImage {
|
|
24
|
+
data: Uint8Array;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}
|
|
28
|
+
export type DecodeResult = {
|
|
29
|
+
ok: true;
|
|
30
|
+
image: DecodedImage;
|
|
31
|
+
warnings: string[];
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
warnings: string[];
|
|
35
|
+
error: string;
|
|
36
|
+
};
|
|
37
|
+
export interface JpegCodecLoader {
|
|
38
|
+
/** Resolve a compiled decoder module (mozjpeg_dec.wasm). */
|
|
39
|
+
decodeModule: () => Promise<WebAssembly.Module>;
|
|
40
|
+
/** Resolve a compiled encoder module (mozjpeg_enc.wasm). */
|
|
41
|
+
encodeModule: () => Promise<WebAssembly.Module>;
|
|
42
|
+
}
|
|
43
|
+
/** Inject how the codec wasm modules are obtained (browser hosts). */
|
|
44
|
+
export declare function setJpegLoader(load: () => Promise<JpegCodecLoader>): void;
|
|
45
|
+
/** Drop the cached codec init (tests, or after a wasm crash). */
|
|
46
|
+
export declare function resetJpegHost(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Decode a JPEG, tolerating truncation/corruption. Returns a discriminated
|
|
49
|
+
* result rather than throwing: `ok:false` for a hard failure (no scan, missing
|
|
50
|
+
* SOS, unusable header), `ok:true` with `warnings` populated for a partial
|
|
51
|
+
* salvage (top rows recovered, remainder grey). Never throws for bad input.
|
|
52
|
+
*/
|
|
53
|
+
export declare function decodeJpeg(bytes: Uint8Array): Promise<DecodeResult>;
|
|
54
|
+
export type JpegEncodeOptions = Partial<EncodeOptions>;
|
|
55
|
+
/** Baseline, widely-compatible re-emission of a salvaged raster. */
|
|
56
|
+
export declare const SALVAGE_ENCODE_OPTIONS: JpegEncodeOptions;
|
|
57
|
+
/** Encode an RGBA raster to a valid baseline JPEG. */
|
|
58
|
+
export declare function encodeJpeg(image: DecodedImage, options?: JpegEncodeOptions): Promise<Uint8Array>;
|
|
59
|
+
export { decodeWasmDefault, encodeWasmDefault };
|
|
60
|
+
//# sourceMappingURL=mozjpeg-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mozjpeg-host.d.ts","sourceRoot":"","sources":["../../src/jpeg/mozjpeg-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,iBAA4C,MAAM,yBAAyB,CAAC;AACnF,OAAO,iBAA4C,MAAM,yBAAyB,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAQ3D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACrD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,4DAA4D;IAC5D,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;CACjD;AAKD,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAGxE;AAED,iEAAiE;AACjE,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAyDD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBnE;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAEvD,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,EAAE,iBAKpC,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAepG;AAGD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isolated host for the MozJPEG (libjpeg-turbo lineage) wasm codec shipped by
|
|
3
|
+
* @jsquash/jpeg 1.6.0 (Apache-2.0). Two wasm modules: the decoder
|
|
4
|
+
* (mozjpeg_dec.wasm, ~163 KB) and the encoder (mozjpeg_enc.wasm, ~246 KB).
|
|
5
|
+
* Everything that touches the codec lives here; nothing else in the package
|
|
6
|
+
* imports @jsquash/jpeg, and the wasm is only compiled on first use.
|
|
7
|
+
*
|
|
8
|
+
* Loading is injectable, same shape as pdf/qpdf-host.ts and video/libav-host.ts:
|
|
9
|
+
* the Node default loader reads the two .wasm files from node_modules and
|
|
10
|
+
* compiles them; a browser host calls setJpegLoader() with a loader that
|
|
11
|
+
* fetches+compiles them from a same-origin URL (see browser-loader.ts). This
|
|
12
|
+
* matters because @jsquash's default codec path uses fetch(import.meta.url)
|
|
13
|
+
* to locate the wasm, which does not work in Node.
|
|
14
|
+
*
|
|
15
|
+
* Why a warning-capturing decoder matters: libjpeg emits "Premature end of
|
|
16
|
+
* JPEG file" / "Corrupt JPEG data" to stderr but STILL returns the rows it
|
|
17
|
+
* managed to decode (the rest filled grey). Capturing that stderr is how we
|
|
18
|
+
* honestly tell a full decode from a partial salvage.
|
|
19
|
+
*/
|
|
20
|
+
import decodeWasmDefault, { init as initDecodeRaw } from '@jsquash/jpeg/decode.js';
|
|
21
|
+
import encodeWasmDefault, { init as initEncodeRaw } from '@jsquash/jpeg/encode.js';
|
|
22
|
+
const initDecode = initDecodeRaw;
|
|
23
|
+
const initEncode = initEncodeRaw;
|
|
24
|
+
let loaderOverride = null;
|
|
25
|
+
let initPromise = null;
|
|
26
|
+
/** Inject how the codec wasm modules are obtained (browser hosts). */
|
|
27
|
+
export function setJpegLoader(load) {
|
|
28
|
+
loaderOverride = load;
|
|
29
|
+
initPromise = null;
|
|
30
|
+
}
|
|
31
|
+
/** Drop the cached codec init (tests, or after a wasm crash). */
|
|
32
|
+
export function resetJpegHost() {
|
|
33
|
+
initPromise = null;
|
|
34
|
+
}
|
|
35
|
+
// stderr is captured per-run via a mutable sink; runs are serialized so the
|
|
36
|
+
// sink can never belong to two decodes at once.
|
|
37
|
+
let activeErr = null;
|
|
38
|
+
function errSink(line) {
|
|
39
|
+
activeErr?.push(typeof line === 'string' ? line : String(line));
|
|
40
|
+
}
|
|
41
|
+
async function defaultNodeLoader() {
|
|
42
|
+
const isNode = typeof process !== 'undefined' && !!process.versions?.node;
|
|
43
|
+
if (!isNode) {
|
|
44
|
+
throw new Error('jpeg host: no loader configured. In the browser, call setJpegLoader() with a loader that ' +
|
|
45
|
+
'fetches and compiles the @jsquash/jpeg dec/enc wasm from a same-origin URL before repairing JPEGs.');
|
|
46
|
+
}
|
|
47
|
+
const { createRequire } = await import('node:module');
|
|
48
|
+
const { readFile } = await import('node:fs/promises');
|
|
49
|
+
const require = createRequire(import.meta.url);
|
|
50
|
+
const decPath = require.resolve('@jsquash/jpeg/codec/dec/mozjpeg_dec.wasm');
|
|
51
|
+
const encPath = require.resolve('@jsquash/jpeg/codec/enc/mozjpeg_enc.wasm');
|
|
52
|
+
return {
|
|
53
|
+
decodeModule: async () => WebAssembly.compile(await readFile(decPath)),
|
|
54
|
+
encodeModule: async () => WebAssembly.compile(await readFile(encPath)),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function ensureInit() {
|
|
58
|
+
initPromise ??= (async () => {
|
|
59
|
+
const loader = await (loaderOverride ?? defaultNodeLoader)();
|
|
60
|
+
const [decMod, encMod] = await Promise.all([loader.decodeModule(), loader.encodeModule()]);
|
|
61
|
+
// Route the decoder's stderr into our capture sink; silence stdout.
|
|
62
|
+
await initDecode(decMod, { printErr: errSink, print: () => { } });
|
|
63
|
+
await initEncode(encMod, { printErr: () => { }, print: () => { } });
|
|
64
|
+
})().catch((e) => {
|
|
65
|
+
initPromise = null;
|
|
66
|
+
throw e;
|
|
67
|
+
});
|
|
68
|
+
return initPromise;
|
|
69
|
+
}
|
|
70
|
+
let runChain = Promise.resolve();
|
|
71
|
+
/** Serialize codec calls so the shared stderr sink is unambiguous. */
|
|
72
|
+
function exclusive(fn) {
|
|
73
|
+
const run = runChain.then(fn);
|
|
74
|
+
runChain = run.catch(() => undefined);
|
|
75
|
+
return run;
|
|
76
|
+
}
|
|
77
|
+
/** Standalone ArrayBuffer copy of `bytes` (jSquash decode wants an ArrayBuffer). */
|
|
78
|
+
function toArrayBuffer(bytes) {
|
|
79
|
+
const copy = new Uint8Array(bytes.length);
|
|
80
|
+
copy.set(bytes);
|
|
81
|
+
return copy.buffer;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Decode a JPEG, tolerating truncation/corruption. Returns a discriminated
|
|
85
|
+
* result rather than throwing: `ok:false` for a hard failure (no scan, missing
|
|
86
|
+
* SOS, unusable header), `ok:true` with `warnings` populated for a partial
|
|
87
|
+
* salvage (top rows recovered, remainder grey). Never throws for bad input.
|
|
88
|
+
*/
|
|
89
|
+
export function decodeJpeg(bytes) {
|
|
90
|
+
return exclusive(async () => {
|
|
91
|
+
await ensureInit();
|
|
92
|
+
const warnings = [];
|
|
93
|
+
activeErr = warnings;
|
|
94
|
+
try {
|
|
95
|
+
const img = await decodeWasmDefault(toArrayBuffer(bytes));
|
|
96
|
+
const data = new Uint8Array(img.data.length);
|
|
97
|
+
data.set(img.data);
|
|
98
|
+
return { ok: true, image: { data, width: img.width, height: img.height }, warnings };
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
warnings,
|
|
104
|
+
error: e instanceof Error ? e.message : String(e),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
activeErr = null;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/** Baseline, widely-compatible re-emission of a salvaged raster. */
|
|
113
|
+
export const SALVAGE_ENCODE_OPTIONS = {
|
|
114
|
+
quality: 85,
|
|
115
|
+
baseline: true,
|
|
116
|
+
progressive: false,
|
|
117
|
+
optimize_coding: true,
|
|
118
|
+
};
|
|
119
|
+
/** Encode an RGBA raster to a valid baseline JPEG. */
|
|
120
|
+
export function encodeJpeg(image, options = {}) {
|
|
121
|
+
return exclusive(async () => {
|
|
122
|
+
await ensureInit();
|
|
123
|
+
const imageData = {
|
|
124
|
+
data: new Uint8ClampedArray(image.data.buffer, image.data.byteOffset, image.data.byteLength),
|
|
125
|
+
width: image.width,
|
|
126
|
+
height: image.height,
|
|
127
|
+
colorSpace: 'srgb',
|
|
128
|
+
};
|
|
129
|
+
const buf = await encodeWasmDefault(imageData, {
|
|
130
|
+
...SALVAGE_ENCODE_OPTIONS,
|
|
131
|
+
...options,
|
|
132
|
+
});
|
|
133
|
+
return new Uint8Array(buf);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// Re-export for the default node path check and browser loader typing.
|
|
137
|
+
export { decodeWasmDefault, encodeWasmDefault };
|
|
138
|
+
//# sourceMappingURL=mozjpeg-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mozjpeg-host.js","sourceRoot":"","sources":["../../src/jpeg/mozjpeg-host.ts"],"names":[],"mappings":"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"}
|