byte-codec 1.2.2 → 1.4.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 +10 -10
- package/dist/index.cjs +86 -17
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +85 -18
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -42,16 +42,16 @@ To run a single test file, pass its path to vitest directly, e.g. `pnpm exec vit
|
|
|
42
42
|
|
|
43
43
|
## What it provides
|
|
44
44
|
|
|
45
|
-
| Module | Exports
|
|
46
|
-
| ------------------ |
|
|
47
|
-
| `bytes/writer` | `ByteWriter` (chunked growable byte-output builder), `concatBytes`
|
|
48
|
-
| `bytes/reader` | `ByteReader` (sequential big/little-endian byte reader), `isAsciiWhitespace`
|
|
49
|
-
| `bytes/crc32` | `crc32` (IEEE 802.3 / ZIP / PNG polynomial table-driven CRC-32)
|
|
50
|
-
| `bytes/flate` | `deflate`, `inflate`, `inflateTolerant` (fflate-backed DEFLATE compression/decompression with a safety cap)
|
|
51
|
-
| `image/png-encode` | `encodePng` (raw RGB/RGBA pixels → PNG bytes)
|
|
52
|
-
| `image/png-decode` | `decodePng` (PNG bytes → raw pixels), `RawImage`
|
|
53
|
-
| `image/png-filter` | `filterScanlines`, `unfilterScanlines` (the five PNG scanline filters)
|
|
54
|
-
| `image/jpeg-info` | `readJpegInfo` (JPEG header reader: dimensions, components, progressive flag — no sample decoding)
|
|
45
|
+
| Module | Exports |
|
|
46
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
47
|
+
| `bytes/writer` | `ByteWriter` (chunked growable byte-output builder), `concatBytes` |
|
|
48
|
+
| `bytes/reader` | `ByteReader` (sequential big/little-endian byte reader), `isAsciiWhitespace` |
|
|
49
|
+
| `bytes/crc32` | `crc32` (IEEE 802.3 / ZIP / PNG polynomial table-driven CRC-32) |
|
|
50
|
+
| `bytes/flate` | `deflate`, `inflate`, `inflateTolerant` (fflate-backed DEFLATE compression/decompression with a safety cap) |
|
|
51
|
+
| `image/png-encode` | `encodePng` (raw RGB/RGBA pixels → PNG bytes; a truecolour source image whose pixels reduce to 256 or fewer distinct colours is encoded both as indexed colour, PNG colour type 3 with a PLTE and, where needed, a tRNS chunk, and as plain truecolour, and whichever comes out smaller is returned -- indexed colour wins for the large flat-colour images typical of diagrams and screenshots, but the PLTE/tRNS chunk overhead can make it larger for small images, so the encoder measures rather than assumes, at the cost of a full second encode for every eligible image; throws if either `width` or `height` is not a positive integer no greater than the PNG spec's own IHDR limit, or if their product exceeds a practical per-call pixel-count ceiling, since PNG's IHDR chunk has no valid encoding for zero, negative, fractional, or non-finite dimensions and this bounds an otherwise-unbounded encode to a fixed worst case) |
|
|
52
|
+
| `image/png-decode` | `decodePng` (PNG bytes → raw pixels, handling every PNG colour type including indexed/palette via its own PLTE/tRNS lookup), `RawImage` |
|
|
53
|
+
| `image/png-filter` | `filterScanlines`, `unfilterScanlines` (the five PNG scanline filters) |
|
|
54
|
+
| `image/jpeg-info` | `readJpegInfo` (JPEG header reader: dimensions, components, progressive flag — no sample decoding) |
|
|
55
55
|
|
|
56
56
|
## Conventions
|
|
57
57
|
|
package/dist/index.cjs
CHANGED
|
@@ -258,6 +258,9 @@ const PNG_SIGNATURE$1 = new Uint8Array([
|
|
|
258
258
|
26,
|
|
259
259
|
10
|
|
260
260
|
]);
|
|
261
|
+
const MAX_PALETTE_ENTRIES = 256;
|
|
262
|
+
const PNG_MAX_DIMENSION = 2147483647;
|
|
263
|
+
const PNG_MAX_PIXELS = 1e8;
|
|
261
264
|
function u32be(value) {
|
|
262
265
|
const bytes = /* @__PURE__ */ new Uint8Array(4);
|
|
263
266
|
new DataView(bytes.buffer).setUint32(0, value);
|
|
@@ -270,11 +273,73 @@ function writeChunk(writer, type, data) {
|
|
|
270
273
|
writer.writeBytes(data);
|
|
271
274
|
writer.writeBytes(u32be(crc32(concatBytes([typeBytes, data]))));
|
|
272
275
|
}
|
|
276
|
+
function writeIhdr(writer, width, height, colorType) {
|
|
277
|
+
const ihdr = /* @__PURE__ */ new Uint8Array(13);
|
|
278
|
+
const ihdrView = new DataView(ihdr.buffer);
|
|
279
|
+
ihdrView.setUint32(0, width);
|
|
280
|
+
ihdrView.setUint32(4, height);
|
|
281
|
+
ihdr[8] = 8;
|
|
282
|
+
ihdr[9] = colorType;
|
|
283
|
+
ihdr[10] = 0;
|
|
284
|
+
ihdr[11] = 0;
|
|
285
|
+
ihdr[12] = 0;
|
|
286
|
+
writeChunk(writer, "IHDR", ihdr);
|
|
287
|
+
}
|
|
273
288
|
function colorTypeFor(image) {
|
|
274
289
|
if (image.channels === 1) return image.alpha === void 0 ? 0 : 4;
|
|
275
290
|
return image.alpha === void 0 ? 2 : 6;
|
|
276
291
|
}
|
|
277
|
-
function
|
|
292
|
+
function detectPalette(image) {
|
|
293
|
+
const { width, height, data, alpha } = image;
|
|
294
|
+
const pixelCount = width * height;
|
|
295
|
+
const colorToIndex = /* @__PURE__ */ new Map();
|
|
296
|
+
const indices = new Uint8Array(pixelCount);
|
|
297
|
+
const paletteRgb = [];
|
|
298
|
+
const paletteAlpha = [];
|
|
299
|
+
for (let i = 0; i < pixelCount; i++) {
|
|
300
|
+
const base = i * 3;
|
|
301
|
+
const r = data[base] ?? 0;
|
|
302
|
+
const g = data[base + 1] ?? 0;
|
|
303
|
+
const b = data[base + 2] ?? 0;
|
|
304
|
+
const a = alpha === void 0 ? 255 : alpha[i] ?? 0;
|
|
305
|
+
const key = r + g * 256 + b * 65536 + a * 16777216;
|
|
306
|
+
let index = colorToIndex.get(key);
|
|
307
|
+
if (index === void 0) {
|
|
308
|
+
if (colorToIndex.size >= MAX_PALETTE_ENTRIES) return;
|
|
309
|
+
index = colorToIndex.size;
|
|
310
|
+
colorToIndex.set(key, index);
|
|
311
|
+
paletteRgb.push(r, g, b);
|
|
312
|
+
paletteAlpha.push(a);
|
|
313
|
+
}
|
|
314
|
+
indices[i] = index;
|
|
315
|
+
}
|
|
316
|
+
const palette = Uint8Array.from(paletteRgb);
|
|
317
|
+
if (alpha === void 0) return {
|
|
318
|
+
indices,
|
|
319
|
+
palette
|
|
320
|
+
};
|
|
321
|
+
let trnsLength = paletteAlpha.length;
|
|
322
|
+
while (trnsLength > 1 && paletteAlpha[trnsLength - 1] === 255) trnsLength--;
|
|
323
|
+
return {
|
|
324
|
+
indices,
|
|
325
|
+
palette,
|
|
326
|
+
trns: Uint8Array.from(paletteAlpha.slice(0, trnsLength))
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function buildPng(writeBody) {
|
|
330
|
+
const writer = new ByteWriter();
|
|
331
|
+
writer.writeBytes(PNG_SIGNATURE$1);
|
|
332
|
+
writeBody(writer);
|
|
333
|
+
writeChunk(writer, "IEND", /* @__PURE__ */ new Uint8Array(0));
|
|
334
|
+
return writer.toBytes();
|
|
335
|
+
}
|
|
336
|
+
function writeIndexedPng(writer, width, height, encoding, options) {
|
|
337
|
+
writeIhdr(writer, width, height, 3);
|
|
338
|
+
writeChunk(writer, "PLTE", encoding.palette);
|
|
339
|
+
if (encoding.trns !== void 0) writeChunk(writer, "tRNS", encoding.trns);
|
|
340
|
+
writeChunk(writer, "IDAT", deflate(filterScanlines(encoding.indices, height, width, 1, options.filter ?? "adaptive")));
|
|
341
|
+
}
|
|
342
|
+
function writeTruecolorPng(writer, image, options) {
|
|
278
343
|
const { width, height, channels, data, alpha } = image;
|
|
279
344
|
const outChannels = alpha === void 0 ? channels : channels + 1;
|
|
280
345
|
const bytesPerRow = width * outChannels;
|
|
@@ -286,22 +351,24 @@ function encodePng(image, options = {}) {
|
|
|
286
351
|
for (let c = 0; c < channels; c++) interleaved[dstBase + c] = data[srcBase + c];
|
|
287
352
|
if (alpha !== void 0) interleaved[dstBase + channels] = alpha[i];
|
|
288
353
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
writer
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
354
|
+
writeIhdr(writer, width, height, colorTypeFor(image));
|
|
355
|
+
writeChunk(writer, "IDAT", deflate(filterScanlines(interleaved, height, bytesPerRow, outChannels, options.filter ?? "adaptive")));
|
|
356
|
+
}
|
|
357
|
+
function encodePng(image, options = {}) {
|
|
358
|
+
if (!Number.isInteger(image.width) || image.width <= 0 || image.width > 2147483647 || !Number.isInteger(image.height) || image.height <= 0 || image.height > 2147483647) throw new Error(`cannot encode a PNG with an invalid dimension (width=${image.width}, height=${image.height}); the PNG spec's IHDR section requires both width and height to be positive integers no greater than ${PNG_MAX_DIMENSION}`);
|
|
359
|
+
const pixelCount = image.width * image.height;
|
|
360
|
+
if (pixelCount > 1e8) throw new Error(`cannot encode a PNG with ${pixelCount} pixels (width=${image.width}, height=${image.height}); each dimension is individually within the PNG spec's own limit, but this encoder bounds their product to ${PNG_MAX_PIXELS} to avoid an unbounded per-pixel scan and allocation`);
|
|
361
|
+
const paletteEncoding = image.channels === 3 ? detectPalette(image) : void 0;
|
|
362
|
+
if (paletteEncoding === void 0) return buildPng((writer) => {
|
|
363
|
+
writeTruecolorPng(writer, image, options);
|
|
364
|
+
});
|
|
365
|
+
const indexed = buildPng((writer) => {
|
|
366
|
+
writeIndexedPng(writer, image.width, image.height, paletteEncoding, options);
|
|
367
|
+
});
|
|
368
|
+
const truecolor = buildPng((writer) => {
|
|
369
|
+
writeTruecolorPng(writer, image, options);
|
|
370
|
+
});
|
|
371
|
+
return indexed.length <= truecolor.length ? indexed : truecolor;
|
|
305
372
|
}
|
|
306
373
|
//#endregion
|
|
307
374
|
//#region src/image/png-decode.ts
|
|
@@ -550,6 +617,8 @@ function readJpegInfo(bytes) {
|
|
|
550
617
|
exports.ByteReader = ByteReader;
|
|
551
618
|
exports.ByteWriter = ByteWriter;
|
|
552
619
|
exports.MAX_INFLATE_OUTPUT_BYTES = MAX_INFLATE_OUTPUT_BYTES;
|
|
620
|
+
exports.PNG_MAX_DIMENSION = PNG_MAX_DIMENSION;
|
|
621
|
+
exports.PNG_MAX_PIXELS = PNG_MAX_PIXELS;
|
|
553
622
|
exports.concatBytes = concatBytes;
|
|
554
623
|
exports.crc32 = crc32;
|
|
555
624
|
exports.decodePng = decodePng;
|
package/dist/index.d.cts
CHANGED
|
@@ -57,6 +57,8 @@ interface PngDecodeOptions {
|
|
|
57
57
|
declare function decodePng(bytes: Uint8Array<ArrayBuffer>, options?: PngDecodeOptions): RawImage;
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/image/png-encode.d.ts
|
|
60
|
+
declare const PNG_MAX_DIMENSION = 2147483647;
|
|
61
|
+
declare const PNG_MAX_PIXELS = 100000000;
|
|
60
62
|
interface PngEncodeOptions {
|
|
61
63
|
readonly filter?: "none" | "adaptive";
|
|
62
64
|
}
|
|
@@ -78,4 +80,4 @@ interface JpegInfo {
|
|
|
78
80
|
}
|
|
79
81
|
declare function readJpegInfo(bytes: Uint8Array<ArrayBuffer>): JpegInfo;
|
|
80
82
|
//#endregion
|
|
81
|
-
export { ByteReader, ByteWriter, DeflateLevel, InflateResult, JpegInfo, MAX_INFLATE_OUTPUT_BYTES, PngDecodeOptions, PngEncodeOptions, PngFilterType, RawImage, concatBytes, crc32, decodePng, deflate, encodePng, filterScanlines, inflate, inflateTolerant, isAsciiWhitespace, readJpegInfo, unfilterScanlines };
|
|
83
|
+
export { ByteReader, ByteWriter, DeflateLevel, InflateResult, JpegInfo, MAX_INFLATE_OUTPUT_BYTES, PNG_MAX_DIMENSION, PNG_MAX_PIXELS, PngDecodeOptions, PngEncodeOptions, PngFilterType, RawImage, concatBytes, crc32, decodePng, deflate, encodePng, filterScanlines, inflate, inflateTolerant, isAsciiWhitespace, readJpegInfo, unfilterScanlines };
|
package/dist/index.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ interface PngDecodeOptions {
|
|
|
57
57
|
declare function decodePng(bytes: Uint8Array<ArrayBuffer>, options?: PngDecodeOptions): RawImage;
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/image/png-encode.d.ts
|
|
60
|
+
declare const PNG_MAX_DIMENSION = 2147483647;
|
|
61
|
+
declare const PNG_MAX_PIXELS = 100000000;
|
|
60
62
|
interface PngEncodeOptions {
|
|
61
63
|
readonly filter?: "none" | "adaptive";
|
|
62
64
|
}
|
|
@@ -78,4 +80,4 @@ interface JpegInfo {
|
|
|
78
80
|
}
|
|
79
81
|
declare function readJpegInfo(bytes: Uint8Array<ArrayBuffer>): JpegInfo;
|
|
80
82
|
//#endregion
|
|
81
|
-
export { ByteReader, ByteWriter, DeflateLevel, InflateResult, JpegInfo, MAX_INFLATE_OUTPUT_BYTES, PngDecodeOptions, PngEncodeOptions, PngFilterType, RawImage, concatBytes, crc32, decodePng, deflate, encodePng, filterScanlines, inflate, inflateTolerant, isAsciiWhitespace, readJpegInfo, unfilterScanlines };
|
|
83
|
+
export { ByteReader, ByteWriter, DeflateLevel, InflateResult, JpegInfo, MAX_INFLATE_OUTPUT_BYTES, PNG_MAX_DIMENSION, PNG_MAX_PIXELS, PngDecodeOptions, PngEncodeOptions, PngFilterType, RawImage, concatBytes, crc32, decodePng, deflate, encodePng, filterScanlines, inflate, inflateTolerant, isAsciiWhitespace, readJpegInfo, unfilterScanlines };
|
package/dist/index.js
CHANGED
|
@@ -257,6 +257,9 @@ const PNG_SIGNATURE$1 = new Uint8Array([
|
|
|
257
257
|
26,
|
|
258
258
|
10
|
|
259
259
|
]);
|
|
260
|
+
const MAX_PALETTE_ENTRIES = 256;
|
|
261
|
+
const PNG_MAX_DIMENSION = 2147483647;
|
|
262
|
+
const PNG_MAX_PIXELS = 1e8;
|
|
260
263
|
function u32be(value) {
|
|
261
264
|
const bytes = /* @__PURE__ */ new Uint8Array(4);
|
|
262
265
|
new DataView(bytes.buffer).setUint32(0, value);
|
|
@@ -269,11 +272,73 @@ function writeChunk(writer, type, data) {
|
|
|
269
272
|
writer.writeBytes(data);
|
|
270
273
|
writer.writeBytes(u32be(crc32(concatBytes([typeBytes, data]))));
|
|
271
274
|
}
|
|
275
|
+
function writeIhdr(writer, width, height, colorType) {
|
|
276
|
+
const ihdr = /* @__PURE__ */ new Uint8Array(13);
|
|
277
|
+
const ihdrView = new DataView(ihdr.buffer);
|
|
278
|
+
ihdrView.setUint32(0, width);
|
|
279
|
+
ihdrView.setUint32(4, height);
|
|
280
|
+
ihdr[8] = 8;
|
|
281
|
+
ihdr[9] = colorType;
|
|
282
|
+
ihdr[10] = 0;
|
|
283
|
+
ihdr[11] = 0;
|
|
284
|
+
ihdr[12] = 0;
|
|
285
|
+
writeChunk(writer, "IHDR", ihdr);
|
|
286
|
+
}
|
|
272
287
|
function colorTypeFor(image) {
|
|
273
288
|
if (image.channels === 1) return image.alpha === void 0 ? 0 : 4;
|
|
274
289
|
return image.alpha === void 0 ? 2 : 6;
|
|
275
290
|
}
|
|
276
|
-
function
|
|
291
|
+
function detectPalette(image) {
|
|
292
|
+
const { width, height, data, alpha } = image;
|
|
293
|
+
const pixelCount = width * height;
|
|
294
|
+
const colorToIndex = /* @__PURE__ */ new Map();
|
|
295
|
+
const indices = new Uint8Array(pixelCount);
|
|
296
|
+
const paletteRgb = [];
|
|
297
|
+
const paletteAlpha = [];
|
|
298
|
+
for (let i = 0; i < pixelCount; i++) {
|
|
299
|
+
const base = i * 3;
|
|
300
|
+
const r = data[base] ?? 0;
|
|
301
|
+
const g = data[base + 1] ?? 0;
|
|
302
|
+
const b = data[base + 2] ?? 0;
|
|
303
|
+
const a = alpha === void 0 ? 255 : alpha[i] ?? 0;
|
|
304
|
+
const key = r + g * 256 + b * 65536 + a * 16777216;
|
|
305
|
+
let index = colorToIndex.get(key);
|
|
306
|
+
if (index === void 0) {
|
|
307
|
+
if (colorToIndex.size >= MAX_PALETTE_ENTRIES) return;
|
|
308
|
+
index = colorToIndex.size;
|
|
309
|
+
colorToIndex.set(key, index);
|
|
310
|
+
paletteRgb.push(r, g, b);
|
|
311
|
+
paletteAlpha.push(a);
|
|
312
|
+
}
|
|
313
|
+
indices[i] = index;
|
|
314
|
+
}
|
|
315
|
+
const palette = Uint8Array.from(paletteRgb);
|
|
316
|
+
if (alpha === void 0) return {
|
|
317
|
+
indices,
|
|
318
|
+
palette
|
|
319
|
+
};
|
|
320
|
+
let trnsLength = paletteAlpha.length;
|
|
321
|
+
while (trnsLength > 1 && paletteAlpha[trnsLength - 1] === 255) trnsLength--;
|
|
322
|
+
return {
|
|
323
|
+
indices,
|
|
324
|
+
palette,
|
|
325
|
+
trns: Uint8Array.from(paletteAlpha.slice(0, trnsLength))
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function buildPng(writeBody) {
|
|
329
|
+
const writer = new ByteWriter();
|
|
330
|
+
writer.writeBytes(PNG_SIGNATURE$1);
|
|
331
|
+
writeBody(writer);
|
|
332
|
+
writeChunk(writer, "IEND", /* @__PURE__ */ new Uint8Array(0));
|
|
333
|
+
return writer.toBytes();
|
|
334
|
+
}
|
|
335
|
+
function writeIndexedPng(writer, width, height, encoding, options) {
|
|
336
|
+
writeIhdr(writer, width, height, 3);
|
|
337
|
+
writeChunk(writer, "PLTE", encoding.palette);
|
|
338
|
+
if (encoding.trns !== void 0) writeChunk(writer, "tRNS", encoding.trns);
|
|
339
|
+
writeChunk(writer, "IDAT", deflate(filterScanlines(encoding.indices, height, width, 1, options.filter ?? "adaptive")));
|
|
340
|
+
}
|
|
341
|
+
function writeTruecolorPng(writer, image, options) {
|
|
277
342
|
const { width, height, channels, data, alpha } = image;
|
|
278
343
|
const outChannels = alpha === void 0 ? channels : channels + 1;
|
|
279
344
|
const bytesPerRow = width * outChannels;
|
|
@@ -285,22 +350,24 @@ function encodePng(image, options = {}) {
|
|
|
285
350
|
for (let c = 0; c < channels; c++) interleaved[dstBase + c] = data[srcBase + c];
|
|
286
351
|
if (alpha !== void 0) interleaved[dstBase + channels] = alpha[i];
|
|
287
352
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
writer
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
353
|
+
writeIhdr(writer, width, height, colorTypeFor(image));
|
|
354
|
+
writeChunk(writer, "IDAT", deflate(filterScanlines(interleaved, height, bytesPerRow, outChannels, options.filter ?? "adaptive")));
|
|
355
|
+
}
|
|
356
|
+
function encodePng(image, options = {}) {
|
|
357
|
+
if (!Number.isInteger(image.width) || image.width <= 0 || image.width > 2147483647 || !Number.isInteger(image.height) || image.height <= 0 || image.height > 2147483647) throw new Error(`cannot encode a PNG with an invalid dimension (width=${image.width}, height=${image.height}); the PNG spec's IHDR section requires both width and height to be positive integers no greater than ${PNG_MAX_DIMENSION}`);
|
|
358
|
+
const pixelCount = image.width * image.height;
|
|
359
|
+
if (pixelCount > 1e8) throw new Error(`cannot encode a PNG with ${pixelCount} pixels (width=${image.width}, height=${image.height}); each dimension is individually within the PNG spec's own limit, but this encoder bounds their product to ${PNG_MAX_PIXELS} to avoid an unbounded per-pixel scan and allocation`);
|
|
360
|
+
const paletteEncoding = image.channels === 3 ? detectPalette(image) : void 0;
|
|
361
|
+
if (paletteEncoding === void 0) return buildPng((writer) => {
|
|
362
|
+
writeTruecolorPng(writer, image, options);
|
|
363
|
+
});
|
|
364
|
+
const indexed = buildPng((writer) => {
|
|
365
|
+
writeIndexedPng(writer, image.width, image.height, paletteEncoding, options);
|
|
366
|
+
});
|
|
367
|
+
const truecolor = buildPng((writer) => {
|
|
368
|
+
writeTruecolorPng(writer, image, options);
|
|
369
|
+
});
|
|
370
|
+
return indexed.length <= truecolor.length ? indexed : truecolor;
|
|
304
371
|
}
|
|
305
372
|
//#endregion
|
|
306
373
|
//#region src/image/png-decode.ts
|
|
@@ -546,4 +613,4 @@ function readJpegInfo(bytes) {
|
|
|
546
613
|
throw new Error("no SOF marker found in JPEG file");
|
|
547
614
|
}
|
|
548
615
|
//#endregion
|
|
549
|
-
export { ByteReader, ByteWriter, MAX_INFLATE_OUTPUT_BYTES, concatBytes, crc32, decodePng, deflate, encodePng, filterScanlines, inflate, inflateTolerant, isAsciiWhitespace, readJpegInfo, unfilterScanlines };
|
|
616
|
+
export { ByteReader, ByteWriter, MAX_INFLATE_OUTPUT_BYTES, PNG_MAX_DIMENSION, PNG_MAX_PIXELS, concatBytes, crc32, decodePng, deflate, encodePng, filterScanlines, inflate, inflateTolerant, isAsciiWhitespace, readJpegInfo, unfilterScanlines };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "byte-codec",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Generic byte-level primitives (ByteWriter, ByteReader, CRC-32, deflate/inflate) and PNG/JPEG image encoding/decoding with zero PDF knowledge — the shared utility package for the documents.js family.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -59,6 +59,8 @@
|
|
|
59
59
|
"test": "turbo run _test",
|
|
60
60
|
"_test": "vitest run",
|
|
61
61
|
"_test:coverage": "vitest run --coverage",
|
|
62
|
+
"test:mutation": "turbo run _test:mutation",
|
|
63
|
+
"_test:mutation": "stryker run stryker.config.mjs",
|
|
62
64
|
"test:watch": "vitest",
|
|
63
65
|
"test:workers": "turbo run _test:workers",
|
|
64
66
|
"_test:workers": "vitest run --config vitest.workers.config.ts",
|
|
@@ -71,9 +73,13 @@
|
|
|
71
73
|
"devDependencies": {
|
|
72
74
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
73
75
|
"@cloudflare/vitest-pool-workers": "^0.20.1",
|
|
76
|
+
"@stryker-mutator/core": "^10.0.0",
|
|
77
|
+
"@stryker-mutator/typescript-checker": "^10.0.0",
|
|
78
|
+
"@stryker-mutator/vitest-runner": "^10.0.0",
|
|
74
79
|
"@types/node": "^26.1.2",
|
|
75
80
|
"eslint": "^10.8.0",
|
|
76
81
|
"husky": "^9.1.7",
|
|
82
|
+
"jiti": "2.7.0",
|
|
77
83
|
"publint": "^0.3.21",
|
|
78
84
|
"tsdown": "^0.22.13",
|
|
79
85
|
"turbo": "^2.10.8",
|