@ironsoftware/ironpdf 2026.6.1 → 2026.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"io.js","sourceRoot":"","sources":["io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"io.js","sourceRoot":"","sources":["io.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import {BytesResultStreamP__Output} from "../../generated_proto/ironpdfenginepro
12
12
  import {
13
13
  PdfiumGetBinaryDataRequestStreamP
14
14
  } from "../../generated_proto/ironpdfengineproto/PdfiumGetBinaryDataRequestStreamP";
15
+ import {PendingSignature} from "./signing";
15
16
 
16
17
  export async function openPdfFileBuffer(
17
18
  buffer: Buffer,
@@ -57,7 +58,8 @@ export async function openPdfFileBuffer(
57
58
 
58
59
  export async function getBinaryData(
59
60
  pdfDocumentId: string,
60
- saveOptions?: SaveOptions | undefined
61
+ saveOptions?: SaveOptions | undefined,
62
+ signatures?: PendingSignature[] | undefined
61
63
  ): Promise<Buffer> {
62
64
  const client: IronPdfServiceClient = await Access.ensureConnection();
63
65
 
@@ -95,42 +97,47 @@ export async function getBinaryData(
95
97
  },
96
98
  });
97
99
 
98
- //not working for now
99
- // // signatures
100
- // const collection = saveOptions?.digitalSignatures?.map(
101
- // (digitalSignature, signatureIndex) => {
102
- // const pdfiumPdfSignatureP: PdfiumPdfSignatureP = {
103
- // index: signatureIndex,
104
- // password: digitalSignature.certificatePassword,
105
- // timestampUrl: digitalSignature.timeStampUrl,
106
- // };
107
- // return pdfiumPdfSignatureP;
108
- // }
109
- // );
110
- // stream.write({ signatures: { signature: collection } });
100
+ // Digital signatures are added as placeholder fields by signPdf(), but the actual
101
+ // cryptographic signing only happens here, at save time. The signature descriptors
102
+ // (index/password/timestamp) and the raw certificate bytes must therefore be re-sent
103
+ // so the engine can fill in the reserved byte range. Skipping this leaves an empty
104
+ // placeholder and produces a PDF with an invalid signature.
105
+ if (signatures && signatures.length > 0) {
106
+ // The engine pairs each certificate with its reserved placeholder using two
107
+ // distinct indices (this matches the C# client, GrpcPdfClient.GetBytes):
108
+ //
109
+ // * rawSignaturesChunk.signatureIndex = the certificate's position in the
110
+ // `signatures` collection below. The engine groups the chunks by this value and
111
+ // looks the descriptor up positionally (`signatures.Signature[signatureIndex]`),
112
+ // so it must be the 0..n-1 array index, NOT the engine signature index.
113
+ // * PdfiumPdfSignatureP.index = the engine signature index returned by
114
+ // signPdf when the placeholder was reserved. The engine uses it to know which
115
+ // placeholder field this certificate fills. For an already-signed document this
116
+ // differs from the array position, which is exactly why the two are separate.
117
+ //
118
+ // Keep the collection order and the chunk order identical so position i in the
119
+ // collection always corresponds to signatureIndex i in the chunks.
120
+ stream.write({
121
+ signatures: {
122
+ signature: signatures.map((signature) => ({
123
+ index: signature.index,
124
+ password: signature.password,
125
+ timestampUrl: signature.timeStampUrl,
126
+ })),
127
+ },
128
+ });
111
129
 
112
- // //rawSignaturesChunk
113
- // saveOptions?.digitalSignatures?.forEach(
114
- // (digitalSignature, signatureIndex) => {
115
- // const buf = digitalSignature.certificatePath
116
- // ? fs.readFileSync(digitalSignature.certificatePath)
117
- // : digitalSignature.certificateBuffer;
118
- //
119
- // if (buf) {
120
- // chunkBuffer(buf).forEach((chunk) => {
121
- // const pdfiumRawSignatureChunkWithIndexP: PdfiumRawSignatureChunkWithIndexP =
122
- // {
123
- // rawSignatureChunk: chunk,
124
- // signatureIndex,
125
- // };
126
- // stream.write({
127
- // rawSignaturesChunk:
128
- // pdfiumRawSignatureChunkWithIndexP,
129
- // });
130
- // });
131
- // }
132
- // }
133
- // );
130
+ signatures.forEach((signature, signatureIndex) => {
131
+ chunkBuffer(signature.certificate).forEach((chunk) => {
132
+ stream.write({
133
+ rawSignaturesChunk: {
134
+ rawSignatureChunk: chunk,
135
+ signatureIndex,
136
+ },
137
+ });
138
+ });
139
+ });
140
+ }
134
141
  //request finished
135
142
  stream.end();
136
143
  }
@@ -1,5 +1,32 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { Buffer } from "buffer";
1
4
  import { DigitalSignature, VerifiedSignature } from "../../../public/signature";
2
- export declare function signPdf(id: string, signature: DigitalSignature): Promise<void>;
5
+ /**
6
+ * A digital signature that has had its placeholder field added to the document, but still needs
7
+ * to be cryptographically finalized when the document is saved (see {@link getBinaryData}).
8
+ *
9
+ * Adding a signature is a two-step process: {@link signPdf} reserves a signature field with byte
10
+ * padding, and the actual signing over the final byte range only happens at save time. The
11
+ * certificate and password therefore have to be re-sent during the save, otherwise the signature
12
+ * placeholder is never filled in and the resulting PDF reports an invalid signature.
13
+ */
14
+ export interface PendingSignature {
15
+ /** The signature index returned by the engine when the placeholder field was added. */
16
+ index: number;
17
+ /** The certificate password. */
18
+ password: string;
19
+ /** Url to use for timestamping. */
20
+ timeStampUrl: string;
21
+ /** The raw .pfx / .p12 certificate bytes used to sign. */
22
+ certificate: Buffer;
23
+ }
24
+ /**
25
+ * Resolves the raw certificate bytes from a {@link DigitalSignature}, reading from the file path
26
+ * if a buffer was not supplied directly.
27
+ */
28
+ export declare function resolveCertificateBuffer(signature: DigitalSignature): Buffer | undefined;
29
+ export declare function signPdf(id: string, signature: DigitalSignature): Promise<number>;
3
30
  export declare function getSignatureCount(id: string): Promise<number>;
4
- export declare function getVerifiedSignatures(id: string): Promise<VerifiedSignature[]>;
31
+ export declare function getVerifiedSignatures(id: string, data?: Buffer | undefined): Promise<VerifiedSignature[]>;
5
32
  //# sourceMappingURL=signing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["signing.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAShF,wBAAsB,OAAO,CAC5B,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CA+Ef;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBnE;AAED,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAwCpF"}
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["signing.ts"],"names":[],"mappings":";;AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAShF;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAChC,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,SAAS,EAAE,gBAAgB,GACzB,MAAM,GAAG,SAAS,CAOpB;AAED,wBAAsB,OAAO,CAC5B,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC,CAyEjB;AAED,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBnE;AAED,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAmD/G"}
@@ -12,10 +12,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getVerifiedSignatures = exports.getSignatureCount = exports.signPdf = void 0;
15
+ exports.getVerifiedSignatures = exports.getSignatureCount = exports.signPdf = exports.resolveCertificateBuffer = void 0;
16
16
  const fs_1 = __importDefault(require("fs"));
