pdf-codec 3.7.0 → 4.0.1
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/image/jpeg2000.cjs +1 -0
- package/dist/image/jpeg2000.d.cts +3 -0
- package/dist/image/jpeg2000.d.ts +3 -0
- package/dist/image/jpeg2000.js +1 -0
- package/dist/images-read.cjs +18 -14
- package/dist/images-read.js +15 -11
- package/package.json +3 -3
- package/dist/image/png-encode.cjs +0 -64
- package/dist/image/png-encode.d.cts +0 -8
- package/dist/image/png-encode.d.ts +0 -8
- package/dist/image/png-encode.js +0 -63
package/dist/image/jpeg2000.cjs
CHANGED
|
@@ -260,6 +260,7 @@ function decodeJpeg2000(data, options = {}) {
|
|
|
260
260
|
const siz = codestream.siz;
|
|
261
261
|
const width = siz.xsiz - siz.xosiz;
|
|
262
262
|
const height = siz.ysiz - siz.yosiz;
|
|
263
|
+
if (options.maxWidth !== void 0 && width > options.maxWidth || options.maxHeight !== void 0 && height > options.maxHeight || options.maxPixels !== void 0 && width * height > options.maxPixels) throw new Error(`cannot decode a ${String(width)}x${String(height)} JPEG 2000 canvas; this exceeds the caller's configured size bound`);
|
|
263
264
|
const componentCount = siz.components.length;
|
|
264
265
|
const first = siz.components[0];
|
|
265
266
|
if (first === void 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the codestream declares no components");
|
|
@@ -38,6 +38,9 @@ interface Jpeg2000Metadata {
|
|
|
38
38
|
}
|
|
39
39
|
interface Jpeg2000DecodeOptions {
|
|
40
40
|
readonly onWarning?: (message: string) => void;
|
|
41
|
+
readonly maxWidth?: number;
|
|
42
|
+
readonly maxHeight?: number;
|
|
43
|
+
readonly maxPixels?: number;
|
|
41
44
|
}
|
|
42
45
|
interface Jpeg2000Image {
|
|
43
46
|
readonly width: number;
|
package/dist/image/jpeg2000.d.ts
CHANGED
|
@@ -38,6 +38,9 @@ interface Jpeg2000Metadata {
|
|
|
38
38
|
}
|
|
39
39
|
interface Jpeg2000DecodeOptions {
|
|
40
40
|
readonly onWarning?: (message: string) => void;
|
|
41
|
+
readonly maxWidth?: number;
|
|
42
|
+
readonly maxHeight?: number;
|
|
43
|
+
readonly maxPixels?: number;
|
|
41
44
|
}
|
|
42
45
|
interface Jpeg2000Image {
|
|
43
46
|
readonly width: number;
|
package/dist/image/jpeg2000.js
CHANGED
|
@@ -259,6 +259,7 @@ function decodeJpeg2000(data, options = {}) {
|
|
|
259
259
|
const siz = codestream.siz;
|
|
260
260
|
const width = siz.xsiz - siz.xosiz;
|
|
261
261
|
const height = siz.ysiz - siz.yosiz;
|
|
262
|
+
if (options.maxWidth !== void 0 && width > options.maxWidth || options.maxHeight !== void 0 && height > options.maxHeight || options.maxPixels !== void 0 && width * height > options.maxPixels) throw new Error(`cannot decode a ${String(width)}x${String(height)} JPEG 2000 canvas; this exceeds the caller's configured size bound`);
|
|
262
263
|
const componentCount = siz.components.length;
|
|
263
264
|
const first = siz.components[0];
|
|
264
265
|
if (first === void 0) throw new Jpeg2000ParseError("the codestream declares no components");
|
package/dist/images-read.cjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_objects = require("./objects.cjs");
|
|
3
3
|
const require_filters = require("./filters.cjs");
|
|
4
|
-
const require_image_png_encode = require("./image/png-encode.cjs");
|
|
5
|
-
const require_image_jpeg_info = require("./image/jpeg-info.cjs");
|
|
6
4
|
const require_image_jpeg2000 = require("./image/jpeg2000.cjs");
|
|
5
|
+
let byte_codec = require("byte-codec");
|
|
7
6
|
//#region src/images-read.ts
|
|
8
7
|
function componentsOf(cs) {
|
|
9
8
|
if (cs.kind === "gray") return 1;
|
|
@@ -185,13 +184,18 @@ function jpeg2000ChannelKind(image, dict, resolver, sink) {
|
|
|
185
184
|
function readJpeg2000Image(dict, raw, resolver, sink) {
|
|
186
185
|
let image;
|
|
187
186
|
try {
|
|
188
|
-
image = require_image_jpeg2000.decodeJpeg2000(raw, {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
image = require_image_jpeg2000.decodeJpeg2000(raw, {
|
|
188
|
+
onWarning: (message) => {
|
|
189
|
+
sink({
|
|
190
|
+
code: "image/jpx-degraded",
|
|
191
|
+
severity: "warning",
|
|
192
|
+
message
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
maxWidth: byte_codec.PNG_MAX_DIMENSION,
|
|
196
|
+
maxHeight: byte_codec.PNG_MAX_DIMENSION,
|
|
197
|
+
maxPixels: byte_codec.PNG_MAX_PIXELS
|
|
198
|
+
});
|
|
195
199
|
} catch (error) {
|
|
196
200
|
sink({
|
|
197
201
|
code: "image/jpx-undecodable",
|
|
@@ -243,7 +247,7 @@ function readJpeg2000Image(dict, raw, resolver, sink) {
|
|
|
243
247
|
} : rawImage;
|
|
244
248
|
return {
|
|
245
249
|
format: "png",
|
|
246
|
-
bytes:
|
|
250
|
+
bytes: (0, byte_codec.encodePng)(withAlpha),
|
|
247
251
|
widthPx: image.width,
|
|
248
252
|
heightPx: image.height
|
|
249
253
|
};
|
|
@@ -261,7 +265,7 @@ function readImageXObject(dict, raw, resolver, sink) {
|
|
|
261
265
|
if (decoded.remainingFilter === "DCTDecode") {
|
|
262
266
|
let info;
|
|
263
267
|
try {
|
|
264
|
-
info =
|
|
268
|
+
info = (0, byte_codec.readJpegInfo)(decoded.bytes);
|
|
265
269
|
} catch {
|
|
266
270
|
sink({
|
|
267
271
|
code: "image/undecodable",
|
|
@@ -281,11 +285,11 @@ function readImageXObject(dict, raw, resolver, sink) {
|
|
|
281
285
|
if (decoded.remainingFilter !== void 0) return;
|
|
282
286
|
const width = require_objects.asNumber(require_objects.dictGet(dict, "Width") ?? require_objects.dictGet(dict, "W"));
|
|
283
287
|
const height = require_objects.asNumber(require_objects.dictGet(dict, "Height") ?? require_objects.dictGet(dict, "H"));
|
|
284
|
-
if (width === void 0 || height === void 0 || width <= 0 || height <= 0) {
|
|
288
|
+
if (width === void 0 || height === void 0 || !Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0 || width > byte_codec.PNG_MAX_DIMENSION || height > byte_codec.PNG_MAX_DIMENSION || width * height > byte_codec.PNG_MAX_PIXELS) {
|
|
285
289
|
sink({
|
|
286
290
|
code: "image/undecodable",
|
|
287
291
|
severity: "warning",
|
|
288
|
-
message: "image XObject
|
|
292
|
+
message: "image XObject has an invalid, out-of-range, or unusably large /Width or /Height; skipping"
|
|
289
293
|
});
|
|
290
294
|
return;
|
|
291
295
|
}
|
|
@@ -317,7 +321,7 @@ function readImageXObject(dict, raw, resolver, sink) {
|
|
|
317
321
|
} : rawImage;
|
|
318
322
|
return {
|
|
319
323
|
format: "png",
|
|
320
|
-
bytes:
|
|
324
|
+
bytes: (0, byte_codec.encodePng)(withAlpha),
|
|
321
325
|
widthPx: width,
|
|
322
326
|
heightPx: height
|
|
323
327
|
};
|
package/dist/images-read.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { asArray, asBool, asName, asNumber, dictGet } from "./objects.js";
|
|
2
2
|
import { decodeStream } from "./filters.js";
|
|
3
|
-
import { encodePng } from "./image/png-encode.js";
|
|
4
|
-
import { readJpegInfo } from "./image/jpeg-info.js";
|
|
5
3
|
import { decodeJpeg2000 } from "./image/jpeg2000.js";
|
|
4
|
+
import { PNG_MAX_DIMENSION, PNG_MAX_PIXELS, encodePng, readJpegInfo } from "byte-codec";
|
|
6
5
|
//#region src/images-read.ts
|
|
7
6
|
function componentsOf(cs) {
|
|
8
7
|
if (cs.kind === "gray") return 1;
|
|
@@ -184,13 +183,18 @@ function jpeg2000ChannelKind(image, dict, resolver, sink) {
|
|
|
184
183
|
function readJpeg2000Image(dict, raw, resolver, sink) {
|
|
185
184
|
let image;
|
|
186
185
|
try {
|
|
187
|
-
image = decodeJpeg2000(raw, {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
186
|
+
image = decodeJpeg2000(raw, {
|
|
187
|
+
onWarning: (message) => {
|
|
188
|
+
sink({
|
|
189
|
+
code: "image/jpx-degraded",
|
|
190
|
+
severity: "warning",
|
|
191
|
+
message
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
maxWidth: PNG_MAX_DIMENSION,
|
|
195
|
+
maxHeight: PNG_MAX_DIMENSION,
|
|
196
|
+
maxPixels: PNG_MAX_PIXELS
|
|
197
|
+
});
|
|
194
198
|
} catch (error) {
|
|
195
199
|
sink({
|
|
196
200
|
code: "image/jpx-undecodable",
|
|
@@ -280,11 +284,11 @@ function readImageXObject(dict, raw, resolver, sink) {
|
|
|
280
284
|
if (decoded.remainingFilter !== void 0) return;
|
|
281
285
|
const width = asNumber(dictGet(dict, "Width") ?? dictGet(dict, "W"));
|
|
282
286
|
const height = asNumber(dictGet(dict, "Height") ?? dictGet(dict, "H"));
|
|
283
|
-
if (width === void 0 || height === void 0 || width <= 0 || height <= 0) {
|
|
287
|
+
if (width === void 0 || height === void 0 || !Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0 || width > PNG_MAX_DIMENSION || height > PNG_MAX_DIMENSION || width * height > PNG_MAX_PIXELS) {
|
|
284
288
|
sink({
|
|
285
289
|
code: "image/undecodable",
|
|
286
290
|
severity: "warning",
|
|
287
|
-
message: "image XObject
|
|
291
|
+
message: "image XObject has an invalid, out-of-range, or unusably large /Width or /Height; skipping"
|
|
288
292
|
});
|
|
289
293
|
return;
|
|
290
294
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-codec",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Hand-written, dependency-minimal PDF codec: parses arbitrary real-world PDFs and generates new ones, built on its own codec-owned LayoutDocument item model and Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"license": "MIT",
|
|
100
100
|
"packageManager": "pnpm@11.6.0",
|
|
101
101
|
"dependencies": {
|
|
102
|
-
"byte-codec": "^1.
|
|
103
|
-
"document-schema.js": "^6.
|
|
102
|
+
"byte-codec": "^1.4.0",
|
|
103
|
+
"document-schema.js": "^6.2.0",
|
|
104
104
|
"fflate": "^0.8.3",
|
|
105
105
|
"zod": "^4.4.3"
|
|
106
106
|
},
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_bytes_writer = require("../bytes/writer.cjs");
|
|
3
|
-
const require_bytes_flate = require("../bytes/flate.cjs");
|
|
4
|
-
const require_image_png_filter = require("./png-filter.cjs");
|
|
5
|
-
const require_bytes_crc32 = require("../bytes/crc32.cjs");
|
|
6
|
-
//#region src/image/png-encode.ts
|
|
7
|
-
const PNG_SIGNATURE = new Uint8Array([
|
|
8
|
-
137,
|
|
9
|
-
80,
|
|
10
|
-
78,
|
|
11
|
-
71,
|
|
12
|
-
13,
|
|
13
|
-
10,
|
|
14
|
-
26,
|
|
15
|
-
10
|
|
16
|
-
]);
|
|
17
|
-
function u32be(value) {
|
|
18
|
-
const bytes = /* @__PURE__ */ new Uint8Array(4);
|
|
19
|
-
new DataView(bytes.buffer).setUint32(0, value);
|
|
20
|
-
return bytes;
|
|
21
|
-
}
|
|
22
|
-
function writeChunk(writer, type, data) {
|
|
23
|
-
const typeBytes = new TextEncoder().encode(type);
|
|
24
|
-
writer.writeBytes(u32be(data.length));
|
|
25
|
-
writer.writeBytes(typeBytes);
|
|
26
|
-
writer.writeBytes(data);
|
|
27
|
-
writer.writeBytes(u32be(require_bytes_crc32.crc32(require_bytes_writer.concatBytes([typeBytes, data]))));
|
|
28
|
-
}
|
|
29
|
-
function colorTypeFor(image) {
|
|
30
|
-
if (image.channels === 1) return image.alpha === void 0 ? 0 : 4;
|
|
31
|
-
return image.alpha === void 0 ? 2 : 6;
|
|
32
|
-
}
|
|
33
|
-
function encodePng(image, options = {}) {
|
|
34
|
-
const { width, height, channels, data, alpha } = image;
|
|
35
|
-
const outChannels = alpha === void 0 ? channels : channels + 1;
|
|
36
|
-
const bytesPerRow = width * outChannels;
|
|
37
|
-
const pixelCount = width * height;
|
|
38
|
-
const interleaved = new Uint8Array(pixelCount * outChannels);
|
|
39
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
40
|
-
const srcBase = i * channels;
|
|
41
|
-
const dstBase = i * outChannels;
|
|
42
|
-
for (let c = 0; c < channels; c++) interleaved[dstBase + c] = data[srcBase + c];
|
|
43
|
-
if (alpha !== void 0) interleaved[dstBase + channels] = alpha[i];
|
|
44
|
-
}
|
|
45
|
-
const filtered = require_image_png_filter.filterScanlines(interleaved, height, bytesPerRow, outChannels, options.filter ?? "adaptive");
|
|
46
|
-
const compressed = require_bytes_flate.deflate(filtered);
|
|
47
|
-
const ihdr = /* @__PURE__ */ new Uint8Array(13);
|
|
48
|
-
const ihdrView = new DataView(ihdr.buffer);
|
|
49
|
-
ihdrView.setUint32(0, width);
|
|
50
|
-
ihdrView.setUint32(4, height);
|
|
51
|
-
ihdr[8] = 8;
|
|
52
|
-
ihdr[9] = colorTypeFor(image);
|
|
53
|
-
ihdr[10] = 0;
|
|
54
|
-
ihdr[11] = 0;
|
|
55
|
-
ihdr[12] = 0;
|
|
56
|
-
const writer = new require_bytes_writer.ByteWriter();
|
|
57
|
-
writer.writeBytes(PNG_SIGNATURE);
|
|
58
|
-
writeChunk(writer, "IHDR", ihdr);
|
|
59
|
-
writeChunk(writer, "IDAT", compressed);
|
|
60
|
-
writeChunk(writer, "IEND", /* @__PURE__ */ new Uint8Array(0));
|
|
61
|
-
return writer.toBytes();
|
|
62
|
-
}
|
|
63
|
-
//#endregion
|
|
64
|
-
exports.encodePng = encodePng;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { RawImage } from "./png-decode.cjs";
|
|
2
|
-
//#region src/image/png-encode.d.ts
|
|
3
|
-
interface PngEncodeOptions {
|
|
4
|
-
readonly filter?: "none" | "adaptive";
|
|
5
|
-
}
|
|
6
|
-
declare function encodePng(image: RawImage, options?: PngEncodeOptions): Uint8Array<ArrayBuffer>;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { PngEncodeOptions, encodePng };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { RawImage } from "./png-decode.js";
|
|
2
|
-
//#region src/image/png-encode.d.ts
|
|
3
|
-
interface PngEncodeOptions {
|
|
4
|
-
readonly filter?: "none" | "adaptive";
|
|
5
|
-
}
|
|
6
|
-
declare function encodePng(image: RawImage, options?: PngEncodeOptions): Uint8Array<ArrayBuffer>;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { PngEncodeOptions, encodePng };
|
package/dist/image/png-encode.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { ByteWriter, concatBytes } from "../bytes/writer.js";
|
|
2
|
-
import { deflate } from "../bytes/flate.js";
|
|
3
|
-
import { filterScanlines } from "./png-filter.js";
|
|
4
|
-
import { crc32 } from "../bytes/crc32.js";
|
|
5
|
-
//#region src/image/png-encode.ts
|
|
6
|
-
const PNG_SIGNATURE = new Uint8Array([
|
|
7
|
-
137,
|
|
8
|
-
80,
|
|
9
|
-
78,
|
|
10
|
-
71,
|
|
11
|
-
13,
|
|
12
|
-
10,
|
|
13
|
-
26,
|
|
14
|
-
10
|
|
15
|
-
]);
|
|
16
|
-
function u32be(value) {
|
|
17
|
-
const bytes = /* @__PURE__ */ new Uint8Array(4);
|
|
18
|
-
new DataView(bytes.buffer).setUint32(0, value);
|
|
19
|
-
return bytes;
|
|
20
|
-
}
|
|
21
|
-
function writeChunk(writer, type, data) {
|
|
22
|
-
const typeBytes = new TextEncoder().encode(type);
|
|
23
|
-
writer.writeBytes(u32be(data.length));
|
|
24
|
-
writer.writeBytes(typeBytes);
|
|
25
|
-
writer.writeBytes(data);
|
|
26
|
-
writer.writeBytes(u32be(crc32(concatBytes([typeBytes, data]))));
|
|
27
|
-
}
|
|
28
|
-
function colorTypeFor(image) {
|
|
29
|
-
if (image.channels === 1) return image.alpha === void 0 ? 0 : 4;
|
|
30
|
-
return image.alpha === void 0 ? 2 : 6;
|
|
31
|
-
}
|
|
32
|
-
function encodePng(image, options = {}) {
|
|
33
|
-
const { width, height, channels, data, alpha } = image;
|
|
34
|
-
const outChannels = alpha === void 0 ? channels : channels + 1;
|
|
35
|
-
const bytesPerRow = width * outChannels;
|
|
36
|
-
const pixelCount = width * height;
|
|
37
|
-
const interleaved = new Uint8Array(pixelCount * outChannels);
|
|
38
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
39
|
-
const srcBase = i * channels;
|
|
40
|
-
const dstBase = i * outChannels;
|
|
41
|
-
for (let c = 0; c < channels; c++) interleaved[dstBase + c] = data[srcBase + c];
|
|
42
|
-
if (alpha !== void 0) interleaved[dstBase + channels] = alpha[i];
|
|
43
|
-
}
|
|
44
|
-
const filtered = filterScanlines(interleaved, height, bytesPerRow, outChannels, options.filter ?? "adaptive");
|
|
45
|
-
const compressed = deflate(filtered);
|
|
46
|
-
const ihdr = /* @__PURE__ */ new Uint8Array(13);
|
|
47
|
-
const ihdrView = new DataView(ihdr.buffer);
|
|
48
|
-
ihdrView.setUint32(0, width);
|
|
49
|
-
ihdrView.setUint32(4, height);
|
|
50
|
-
ihdr[8] = 8;
|
|
51
|
-
ihdr[9] = colorTypeFor(image);
|
|
52
|
-
ihdr[10] = 0;
|
|
53
|
-
ihdr[11] = 0;
|
|
54
|
-
ihdr[12] = 0;
|
|
55
|
-
const writer = new ByteWriter();
|
|
56
|
-
writer.writeBytes(PNG_SIGNATURE);
|
|
57
|
-
writeChunk(writer, "IHDR", ihdr);
|
|
58
|
-
writeChunk(writer, "IDAT", compressed);
|
|
59
|
-
writeChunk(writer, "IEND", /* @__PURE__ */ new Uint8Array(0));
|
|
60
|
-
return writer.toBytes();
|
|
61
|
-
}
|
|
62
|
-
//#endregion
|
|
63
|
-
export { encodePng };
|