@poe-platform/safe-bash 0.1.845 → 0.1.846
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-ast/ast.d.ts +12 -2
- package/dist/image-ast/browser/ast.d.ts +12 -2
- package/dist/image-ast/browser/codecs/exif-metadata.d.ts +2 -0
- package/dist/image-ast/browser/codecs/exif.d.ts +2 -0
- package/dist/image-ast/browser/codecs/gif-metadata-storage.d.ts +1 -0
- package/dist/image-ast/browser/codecs/gif-metadata.d.ts +1 -0
- package/dist/image-ast/browser/codecs/gif-output-parts.d.ts +1 -1
- package/dist/image-ast/browser/codecs/jpeg.d.ts +1 -1
- package/dist/image-ast/browser/codecs/netpbm-storage.d.ts +2 -2
- package/dist/image-ast/browser/codecs/netpbm.d.ts +4 -4
- package/dist/image-ast/browser/codecs/png-storage.d.ts +9 -1
- package/dist/image-ast/browser/codecs/png.d.ts +1 -0
- package/dist/image-ast/browser/codecs/tiff-layout.d.ts +3 -2
- package/dist/image-ast/codecs/exif-metadata.d.ts +2 -0
- package/dist/image-ast/codecs/exif.d.ts +2 -0
- package/dist/image-ast/codecs/gif-metadata-storage.d.ts +1 -0
- package/dist/image-ast/codecs/gif-metadata.d.ts +1 -0
- package/dist/image-ast/codecs/gif-output-parts.d.ts +1 -1
- package/dist/image-ast/codecs/jpeg.d.ts +1 -1
- package/dist/image-ast/codecs/netpbm-storage.d.ts +2 -2
- package/dist/image-ast/codecs/netpbm.d.ts +4 -4
- package/dist/image-ast/codecs/png-storage.d.ts +9 -1
- package/dist/image-ast/codecs/png.d.ts +1 -0
- package/dist/image-ast/codecs/tiff-layout.d.ts +3 -2
- package/dist/image-ast/index.js +554 -163
- package/dist/mp4-ast/types.d.ts +2 -0
- package/dist/safe-bash/command-chunks/{chunk-CMGVQM4Y.js → chunk-CSJHADNR.js} +17 -3
- package/dist/safe-bash/command-chunks/{chunk-KSCVKF7I.js → chunk-F42YLXD4.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-2EEIB5O3.js → chunk-HUE2ATJY.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-4KM2VJRB.js → chunk-NBQWCUOP.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-U5TQVW64.js → chunk-ZTEK2JJD.js} +1 -1
- package/dist/safe-bash-command-ffmpeg/index.js +433 -74
- package/dist/safe-bash-command-ffprobe/index.js +2 -2
- package/dist/safe-bash-command-ffprobe/media.js +2 -2
- package/dist/safe-bash-command-imagemagick/compare-file.d.ts +3 -2
- package/dist/safe-bash-command-imagemagick/index.js +835 -247
- package/dist/safe-bash-command-imagemagick/raw-output.d.ts +10 -0
- package/dist/safe-bash-command-python/executor.js +3 -3
- package/dist/safe-bash-command-python/index.js +3 -3
- package/dist/safe-bash-command-python/jspi.js +2 -2
- package/dist/safe-bash-command-python/worker.js +1 -1
- package/package.json +2 -2
package/dist/image-ast/index.js
CHANGED
|
@@ -1301,6 +1301,18 @@ function canvasChunk(canvas) {
|
|
|
1301
1301
|
let bytes = new Uint8Array(16), view = new DataView(bytes.buffer);
|
|
1302
1302
|
return view.setUint32(0, canvas.width), view.setUint32(4, canvas.height), view.setInt32(8, canvas.x), view.setInt32(12, canvas.y), makeChunk("caNv", bytes);
|
|
1303
1303
|
}
|
|
1304
|
+
function* textChunks(properties) {
|
|
1305
|
+
for (let [key, value] of Object.entries(properties ?? {})) {
|
|
1306
|
+
let keyword = Uint8Array.from(key, (char) => char.charCodeAt(0));
|
|
1307
|
+
if (!key.length || key.length > 79 || [...key].some((char) => char.charCodeAt(0) > 255 || char === "\0")) continue;
|
|
1308
|
+
let text = new TextEncoder().encode(value), payload = new Uint8Array(keyword.length + 5 + text.length);
|
|
1309
|
+
payload.set(keyword), payload.set(text, keyword.length + 5), yield makeChunk("iTXt", payload);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
function iccChunk(icc) {
|
|
1313
|
+
let compressed = transformBytes(icc, { direction: "encode", format: "zlib" }), payload = new Uint8Array(5 + compressed.length);
|
|
1314
|
+
return payload.set([73, 67, 67, 0, 0]), payload.set(compressed, 5), makeChunk("iCCP", payload);
|
|
1315
|
+
}
|
|
1304
1316
|
|
|
1305
1317
|
// src/codecs/exif-metadata.ts
|
|
1306
1318
|
function* exifMetadataSteps(size, base = 0) {
|
|
@@ -1316,7 +1328,7 @@ function* exifMetadataSteps(size, base = 0) {
|
|
|
1316
1328
|
if (view.getUint16(2, little) !== 42) return {};
|
|
1317
1329
|
let ifd = view.getUint32(4, little), length = size - offset, start = base + offset;
|
|
1318
1330
|
if (ifd + 2 > length) return {};
|
|
1319
|
-
let countBytes = yield { position: start + ifd, length: 2 }, count = new DataView(countBytes.buffer, countBytes.byteOffset, countBytes.byteLength).getUint16(0, little), orientation, xRes, unit = 2;
|
|
1331
|
+
let countBytes = yield { position: start + ifd, length: 2 }, count = new DataView(countBytes.buffer, countBytes.byteOffset, countBytes.byteLength).getUint16(0, little), orientation, xRes, yRes, unit = 2;
|
|
1320
1332
|
for (let i = 0; i < count; i++) {
|
|
1321
1333
|
let position = ifd + 2 + i * 12;
|
|
1322
1334
|
if (position + 12 > length) break;
|
|
@@ -1326,14 +1338,17 @@ function* exifMetadataSteps(size, base = 0) {
|
|
|
1326
1338
|
value >= 1 && value <= 8 && (orientation = value);
|
|
1327
1339
|
} else if (tag === 296) {
|
|
1328
1340
|
let value = type === 3 ? entry.getUint16(8, little) : valueOffset;
|
|
1329
|
-
(value === 2 || value === 3) && (unit = value);
|
|
1330
|
-
} else if (tag === 282 && type === 5 && valueOffset + 8 <= length) {
|
|
1341
|
+
(value === 1 || value === 2 || value === 3) && (unit = value);
|
|
1342
|
+
} else if ((tag === 282 || tag === 283) && type === 5 && valueOffset + 8 <= length) {
|
|
1331
1343
|
let bytes2 = yield { position: start + valueOffset, length: 8 }, ratio = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength), den = ratio.getUint32(4, little);
|
|
1332
|
-
den > 0
|
|
1344
|
+
if (den > 0) {
|
|
1345
|
+
let value = ratio.getUint32(0, little) / den;
|
|
1346
|
+
tag === 282 ? xRes = value : yRes = value;
|
|
1347
|
+
}
|
|
1333
1348
|
}
|
|
1334
1349
|
}
|
|
1335
1350
|
let density = xRes !== void 0 && xRes > 0 ? Math.round(xRes * (unit === 3 ? 2.54 : 1)) : void 0;
|
|
1336
|
-
return { ...orientation === void 0 ? {} : { orientation }, ...density === void 0 ? {} : { density } };
|
|
1351
|
+
return { ...xRes !== void 0 && yRes !== void 0 ? { resolution: { x: xRes, y: yRes, unit: unit === 3 ? "cm" : unit === 1 ? "unknown" : "inch" } } : {}, ...orientation === void 0 ? {} : { orientation }, ...density === void 0 ? {} : { density } };
|
|
1337
1352
|
}
|
|
1338
1353
|
|
|
1339
1354
|
// src/codecs/png-metadata.ts
|
|
@@ -1341,13 +1356,68 @@ function* pngMetadataSteps(size) {
|
|
|
1341
1356
|
let signature = size >= 8 ? yield { position: 0, length: 8 } : new Uint8Array();
|
|
1342
1357
|
if (size < 24 || !PNG_SIGNATURE.every((byte2, index) => signature[index] === byte2))
|
|
1343
1358
|
throw new Error("Invalid PNG header");
|
|
1344
|
-
let width = 0, height = 0, bitDepth = 8, colorType = 6, interlace = 0, density = 72, resolution, hasTrns = !1, virtualCanvas, orientation, backgroundColor, palette, pos = 8;
|
|
1359
|
+
let width = 0, height = 0, bitDepth = 8, colorType = 6, interlace = 0, density = 72, resolution, hasTrns = !1, virtualCanvas, properties = /* @__PURE__ */ Object.create(null), icc, orientation, backgroundColor, palette, pos = 8;
|
|
1345
1360
|
for (; pos + 8 <= size; ) {
|
|
1346
1361
|
let header = yield { position: pos, length: 8 }, len = new DataView(header.buffer, header.byteOffset, header.byteLength).getUint32(0, !1), type = String.fromCharCode(header[4], header[5], header[6], header[7]), dataStart = pos + 8;
|
|
1347
1362
|
if (dataStart + len > size) break;
|
|
1348
1363
|
if (type === "IHDR" && len >= 13) {
|
|
1349
1364
|
let chunk = yield { position: dataStart, length: 13 }, view = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
1350
1365
|
width = view.getUint32(0, !1), height = view.getUint32(4, !1), bitDepth = chunk[8], colorType = chunk[9], interlace = chunk[12];
|
|
1366
|
+
} else if (type === "tEXt" || type === "zTXt" || type === "iTXt") {
|
|
1367
|
+
if (len > 16 * 1024 * 1024) throw new Error("PNG text exceeds 16 MiB");
|
|
1368
|
+
let end = (yield { position: dataStart, length: Math.min(len, 80) }).indexOf(0);
|
|
1369
|
+
if (end < 1 || end > 79) {
|
|
1370
|
+
pos = dataStart + len + 4;
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
let chunk = yield { position: dataStart, length: len }, start = end + 1, compressed = type === "zTXt";
|
|
1374
|
+
if (type === "zTXt") {
|
|
1375
|
+
if (chunk[start++] !== 0) throw new Error("Invalid PNG text compression");
|
|
1376
|
+
} else if (type === "iTXt") {
|
|
1377
|
+
let flag = chunk[start++];
|
|
1378
|
+
if (flag !== 0 && flag !== 1 || chunk[start++] !== 0) throw new Error("Invalid PNG text compression");
|
|
1379
|
+
compressed = flag === 1;
|
|
1380
|
+
for (let field = 0; field < 2; field++) {
|
|
1381
|
+
let zero = chunk.indexOf(0, start);
|
|
1382
|
+
if (zero < 0) throw new Error("Invalid PNG international text");
|
|
1383
|
+
start = zero + 1;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
let value = chunk.subarray(start);
|
|
1387
|
+
if (compressed) {
|
|
1388
|
+
let codec = createByteCodec({ direction: "decode", format: "zlib" }), parts = [], length = 0;
|
|
1389
|
+
try {
|
|
1390
|
+
for (let part of codec.push(value, !0)) {
|
|
1391
|
+
if (length += part.length, length > 16 * 1024 * 1024) throw new Error("PNG text exceeds 16 MiB");
|
|
1392
|
+
parts.push(part);
|
|
1393
|
+
}
|
|
1394
|
+
} finally {
|
|
1395
|
+
codec.close();
|
|
1396
|
+
}
|
|
1397
|
+
value = new Uint8Array(length);
|
|
1398
|
+
let offset = 0;
|
|
1399
|
+
for (let part of parts)
|
|
1400
|
+
value.set(part, offset), offset += part.length;
|
|
1401
|
+
}
|
|
1402
|
+
let latin1 = (bytes) => Array.from(bytes, (byte2) => String.fromCharCode(byte2)).join("");
|
|
1403
|
+
properties[latin1(chunk.subarray(0, end))] = type === "iTXt" ? new TextDecoder().decode(value) : latin1(value);
|
|
1404
|
+
} else if (type === "iCCP") {
|
|
1405
|
+
if (len > 16 * 1024 * 1024) throw new Error("ICC profile exceeds 16 MiB");
|
|
1406
|
+
let chunk = yield { position: dataStart, length: len }, end = chunk.indexOf(0);
|
|
1407
|
+
if (end < 1 || end > 79 || chunk[end + 1] !== 0) throw new Error("Invalid PNG ICC profile");
|
|
1408
|
+
let codec = createByteCodec({ direction: "decode", format: "zlib" }), parts = [], length = 0;
|
|
1409
|
+
try {
|
|
1410
|
+
for (let part of codec.push(chunk.subarray(end + 2), !0)) {
|
|
1411
|
+
if (length += part.length, length > 16 * 1024 * 1024) throw new Error("ICC profile exceeds 16 MiB");
|
|
1412
|
+
parts.push(part);
|
|
1413
|
+
}
|
|
1414
|
+
} finally {
|
|
1415
|
+
codec.close();
|
|
1416
|
+
}
|
|
1417
|
+
icc = new Uint8Array(length);
|
|
1418
|
+
let offset = 0;
|
|
1419
|
+
for (let part of parts)
|
|
1420
|
+
icc.set(part, offset), offset += part.length;
|
|
1351
1421
|
} else if (type === "PLTE" && len <= 768)
|
|
1352
1422
|
palette = yield { position: dataStart, length: len };
|
|
1353
1423
|
else if (type === "bKGD") {
|
|
@@ -1370,15 +1440,20 @@ function* pngMetadataSteps(size) {
|
|
|
1370
1440
|
virtualCanvas = { width: view.getUint32(0), height: view.getUint32(4), x: view.getInt32(8), y: view.getInt32(12) };
|
|
1371
1441
|
} else if (type === "tRNS")
|
|
1372
1442
|
hasTrns = !0;
|
|
1373
|
-
else if (type === "
|
|
1443
|
+
else if (type === "orNT" && len === 1) {
|
|
1444
|
+
let chunk = yield { position: dataStart, length: 1 };
|
|
1445
|
+
chunk[0] <= 8 && (orientation = chunk[0]);
|
|
1446
|
+
} else if (type === "eXIf" && len >= 8) {
|
|
1374
1447
|
let exif = yield* exifMetadataSteps(len, dataStart);
|
|
1375
|
-
exif.orientation !== void 0 && (orientation = exif.orientation), exif.density !== void 0 && (density = exif.density);
|
|
1448
|
+
exif.orientation !== void 0 && (orientation = exif.orientation), exif.density !== void 0 && (density = exif.density), resolution ??= exif.resolution;
|
|
1376
1449
|
} else if ((type === "IDAT" || type === "IEND") && type === "IEND")
|
|
1377
1450
|
break;
|
|
1378
1451
|
pos = dataStart + len + 4;
|
|
1379
1452
|
}
|
|
1380
1453
|
let channels = colorType === 6 ? 4 : colorType === 4 ? 2 : colorType === 2 || colorType === 3 ? hasTrns ? 4 : 3 : hasTrns ? 2 : 1, hasAlpha = colorType === 6 || colorType === 4 || hasTrns, space = colorType === 0 || colorType === 4 ? bitDepth === 16 ? "grey16" : "b-w" : bitDepth === 16 ? "rgb16" : "srgb", depth = bitDepth === 16 ? "ushort" : bitDepth < 8 ? "bit" : "uchar";
|
|
1381
1454
|
return {
|
|
1455
|
+
...Object.keys(properties).length ? { properties } : {},
|
|
1456
|
+
...icc === void 0 ? {} : { icc },
|
|
1382
1457
|
format: "png",
|
|
1383
1458
|
...colorType === 3 ? { isPalette: !0 } : {},
|
|
1384
1459
|
width,
|
|
@@ -1460,7 +1535,7 @@ function parseExifBuffer(raw) {
|
|
|
1460
1535
|
return next.value;
|
|
1461
1536
|
}
|
|
1462
1537
|
function buildExifApp1Segment(options) {
|
|
1463
|
-
let orientation = options.orientation ?? 1, density = Math.max(1, Math.round(options.density ?? 72)), payload = new Uint8Array(84), view = new DataView(payload.buffer);
|
|
1538
|
+
let orientation = options.orientation ?? 1, density = Math.max(1, Math.round(options.density ?? 72)), resolution = options.resolution, scale = resolution?.unit === "meter" ? 100 : 1, x = resolution ? resolution.x / scale : density, y = resolution ? resolution.y / scale : density, denominator = Number.isInteger(x) && Number.isInteger(y) ? 1 : 1e4, payload = new Uint8Array(84), view = new DataView(payload.buffer);
|
|
1464
1539
|
payload[0] = 69, payload[1] = 120, payload[2] = 105, payload[3] = 102, payload[4] = 0, payload[5] = 0;
|
|
1465
1540
|
let tiff = 6;
|
|
1466
1541
|
payload[tiff] = 73, payload[tiff + 1] = 73, view.setUint16(tiff + 2, 42, !0), view.setUint32(tiff + 4, 8, !0);
|
|
@@ -1470,7 +1545,7 @@ function buildExifApp1Segment(options) {
|
|
|
1470
1545
|
let p = ifd + 2 + idx * 12;
|
|
1471
1546
|
view.setUint16(p, tag, !0), view.setUint16(p + 2, type, !0), view.setUint32(p + 4, count, !0), type === 3 && count === 1 ? (view.setUint16(p + 8, valueOrOffset, !0), view.setUint16(p + 10, 0, !0)) : view.setUint32(p + 8, valueOrOffset, !0);
|
|
1472
1547
|
}, ratOffsetX = 62, ratOffsetY = ratOffsetX + 8;
|
|
1473
|
-
return writeEntry(0, 274, 3, 1, orientation), writeEntry(1, 282, 5, 1, ratOffsetX), writeEntry(2, 283, 5, 1, ratOffsetY), writeEntry(3, 296, 3, 1, 2), view.setUint32(ifd + 2 + 48, 0, !0), view.setUint32(tiff + ratOffsetX,
|
|
1548
|
+
return writeEntry(0, 274, 3, 1, orientation), writeEntry(1, 282, 5, 1, ratOffsetX), writeEntry(2, 283, 5, 1, ratOffsetY), writeEntry(3, 296, 3, 1, resolution?.unit === "meter" || resolution?.unit === "cm" ? 3 : resolution?.unit === "unknown" ? 1 : 2), view.setUint32(ifd + 2 + 48, 0, !0), view.setUint32(tiff + ratOffsetX, Math.round(x * denominator), !0), view.setUint32(tiff + ratOffsetX + 4, denominator, !0), view.setUint32(tiff + ratOffsetY, Math.round(y * denominator), !0), view.setUint32(tiff + ratOffsetY + 4, denominator, !0), payload;
|
|
1474
1549
|
}
|
|
1475
1550
|
|
|
1476
1551
|
// src/codecs/png.ts
|
|
@@ -1609,14 +1684,17 @@ function decodePngImage(bytes) {
|
|
|
1609
1684
|
...meta.bitsPerSample === void 0 ? {} : { bitsPerSample: meta.bitsPerSample },
|
|
1610
1685
|
...meta.backgroundColor === void 0 ? {} : { backgroundColor: meta.backgroundColor },
|
|
1611
1686
|
density: meta.density,
|
|
1687
|
+
...meta.resolution ? { resolution: meta.resolution } : {},
|
|
1612
1688
|
hasAlpha: meta.hasAlpha,
|
|
1613
1689
|
...meta.virtualCanvas === void 0 ? {} : { virtualCanvas: meta.virtualCanvas },
|
|
1690
|
+
...meta.properties === void 0 ? {} : { properties: meta.properties },
|
|
1691
|
+
...meta.icc === void 0 ? {} : { icc: meta.icc },
|
|
1614
1692
|
...meta.orientation !== void 0 ? { orientation: meta.orientation } : {},
|
|
1615
1693
|
...meta.isProgressive !== void 0 ? { isProgressive: meta.isProgressive } : {}
|
|
1616
1694
|
};
|
|
1617
1695
|
}
|
|
1618
1696
|
function encodePngImage(img, options) {
|
|
1619
|
-
let { width, height, data, data16 } = img, density = options?.density ?? img.density ?? 72, hasAlpha = !!(img.hasAlpha || img.channels === 4 || img.channels === 2);
|
|
1697
|
+
let { width, height, data, data16 } = img, density = options?.density ?? img.density ?? 72, resolution = options?.density === void 0 ? img.resolution : void 0, scale = resolution?.unit === "inch" ? 1 / 0.0254 : resolution?.unit === "cm" ? 100 : 1, hasAlpha = !!(img.hasAlpha || img.channels === 4 || img.channels === 2);
|
|
1620
1698
|
if (options?.forceOpaque)
|
|
1621
1699
|
hasAlpha = !1;
|
|
1622
1700
|
else if (!hasAlpha) {
|
|
@@ -1676,12 +1754,14 @@ function encodePngImage(img, options) {
|
|
|
1676
1754
|
let ihdr = new Uint8Array(13), ihdrView = new DataView(ihdr.buffer);
|
|
1677
1755
|
ihdrView.setUint32(0, width, !1), ihdrView.setUint32(4, height, !1), ihdr[8] = data16 ? 16 : 8, ihdr[9] = colorType, ihdr[10] = 0, ihdr[11] = 0, ihdr[12] = 0;
|
|
1678
1756
|
let phys = new Uint8Array(9), physView = new DataView(phys.buffer), ppu = Math.round(density / 0.0254);
|
|
1679
|
-
physView.setUint32(0, ppu, !1), physView.setUint32(4, ppu, !1), phys[8] = 1;
|
|
1680
|
-
let orientation = options?.orientation ?? img.orientation, exifChunk = orientation !== void 0 ? [makeChunk("eXIf", buildExifApp1Segment({ orientation, density }).subarray(6))] : [], chunks2 = [
|
|
1757
|
+
physView.setUint32(0, resolution ? Math.round(resolution.x * scale) : ppu, !1), physView.setUint32(4, resolution ? Math.round(resolution.y * scale) : ppu, !1), phys[8] = resolution?.unit === "unknown" ? 0 : 1;
|
|
1758
|
+
let orientation = options?.orientation ?? img.orientation, exifChunk = orientation !== void 0 ? [makeChunk("eXIf", buildExifApp1Segment({ orientation, density, resolution }).subarray(6))] : [], chunks2 = [
|
|
1681
1759
|
PNG_SIGNATURE,
|
|
1682
1760
|
makeChunk("IHDR", ihdr),
|
|
1683
|
-
makeChunk("pHYs", phys),
|
|
1761
|
+
...!options?.omitPngResolution && (resolution !== void 0 || options?.density !== void 0) ? [makeChunk("pHYs", phys)] : [],
|
|
1684
1762
|
...exifChunk,
|
|
1763
|
+
...textChunks(img.properties),
|
|
1764
|
+
...img.icc ? [iccChunk(img.icc)] : [],
|
|
1685
1765
|
...img.virtualCanvas === void 0 ? [] : [canvasChunk(img.virtualCanvas)],
|
|
1686
1766
|
makeChunk("IDAT", compressed),
|
|
1687
1767
|
makeChunk("IEND", new Uint8Array(0))
|
|
@@ -1980,7 +2060,7 @@ async function tryPdfDecode(source, storage, fs, directory, signal, options = {}
|
|
|
1980
2060
|
await storage.write(position + written, bytes, { signal }), signal.throwIfAborted(), written += bytes.length;
|
|
1981
2061
|
}
|
|
1982
2062
|
if (written !== length) throw new Error("Truncated PDF raster pixels");
|
|
1983
|
-
return { format: "pdf", width, height, space: "srgb", channels: 4, depth: "uchar", density: settings.density ?? 72, hasAlpha: !0, isProgressive: !1, pages: owner.metadata.pages, position };
|
|
2063
|
+
return { format: "pdf", width, height, space: "srgb", channels: 4, depth: "uchar", density: settings.density ?? 72, hasAlpha: !0, bitsPerSample: 8, isProgressive: !1, pages: owner.metadata.pages, position };
|
|
1984
2064
|
} catch (error) {
|
|
1985
2065
|
throw failed = !0, error;
|
|
1986
2066
|
} finally {
|
|
@@ -1995,21 +2075,63 @@ function imageOutputFormat(input, requested) {
|
|
|
1995
2075
|
return requested === "svg" ? "png" : requested ?? (input === "svg" || input === "pdf" ? "png" : input);
|
|
1996
2076
|
}
|
|
1997
2077
|
|
|
2078
|
+
// src/codecs/miff.ts
|
|
2079
|
+
function miffHeader(image) {
|
|
2080
|
+
let { width, height } = image;
|
|
2081
|
+
if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0 || !Number.isSafeInteger(width * height * 4)) throw new RangeError("Invalid MIFF dimensions");
|
|
2082
|
+
return new TextEncoder().encode(`id=ImageMagick version=1.0
|
|
2083
|
+
class=DirectClass colors=0 matte=True
|
|
2084
|
+
columns=${width} rows=${height} depth=8
|
|
2085
|
+
colorspace=sRGB
|
|
2086
|
+
compression=None
|
|
2087
|
+
\f
|
|
2088
|
+
:`);
|
|
2089
|
+
}
|
|
2090
|
+
function encodeMiffImage(image) {
|
|
2091
|
+
let chunks2 = [], length = 0;
|
|
2092
|
+
for (let page of image.miffPages ?? [image]) {
|
|
2093
|
+
let header = miffHeader(page), size = page.width * page.height * 4;
|
|
2094
|
+
if (page.data.length !== size) throw new Error("Invalid MIFF pixels");
|
|
2095
|
+
chunks2.push(header, page.data), length += header.length + size;
|
|
2096
|
+
}
|
|
2097
|
+
let bytes = new Uint8Array(length), offset = 0;
|
|
2098
|
+
for (let chunk of chunks2)
|
|
2099
|
+
bytes.set(chunk, offset), offset += chunk.length;
|
|
2100
|
+
return bytes;
|
|
2101
|
+
}
|
|
2102
|
+
async function* encodeMiffFromStorage(image, storage, signal) {
|
|
2103
|
+
for (let index = 0; index < (image.storedMiffPages?.length ?? 1); index++) {
|
|
2104
|
+
signal.throwIfAborted();
|
|
2105
|
+
let page = image.storedMiffPages ? await image.storedMiffPages.at(index) : image;
|
|
2106
|
+
signal.throwIfAborted(), yield miffHeader(page);
|
|
2107
|
+
let length = page.width * page.height * 4;
|
|
2108
|
+
for (let offset = 0; offset < length; offset += 4096) {
|
|
2109
|
+
signal.throwIfAborted(), offset % 65536 === 0 && await defaultRuntime.yieldTurn(signal);
|
|
2110
|
+
let size = Math.min(4096, length - offset), bytes = await storage.read(page.position + offset, size, { signal });
|
|
2111
|
+
if (signal.throwIfAborted(), bytes.length !== size) throw new Error("Truncated MIFF backing storage");
|
|
2112
|
+
yield new Uint8Array(bytes);
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
1998
2117
|
// src/codecs/tiff-layout.ts
|
|
1999
2118
|
function tiffChannels(img) {
|
|
2000
2119
|
return img.space === "b-w" || img.space === "grey16" ? img.hasAlpha ? 2 : 1 : 4;
|
|
2001
2120
|
}
|
|
2002
|
-
function createTiffLayout(img, options) {
|
|
2003
|
-
let { width, height } = img, channels = tiffChannels(img), hasAlpha = channels !== 1, pixelBytes = width * height * channels, density = Math.max(1, Math.round(options?.density ?? img.density ?? 72)), orientation = options?.orientation ?? img.orientation ?? 1, padding = pixelBytes % 2,
|
|
2004
|
-
if (!Number.isSafeInteger(width) || width <= 0 || width > 4294967295 || !Number.isSafeInteger(height) || height <= 0 || height > 4294967295 || !Number.isSafeInteger(pixelBytes) || pixelBytes > 4294967295 || yResOffset + 8 > 4294967296)
|
|
2121
|
+
function createTiffLayout(img, options, offset = 0, hasNext = !1) {
|
|
2122
|
+
let { width, height } = img, channels = tiffChannels(img), hasAlpha = channels !== 1, pixelBytes = width * height * channels, density = Math.max(1, Math.round(options?.density ?? img.density ?? 72)), resolution = options?.density === void 0 ? img.resolution : void 0, scale = resolution?.unit === "meter" ? 100 : 1, x = resolution ? resolution.x / scale : density, y = resolution ? resolution.y / scale : density, denominator = Number.isInteger(x) && Number.isInteger(y) ? 1 : 1e4, orientation = options?.orientation ?? img.orientation ?? 1, padding = pixelBytes % 2, comment = img.properties?.comment === void 0 ? void 0 : new TextEncoder().encode(img.properties.comment + "\0"), commentSize = comment ? comment.length + comment.length % 2 : 0, numEntries = (hasAlpha ? 15 : 14) + (comment ? 1 : 0), directorySize = 2 + numEntries * 12 + 4 + 24 + commentSize, pixelOffset = offset === 0 ? 8 : offset + directorySize, ifdOffset = offset === 0 ? pixelOffset + pixelBytes + padding : offset, bpsOffset = ifdOffset + 2 + numEntries * 12 + 4, xResOffset = bpsOffset + 8, yResOffset = xResOffset + 8;
|
|
2123
|
+
if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(width) || width <= 0 || width > 4294967295 || !Number.isSafeInteger(height) || height <= 0 || height > 4294967295 || !Number.isSafeInteger(pixelBytes) || pixelBytes > 4294967295 || pixelOffset + pixelBytes + padding > 4294967296 || yResOffset + 8 + commentSize > 4294967296)
|
|
2005
2124
|
throw new RangeError("TIFF layout exceeds classic TIFF offsets");
|
|
2006
|
-
let header = new Uint8Array(8), directory = new Uint8Array(yResOffset + 8 - ifdOffset), headerView = new DataView(header.buffer), view = new DataView(directory.buffer);
|
|
2125
|
+
let header = new Uint8Array(8), directory = new Uint8Array(yResOffset + 8 + commentSize - ifdOffset), headerView = new DataView(header.buffer), view = new DataView(directory.buffer);
|
|
2007
2126
|
header[0] = 73, header[1] = 73, headerView.setUint16(2, 42, !0), headerView.setUint32(4, ifdOffset, !0), view.setUint16(0, numEntries, !0);
|
|
2008
2127
|
let writeEntry = (idx, tag, type, count, val) => {
|
|
2009
|
-
let p = 2 + idx * 12;
|
|
2128
|
+
let p = 2 + (idx + (comment && tag > 270 ? 1 : 0)) * 12;
|
|
2010
2129
|
view.setUint16(p, tag, !0), view.setUint16(p + 2, type, !0), view.setUint32(p + 4, count, !0), type === 3 && count === 1 ? view.setUint16(p + 8, val, !0) : view.setUint32(p + 8, val, !0);
|
|
2011
2130
|
};
|
|
2012
|
-
|
|
2131
|
+
writeEntry(0, 256, 4, 1, width), writeEntry(1, 257, 4, 1, height), writeEntry(2, 258, 3, channels, channels === 1 ? 8 : channels === 2 ? 524296 : bpsOffset), writeEntry(3, 259, 3, 1, 1), writeEntry(4, 262, 3, 1, channels < 3 ? 1 : 2), writeEntry(5, 273, 4, 1, pixelOffset), writeEntry(6, 274, 3, 1, orientation), writeEntry(7, 277, 3, 1, channels), writeEntry(8, 278, 4, 1, height), writeEntry(9, 279, 4, 1, pixelBytes), writeEntry(10, 282, 5, 1, xResOffset), writeEntry(11, 283, 5, 1, yResOffset), writeEntry(12, 284, 3, 1, 1), writeEntry(13, 296, 3, 1, resolution?.unit === "meter" || resolution?.unit === "cm" ? 3 : resolution?.unit === "unknown" ? 1 : 2), hasAlpha && writeEntry(14, 338, 3, 1, 2), comment && (writeEntry(5, 270, 2, comment.length, comment.length <= 4 ? 0 : yResOffset + 8), directory.set(comment, comment.length <= 4 ? 70 : yResOffset + 8 - ifdOffset));
|
|
2132
|
+
let end = offset === 0 ? yResOffset + 8 + commentSize : pixelOffset + pixelBytes + padding;
|
|
2133
|
+
if (hasNext && end > 4294967295) throw new RangeError("TIFF layout exceeds classic TIFF offsets");
|
|
2134
|
+
return view.setUint32(2 + numEntries * 12, hasNext ? end : 0, !0), view.setUint16(bpsOffset - ifdOffset, 8, !0), view.setUint16(bpsOffset - ifdOffset + 2, 8, !0), view.setUint16(bpsOffset - ifdOffset + 4, 8, !0), view.setUint16(bpsOffset - ifdOffset + 6, 8, !0), view.setUint32(xResOffset - ifdOffset, Math.round(x * denominator), !0), view.setUint32(xResOffset - ifdOffset + 4, denominator, !0), view.setUint32(yResOffset - ifdOffset, Math.round(y * denominator), !0), view.setUint32(yResOffset - ifdOffset + 4, denominator, !0), { header, directory, channels, padding, end };
|
|
2013
2135
|
}
|
|
2014
2136
|
|
|
2015
2137
|
// src/codecs/pdf-storage.ts
|
|
@@ -2318,15 +2440,31 @@ var JpegTables = class {
|
|
|
2318
2440
|
|
|
2319
2441
|
// src/codecs/jpeg-metadata.ts
|
|
2320
2442
|
function applyJpegMetadata(state, marker, payload) {
|
|
2443
|
+
marker === 254 && (state.properties ??= {}, state.properties.comment = (state.properties.comment ?? "") + new TextDecoder().decode(payload));
|
|
2321
2444
|
let { width, height, channels, isProgressive, density, orientation } = state;
|
|
2445
|
+
if (marker === 226 && payload.length >= 14 && new TextDecoder().decode(payload.subarray(0, 12)) === "ICC_PROFILE\0") {
|
|
2446
|
+
let index = payload[12], count = payload[13];
|
|
2447
|
+
if (!index || index > count || state.iccCount !== void 0 && state.iccCount !== count || state.iccParts?.has(index)) throw new Error("Invalid JPEG ICC sequence");
|
|
2448
|
+
if (state.iccCount = count, (state.iccParts ??= /* @__PURE__ */ new Map()).set(index, payload.slice(14)), state.iccParts.size === count) {
|
|
2449
|
+
let length = 0;
|
|
2450
|
+
for (let part of state.iccParts.values()) length += part.length;
|
|
2451
|
+
state.icc = new Uint8Array(length);
|
|
2452
|
+
let offset = 0;
|
|
2453
|
+
for (let i = 1; i <= count; i++) {
|
|
2454
|
+
let part = state.iccParts.get(i);
|
|
2455
|
+
state.icc.set(part, offset), offset += part.length;
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
if (marker === 218 && state.iccParts && !state.icc) throw new Error("Incomplete JPEG ICC sequence");
|
|
2322
2460
|
if (marker === 219 && (state.tables ??= new JpegTables(), state.tables.read(marker, payload), state.quality = estimateJpegQuality(state.tables.quantTables)), marker === 224 && payload.length >= 12) {
|
|
2323
2461
|
if (payload[0] === 74 && payload[1] === 70 && payload[2] === 73 && payload[3] === 70 && payload[4] === 0) {
|
|
2324
|
-
let units = payload[7], xDensity = payload[8] << 8 | payload[9];
|
|
2325
|
-
xDensity > 0 && (units === 1 ? density = xDensity : units === 2 && (density = Math.round(xDensity * 2.54)));
|
|
2462
|
+
let units = payload[7], yDensity = payload[10] << 8 | payload[11], xDensity = payload[8] << 8 | payload[9];
|
|
2463
|
+
xDensity > 0 && (state.resolution = { x: xDensity, y: yDensity, unit: units === 1 ? "inch" : units === 2 ? "cm" : "unknown" }, units === 1 ? density = xDensity : units === 2 && (density = Math.round(xDensity * 2.54)));
|
|
2326
2464
|
}
|
|
2327
2465
|
} else if (marker === 225 && payload.length >= 8) {
|
|
2328
2466
|
let exif = parseExifBuffer(payload);
|
|
2329
|
-
exif.orientation !== void 0 && (orientation = exif.orientation), exif.density !== void 0 && (density = exif.density);
|
|
2467
|
+
exif.orientation !== void 0 && (orientation = exif.orientation), exif.resolution !== void 0 && (state.resolution = exif.resolution), exif.density !== void 0 && (density = exif.density);
|
|
2330
2468
|
} else if (marker === 192 || marker === 193 || marker === 194) {
|
|
2331
2469
|
isProgressive = marker === 194, height = payload[1] << 8 | payload[2], width = payload[3] << 8 | payload[4];
|
|
2332
2470
|
let comps = payload[5];
|
|
@@ -3345,6 +3483,8 @@ function readJpegMetadata(bytes) {
|
|
|
3345
3483
|
if (width <= 0 || height <= 0)
|
|
3346
3484
|
throw new Error("Invalid JPEG dimensions");
|
|
3347
3485
|
return {
|
|
3486
|
+
...state.properties === void 0 ? {} : { properties: state.properties },
|
|
3487
|
+
...state.icc === void 0 ? {} : { icc: state.icc },
|
|
3348
3488
|
format: "jpeg",
|
|
3349
3489
|
...state.jpegSamplingFactor === void 0 ? {} : { jpegSamplingFactor: state.jpegSamplingFactor },
|
|
3350
3490
|
width,
|
|
@@ -3353,6 +3493,7 @@ function readJpegMetadata(bytes) {
|
|
|
3353
3493
|
channels,
|
|
3354
3494
|
depth: "uchar",
|
|
3355
3495
|
density,
|
|
3496
|
+
...state.resolution ? { resolution: state.resolution } : {},
|
|
3356
3497
|
hasAlpha: !1,
|
|
3357
3498
|
...orientation !== void 0 ? { orientation } : {},
|
|
3358
3499
|
...state.quality === void 0 ? {} : { quality: state.quality },
|
|
@@ -3575,7 +3716,10 @@ function decodeJpegImage(bytes, options) {
|
|
|
3575
3716
|
channels: meta.channels,
|
|
3576
3717
|
depth: "uchar",
|
|
3577
3718
|
density: meta.density,
|
|
3719
|
+
...meta.resolution ? { resolution: meta.resolution } : {},
|
|
3578
3720
|
hasAlpha: !1,
|
|
3721
|
+
...meta.properties === void 0 ? {} : { properties: meta.properties },
|
|
3722
|
+
...meta.icc === void 0 ? {} : { icc: meta.icc },
|
|
3579
3723
|
...meta.orientation !== void 0 ? { orientation: meta.orientation } : {},
|
|
3580
3724
|
...meta.isProgressive !== void 0 ? { isProgressive: meta.isProgressive } : {}
|
|
3581
3725
|
};
|
|
@@ -3623,7 +3767,10 @@ function decodeJpegImage(bytes, options) {
|
|
|
3623
3767
|
channels: meta.channels,
|
|
3624
3768
|
depth: "uchar",
|
|
3625
3769
|
density: meta.density,
|
|
3770
|
+
...meta.resolution ? { resolution: meta.resolution } : {},
|
|
3626
3771
|
hasAlpha: !1,
|
|
3772
|
+
...meta.properties === void 0 ? {} : { properties: meta.properties },
|
|
3773
|
+
...meta.icc === void 0 ? {} : { icc: meta.icc },
|
|
3627
3774
|
...meta.orientation !== void 0 ? { orientation: meta.orientation } : {},
|
|
3628
3775
|
...meta.isProgressive !== void 0 ? { isProgressive: meta.isProgressive } : {}
|
|
3629
3776
|
};
|
|
@@ -3742,7 +3889,7 @@ function createJpegEncoder(img, options) {
|
|
|
3742
3889
|
let maxH = Math.max(...factors.map((value) => value[0])), maxV = Math.max(...factors.map((value) => value[1]));
|
|
3743
3890
|
if (factors.length !== 3 || factors.some((value) => value.length !== 2 || value.some((n) => !Number.isInteger(n) || n < 1 || n > 4) || maxH % value[0] !== 0 || maxV % value[1] !== 0) || factors.reduce((sum, value) => sum + value[0] * value[1], 0) > 10)
|
|
3744
3891
|
throw new RangeError(`Invalid JPEG sampling factor: ${spec}`);
|
|
3745
|
-
let blockWidth = maxH * 8, blockHeight = maxV * 8, quality = options?.quality ?? 85, density = Math.max(1, Math.round(options?.density ?? img.density ?? 72)), orientation = options?.orientation ?? img.orientation, lumaQ = scaleQuantTable(STD_LUMA_QUANT, quality), chromaQ = scaleQuantTable(STD_CHROMA_QUANT, quality), bytes = [], writeU16 = (v) => {
|
|
3892
|
+
let blockWidth = maxH * 8, blockHeight = maxV * 8, quality = options?.quality ?? 85, density = Math.max(1, Math.round(options?.density ?? img.density ?? 72)), resolution = options?.density === void 0 ? img.resolution : void 0, scale = resolution?.unit === "meter" ? 100 : 1, xDensity = resolution ? Math.round(resolution.x / scale) : density, yDensity = resolution ? Math.round(resolution.y / scale) : density, orientation = options?.orientation ?? img.orientation, lumaQ = scaleQuantTable(STD_LUMA_QUANT, quality), chromaQ = scaleQuantTable(STD_CHROMA_QUANT, quality), bytes = [], writeU16 = (v) => {
|
|
3746
3893
|
bytes.push(v >>> 8 & 255, v & 255);
|
|
3747
3894
|
}, writeSegment = (marker, payload) => {
|
|
3748
3895
|
bytes.push(255, marker), writeU16(payload.length + 2);
|
|
@@ -3757,16 +3904,32 @@ function createJpegEncoder(img, options) {
|
|
|
3757
3904
|
0,
|
|
3758
3905
|
1,
|
|
3759
3906
|
1,
|
|
3760
|
-
1,
|
|
3761
|
-
// units
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3907
|
+
resolution?.unit === "meter" || resolution?.unit === "cm" ? 2 : resolution?.unit === "unknown" ? 0 : 1,
|
|
3908
|
+
// density units
|
|
3909
|
+
xDensity >>> 8 & 255,
|
|
3910
|
+
xDensity & 255,
|
|
3911
|
+
yDensity >>> 8 & 255,
|
|
3912
|
+
yDensity & 255,
|
|
3766
3913
|
0,
|
|
3767
3914
|
0
|
|
3768
3915
|
]);
|
|
3769
|
-
writeSegment(224, app0),
|
|
3916
|
+
if (writeSegment(224, app0), img.properties?.comment !== void 0) {
|
|
3917
|
+
let comment = new TextEncoder().encode(img.properties.comment);
|
|
3918
|
+
for (let offset = 0; offset < comment.length; ) {
|
|
3919
|
+
let end = Math.min(comment.length, offset + 65533);
|
|
3920
|
+
for (; end < comment.length && (comment[end] & 192) === 128; ) end--;
|
|
3921
|
+
writeSegment(254, comment.subarray(offset, end)), offset = end;
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
if (img.icc) {
|
|
3925
|
+
let count = Math.ceil(img.icc.length / 65519);
|
|
3926
|
+
if (count > 255) throw new Error("ICC profile exceeds JPEG segment limit");
|
|
3927
|
+
for (let index = 0; index < count; index++) {
|
|
3928
|
+
let part = img.icc.subarray(index * 65519, (index + 1) * 65519), payload = new Uint8Array(14 + part.length);
|
|
3929
|
+
payload.set(new TextEncoder().encode("ICC_PROFILE\0")), payload[12] = index + 1, payload[13] = count, payload.set(part, 14), writeSegment(226, payload);
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
orientation !== void 0 && orientation >= 1 && orientation <= 8 && writeSegment(225, buildExifApp1Segment({ orientation, density, resolution }));
|
|
3770
3933
|
let dqt = new Uint8Array(130);
|
|
3771
3934
|
dqt[0] = 0, dqt.set(lumaQ, 1), dqt[65] = 1, dqt.set(chromaQ, 66), writeSegment(219, dqt);
|
|
3772
3935
|
let sof0 = new Uint8Array([
|
|
@@ -4437,11 +4600,19 @@ async function readJpegMetadataFromSource(source, signal) {
|
|
|
4437
4600
|
if (position + 2 > source.size) break;
|
|
4438
4601
|
let length = await reader.at(position) << 8 | await reader.at(position + 1);
|
|
4439
4602
|
if (length < 2 || position + length > source.size) break;
|
|
4440
|
-
if (marker ===
|
|
4603
|
+
if (marker === 254) {
|
|
4604
|
+
let decoder = new TextDecoder(), comment = "";
|
|
4605
|
+
for (let offset = 0; offset < length - 2; offset += 4096) {
|
|
4606
|
+
let payload = await payloadBytes(reader, position + 2 + offset, Math.min(4096, length - 2 - offset));
|
|
4607
|
+
comment += decoder.decode(payload, { stream: !0 });
|
|
4608
|
+
}
|
|
4609
|
+
state.properties ??= {}, state.properties.comment = (state.properties.comment ?? "") + comment + decoder.decode();
|
|
4610
|
+
}
|
|
4611
|
+
if (marker === 219 || marker === 218 || marker === 224 || marker === 226 || marker === 225 || marker === 192 || marker === 193 || marker === 194) {
|
|
4441
4612
|
let payload = await payloadBytes(
|
|
4442
4613
|
reader,
|
|
4443
4614
|
position + 2,
|
|
4444
|
-
Math.min(length - 2, marker === 224 ? 12 : marker === 225 || marker === 219 ? 65533 : 771)
|
|
4615
|
+
Math.min(length - 2, marker === 224 ? 12 : marker === 226 || marker === 225 || marker === 219 ? 65533 : 771)
|
|
4445
4616
|
);
|
|
4446
4617
|
if (applyJpegMetadata(state, marker, payload)) break;
|
|
4447
4618
|
}
|
|
@@ -4451,6 +4622,8 @@ async function readJpegMetadataFromSource(source, signal) {
|
|
|
4451
4622
|
let { width, height, channels, isProgressive, density, orientation } = state;
|
|
4452
4623
|
if (width <= 0 || height <= 0) throw new Error("Invalid JPEG dimensions");
|
|
4453
4624
|
return {
|
|
4625
|
+
...state.properties === void 0 ? {} : { properties: state.properties },
|
|
4626
|
+
...state.icc === void 0 ? {} : { icc: state.icc },
|
|
4454
4627
|
format: "jpeg",
|
|
4455
4628
|
...state.jpegSamplingFactor === void 0 ? {} : { jpegSamplingFactor: state.jpegSamplingFactor },
|
|
4456
4629
|
width,
|
|
@@ -4459,6 +4632,7 @@ async function readJpegMetadataFromSource(source, signal) {
|
|
|
4459
4632
|
channels,
|
|
4460
4633
|
depth: "uchar",
|
|
4461
4634
|
density,
|
|
4635
|
+
...state.resolution ? { resolution: state.resolution } : {},
|
|
4462
4636
|
hasAlpha: !1,
|
|
4463
4637
|
...orientation === void 0 ? {} : { orientation },
|
|
4464
4638
|
...state.quality === void 0 ? {} : { quality: state.quality },
|
|
@@ -4636,7 +4810,10 @@ async function decodeJpegToStorage(source, storage, signal, options) {
|
|
|
4636
4810
|
channels: meta.channels,
|
|
4637
4811
|
depth: "uchar",
|
|
4638
4812
|
density: meta.density,
|
|
4813
|
+
...meta.resolution ? { resolution: meta.resolution } : {},
|
|
4639
4814
|
hasAlpha: !1,
|
|
4815
|
+
...meta.properties === void 0 ? {} : { properties: meta.properties },
|
|
4816
|
+
...meta.icc === void 0 ? {} : { icc: meta.icc },
|
|
4640
4817
|
...meta.orientation !== void 0 ? { orientation: meta.orientation } : {},
|
|
4641
4818
|
...meta.isProgressive !== void 0 ? { isProgressive: meta.isProgressive } : {}
|
|
4642
4819
|
};
|
|
@@ -4690,7 +4867,10 @@ async function decodeJpegToStorage(source, storage, signal, options) {
|
|
|
4690
4867
|
channels: meta.channels,
|
|
4691
4868
|
depth: "uchar",
|
|
4692
4869
|
density: meta.density,
|
|
4870
|
+
...meta.resolution ? { resolution: meta.resolution } : {},
|
|
4693
4871
|
hasAlpha: !1,
|
|
4872
|
+
...meta.properties === void 0 ? {} : { properties: meta.properties },
|
|
4873
|
+
...meta.icc === void 0 ? {} : { icc: meta.icc },
|
|
4694
4874
|
...meta.orientation !== void 0 ? { orientation: meta.orientation } : {},
|
|
4695
4875
|
...meta.isProgressive !== void 0 ? { isProgressive: meta.isProgressive } : {}
|
|
4696
4876
|
};
|
|
@@ -4822,10 +5002,18 @@ async function* encodePngFromStorage(image, storage, signal, options = {}) {
|
|
|
4822
5002
|
}
|
|
4823
5003
|
let gray = image.space === "b-w" || image.channels === 1 || image.channels === 2, channels = gray ? alpha ? [0, 3] : [0] : alpha ? [0, 1, 2, 3] : [0, 1, 2], sampleBytes = image.storedData16 ? 2 : 1, header = new Uint8Array(13), view = new DataView(header.buffer);
|
|
4824
5004
|
view.setUint32(0, width), view.setUint32(4, height), header[8] = sampleBytes * 8, header[9] = gray ? alpha ? 4 : 0 : alpha ? 6 : 2, yield new Uint8Array(PNG_SIGNATURE), signal.throwIfAborted(), yield makeChunk("IHDR", header);
|
|
4825
|
-
let density = options.density ?? image.density ?? 72, physical = new Uint8Array(9), physicalView = new DataView(physical.buffer);
|
|
4826
|
-
physicalView.setUint32(0, Math.round(density / 0.0254)), physicalView.setUint32(4, Math.round(density / 0.0254)), physical[8] = 1, signal.throwIfAborted(), yield makeChunk("pHYs", physical), image.virtualCanvas !== void 0 && (signal.throwIfAborted(), yield canvasChunk(image.virtualCanvas));
|
|
5005
|
+
let density = options.density ?? image.density ?? 72, resolution = options.density === void 0 ? image.resolution : void 0, scale = resolution?.unit === "inch" ? 1 / 0.0254 : resolution?.unit === "cm" ? 100 : 1, physical = new Uint8Array(9), physicalView = new DataView(physical.buffer);
|
|
5006
|
+
physicalView.setUint32(0, Math.round(resolution ? resolution.x * scale : density / 0.0254)), physicalView.setUint32(4, Math.round(resolution ? resolution.y * scale : density / 0.0254)), physical[8] = resolution?.unit === "unknown" ? 0 : 1, !options.omitPngResolution && (resolution !== void 0 || options.density !== void 0) && (signal.throwIfAborted(), yield makeChunk("pHYs", physical)), image.virtualCanvas !== void 0 && (signal.throwIfAborted(), yield canvasChunk(image.virtualCanvas));
|
|
5007
|
+
for (let chunk of textChunks(image.properties))
|
|
5008
|
+
for (let offset = 0; offset < chunk.length; offset += 4096)
|
|
5009
|
+
signal.throwIfAborted(), yield chunk.subarray(offset, offset + 4096);
|
|
5010
|
+
if (image.icc) {
|
|
5011
|
+
let chunk = iccChunk(image.icc);
|
|
5012
|
+
for (let offset = 0; offset < chunk.length; offset += 4096)
|
|
5013
|
+
signal.throwIfAborted(), yield chunk.subarray(offset, offset + 4096);
|
|
5014
|
+
}
|
|
4827
5015
|
let orientation = options.orientation ?? image.orientation;
|
|
4828
|
-
orientation !== void 0 && (signal.throwIfAborted(), yield makeChunk("eXIf", buildExifApp1Segment({ orientation, density }).subarray(6)));
|
|
5016
|
+
orientation !== void 0 && (signal.throwIfAborted(), yield makeChunk("eXIf", buildExifApp1Segment({ orientation, density, resolution }).subarray(6)));
|
|
4829
5017
|
let encoder = createByteCodec({ direction: "encode", format: "zlib", chunkSize: 4084, level: Math.max(0, Math.min(9, options.compressionLevel ?? 6)) });
|
|
4830
5018
|
try {
|
|
4831
5019
|
for (let y = 0; y < height; y++) {
|
|
@@ -6059,7 +6247,7 @@ function gifLayout(image, options = {}) {
|
|
|
6059
6247
|
return { width, height, frames, frameHeight, framePixels: width * frameHeight };
|
|
6060
6248
|
}
|
|
6061
6249
|
function gifHeader(image, options, layout, palette) {
|
|
6062
|
-
let { frames } = layout, width = image.virtualCanvas?.width || layout.width, frameHeight = image.virtualCanvas?.height || layout.frameHeight, loop = options.loop ?? image.loop ?? (frames > 1 ? 0 : void 0), out = new Uint8Array(781 + (loop === void 0 || loop === 1 ? 0 : 19));
|
|
6250
|
+
let comment = new TextEncoder().encode(image.properties?.comment ?? ""), { frames } = layout, width = image.virtualCanvas?.width || layout.width, frameHeight = image.virtualCanvas?.height || layout.frameHeight, loop = options.loop ?? image.loop ?? (frames > 1 ? 0 : void 0), out = new Uint8Array(781 + (loop === void 0 || loop === 1 ? 0 : 19) + (comment.length ? 3 + comment.length + Math.ceil(comment.length / 255) : 0));
|
|
6063
6251
|
if (out.set([
|
|
6064
6252
|
71,
|
|
6065
6253
|
73,
|
|
@@ -6101,6 +6289,14 @@ function gifHeader(image, options, layout, palette) {
|
|
|
6101
6289
|
781
|
|
6102
6290
|
);
|
|
6103
6291
|
}
|
|
6292
|
+
if (comment.length) {
|
|
6293
|
+
let at = 781 + (loop === void 0 || loop === 1 ? 0 : 19);
|
|
6294
|
+
out.set([33, 254], at), at += 2;
|
|
6295
|
+
for (let offset = 0; offset < comment.length; offset += 255) {
|
|
6296
|
+
let part = comment.subarray(offset, offset + 255);
|
|
6297
|
+
out[at++] = part.length, out.set(part, at), at += part.length;
|
|
6298
|
+
}
|
|
6299
|
+
}
|
|
6104
6300
|
return out;
|
|
6105
6301
|
}
|
|
6106
6302
|
function gifFrameHeader(image, options, layout, frame, transparent, frameDelay = image.delay?.[frame], frameDisposal = typeof image.disposal == "number" ? image.disposal : image.disposal?.[frame], rectangle = { left: 0, top: 0, width: layout.width, height: layout.frameHeight }) {
|
|
@@ -6150,7 +6346,7 @@ function* gifAnimationSteps(size, start) {
|
|
|
6150
6346
|
return at2;
|
|
6151
6347
|
}, word3 = function* (at2) {
|
|
6152
6348
|
return ((yield at2) ?? 0) | ((yield at2 + 1) ?? 0) << 8;
|
|
6153
|
-
}, at = start, pending = 100, frames = 0, loop;
|
|
6349
|
+
}, comments = [], at = start, pending = 100, frames = 0, loop;
|
|
6154
6350
|
for (; at < size; ) {
|
|
6155
6351
|
let intro = yield at++;
|
|
6156
6352
|
if (intro === 59) break;
|
|
@@ -6171,7 +6367,14 @@ function* gifAnimationSteps(size, start) {
|
|
|
6171
6367
|
}
|
|
6172
6368
|
at += n;
|
|
6173
6369
|
}
|
|
6174
|
-
} else
|
|
6370
|
+
} else if (label === 254)
|
|
6371
|
+
for (; at < size; ) {
|
|
6372
|
+
let n = (yield at++) ?? 0;
|
|
6373
|
+
if (!n) break;
|
|
6374
|
+
if (comments.length + n > 16 * 1024 * 1024) throw new Error("GIF comment exceeds 16 MiB");
|
|
6375
|
+
for (let i = 0; i < n && at < size; i++) comments.push((yield at++) ?? 0);
|
|
6376
|
+
}
|
|
6377
|
+
else at = yield* skip(at);
|
|
6175
6378
|
} else if (intro === 44) {
|
|
6176
6379
|
if (at + 9 > size) break;
|
|
6177
6380
|
yield { frame: frames++, delay: pending }, pending = 100;
|
|
@@ -6179,7 +6382,7 @@ function* gifAnimationSteps(size, start) {
|
|
|
6179
6382
|
at += 9, flags & 128 && (at += 3 * (1 << (flags & 7) + 1)), at = yield* skip(at + 1);
|
|
6180
6383
|
} else break;
|
|
6181
6384
|
}
|
|
6182
|
-
return { frames, loop };
|
|
6385
|
+
return { frames, loop, ...comments.length ? { properties: { comment: new TextDecoder().decode(new Uint8Array(comments)) } } : {} };
|
|
6183
6386
|
}
|
|
6184
6387
|
function gifMetadataFields(width, height, size, frames, loop, options) {
|
|
6185
6388
|
let total = Math.max(1, frames), multi = options?.animated === !0 || options?.pages === -1 || options?.pages !== void 0 && options.pages > 1, page = Math.max(0, options?.page ?? 0), pages = multi ? options?.pages !== void 0 && options.pages > 0 ? Math.min(options.pages, Math.max(1, total - page)) : Math.max(1, total - page) : 1;
|
|
@@ -6205,7 +6408,7 @@ function readGifMetadata(bytes, options) {
|
|
|
6205
6408
|
let start = 13 + (bytes[10] & 128 ? 3 * (1 << (bytes[10] & 7) + 1) : 0), steps = gifAnimationSteps(bytes.length, start), delays = [], next = steps.next();
|
|
6206
6409
|
for (; !next.done; )
|
|
6207
6410
|
typeof next.value == "number" ? next = steps.next(bytes[next.value]) : (delays.push(next.value.delay), next = steps.next());
|
|
6208
|
-
return { ...gifMetadataFields(bytes[6] | bytes[7] << 8, bytes[8] | bytes[9] << 8, bytes.length, next.value.frames, next.value.loop, options), ...delays.length ? { delay: delays } : {} };
|
|
6411
|
+
return { ...next.value.properties ? { properties: next.value.properties } : {}, ...gifMetadataFields(bytes[6] | bytes[7] << 8, bytes[8] | bytes[9] << 8, bytes.length, next.value.frames, next.value.loop, options), ...delays.length ? { delay: delays } : {} };
|
|
6209
6412
|
}
|
|
6210
6413
|
function lzwDecode(minCodeSize, data, pixelCount) {
|
|
6211
6414
|
let clearCode = 1 << minCodeSize, eoiCode = clearCode + 1, codeSize = minCodeSize + 1, nextCode = eoiCode + 1, prefix = new Int32Array(4096), suffix = new Uint8Array(4096), stack = new Uint8Array(4096);
|
|
@@ -6292,6 +6495,7 @@ function decodeGifImage(bytes, options) {
|
|
|
6292
6495
|
index !== transparentIdx && data.set([palette[index * 3] ?? 0, palette[index * 3 + 1] ?? 0, palette[index * 3 + 2] ?? 0, 255], at);
|
|
6293
6496
|
}
|
|
6294
6497
|
return {
|
|
6498
|
+
...meta.properties ? { properties: meta.properties } : {},
|
|
6295
6499
|
width: imgW,
|
|
6296
6500
|
height: imgH,
|
|
6297
6501
|
data,
|
|
@@ -6350,6 +6554,7 @@ function decodeGifImage(bytes, options) {
|
|
|
6350
6554
|
width,
|
|
6351
6555
|
height: height * numPages,
|
|
6352
6556
|
data: outData,
|
|
6557
|
+
...meta.properties ? { properties: meta.properties } : {},
|
|
6353
6558
|
format: "gif",
|
|
6354
6559
|
space: "srgb",
|
|
6355
6560
|
channels: 4,
|
|
@@ -6421,7 +6626,32 @@ function createBmpHeader(img) {
|
|
|
6421
6626
|
|
|
6422
6627
|
// src/codecs/netpbm-header.ts
|
|
6423
6628
|
function* netpbmHeaderSteps(size) {
|
|
6424
|
-
let magic = String.fromCharCode(yield 0, yield 1)
|
|
6629
|
+
let magic = String.fromCharCode(yield 0, yield 1);
|
|
6630
|
+
if (magic === "P7") {
|
|
6631
|
+
let pos2 = 2, fields2 = /* @__PURE__ */ new Map();
|
|
6632
|
+
for (; pos2 < size; ) {
|
|
6633
|
+
let line = "";
|
|
6634
|
+
for (; pos2 < size; ) {
|
|
6635
|
+
let byte2 = yield pos2++;
|
|
6636
|
+
if (byte2 === 10) break;
|
|
6637
|
+
if (line += String.fromCharCode(byte2), line.length > 4096) throw new Error("PAM header line too long");
|
|
6638
|
+
}
|
|
6639
|
+
if (line = line.split("#")[0].trim(), line === "ENDHDR") {
|
|
6640
|
+
let width = Number(fields2.get("WIDTH")), height = Number(fields2.get("HEIGHT")), channels = Number(fields2.get("DEPTH")), maxval = Number(fields2.get("MAXVAL")), tuple = fields2.get("TUPLTYPE");
|
|
6641
|
+
if (!Number.isSafeInteger(width * height * 4) || !Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0 || ![1, 2, 3, 4].includes(channels) || !Number.isInteger(maxval) || maxval < 1 || maxval > 65535)
|
|
6642
|
+
throw new Error("Invalid PAM header");
|
|
6643
|
+
if (tuple && { BLACKANDWHITE: 1, BLACKANDWHITE_ALPHA: 2, GRAYSCALE: 1, GRAYSCALE_ALPHA: 2, RGB: 3, RGB_ALPHA: 4 }[tuple] !== channels) throw new Error("Unsupported PAM tuple type");
|
|
6644
|
+
return { magic, format: "pam", width, height, maxval, channels, hasAlpha: channels === 2 || channels === 4, dataOffset: pos2 };
|
|
6645
|
+
}
|
|
6646
|
+
if (!line) continue;
|
|
6647
|
+
let separator = 0;
|
|
6648
|
+
for (; separator < line.length && line[separator] !== " " && line[separator] !== " "; ) separator++;
|
|
6649
|
+
let key = line.slice(0, separator);
|
|
6650
|
+
["WIDTH", "HEIGHT", "DEPTH", "MAXVAL", "TUPLTYPE"].includes(key) && fields2.set(key, line.slice(separator).trim());
|
|
6651
|
+
}
|
|
6652
|
+
throw new Error("Missing PAM ENDHDR");
|
|
6653
|
+
}
|
|
6654
|
+
let format = magic === "P1" || magic === "P4" ? "pbm" : magic === "P2" || magic === "P5" ? "pgm" : "ppm", pos = 2, tokens = [], needed = format === "pbm" ? 2 : 3;
|
|
6425
6655
|
for (; pos < size && tokens.length < needed; ) {
|
|
6426
6656
|
for (; pos < size; ) {
|
|
6427
6657
|
let c = yield pos;
|
|
@@ -6448,11 +6678,53 @@ function* netpbmHeaderSteps(size) {
|
|
|
6448
6678
|
width: tokens[0] ?? 0,
|
|
6449
6679
|
height: tokens[1] ?? 0,
|
|
6450
6680
|
maxval: format === "pbm" ? 1 : tokens[2] ?? 255,
|
|
6681
|
+
channels: format === "ppm" ? 3 : 1,
|
|
6682
|
+
hasAlpha: !1,
|
|
6451
6683
|
dataOffset: pos
|
|
6452
6684
|
};
|
|
6453
6685
|
}
|
|
6454
|
-
function
|
|
6455
|
-
let
|
|
6686
|
+
function* netpbmSequenceSteps(size, page) {
|
|
6687
|
+
let offset = 0, pages = 0, first;
|
|
6688
|
+
for (; offset < size; ) {
|
|
6689
|
+
let steps = netpbmHeaderSteps(size - offset), next = steps.next();
|
|
6690
|
+
for (; !next.done; ) next = steps.next(yield offset + next.value);
|
|
6691
|
+
let header = { ...next.value, dataOffset: offset + next.value.dataOffset };
|
|
6692
|
+
if (!["P1", "P2", "P3", "P4", "P5", "P6", "P7"].includes(header.magic)) throw new Error("Invalid Netpbm signature");
|
|
6693
|
+
if (first ??= header, pages++ === page) return { header, pages };
|
|
6694
|
+
let { width, height, magic, maxval } = header;
|
|
6695
|
+
if (!Number.isSafeInteger(width * height) || width <= 0 || height <= 0) throw new RangeError("Invalid Netpbm dimensions");
|
|
6696
|
+
if (offset = header.dataOffset, magic === "P4") offset += Math.ceil(width / 8) * height;
|
|
6697
|
+
else if (magic === "P5" || magic === "P6" || magic === "P7") {
|
|
6698
|
+
if (offset += width * height * header.channels * (maxval > 255 ? 2 : 1), magic === "P7" && offset > size) throw new Error("Truncated PAM raster");
|
|
6699
|
+
} else
|
|
6700
|
+
for (let samples = width * height * (magic === "P3" ? 3 : 1); samples > 0 && offset < size; samples--) {
|
|
6701
|
+
for (; offset < size; ) {
|
|
6702
|
+
let c = yield offset;
|
|
6703
|
+
if (c === 35)
|
|
6704
|
+
for (; offset < size && (yield offset) !== 10 && (yield offset) !== 13; ) offset++;
|
|
6705
|
+
else if (c <= 32) offset++;
|
|
6706
|
+
else break;
|
|
6707
|
+
}
|
|
6708
|
+
let start = offset;
|
|
6709
|
+
for (; offset < size && (yield offset) >= 48 && (yield offset) <= 57; ) offset++;
|
|
6710
|
+
if (start === offset) {
|
|
6711
|
+
offset = size;
|
|
6712
|
+
break;
|
|
6713
|
+
}
|
|
6714
|
+
}
|
|
6715
|
+
for (; offset < size; ) {
|
|
6716
|
+
let c = yield offset;
|
|
6717
|
+
if (c === 35)
|
|
6718
|
+
for (; offset < size && (yield offset) !== 10 && (yield offset) !== 13; ) offset++;
|
|
6719
|
+
else if (c <= 32) offset++;
|
|
6720
|
+
else break;
|
|
6721
|
+
}
|
|
6722
|
+
}
|
|
6723
|
+
if (!first || page !== void 0) throw new RangeError("Netpbm page out of range");
|
|
6724
|
+
return { header: first, pages };
|
|
6725
|
+
}
|
|
6726
|
+
function parseNetpbmSequence(bytes, page) {
|
|
6727
|
+
let steps = netpbmSequenceSteps(bytes.length, page), next = steps.next();
|
|
6456
6728
|
for (; !next.done; ) next = steps.next(bytes[next.value]);
|
|
6457
6729
|
return next.value;
|
|
6458
6730
|
}
|
|
@@ -6461,7 +6733,7 @@ function parseNetpbmHeader(bytes) {
|
|
|
6461
6733
|
function isNetpbmBytes(bytes) {
|
|
6462
6734
|
if (bytes.length < 7 || bytes[0] !== 80) return !1;
|
|
6463
6735
|
let m = bytes[1];
|
|
6464
|
-
if (m < 49 || m >
|
|
6736
|
+
if (m < 49 || m > 55) return !1;
|
|
6465
6737
|
let ws = bytes[2];
|
|
6466
6738
|
return ws === 32 || ws === 10 || ws === 13 || ws === 9;
|
|
6467
6739
|
}
|
|
@@ -6472,21 +6744,26 @@ function isTiffBytes(bytes) {
|
|
|
6472
6744
|
return bytes.length >= 8 && (bytes[0] === 73 && bytes[1] === 73 && bytes[2] === 42 && bytes[3] === 0 || bytes[0] === 77 && bytes[1] === 77 && bytes[2] === 0 && bytes[3] === 42);
|
|
6473
6745
|
}
|
|
6474
6746
|
function readNetpbmMetadata(bytes) {
|
|
6475
|
-
let hdr =
|
|
6747
|
+
let { header: hdr, pages } = parseNetpbmSequence(bytes);
|
|
6476
6748
|
return {
|
|
6477
6749
|
format: hdr.format,
|
|
6478
6750
|
width: hdr.width,
|
|
6479
6751
|
height: hdr.height,
|
|
6480
|
-
space: hdr.
|
|
6481
|
-
channels: hdr.
|
|
6752
|
+
space: hdr.channels >= 3 ? "srgb" : "b-w",
|
|
6753
|
+
channels: hdr.channels,
|
|
6482
6754
|
depth: hdr.format === "pbm" ? "bit" : hdr.maxval > 255 ? "ushort" : "uchar",
|
|
6483
6755
|
density: 72,
|
|
6484
|
-
hasAlpha:
|
|
6485
|
-
size: bytes.byteLength
|
|
6756
|
+
hasAlpha: hdr.hasAlpha,
|
|
6757
|
+
size: bytes.byteLength,
|
|
6758
|
+
...pages > 1 ? { pages } : {}
|
|
6486
6759
|
};
|
|
6487
6760
|
}
|
|
6488
|
-
function decodeNetpbmImage(bytes) {
|
|
6489
|
-
let hdr =
|
|
6761
|
+
function decodeNetpbmImage(bytes, page = 0) {
|
|
6762
|
+
let { header: hdr } = parseNetpbmSequence(bytes, page), { width, height, maxval, magic, format, channels, hasAlpha } = hdr;
|
|
6763
|
+
if (magic === "P6" && bytes.length - hdr.dataOffset < width * height * 3 * (maxval > 255 ? 2 : 1))
|
|
6764
|
+
throw new Error("Truncated PPM raster");
|
|
6765
|
+
if (magic === "P7" && bytes.length - hdr.dataOffset < width * height * channels * (maxval > 255 ? 2 : 1)) throw new Error("Truncated PAM raster");
|
|
6766
|
+
let rgba = new Uint8Array(width * height * 4), data16 = maxval > 255 ? new Uint16Array(width * height * 4) : void 0, pos = hdr.dataOffset, readNextAsciiInt = () => {
|
|
6490
6767
|
for (; pos < bytes.length; ) {
|
|
6491
6768
|
let c = bytes[pos];
|
|
6492
6769
|
if (c === 35)
|
|
@@ -6501,21 +6778,16 @@ function decodeNetpbmImage(bytes) {
|
|
|
6501
6778
|
val = val * 10 + (bytes[pos] - 48), pos++;
|
|
6502
6779
|
return val;
|
|
6503
6780
|
};
|
|
6504
|
-
if (magic === "P6") {
|
|
6505
|
-
let readSample =
|
|
6506
|
-
let hi = bytes[pos++] ?? 0
|
|
6507
|
-
return hi << 8 |
|
|
6508
|
-
}
|
|
6509
|
-
for (let i = 0; i < width * height; i++)
|
|
6510
|
-
rgba[i * 4] = Math.round(readSample() * 255 / maxval), rgba[i * 4 + 1] = Math.round(readSample() * 255 / maxval), rgba[i * 4 + 2] = Math.round(readSample() * 255 / maxval), rgba[i * 4 + 3] = 255;
|
|
6511
|
-
} else if (magic === "P5") {
|
|
6512
|
-
let readSample = maxval > 255 ? () => {
|
|
6513
|
-
let hi = bytes[pos++] ?? 0, lo = bytes[pos++] ?? 0;
|
|
6514
|
-
return hi << 8 | lo;
|
|
6515
|
-
} : () => bytes[pos++] ?? 0;
|
|
6781
|
+
if (magic === "P7" || magic === "P6" || magic === "P5" || magic === "P3" || magic === "P2") {
|
|
6782
|
+
let readSample = magic === "P3" || magic === "P2" ? readNextAsciiInt : () => {
|
|
6783
|
+
let hi = bytes[pos++] ?? 0;
|
|
6784
|
+
return maxval > 255 ? hi << 8 | (bytes[pos++] ?? 0) : hi;
|
|
6785
|
+
};
|
|
6516
6786
|
for (let i = 0; i < width * height; i++) {
|
|
6517
|
-
let g =
|
|
6518
|
-
|
|
6787
|
+
let r = readSample(), g = channels >= 3 ? readSample() : r, b = channels >= 3 ? readSample() : r, a = hasAlpha ? readSample() : maxval;
|
|
6788
|
+
for (let [channel, value] of [r, g, b, a].entries())
|
|
6789
|
+
rgba[i * 4 + channel] = Math.round(value * 255 / maxval), data16 && (data16[i * 4 + channel] = Math.round(value * 65535 / maxval));
|
|
6790
|
+
hasAlpha || (rgba[i * 4 + 3] = 255, data16 && (data16[i * 4 + 3] = 65535));
|
|
6519
6791
|
}
|
|
6520
6792
|
} else if (magic === "P4") {
|
|
6521
6793
|
let rowBytes = Math.ceil(width / 8);
|
|
@@ -6526,15 +6798,7 @@ function decodeNetpbmImage(bytes) {
|
|
|
6526
6798
|
rgba[idx] = g, rgba[idx + 1] = g, rgba[idx + 2] = g, rgba[idx + 3] = 255;
|
|
6527
6799
|
}
|
|
6528
6800
|
}
|
|
6529
|
-
} else if (magic === "
|
|
6530
|
-
for (let i = 0; i < width * height; i++)
|
|
6531
|
-
rgba[i * 4] = Math.round(readNextAsciiInt() * 255 / maxval), rgba[i * 4 + 1] = Math.round(readNextAsciiInt() * 255 / maxval), rgba[i * 4 + 2] = Math.round(readNextAsciiInt() * 255 / maxval), rgba[i * 4 + 3] = 255;
|
|
6532
|
-
else if (magic === "P2")
|
|
6533
|
-
for (let i = 0; i < width * height; i++) {
|
|
6534
|
-
let g = Math.round(readNextAsciiInt() * 255 / maxval);
|
|
6535
|
-
rgba[i * 4] = g, rgba[i * 4 + 1] = g, rgba[i * 4 + 2] = g, rgba[i * 4 + 3] = 255;
|
|
6536
|
-
}
|
|
6537
|
-
else if (magic === "P1")
|
|
6801
|
+
} else if (magic === "P1")
|
|
6538
6802
|
for (let i = 0; i < width * height; i++) {
|
|
6539
6803
|
let g = readNextAsciiInt() === 1 ? 0 : 255;
|
|
6540
6804
|
rgba[i * 4] = g, rgba[i * 4 + 1] = g, rgba[i * 4 + 2] = g, rgba[i * 4 + 3] = 255;
|
|
@@ -6543,54 +6807,87 @@ function decodeNetpbmImage(bytes) {
|
|
|
6543
6807
|
width,
|
|
6544
6808
|
height,
|
|
6545
6809
|
data: rgba,
|
|
6810
|
+
...data16 ? { data16 } : {},
|
|
6546
6811
|
format,
|
|
6547
|
-
space:
|
|
6548
|
-
channels
|
|
6812
|
+
space: channels >= 3 ? "srgb" : "b-w",
|
|
6813
|
+
channels,
|
|
6549
6814
|
depth: format === "pbm" ? "bit" : maxval > 255 ? "ushort" : "uchar",
|
|
6550
6815
|
density: 72,
|
|
6551
|
-
hasAlpha
|
|
6816
|
+
hasAlpha
|
|
6552
6817
|
};
|
|
6553
6818
|
}
|
|
6554
|
-
function encodePpm(img) {
|
|
6555
|
-
|
|
6819
|
+
function encodePpm(img, depth = img.data16 ? 16 : 8, ascii = !1, pam = !1) {
|
|
6820
|
+
pam && (ascii = !1);
|
|
6821
|
+
let channels = pam && img.hasAlpha ? 4 : 3;
|
|
6822
|
+
if (!Number.isInteger(depth) || depth < 1 || depth > 16) throw new RangeError("Invalid Netpbm depth");
|
|
6823
|
+
let maximum = 2 ** depth - 1, text = [], header = pam ? `P7
|
|
6824
|
+
WIDTH ${img.width}
|
|
6825
|
+
HEIGHT ${img.height}
|
|
6826
|
+
DEPTH ${channels}
|
|
6827
|
+
MAXVAL ${maximum}
|
|
6828
|
+
TUPLTYPE ${img.hasAlpha ? "RGB_ALPHA" : "RGB"}
|
|
6829
|
+
ENDHDR
|
|
6830
|
+
` : `${ascii ? "P3" : "P6"}
|
|
6556
6831
|
${img.width} ${img.height}
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
out.set(header, 0);
|
|
6832
|
+
${maximum}
|
|
6833
|
+
`, out = new Uint8Array(ascii ? 0 : header.length + img.width * img.height * channels * (depth > 8 ? 2 : 1));
|
|
6834
|
+
ascii || out.set(new TextEncoder().encode(header), 0);
|
|
6560
6835
|
let dst = header.length;
|
|
6561
6836
|
for (let i = 0; i < img.width * img.height; i++)
|
|
6562
|
-
|
|
6563
|
-
|
|
6837
|
+
for (let channel = 0; channel < channels; channel++) {
|
|
6838
|
+
let value = Math.round((img.data16 ?? img.data)[i * 4 + channel] * maximum / (img.data16 ? 65535 : 255));
|
|
6839
|
+
if (ascii) {
|
|
6840
|
+
text.push(String(value));
|
|
6841
|
+
continue;
|
|
6842
|
+
}
|
|
6843
|
+
depth > 8 && (out[dst++] = value >>> 8), out[dst++] = value & 255;
|
|
6844
|
+
}
|
|
6845
|
+
return ascii ? new TextEncoder().encode(header + text.join(`
|
|
6846
|
+
`) + `
|
|
6847
|
+
`) : out;
|
|
6564
6848
|
}
|
|
6565
|
-
function encodePgm(img) {
|
|
6566
|
-
|
|
6849
|
+
function encodePgm(img, depth = img.data16 ? 16 : 8, ascii = !1) {
|
|
6850
|
+
if (!Number.isInteger(depth) || depth < 1 || depth > 16) throw new RangeError("Invalid Netpbm depth");
|
|
6851
|
+
let maximum = 2 ** depth - 1, text = [], header = `${ascii ? "P2" : "P5"}
|
|
6567
6852
|
${img.width} ${img.height}
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
out.set(header, 0);
|
|
6853
|
+
${maximum}
|
|
6854
|
+
`, out = new Uint8Array(ascii ? 0 : header.length + img.width * img.height * (depth > 8 ? 2 : 1));
|
|
6855
|
+
ascii || out.set(new TextEncoder().encode(header), 0);
|
|
6571
6856
|
let dst = header.length;
|
|
6572
6857
|
for (let i = 0; i < img.width * img.height; i++) {
|
|
6573
|
-
let
|
|
6574
|
-
|
|
6858
|
+
let samples = img.data16 ?? img.data, r = samples[i * 4], g = samples[i * 4 + 1], b = samples[i * 4 + 2], value = Math.round((0.212656 * r + 0.715158 * g + 0.072186 * b) * maximum / (img.data16 ? 65535 : 255));
|
|
6859
|
+
if (ascii) {
|
|
6860
|
+
text.push(String(value));
|
|
6861
|
+
continue;
|
|
6862
|
+
}
|
|
6863
|
+
depth > 8 && (out[dst++] = value >>> 8), out[dst++] = value & 255;
|
|
6575
6864
|
}
|
|
6576
|
-
return
|
|
6865
|
+
return ascii ? new TextEncoder().encode(header + text.join(`
|
|
6866
|
+
`) + `
|
|
6867
|
+
`) : out;
|
|
6577
6868
|
}
|
|
6578
|
-
function encodePbm(img) {
|
|
6579
|
-
let header =
|
|
6869
|
+
function encodePbm(img, ascii = !1) {
|
|
6870
|
+
let text = [], header = `${ascii ? "P1" : "P4"}
|
|
6580
6871
|
${img.width} ${img.height}
|
|
6581
|
-
|
|
6582
|
-
out.set(header, 0);
|
|
6872
|
+
`, rowBytes = Math.ceil(img.width / 8), out = new Uint8Array(ascii ? 0 : header.length + rowBytes * img.height);
|
|
6873
|
+
ascii || out.set(new TextEncoder().encode(header), 0);
|
|
6583
6874
|
for (let y = 0; y < img.height; y++) {
|
|
6584
6875
|
let rowOffset = header.length + y * rowBytes;
|
|
6585
6876
|
for (let x = 0; x < img.width; x++) {
|
|
6586
|
-
let idx = (y * img.width + x) * 4;
|
|
6587
|
-
if (
|
|
6877
|
+
let idx = (y * img.width + x) * 4, bit = 0.299 * img.data[idx] + 0.587 * img.data[idx + 1] + 0.114 * img.data[idx + 2] < 128 ? 1 : 0;
|
|
6878
|
+
if (ascii) {
|
|
6879
|
+
text.push(String(bit));
|
|
6880
|
+
continue;
|
|
6881
|
+
}
|
|
6882
|
+
if (bit) {
|
|
6588
6883
|
let bIdx = rowOffset + (x >>> 3);
|
|
6589
6884
|
out[bIdx] = (out[bIdx] ?? 0) | 1 << 7 - (x & 7);
|
|
6590
6885
|
}
|
|
6591
6886
|
}
|
|
6592
6887
|
}
|
|
6593
|
-
return
|
|
6888
|
+
return ascii ? new TextEncoder().encode(header + text.join(`
|
|
6889
|
+
`) + `
|
|
6890
|
+
`) : out;
|
|
6594
6891
|
}
|
|
6595
6892
|
function readBmpMetadata(bytes) {
|
|
6596
6893
|
let view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength), width = Math.abs(view.getInt32(18, !0)), height = Math.abs(view.getInt32(22, !0)), bpp = view.getUint16(28, !0), ppmX = view.getInt32(38, !0), density = ppmX > 0 ? Math.max(1, Math.round(ppmX * 0.0254)) : 72;
|
|
@@ -6653,11 +6950,18 @@ function encodeBmpImage(img) {
|
|
|
6653
6950
|
return out;
|
|
6654
6951
|
}
|
|
6655
6952
|
function encodeTiffImage(img, options) {
|
|
6656
|
-
let
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6953
|
+
let pages = img.tiffPages ?? [img], layouts = [], end = 0;
|
|
6954
|
+
for (let index = 0; index < pages.length; index++)
|
|
6955
|
+
layouts[index] = createTiffLayout(pages[index], options, end, index + 1 < pages.length), end = layouts[index].end;
|
|
6956
|
+
let out = new Uint8Array(end), offset = 0;
|
|
6957
|
+
for (let index = 0; index < pages.length; index++) {
|
|
6958
|
+
let page = pages[index], { header, directory, channels, padding } = layouts[index], pixelBytes = page.width * page.height * channels;
|
|
6959
|
+
if (out.set(index === 0 ? header : directory, offset), offset += index === 0 ? header.length : directory.length, channels === 4) out.set(page.data.subarray(0, pixelBytes), offset);
|
|
6960
|
+
else for (let src = 0, dst = offset; dst < offset + pixelBytes; src += 4)
|
|
6961
|
+
out[dst++] = page.data[src], channels === 2 && (out[dst++] = page.data[src + 3]);
|
|
6962
|
+
offset += pixelBytes + padding, index === 0 && (out.set(directory, offset), offset += directory.length);
|
|
6963
|
+
}
|
|
6964
|
+
return out;
|
|
6661
6965
|
}
|
|
6662
6966
|
function readTiffTagValues(view, entryPos, le) {
|
|
6663
6967
|
let type = view.getUint16(entryPos + 2, le), count = view.getUint32(entryPos + 4, le), elemSize = type === 3 ? 2 : type === 4 ? 4 : type === 5 ? 8 : 1, valPos = count * elemSize <= 4 ? entryPos + 8 : view.getUint32(entryPos + 8, le), values = [];
|
|
@@ -6734,7 +7038,7 @@ function decodeTiffLzw(src, expectedLen) {
|
|
|
6734
7038
|
return out;
|
|
6735
7039
|
}
|
|
6736
7040
|
function decodeTiffImage(bytes) {
|
|
6737
|
-
let le = bytes[0] === 73, view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength), ifdOffset = view.getUint32(4, le), numEntries = view.getUint16(ifdOffset, le), width = 0, height = 0, bitsPerSample = 8, compression = 1, photometric = 2, stripOffsets = [8], stripByteCounts = [], tileWidth = 0, tileLength = 0, tileOffsets = [], tileByteCounts = [], samplesPerPixel = 4, rowsPerStrip = 0, predictor = 1, xRes = 72, resUnit = 2, orientation, jpegTables;
|
|
7041
|
+
let le = bytes[0] === 73, view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength), ifdOffset = view.getUint32(4, le), numEntries = view.getUint16(ifdOffset, le), width = 0, height = 0, bitsPerSample = 8, compression = 1, photometric = 2, stripOffsets = [8], stripByteCounts = [], tileWidth = 0, tileLength = 0, tileOffsets = [], tileByteCounts = [], samplesPerPixel = 4, rowsPerStrip = 0, predictor = 1, xRes = 72, yRes = 72, resUnit = 2, orientation, properties, jpegTables;
|
|
6738
7042
|
for (let i = 0; i < numEntries; i++) {
|
|
6739
7043
|
let p = ifdOffset + 2 + i * 12, tag = view.getUint16(p, le), vals = readTiffTagValues(view, p, le), first = vals[0] ?? 0;
|
|
6740
7044
|
if (tag === 256) width = first;
|
|
@@ -6742,13 +7046,15 @@ function decodeTiffImage(bytes) {
|
|
|
6742
7046
|
else if (tag === 258 && first > 0) bitsPerSample = first;
|
|
6743
7047
|
else if (tag === 259 && first > 0) compression = first;
|
|
6744
7048
|
else if (tag === 262) photometric = first;
|
|
7049
|
+
else if (tag === 270) properties = { comment: new TextDecoder().decode(new Uint8Array(vals.slice(0, vals.indexOf(0) < 0 ? vals.length : vals.indexOf(0)))) };
|
|
6745
7050
|
else if (tag === 273 && vals.length > 0) stripOffsets = vals;
|
|
6746
7051
|
else if (tag === 274 && first >= 1 && first <= 8) orientation = first;
|
|
6747
7052
|
else if (tag === 277 && first > 0) samplesPerPixel = first;
|
|
6748
7053
|
else if (tag === 278 && first > 0) rowsPerStrip = first;
|
|
6749
7054
|
else if (tag === 279 && vals.length > 0) stripByteCounts = vals;
|
|
6750
7055
|
else if (tag === 282 && first > 0) xRes = first;
|
|
6751
|
-
else if (tag ===
|
|
7056
|
+
else if (tag === 283 && first > 0) yRes = first;
|
|
7057
|
+
else if (tag === 296 && (first === 1 || first === 2 || first === 3)) resUnit = first;
|
|
6752
7058
|
else if (tag === 317 && first > 0) predictor = first;
|
|
6753
7059
|
else if (tag === 322 && first > 0) tileWidth = first;
|
|
6754
7060
|
else if (tag === 323 && first > 0) tileLength = first;
|
|
@@ -6841,7 +7147,9 @@ function decodeTiffImage(bytes) {
|
|
|
6841
7147
|
depth: bitsPerSample === 16 ? "ushort" : "uchar",
|
|
6842
7148
|
bitsPerSample,
|
|
6843
7149
|
density,
|
|
7150
|
+
resolution: { x: xRes, y: yRes, unit: resUnit === 3 ? "cm" : resUnit === 1 ? "unknown" : "inch" },
|
|
6844
7151
|
hasAlpha: samplesPerPixel === 2 || samplesPerPixel === 4,
|
|
7152
|
+
...properties ? { properties } : {},
|
|
6845
7153
|
...orientation !== void 0 ? { orientation } : {}
|
|
6846
7154
|
};
|
|
6847
7155
|
}
|
|
@@ -6855,7 +7163,7 @@ function detectImageFormat(bytes) {
|
|
|
6855
7163
|
if (isGifBytes(bytes)) return "gif";
|
|
6856
7164
|
if (isNetpbmBytes(bytes)) {
|
|
6857
7165
|
let m = String.fromCharCode(bytes[0], bytes[1]);
|
|
6858
|
-
return m === "P1" || m === "P4" ? "pbm" : m === "P2" || m === "P5" ? "pgm" : "ppm";
|
|
7166
|
+
return m === "P7" ? "pam" : m === "P1" || m === "P4" ? "pbm" : m === "P2" || m === "P5" ? "pgm" : "ppm";
|
|
6859
7167
|
}
|
|
6860
7168
|
if (isBmpBytes(bytes)) return "bmp";
|
|
6861
7169
|
if (isTiffBytes(bytes)) return "tiff";
|
|
@@ -6935,6 +7243,7 @@ function readImageMetadata(bytes, options) {
|
|
|
6935
7243
|
case "gif":
|
|
6936
7244
|
meta = readGifMetadata(bytes, options);
|
|
6937
7245
|
break;
|
|
7246
|
+
case "pam":
|
|
6938
7247
|
case "ppm":
|
|
6939
7248
|
case "pgm":
|
|
6940
7249
|
case "pbm":
|
|
@@ -6946,6 +7255,7 @@ function readImageMetadata(bytes, options) {
|
|
|
6946
7255
|
case "tiff": {
|
|
6947
7256
|
let decoded = decodeTiffImage(bytes);
|
|
6948
7257
|
meta = {
|
|
7258
|
+
...decoded.properties ? { properties: decoded.properties } : {},
|
|
6949
7259
|
format: "tiff",
|
|
6950
7260
|
width: decoded.width,
|
|
6951
7261
|
height: decoded.height,
|
|
@@ -6954,6 +7264,7 @@ function readImageMetadata(bytes, options) {
|
|
|
6954
7264
|
depth: decoded.depth,
|
|
6955
7265
|
...decoded.bitsPerSample !== void 0 ? { bitsPerSample: decoded.bitsPerSample } : {},
|
|
6956
7266
|
density: decoded.density,
|
|
7267
|
+
...decoded.resolution ? { resolution: decoded.resolution } : {},
|
|
6957
7268
|
hasAlpha: decoded.hasAlpha,
|
|
6958
7269
|
...decoded.orientation !== void 0 ? { orientation: decoded.orientation } : {},
|
|
6959
7270
|
size: bytes.byteLength
|
|
@@ -7073,10 +7384,11 @@ function decodeImage(bytes, options) {
|
|
|
7073
7384
|
case "gif":
|
|
7074
7385
|
decoded = decodeGifImage(bytes, options);
|
|
7075
7386
|
break;
|
|
7387
|
+
case "pam":
|
|
7076
7388
|
case "ppm":
|
|
7077
7389
|
case "pgm":
|
|
7078
7390
|
case "pbm":
|
|
7079
|
-
decoded = decodeNetpbmImage(bytes);
|
|
7391
|
+
decoded = decodeNetpbmImage(bytes, options?.page);
|
|
7080
7392
|
break;
|
|
7081
7393
|
case "bmp":
|
|
7082
7394
|
decoded = decodeBmpImage(bytes);
|
|
@@ -7098,11 +7410,14 @@ function decodeImage(bytes, options) {
|
|
|
7098
7410
|
function encodeImage(img, options) {
|
|
7099
7411
|
let fmt = imageOutputFormat(img.format, options.format);
|
|
7100
7412
|
switch (fmt) {
|
|
7413
|
+
case "miff":
|
|
7414
|
+
return { data: encodeMiffImage(img), format: "miff", channels: 4 };
|
|
7101
7415
|
case "png": {
|
|
7102
7416
|
let data = encodePngImage(img, {
|
|
7417
|
+
...options.omitPngResolution ? { omitPngResolution: !0 } : {},
|
|
7103
7418
|
...options.compressionLevel !== void 0 ? { compressionLevel: options.compressionLevel } : {},
|
|
7104
7419
|
...options.consumeInput ? { consumeInput: !0 } : {},
|
|
7105
|
-
density: options.density
|
|
7420
|
+
...options.density === void 0 ? {} : { density: options.density },
|
|
7106
7421
|
...options.orientation !== void 0 ? { orientation: options.orientation } : img.orientation !== void 0 ? { orientation: img.orientation } : {}
|
|
7107
7422
|
}), outChannels = img.space === "b-w" || img.channels === 1 || img.channels === 2 ? img.hasAlpha ? 2 : 1 : img.hasAlpha ? 4 : 3;
|
|
7108
7423
|
return { data, format: "png", channels: outChannels };
|
|
@@ -7112,7 +7427,7 @@ function encodeImage(img, options) {
|
|
|
7112
7427
|
quality: options.quality ?? 85,
|
|
7113
7428
|
...options.samplingFactor === void 0 ? {} : { samplingFactor: options.samplingFactor },
|
|
7114
7429
|
...options.chromaSubsampling === void 0 ? {} : { chromaSubsampling: options.chromaSubsampling },
|
|
7115
|
-
density: options.density
|
|
7430
|
+
...options.density === void 0 ? {} : { density: options.density },
|
|
7116
7431
|
...options.orientation !== void 0 ? { orientation: options.orientation } : {}
|
|
7117
7432
|
}), format: "jpeg", channels: 3 };
|
|
7118
7433
|
case "webp": {
|
|
@@ -7144,18 +7459,20 @@ function encodeImage(img, options) {
|
|
|
7144
7459
|
...options.loop !== void 0 ? { loop: options.loop } : {},
|
|
7145
7460
|
...options.optimizeFrames ? { optimizeFrames: !0 } : {}
|
|
7146
7461
|
}), format: "gif", channels: 4 };
|
|
7462
|
+
case "pam":
|
|
7463
|
+
return { data: encodePpm(img, options.netpbmDepth, !1, !0), format: "pam", channels: img.hasAlpha ? 4 : 3 };
|
|
7147
7464
|
case "ppm":
|
|
7148
|
-
return { data: encodePpm(img), format: "ppm", channels: 3 };
|
|
7465
|
+
return { data: encodePpm(img, options.netpbmDepth, options.netpbmAscii), format: "ppm", channels: 3 };
|
|
7149
7466
|
case "pgm":
|
|
7150
|
-
return { data: encodePgm(img), format: "pgm", channels: 1 };
|
|
7467
|
+
return { data: encodePgm(img, options.netpbmDepth, options.netpbmAscii), format: "pgm", channels: 1 };
|
|
7151
7468
|
case "pbm":
|
|
7152
|
-
return { data: encodePbm(img), format: "pbm", channels: 1 };
|
|
7469
|
+
return { data: encodePbm(img, options.netpbmAscii), format: "pbm", channels: 1 };
|
|
7153
7470
|
case "bmp":
|
|
7154
7471
|
return { data: encodeBmpImage(img), format: "bmp", channels: 3 };
|
|
7155
7472
|
case "tiff": {
|
|
7156
7473
|
let orientation = options.orientation ?? img.orientation;
|
|
7157
7474
|
return { data: encodeTiffImage(img, {
|
|
7158
|
-
density: options.density
|
|
7475
|
+
...options.density === void 0 ? {} : { density: options.density },
|
|
7159
7476
|
...orientation !== void 0 ? { orientation } : {}
|
|
7160
7477
|
}), format: "tiff", channels: tiffChannels(img) };
|
|
7161
7478
|
}
|
|
@@ -7395,33 +7712,41 @@ async function* encodeGifFromStorage(image, storage, signal, options = {}) {
|
|
|
7395
7712
|
// src/codecs/tiff-storage.ts
|
|
7396
7713
|
async function* encodeTiffFromStorage(image, storage, signal, options = {}) {
|
|
7397
7714
|
signal.throwIfAborted();
|
|
7398
|
-
let
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
let
|
|
7405
|
-
|
|
7406
|
-
let
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7715
|
+
let end = 0, count = image.storedTiffPages?.length ?? 1;
|
|
7716
|
+
for (let index = 0; index < count; index++) {
|
|
7717
|
+
let page = image.storedTiffPages ? await image.storedTiffPages.at(index) : image;
|
|
7718
|
+
signal.throwIfAborted();
|
|
7719
|
+
let { width, height, position } = page, length = width * height * 4;
|
|
7720
|
+
if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0 || !Number.isSafeInteger(length) || !Number.isSafeInteger(position) || position < 0 || !Number.isSafeInteger(position + length)) throw new RangeError("Invalid TIFF backing dimensions");
|
|
7721
|
+
let { header, directory, channels, padding, end: nextEnd } = createTiffLayout(page, options, end, index + 1 < count);
|
|
7722
|
+
end = nextEnd, yield index === 0 ? header : directory;
|
|
7723
|
+
for (let offset = 0; offset < length; offset += 4096) {
|
|
7724
|
+
signal.throwIfAborted(), offset % 65536 === 0 && await defaultRuntime.yieldTurn(signal);
|
|
7725
|
+
let size = Math.min(4096, length - offset), bytes = await storage.read(position + offset, size, { signal });
|
|
7726
|
+
if (signal.throwIfAborted(), !(bytes instanceof Uint8Array) || bytes.length !== size) throw new Error("Truncated TIFF backing storage");
|
|
7727
|
+
let output = new Uint8Array(size / 4 * channels);
|
|
7728
|
+
if (channels === 4) output.set(bytes);
|
|
7729
|
+
else for (let src = 0, dst = 0; src < size; src += 4)
|
|
7730
|
+
output[dst++] = bytes[src], channels === 2 && (output[dst++] = bytes[src + 3]);
|
|
7731
|
+
yield output;
|
|
7732
|
+
}
|
|
7733
|
+
signal.throwIfAborted(), padding && (yield new Uint8Array(padding)), signal.throwIfAborted(), index === 0 && (yield directory);
|
|
7411
7734
|
}
|
|
7412
|
-
signal.throwIfAborted(), padding && (yield new Uint8Array(padding)), signal.throwIfAborted(), yield directory;
|
|
7413
7735
|
}
|
|
7414
7736
|
|
|
7415
7737
|
// src/codecs/netpbm-storage.ts
|
|
7416
7738
|
async function decodeNetpbmToStorage(source, storage, signal, options) {
|
|
7417
7739
|
signal.throwIfAborted();
|
|
7418
|
-
let reader = new SourceBytes(source, signal, "Netpbm"), steps =
|
|
7740
|
+
let reader = new SourceBytes(source, signal, "Netpbm"), steps = netpbmSequenceSteps(source.size, options?.page ?? 0), next = steps.next();
|
|
7419
7741
|
for (; !next.done; ) next = steps.next(await reader.at(next.value));
|
|
7420
|
-
let { width, height, maxval, magic, format, dataOffset } = next.value;
|
|
7421
|
-
if (!["P1", "P2", "P3", "P4", "P5", "P6"].includes(magic)) throw new Error("Invalid Netpbm signature");
|
|
7742
|
+
let { width, height, maxval, magic, format, dataOffset, channels, hasAlpha } = next.value.header;
|
|
7743
|
+
if (!["P1", "P2", "P3", "P4", "P5", "P6", "P7"].includes(magic)) throw new Error("Invalid Netpbm signature");
|
|
7422
7744
|
if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0 || !Number.isSafeInteger(width * height * 4)) throw new RangeError("Invalid Netpbm dimensions");
|
|
7423
|
-
checkLimitInputPixels(width, height, options);
|
|
7424
|
-
|
|
7745
|
+
if (checkLimitInputPixels(width, height, options), magic === "P6" && source.size - dataOffset < width * height * 3 * (maxval > 255 ? 2 : 1)) throw new Error("Truncated PPM raster");
|
|
7746
|
+
if (magic === "P7" && source.size - dataOffset < width * height * channels * (maxval > 255 ? 2 : 1)) throw new Error("Truncated PAM raster");
|
|
7747
|
+
let metadata = { width, height, position: 0, format, space: channels >= 3 ? "srgb" : "b-w", channels, depth: format === "pbm" ? "bit" : maxval > 255 ? "ushort" : "uchar", density: 72, hasAlpha }, output = new Output(metadata, width, height, storage, signal), position = dataOffset, storedData16 = maxval > 255 ? { position: storage.allocate(width * height * 8), length: width * height * 4 } : void 0, samples16 = storedData16 ? new Uint16Array(2048) : void 0, used16 = 0, offset16 = 0, flush16 = async () => {
|
|
7748
|
+
!storedData16 || !samples16 || !used16 || (await storage.write(storedData16.position + offset16, new Uint8Array(samples16.buffer, 0, used16 * 2), { signal }), offset16 += used16 * 2, used16 = 0);
|
|
7749
|
+
}, ascii = async () => {
|
|
7425
7750
|
for (; position < source.size; ) {
|
|
7426
7751
|
let value2 = await reader.at(position);
|
|
7427
7752
|
if (value2 === 35)
|
|
@@ -7448,30 +7773,79 @@ async function decodeNetpbmToStorage(source, storage, signal, options) {
|
|
|
7448
7773
|
} else if (magic === "P1") {
|
|
7449
7774
|
let g = await ascii() === 1 ? 0 : 255;
|
|
7450
7775
|
await output.pixel(g, g, g, 255);
|
|
7451
|
-
} else
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
}
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7776
|
+
} else {
|
|
7777
|
+
let r = await sample(), g = channels >= 3 ? await sample() : r, b = channels >= 3 ? await sample() : r, a = hasAlpha ? await sample() : maxval;
|
|
7778
|
+
if (await output.pixel(Math.round(r * 255 / maxval), Math.round(g * 255 / maxval), Math.round(b * 255 / maxval), hasAlpha ? Math.round(a * 255 / maxval) : 255), samples16) {
|
|
7779
|
+
for (let value of [r, g, b, a]) samples16[used16++] = Math.round(value * 65535 / maxval);
|
|
7780
|
+
used16 === samples16.length && await flush16();
|
|
7781
|
+
}
|
|
7782
|
+
}
|
|
7783
|
+
return await flush16(), { ...await output.finish(), ...storedData16 ? { storedData16 } : {} };
|
|
7784
|
+
}
|
|
7785
|
+
async function* encodeNetpbmFromStorage(image, storage, signal, format, depth = image.storedData16 ? 16 : 8, ascii = !1) {
|
|
7786
|
+
if (signal.throwIfAborted(), format !== "pam" && format !== "ppm" && format !== "pgm" && format !== "pbm") throw new Error(`Unsupported Netpbm output format: ${format}`);
|
|
7787
|
+
if (!Number.isInteger(depth) || depth < 1 || depth > 16) throw new RangeError("Invalid Netpbm depth");
|
|
7788
|
+
let maximum = 2 ** depth - 1;
|
|
7789
|
+
format === "pam" && (ascii = !1);
|
|
7790
|
+
let channels = format === "pam" ? image.hasAlpha ? 4 : 3 : format === "ppm" ? 3 : 1, pamHeader = `P7
|
|
7791
|
+
WIDTH ${image.width}
|
|
7792
|
+
HEIGHT ${image.height}
|
|
7793
|
+
DEPTH ${channels}
|
|
7794
|
+
MAXVAL ${maximum}
|
|
7795
|
+
TUPLTYPE ${image.hasAlpha ? "RGB_ALPHA" : "RGB"}
|
|
7796
|
+
ENDHDR
|
|
7797
|
+
`, { width, height, position } = image;
|
|
7461
7798
|
if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0 || !Number.isSafeInteger(width * height * 4) || !Number.isSafeInteger(position) || position < 0 || !Number.isSafeInteger(position + width * height * 4)) throw new RangeError("Invalid Netpbm backing dimensions");
|
|
7462
|
-
|
|
7799
|
+
if (format !== "pbm" && image.storedData16) {
|
|
7800
|
+
let samples = image.storedData16, count = width * height;
|
|
7801
|
+
if (!Number.isSafeInteger(samples.position) || samples.position < 0 || !Number.isSafeInteger(samples.position + count * 8) || !Number.isSafeInteger(samples.length) || samples.length < count * 4) throw new RangeError("Invalid Netpbm sample backing");
|
|
7802
|
+
yield new TextEncoder().encode(format === "pam" ? pamHeader : `${format === "ppm" ? ascii ? "P3" : "P6" : ascii ? "P2" : "P5"}
|
|
7463
7803
|
${width} ${height}
|
|
7464
|
-
${
|
|
7804
|
+
${maximum}
|
|
7805
|
+
`);
|
|
7806
|
+
for (let offset = 0; offset < count; offset += 512) {
|
|
7807
|
+
signal.throwIfAborted(), offset % 16384 === 0 && await defaultRuntime.yieldTurn(signal);
|
|
7808
|
+
let pixels2 = Math.min(512, count - offset), length = pixels2 * 8, bytes = await storage.read(samples.position + offset * 8, length, { signal });
|
|
7809
|
+
if (signal.throwIfAborted(), bytes.length !== length) throw new Error("Truncated Netpbm sample storage");
|
|
7810
|
+
let data = new Uint16Array(new Uint8Array(bytes).buffer), out = new Uint8Array(ascii ? 0 : pixels2 * channels * (depth > 8 ? 2 : 1)), dst = 0, text = [];
|
|
7811
|
+
for (let i = 0; i < pixels2; i++) {
|
|
7812
|
+
let r = data[i * 4], g = data[i * 4 + 1], b = data[i * 4 + 2];
|
|
7813
|
+
for (let value of format === "pam" ? image.hasAlpha ? [r, g, b, data[i * 4 + 3]] : [r, g, b] : format === "ppm" ? [r, g, b] : [0.212656 * r + 0.715158 * g + 0.072186 * b]) {
|
|
7814
|
+
let scaled = Math.round(value * maximum / 65535);
|
|
7815
|
+
if (ascii) {
|
|
7816
|
+
text.push(String(scaled));
|
|
7817
|
+
continue;
|
|
7818
|
+
}
|
|
7819
|
+
depth > 8 && (out[dst++] = scaled >>> 8), out[dst++] = scaled & 255;
|
|
7820
|
+
}
|
|
7821
|
+
}
|
|
7822
|
+
yield ascii ? new TextEncoder().encode(text.join(`
|
|
7823
|
+
`) + `
|
|
7824
|
+
`) : out;
|
|
7825
|
+
}
|
|
7826
|
+
return;
|
|
7827
|
+
}
|
|
7828
|
+
yield new TextEncoder().encode(format === "pam" ? pamHeader : `${format === "ppm" ? ascii ? "P3" : "P6" : format === "pgm" ? ascii ? "P2" : "P5" : ascii ? "P1" : "P4"}
|
|
7829
|
+
${width} ${height}
|
|
7830
|
+
${format === "pbm" ? "" : `${maximum}
|
|
7465
7831
|
`}`);
|
|
7466
7832
|
let pixels = new Pixels(image, storage, signal), buffer = new Uint8Array(4096), used = 0;
|
|
7467
7833
|
for (let y = 0; y < height; y++) {
|
|
7468
7834
|
let bits = 0;
|
|
7469
7835
|
for (let x = 0; x < width; x++) {
|
|
7470
7836
|
let value = await pixels.pixel(y * width + x), r = value & 255, g = value >>> 8 & 255, b = value >>> 16 & 255;
|
|
7471
|
-
if (format
|
|
7472
|
-
for (let channel of [r, g, b])
|
|
7473
|
-
|
|
7474
|
-
|
|
7837
|
+
if (format !== "pbm")
|
|
7838
|
+
for (let channel of format === "pam" ? image.hasAlpha ? [r, g, b, value >>> 24] : [r, g, b] : format === "ppm" ? [r, g, b] : [0.212656 * r + 0.715158 * g + 0.072186 * b]) {
|
|
7839
|
+
let scaled = Math.round(channel * maximum / 255);
|
|
7840
|
+
if (ascii) {
|
|
7841
|
+
for (let byte2 of new TextEncoder().encode(`${scaled}
|
|
7842
|
+
`))
|
|
7843
|
+
buffer[used++] = byte2, used === buffer.length && (yield new Uint8Array(buffer), used = 0);
|
|
7844
|
+
continue;
|
|
7845
|
+
}
|
|
7846
|
+
depth > 8 && (buffer[used++] = scaled >>> 8, used === buffer.length && (yield new Uint8Array(buffer), used = 0)), buffer[used++] = scaled & 255, used === buffer.length && (yield new Uint8Array(buffer), used = 0);
|
|
7847
|
+
}
|
|
7848
|
+
else ascii ? (buffer[used++] = 0.299 * r + 0.587 * g + 0.114 * b < 128 ? 49 : 48, used === buffer.length && (yield new Uint8Array(buffer), used = 0), buffer[used++] = 10) : (0.299 * r + 0.587 * g + 0.114 * b < 128 && (bits |= 1 << 7 - (x & 7)), ((x & 7) === 7 || x + 1 === width) && (buffer[used++] = bits, bits = 0));
|
|
7475
7849
|
used === buffer.length && (yield new Uint8Array(buffer), used = 0);
|
|
7476
7850
|
}
|
|
7477
7851
|
}
|
|
@@ -7529,16 +7903,16 @@ async function* encodeBmpFromStorage(image, storage, signal) {
|
|
|
7529
7903
|
|
|
7530
7904
|
// src/image-encode.ts
|
|
7531
7905
|
function isStoredOutputFormat(format) {
|
|
7532
|
-
return ["pdf", "heic", "heif", "avif", "raw", "png", "ppm", "pgm", "pbm", "bmp", "tiff", "gif", "jpeg", "webp"].includes(format);
|
|
7906
|
+
return ["miff", "pdf", "heic", "heif", "avif", "raw", "png", "pam", "ppm", "pgm", "pbm", "bmp", "tiff", "gif", "jpeg", "webp"].includes(format);
|
|
7533
7907
|
}
|
|
7534
7908
|
async function* encodeStoredImage(image, backing, signal, encoding) {
|
|
7535
7909
|
let format = imageOutputFormat(image.format, encoding.format);
|
|
7536
7910
|
if (!isStoredOutputFormat(format)) throw new UnsupportedStoredResource();
|
|
7537
7911
|
let size = 0;
|
|
7538
|
-
for await (let bytes of format === "pdf" ? encodePdfFromStorage(image, backing, signal) : ["heic", "heif", "avif"].includes(format) ? encodeHeifFromStorage(image, backing, signal, { ...encoding, format }) : format === "raw" ? encodeRawFromStorage(image, backing, signal, encoding) : format === "png" ? encodePngFromStorage(image, backing, signal, encoding) : format === "webp" ? encodeWebpFromStorage(image, backing, signal, encoding) : format === "jpeg" ? encodeJpegFromStorage(image, backing, signal, encoding) : format === "gif" ? encodeGifFromStorage(image, backing, signal, encoding) : format === "tiff" ? encodeTiffFromStorage(image, backing, signal, encoding) : format === "bmp" ? encodeBmpFromStorage(image, backing, signal) : encodeNetpbmFromStorage(image, backing, signal, format))
|
|
7912
|
+
for await (let bytes of format === "miff" ? encodeMiffFromStorage(image, backing, signal) : format === "pdf" ? encodePdfFromStorage(image, backing, signal) : ["heic", "heif", "avif"].includes(format) ? encodeHeifFromStorage(image, backing, signal, { ...encoding, format }) : format === "raw" ? encodeRawFromStorage(image, backing, signal, encoding) : format === "png" ? encodePngFromStorage(image, backing, signal, encoding) : format === "webp" ? encodeWebpFromStorage(image, backing, signal, encoding) : format === "jpeg" ? encodeJpegFromStorage(image, backing, signal, encoding) : format === "gif" ? encodeGifFromStorage(image, backing, signal, encoding) : format === "tiff" ? encodeTiffFromStorage(image, backing, signal, encoding) : format === "bmp" ? encodeBmpFromStorage(image, backing, signal) : encodeNetpbmFromStorage(image, backing, signal, format, encoding.netpbmDepth, encoding.netpbmAscii))
|
|
7539
7913
|
size += bytes.length, yield bytes;
|
|
7540
7914
|
let gray = image.space === "b-w" || image.channels === 1 || image.channels === 2;
|
|
7541
|
-
return { ...image.textAutofitDpi === void 0 ? {} : { textAutofitDpi: image.textAutofitDpi }, format, width: image.width, height: image.height, ...format === "raw" ? { depth: encoding.rawDepth ?? image.depth } : {}, channels: format === "raw" ? image.channels : format === "webp" || format === "pdf" ? image.hasAlpha ? 4 : 3 : format === "tiff" ? tiffChannels(image) : format === "gif" ? 4 : format === "ppm" || format === "bmp" || format === "jpeg" ? 3 : format === "pgm" || format === "pbm" ? 1 : gray ? image.hasAlpha ? 2 : 1 : image.hasAlpha ? 4 : 3, premultiplied: !!image.wasPremultiplied, ...image.pageHeight === void 0 ? {} : { pageHeight: image.pageHeight }, ...image.pageHeight !== void 0 && (image.sourcePages ?? image.pages) !== void 0 ? { pages: image.sourcePages ?? image.pages } : {}, ...image.trimOffsetLeft === void 0 ? {} : { trimOffsetLeft: image.trimOffsetLeft }, ...image.trimOffsetTop === void 0 ? {} : { trimOffsetTop: image.trimOffsetTop }, size };
|
|
7915
|
+
return { ...image.textAutofitDpi === void 0 ? {} : { textAutofitDpi: image.textAutofitDpi }, format, width: image.width, height: image.height, ...format === "raw" ? { depth: encoding.rawDepth ?? image.depth } : {}, channels: format === "miff" ? 4 : format === "raw" ? image.channels : format === "pam" || format === "webp" || format === "pdf" ? image.hasAlpha ? 4 : 3 : format === "tiff" ? tiffChannels(image) : format === "gif" ? 4 : format === "ppm" || format === "bmp" || format === "jpeg" ? 3 : format === "pgm" || format === "pbm" ? 1 : gray ? image.hasAlpha ? 2 : 1 : image.hasAlpha ? 4 : 3, premultiplied: !!image.wasPremultiplied, ...image.pageHeight === void 0 ? {} : { pageHeight: image.pageHeight }, ...image.pageHeight !== void 0 && (image.sourcePages ?? image.pages) !== void 0 ? { pages: image.sourcePages ?? image.pages } : {}, ...image.trimOffsetLeft === void 0 ? {} : { trimOffsetLeft: image.trimOffsetLeft }, ...image.trimOffsetTop === void 0 ? {} : { trimOffsetTop: image.trimOffsetTop }, size };
|
|
7542
7916
|
}
|
|
7543
7917
|
|
|
7544
7918
|
// src/codecs/resource-storage.ts
|
|
@@ -11361,7 +11735,7 @@ async function readGifMetadataFromSource(source, storage, signal, options) {
|
|
|
11361
11735
|
let captured = { ...options }, reader = new SourceBytes(source, signal, "GIF"), header = new Uint8Array(Math.min(13, source.size));
|
|
11362
11736
|
for (let i = 0; i < header.length; i++) header[i] = await reader.at(i) ?? 0;
|
|
11363
11737
|
if (!isGifBytes(header) || header.length < 13) throw new Error("Invalid GIF header");
|
|
11364
|
-
let start = 13 + (header[10] & 128 ? 3 * (1 << (header[10] & 7) + 1) : 0), { frames, loop } = await scanGifAnimation(reader, source.size, start), metadata = gifMetadataFields(header[6] | header[7] << 8, header[8] | header[9] << 8, source.size, frames, loop, captured);
|
|
11738
|
+
let start = 13 + (header[10] & 128 ? 3 * (1 << (header[10] & 7) + 1) : 0), { frames, loop, properties } = await scanGifAnimation(reader, source.size, start), metadata = { ...properties ? { properties } : {}, ...gifMetadataFields(header[6] | header[7] << 8, header[8] | header[9] << 8, source.size, frames, loop, captured) };
|
|
11365
11739
|
if (!frames) return metadata;
|
|
11366
11740
|
let position = storage.allocate(frames * 4);
|
|
11367
11741
|
if (!Number.isSafeInteger(position) || position < 0 || !Number.isSafeInteger(position + frames * 4)) throw new RangeError("Invalid GIF delay storage");
|
|
@@ -11432,7 +11806,7 @@ async function decodeGifToStorage(source, storage, signal, options) {
|
|
|
11432
11806
|
at2 += length;
|
|
11433
11807
|
}
|
|
11434
11808
|
return at2;
|
|
11435
|
-
}, { frames, loop } = await scanGifAnimation(reader, source.size, start), totalPages = Math.max(1, frames), multi = options?.coalesce !== !1 && (options?.animated === !0 || options?.pages === -1 || options?.pages !== void 0 && options.pages > 1), page = Math.max(0, options?.page ?? 0), pages = multi ? options?.pages !== void 0 && options.pages > 0 ? Math.min(options.pages, Math.max(1, totalPages - page)) : Math.max(1, totalPages - page) : 1, end = page + pages - 1;
|
|
11809
|
+
}, { frames, loop, properties } = await scanGifAnimation(reader, source.size, start), totalPages = Math.max(1, frames), multi = options?.coalesce !== !1 && (options?.animated === !0 || options?.pages === -1 || options?.pages !== void 0 && options.pages > 1), page = Math.max(0, options?.page ?? 0), pages = multi ? options?.pages !== void 0 && options.pages > 0 ? Math.min(options.pages, Math.max(1, totalPages - page)) : Math.max(1, totalPages - page) : 1, end = page + pages - 1;
|
|
11436
11810
|
if (!Number.isSafeInteger(frameBytes * pages)) throw new RangeError("Invalid GIF dimensions");
|
|
11437
11811
|
checkLimitInputPixels(width, height * pages, options);
|
|
11438
11812
|
let allocate = (length) => {
|
|
@@ -11537,6 +11911,7 @@ async function decodeGifToStorage(source, storage, signal, options) {
|
|
|
11537
11911
|
height: height * (virtualCanvas ? 1 : pages),
|
|
11538
11912
|
...virtualCanvas ? { virtualCanvas, disposal } : {},
|
|
11539
11913
|
...backgroundColor ? { backgroundColor } : {},
|
|
11914
|
+
...properties ? { properties } : {},
|
|
11540
11915
|
position: output,
|
|
11541
11916
|
format: "gif",
|
|
11542
11917
|
space: "srgb",
|
|
@@ -11652,7 +12027,7 @@ async function decodeTiffToStorage(source, storage, signal, options) {
|
|
|
11652
12027
|
let value = 0;
|
|
11653
12028
|
for (let i = 0; i < size; i++) value += await byte2(at + i) * 2 ** (8 * (le ? i : size - i - 1));
|
|
11654
12029
|
return value;
|
|
11655
|
-
}, ifd = await number(4, 4), count = await number(ifd, 2), width = 0, height = 0, bits = 8, compression = 1, photometric = 2, samples = 4, rows = 0, predictor = 1, xRes = 72, resUnit = 2, tileWidth = 0, tileHeight = 0, orientation, jpegTables, offsets = { count: 1, async at(i) {
|
|
12030
|
+
}, ifd = await number(4, 4), count = await number(ifd, 2), width = 0, height = 0, bits = 8, compression = 1, photometric = 2, samples = 4, rows = 0, predictor = 1, xRes = 72, yRes = 72, resUnit = 2, tileWidth = 0, tileHeight = 0, orientation, properties, jpegTables, offsets = { count: 1, async at(i) {
|
|
11656
12031
|
return i === 0 ? 8 : void 0;
|
|
11657
12032
|
} }, counts = empty, tileOffsets = empty, tileCounts = empty;
|
|
11658
12033
|
for (let i = 0; i < count; i++) {
|
|
@@ -11663,6 +12038,16 @@ async function decodeTiffToStorage(source, storage, signal, options) {
|
|
|
11663
12038
|
let num = await number(at, 4), den = await number(at + 4, 4);
|
|
11664
12039
|
return den > 0 ? num / den : num;
|
|
11665
12040
|
} }, first = await values.at(0) ?? 0;
|
|
12041
|
+
if (tag === 270 && type === 2) {
|
|
12042
|
+
if (available > 16 * 1024 * 1024) throw new Error("TIFF comment exceeds 16 MiB");
|
|
12043
|
+
let text = [];
|
|
12044
|
+
for (let j = 0; j < available; j++) {
|
|
12045
|
+
let value = await values.at(j);
|
|
12046
|
+
if (!value) break;
|
|
12047
|
+
text.push(value);
|
|
12048
|
+
}
|
|
12049
|
+
properties = { comment: new TextDecoder().decode(new Uint8Array(text)) };
|
|
12050
|
+
}
|
|
11666
12051
|
if (tag === 256) width = first;
|
|
11667
12052
|
else if (tag === 257) height = first;
|
|
11668
12053
|
else if (tag === 258 && first > 0) bits = first;
|
|
@@ -11674,7 +12059,8 @@ async function decodeTiffToStorage(source, storage, signal, options) {
|
|
|
11674
12059
|
else if (tag === 278 && first > 0) rows = first;
|
|
11675
12060
|
else if (tag === 279 && available) counts = values;
|
|
11676
12061
|
else if (tag === 282 && first > 0) xRes = first;
|
|
11677
|
-
else if (tag ===
|
|
12062
|
+
else if (tag === 283 && first > 0) yRes = first;
|
|
12063
|
+
else if (tag === 296 && (first === 1 || first === 2 || first === 3)) resUnit = first;
|
|
11678
12064
|
else if (tag === 317 && first > 0) predictor = first;
|
|
11679
12065
|
else if (tag === 322 && first > 0) tileWidth = first;
|
|
11680
12066
|
else if (tag === 323 && first > 0) tileHeight = first;
|
|
@@ -11828,7 +12214,7 @@ async function decodeTiffToStorage(source, storage, signal, options) {
|
|
|
11828
12214
|
}
|
|
11829
12215
|
await predict(combined, total, height, stride);
|
|
11830
12216
|
}
|
|
11831
|
-
let metadata = { width, height, position: combined, format: "tiff", space: samples < 3 ? bits === 16 ? "grey16" : "b-w" : bits === 16 ? "rgb16" : "srgb", channels: samples === 4 ? 4 : samples === 1 ? 1 : samples === 2 ? 2 : 3, depth: bits === 16 ? "ushort" : "uchar", bitsPerSample: bits, density: Math.max(1, Math.round(xRes * (resUnit === 3 ? 2.54 : 1))), hasAlpha: samples === 2 || samples === 4, ...orientation === void 0 ? {} : { orientation } }, raster = new Raster(combined, total, storage, signal), output = new Output(metadata, width, height, storage, signal);
|
|
12217
|
+
let metadata = { ...properties ? { properties } : {}, width, height, position: combined, format: "tiff", space: samples < 3 ? bits === 16 ? "grey16" : "b-w" : bits === 16 ? "rgb16" : "srgb", channels: samples === 4 ? 4 : samples === 1 ? 1 : samples === 2 ? 2 : 3, depth: bits === 16 ? "ushort" : "uchar", bitsPerSample: bits, density: Math.max(1, Math.round(xRes * (resUnit === 3 ? 2.54 : 1))), resolution: { x: xRes, y: yRes, unit: resUnit === 3 ? "cm" : resUnit === 1 ? "unknown" : "inch" }, hasAlpha: samples === 2 || samples === 4, ...orientation === void 0 ? {} : { orientation } }, raster = new Raster(combined, total, storage, signal), output = new Output(metadata, width, height, storage, signal);
|
|
11832
12218
|
for (let i = 0; i < width * height; i++) {
|
|
11833
12219
|
let base = i * pixelBytes + (sampleBytes === 2 && le ? 1 : 0), r = await raster.at(base);
|
|
11834
12220
|
if (samples < 3) {
|
|
@@ -12180,6 +12566,7 @@ async function readImageMetadataFromSource(source, signal, options, storage) {
|
|
|
12180
12566
|
if (!storage) throw new UnsupportedStoredResource();
|
|
12181
12567
|
let decoded = await decodeTiffToStorage(source, storage, signal);
|
|
12182
12568
|
metadata = {
|
|
12569
|
+
...decoded.properties ? { properties: decoded.properties } : {},
|
|
12183
12570
|
format: "tiff",
|
|
12184
12571
|
width: decoded.width,
|
|
12185
12572
|
height: decoded.height,
|
|
@@ -12188,16 +12575,17 @@ async function readImageMetadataFromSource(source, signal, options, storage) {
|
|
|
12188
12575
|
depth: decoded.depth,
|
|
12189
12576
|
...decoded.bitsPerSample === void 0 ? {} : { bitsPerSample: decoded.bitsPerSample },
|
|
12190
12577
|
density: decoded.density,
|
|
12578
|
+
...decoded.resolution ? { resolution: decoded.resolution } : {},
|
|
12191
12579
|
hasAlpha: decoded.hasAlpha,
|
|
12192
12580
|
...decoded.orientation === void 0 ? {} : { orientation: decoded.orientation },
|
|
12193
12581
|
size: source.size
|
|
12194
12582
|
};
|
|
12195
12583
|
} else if (isBmpBytes(prefix)) metadata = { ...readBmpMetadata(prefix), size: source.size };
|
|
12196
12584
|
else if (isNetpbmBytes(prefix)) {
|
|
12197
|
-
let reader = new SourceBytes(source, signal, "Netpbm"), steps =
|
|
12585
|
+
let reader = new SourceBytes(source, signal, "Netpbm"), steps = netpbmSequenceSteps(source.size), next = steps.next();
|
|
12198
12586
|
for (; !next.done; ) next = steps.next(await reader.at(next.value));
|
|
12199
|
-
let { format, width, height, maxval } = next.value;
|
|
12200
|
-
metadata = { format, width, height, space:
|
|
12587
|
+
let { header: { format, width, height, maxval, channels, hasAlpha }, pages } = next.value;
|
|
12588
|
+
metadata = { format, width, height, space: channels >= 3 ? "srgb" : "b-w", channels, depth: format === "pbm" ? "bit" : maxval > 255 ? "ushort" : "uchar", density: 72, hasAlpha, size: source.size, ...pages > 1 ? { pages } : {} };
|
|
12201
12589
|
} else {
|
|
12202
12590
|
let length2 = Math.min(1029, source.size), head = await source.read(0, length2, { signal });
|
|
12203
12591
|
if (signal.throwIfAborted(), !(head instanceof Uint8Array) || head.length !== length2) throw new Error("Truncated image metadata source");
|
|
@@ -12643,6 +13031,8 @@ function inferFormatFromPath(fileOut) {
|
|
|
12643
13031
|
return "heif";
|
|
12644
13032
|
case "pdf":
|
|
12645
13033
|
return "pdf";
|
|
13034
|
+
case "pam":
|
|
13035
|
+
return "pam";
|
|
12646
13036
|
case "ppm":
|
|
12647
13037
|
return "ppm";
|
|
12648
13038
|
case "pgm":
|
|
@@ -14020,6 +14410,7 @@ var SharpInstance = class _SharpInstance extends Duplex {
|
|
|
14020
14410
|
"gif",
|
|
14021
14411
|
"svg",
|
|
14022
14412
|
"pdf",
|
|
14413
|
+
"pam",
|
|
14023
14414
|
"ppm",
|
|
14024
14415
|
"pgm",
|
|
14025
14416
|
"pbm",
|
|
@@ -14220,7 +14611,7 @@ Object.assign(sharp, {
|
|
|
14220
14611
|
vertexSplitQuadraticBasisSpline: "vsqbs"
|
|
14221
14612
|
},
|
|
14222
14613
|
format: Object.fromEntries(
|
|
14223
|
-
["jpeg", "png", "webp", "tiff", "heif", "heic", "avif", "gif", "svg", "pdf", "ppm", "pgm", "pbm", "bmp", "raw"].map(
|
|
14614
|
+
["jpeg", "png", "webp", "tiff", "heif", "heic", "avif", "gif", "svg", "pdf", "pam", "ppm", "pgm", "pbm", "bmp", "raw"].map(
|
|
14224
14615
|
(id) => [
|
|
14225
14616
|
id,
|
|
14226
14617
|
{
|