17
17
  const access_1 = require("../../access");
18
18
  const util_1 = require("../util");
19
+ /**
20
+ * Resolves the raw certificate bytes from a {@link DigitalSignature}, reading from the file path
21
+ * if a buffer was not supplied directly.
22
+ */
23
+ function resolveCertificateBuffer(signature) {
24
+ if (signature.certificateBuffer) {
25
+ return signature.certificateBuffer;
26
+ }
27
+ else if (signature.certificatePath) {
28
+ return fs_1.default.readFileSync(signature.certificatePath);
29
+ }
30
+ return undefined;
31
+ }
32
+ exports.resolveCertificateBuffer = resolveCertificateBuffer;
19
33
  function signPdf(id, signature) {
20
34
  return __awaiter(this, void 0, void 0, function* () {
21
35
  const client = yield access_1.Access.ensureConnection();
@@ -23,6 +37,7 @@ function signPdf(id, signature) {
23
37
  return new Promise((resolve, reject) => {
24
38
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
25
39
  const stream = client.Pdfium_Signature_Sign((err, value) => {
40
+ var _a;
26
41
  if (err) {
27
42
  reject(`${err.name}/n${err.message}`);
28
43
  }
@@ -30,7 +45,7 @@ function signPdf(id, signature) {
30
45
  if (value === null || value === void 0 ? void 0 : value.exception) {
31
46
  (0, util_1.handleRemoteException)(value.exception, reject);
32
47
  }
33
- resolve();
48
+ resolve((_a = value.result) !== null && _a !== void 0 ? _a : 0);
34
49
  }
35
50
  });
36
51
  const info = {
@@ -55,13 +70,7 @@ function signPdf(id, signature) {
55
70
  };
56
71
  }
57
72
  stream.write({ info: info });
58
- let certBuffer = undefined;
59
- if (signature.certificateBuffer) {
60
- certBuffer = signature.certificateBuffer;
61
- }
62
- else if (signature.certificatePath) {
63
- certBuffer = fs_1.default.readFileSync(signature.certificatePath);
64
- }
73
+ const certBuffer = resolveCertificateBuffer(signature);
65
74
  if (certBuffer) {
66
75
  (0, util_1.chunkBuffer)(certBuffer).forEach((chunk) => {
67
76
  stream.write({ certificateFileBytesChunk: chunk });
@@ -103,7 +112,7 @@ function getSignatureCount(id) {
103
112
  });
104
113
  }
105
114
  exports.getSignatureCount = getSignatureCount;
106
- function getVerifiedSignatures(id) {
115
+ function getVerifiedSignatures(id, data) {
107
116
  return __awaiter(this, void 0, void 0, function* () {
108
117
  const client = yield access_1.Access.ensureConnection();
109
118
  return new Promise((resolve, reject) => {
@@ -135,6 +144,15 @@ function getVerifiedSignatures(id) {
135
144
  }
136
145
  });
137
146
  stream.write({ info: { document: { documentId: id } } });
147
+ // Verification must run against the actual document bytes (the finalized, signed
148
+ // output). If we don't send them, the engine falls back to a fresh non-incremental
149
+ // save that recomputes object offsets and breaks the signed byte range, making every
150
+ // signature look invalid. This mirrors the C# client which always passes the bytes.
151
+ if (data) {
152
+ (0, util_1.chunkBuffer)(data).forEach((chunk) => {
153
+ stream.write({ dataChunk: chunk });
154
+ });
155
+ }
138
156
  stream.end();
139
157
  });
140
158
  });
@@ -1 +1 @@
1
- {"version":3,"file":"signing.js","sourceRoot":"","sources":["signing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["signing.ts"],"names":[],"mappings":"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"}
@@ -10,14 +10,49 @@ import { _ironpdfengineproto_PdfiumSignRequestStreamP_InfoP } from "../../genera
10
10
  import { PdfiumGetSignatureCountResultP__Output } from "../../generated_proto/ironpdfengineproto/PdfiumGetSignatureCountResultP";
11
11
  import { PdfiumGetVerifySignatureResultP__Output } from "../../generated_proto/ironpdfengineproto/PdfiumGetVerifySignatureResultP";
12
12
 
13
+ /**
14
+ * A digital signature that has had its placeholder field added to the document, but still needs
15
+ * to be cryptographically finalized when the document is saved (see {@link getBinaryData}).
16
+ *
17
+ * Adding a signature is a two-step process: {@link signPdf} reserves a signature field with byte
18
+ * padding, and the actual signing over the final byte range only happens at save time. The
19
+ * certificate and password therefore have to be re-sent during the save, otherwise the signature
20
+ * placeholder is never filled in and the resulting PDF reports an invalid signature.
21
+ */
22
+ export interface PendingSignature {
23
+ /** The signature index returned by the engine when the placeholder field was added. */
24
+ index: number;
25
+ /** The certificate password. */
26
+ password: string;
27
+ /** Url to use for timestamping. */
28
+ timeStampUrl: string;
29
+ /** The raw .pfx / .p12 certificate bytes used to sign. */
30
+ certificate: Buffer;
31
+ }
32
+
33
+ /**
34
+ * Resolves the raw certificate bytes from a {@link DigitalSignature}, reading from the file path
35
+ * if a buffer was not supplied directly.
36
+ */
37
+ export function resolveCertificateBuffer(
38
+ signature: DigitalSignature
39
+ ): Buffer | undefined {
40
+ if (signature.certificateBuffer) {
41
+ return signature.certificateBuffer;
42
+ } else if (signature.certificatePath) {
43
+ return fs.readFileSync(signature.certificatePath);
44
+ }
45
+ return undefined;
46
+ }
47
+
13
48
  export async function signPdf(
14
49
  id: string,
15
50
  signature: DigitalSignature
16
- ): Promise<void> {
51
+ ): Promise<number> {
17
52
  const client: IronPdfServiceClient = await Access.ensureConnection();
18
53
  const existing_sigs = await getSignatureCount(id);
19
54
  return new Promise(
20
- (resolve: () => void, reject: (errorMsg: string) => void) => {
55
+ (resolve: (_: number) => void, reject: (errorMsg: string) => void) => {
21
56
  const stream = client.Pdfium_Signature_Sign(
22
57
  (
23
58
  err: ServiceError | null,
@@ -29,7 +64,7 @@ export async function signPdf(
29
64
  if (value?.exception) {
30
65
  handleRemoteException(value.exception, reject);
31
66
  }
32
- resolve();
67
+ resolve(value.result ?? 0);
33
68
  }
34
69
  }
35
70
  );
@@ -59,13 +94,7 @@ export async function signPdf(
59
94
 
60
95
  stream.write({ info: info });
61
96
 
62
- let certBuffer: Buffer | undefined = undefined;
63
-
64
- if (signature.certificateBuffer) {
65
- certBuffer = signature.certificateBuffer;
66
- } else if (signature.certificatePath) {
67
- certBuffer = fs.readFileSync(signature.certificatePath);
68
- }
97
+ const certBuffer: Buffer | undefined = resolveCertificateBuffer(signature);
69
98
 
70
99
  if (certBuffer) {
71
100
  chunkBuffer(certBuffer).forEach((chunk) => {
@@ -118,7 +147,7 @@ export async function getSignatureCount(id: string): Promise<number> {
118
147
  );
119
148
  }
120
149
 
121
- export async function getVerifiedSignatures(id: string): Promise<VerifiedSignature[]> {
150
+ export async function getVerifiedSignatures(id: string, data?: Buffer | undefined): Promise<VerifiedSignature[]> {
122
151
  const client: IronPdfServiceClient = await Access.ensureConnection();
123
152
  return new Promise(
124
153
  (resolve: (_: VerifiedSignature[]) => void, reject: (errorMsg: string) => void) => {
@@ -155,6 +184,17 @@ export async function getVerifiedSignatures(id: string): Promise<VerifiedSignatu
155
184
  );
156
185
 
157
186
  stream.write({ info: { document: { documentId: id } } });
187
+
188
+ // Verification must run against the actual document bytes (the finalized, signed
189
+ // output). If we don't send them, the engine falls back to a fresh non-incremental
190
+ // save that recomputes object offsets and breaks the signed byte range, making every
191
+ // signature look invalid. This mirrors the C# client which always passes the bytes.
192
+ if (data) {
193
+ chunkBuffer(data).forEach((chunk) => {
194
+ stream.write({ dataChunk: chunk });
195
+ });
196
+ }
197
+
158
198
  stream.end();
159
199
  }
160
200
  );
@@ -0,0 +1,20 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { ImageType } from "../public/image";
4
+ export interface Bitmap {
5
+ /** RGBA bytes, row-major, top-to-bottom. */
6
+ data: Buffer;
7
+ width: number;
8
+ height: number;
9
+ }
10
+ export declare function decodeImage(buffer: Buffer): Bitmap;
11
+ /**
12
+ * Decode the engine's image bytes and re-encode to the requested format.
13
+ * Fast path: when input is PNG and target is PNG, the bytes pass through unchanged.
14
+ */
15
+ export declare function transcodeImage(buffer: Buffer, type: ImageType | undefined): Buffer;
16
+ /**
17
+ * Transcode + write to disk. Format is selected by `type`, not by the file extension.
18
+ */
19
+ export declare function writeImageFile(buffer: Buffer, outputPath: string, type: ImageType | undefined): Promise<void>;
20
+ //# sourceMappingURL=image_codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image_codec.d.ts","sourceRoot":"","sources":["image_codec.ts"],"names":[],"mappings":";;AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,WAAW,MAAM;IACtB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAiCD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBlD;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAclF;AAED;;GAEG;AACH,wBAAsB,cAAc,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,SAAS,GAAG,SAAS,GACzB,OAAO,CAAC,IAAI,CAAC,CAEf"}
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.writeImageFile = exports.transcodeImage = exports.decodeImage = void 0;
36
+ const fs = __importStar(require("fs/promises"));
37
+ const pngjs_1 = require("pngjs");
38
+ const jpeg = __importStar(require("jpeg-js"));
39
+ const bmp = __importStar(require("bmp-js"));
40
+ const image_1 = require("../public/image");
41
+ const PNG_MAGIC = 0x89504e47;
42
+ function isPng(buffer) {
43
+ return buffer.length >= 8 && buffer.readUInt32BE(0) === PNG_MAGIC;
44
+ }
45
+ function isJpeg(buffer) {
46
+ return buffer.length >= 3
47
+ && buffer.readUInt8(0) === 0xff
48
+ && buffer.readUInt8(1) === 0xd8
49
+ && buffer.readUInt8(2) === 0xff;
50
+ }
51
+ function isBmp(buffer) {
52
+ return buffer.length >= 2
53
+ && buffer.readUInt8(0) === 0x42
54
+ && buffer.readUInt8(1) === 0x4d;
55
+ }
56
+ // bmp-js stores pixels in ABGR; pngjs/jpeg-js use RGBA. Swap on both sides.
57
+ function swapAbgrRgba(src) {
58
+ const out = Buffer.alloc(src.length);
59
+ for (let i = 0; i < src.length; i += 4) {
60
+ out.writeUInt8(src.readUInt8(i + 3), i + 0);
61
+ out.writeUInt8(src.readUInt8(i + 2), i + 1);
62
+ out.writeUInt8(src.readUInt8(i + 1), i + 2);
63
+ out.writeUInt8(src.readUInt8(i + 0), i + 3);
64
+ }
65
+ return out;
66
+ }
67
+ function decodeImage(buffer) {
68
+ if (isPng(buffer)) {
69
+ const png = pngjs_1.PNG.sync.read(buffer);
70
+ return { data: png.data, width: png.width, height: png.height };
71
+ }
72
+ if (isJpeg(buffer)) {
73
+ const d = jpeg.decode(buffer, { useTArray: true, formatAsRGBA: true });
74
+ return {
75
+ data: Buffer.from(d.data.buffer, d.data.byteOffset, d.data.byteLength),
76
+ width: d.width,
77
+ height: d.height,
78
+ };
79
+ }
80
+ if (isBmp(buffer)) {
81
+ const d = bmp.decode(buffer);
82
+ return { data: swapAbgrRgba(d.data), width: d.width, height: d.height };
83
+ }
84
+ throw new Error("Unsupported image format in engine response");
85
+ }
86
+ exports.decodeImage = decodeImage;
87
+ function encodePng({ data, width, height }) {
88
+ const png = new pngjs_1.PNG({ width, height });
89
+ data.copy(png.data);
90
+ return pngjs_1.PNG.sync.write(png);
91
+ }
92
+ function encodeJpeg({ data, width, height }) {
93
+ return Buffer.from(jpeg.encode({ data, width, height }, 90).data);
94
+ }
95
+ function encodeBmp({ data, width, height }) {
96
+ return bmp.encode({ data: swapAbgrRgba(data), width, height }).data;
97
+ }
98
+ /**
99
+ * Decode the engine's image bytes and re-encode to the requested format.
100
+ * Fast path: when input is PNG and target is PNG, the bytes pass through unchanged.
101
+ */
102
+ function transcodeImage(buffer, type) {
103
+ if ((type === undefined || type === image_1.ImageType.PNG) && isPng(buffer)) {
104
+ return buffer;
105
+ }
106
+ const bitmap = decodeImage(buffer);
107
+ switch (type) {
108
+ case image_1.ImageType.BMP:
109
+ return encodeBmp(bitmap);
110
+ case image_1.ImageType.JPG:
111
+ return encodeJpeg(bitmap);
112
+ case image_1.ImageType.PNG:
113
+ default:
114
+ return encodePng(bitmap);
115
+ }
116
+ }
117
+ exports.transcodeImage = transcodeImage;
118
+ /**
119
+ * Transcode + write to disk. Format is selected by `type`, not by the file extension.
120
+ */
121
+ function writeImageFile(buffer, outputPath, type) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ yield fs.writeFile(outputPath, transcodeImage(buffer, type));
124
+ });
125
+ }
126
+ exports.writeImageFile = writeImageFile;
127
+ //# sourceMappingURL=image_codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image_codec.js","sourceRoot":"","sources":["image_codec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ import * as fs from "fs/promises";
2
+ import { PNG } from "pngjs";
3
+ import * as jpeg from "jpeg-js";
4
+ import * as bmp from "bmp-js";
5
+ import { ImageType } from "../public/image";
6
+
7
+ export interface Bitmap {
8
+ /** RGBA bytes, row-major, top-to-bottom. */
9
+ data: Buffer;
10
+ width: number;
11
+ height: number;
12
+ }
13
+
14
+ const PNG_MAGIC = 0x89504e47;
15
+
16
+ function isPng(buffer: Buffer): boolean {
17
+ return buffer.length >= 8 && buffer.readUInt32BE(0) === PNG_MAGIC;
18
+ }
19
+
20
+ function isJpeg(buffer: Buffer): boolean {
21
+ return buffer.length >= 3
22
+ && buffer.readUInt8(0) === 0xff
23
+ && buffer.readUInt8(1) === 0xd8
24
+ && buffer.readUInt8(2) === 0xff;
25
+ }
26
+
27
+ function isBmp(buffer: Buffer): boolean {
28
+ return buffer.length >= 2
29
+ && buffer.readUInt8(0) === 0x42
30
+ && buffer.readUInt8(1) === 0x4d;
31
+ }
32
+
33
+ // bmp-js stores pixels in ABGR; pngjs/jpeg-js use RGBA. Swap on both sides.
34
+ function swapAbgrRgba(src: Buffer): Buffer {
35
+ const out = Buffer.alloc(src.length);
36
+ for (let i = 0; i < src.length; i += 4) {
37
+ out.writeUInt8(src.readUInt8(i + 3), i + 0);
38
+ out.writeUInt8(src.readUInt8(i + 2), i + 1);
39
+ out.writeUInt8(src.readUInt8(i + 1), i + 2);
40
+ out.writeUInt8(src.readUInt8(i + 0), i + 3);
41
+ }
42
+ return out;
43
+ }
44
+
45
+ export function decodeImage(buffer: Buffer): Bitmap {
46
+ if (isPng(buffer)) {
47
+ const png = PNG.sync.read(buffer);
48
+ return { data: png.data, width: png.width, height: png.height };
49
+ }
50
+ if (isJpeg(buffer)) {
51
+ const d = jpeg.decode(buffer, { useTArray: true, formatAsRGBA: true });
52
+ return {
53
+ data: Buffer.from(d.data.buffer, d.data.byteOffset, d.data.byteLength),
54
+ width: d.width,
55
+ height: d.height,
56
+ };
57
+ }
58
+ if (isBmp(buffer)) {
59
+ const d = bmp.decode(buffer);
60
+ return { data: swapAbgrRgba(d.data), width: d.width, height: d.height };
61
+ }
62
+ throw new Error("Unsupported image format in engine response");
63
+ }
64
+
65
+ function encodePng({ data, width, height }: Bitmap): Buffer {
66
+ const png = new PNG({ width, height });
67
+ data.copy(png.data);
68
+ return PNG.sync.write(png);
69
+ }
70
+
71
+ function encodeJpeg({ data, width, height }: Bitmap): Buffer {
72
+ return Buffer.from(jpeg.encode({ data, width, height }, 90).data);
73
+ }
74
+
75
+ function encodeBmp({ data, width, height }: Bitmap): Buffer {
76
+ return bmp.encode({ data: swapAbgrRgba(data), width, height }).data;
77
+ }
78
+
79
+ /**
80
+ * Decode the engine's image bytes and re-encode to the requested format.
81
+ * Fast path: when input is PNG and target is PNG, the bytes pass through unchanged.
82
+ */
83
+ export function transcodeImage(buffer: Buffer, type: ImageType | undefined): Buffer {
84
+ if ((type === undefined || type === ImageType.PNG) && isPng(buffer)) {
85
+ return buffer;
86
+ }
87
+ const bitmap = decodeImage(buffer);
88
+ switch (type) {
89
+ case ImageType.BMP:
90
+ return encodeBmp(bitmap);
91
+ case ImageType.JPG:
92
+ return encodeJpeg(bitmap);
93
+ case ImageType.PNG:
94
+ default:
95
+ return encodePng(bitmap);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Transcode + write to disk. Format is selected by `type`, not by the file extension.
101
+ */
102
+ export async function writeImageFile(
103
+ buffer: Buffer,
104
+ outputPath: string,
105
+ type: ImageType | undefined
106
+ ): Promise<void> {
107
+ await fs.writeFile(outputPath, transcodeImage(buffer, type));
108
+ }