@ironsoftware/ironpdf 2026.5.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.
Files changed (103) hide show
  1. package/package.json +8 -5
  2. package/src/index.d.ts +1 -0
  3. package/src/index.d.ts.map +1 -1
  4. package/src/index.js +1 -0
  5. package/src/index.js.map +1 -1
  6. package/src/index.ts +1 -0
  7. package/src/internal/IronPdfEngine.ProtoFiles/iron_pdf_service.proto +5 -0
  8. package/src/internal/IronPdfEngine.ProtoFiles/pdfium_compress.proto +1 -0
  9. package/src/internal/IronPdfEngine.ProtoFiles/pdfium_form.proto +32 -0
  10. package/src/internal/IronPdfEngine.ProtoFiles/qpdf.proto +35 -0
  11. package/src/internal/access.d.ts.map +1 -1
  12. package/src/internal/access.js +3 -0
  13. package/src/internal/access.js.map +1 -1
  14. package/src/internal/access.ts +4 -0
  15. package/src/internal/generated_proto/iron_pdf_service.d.ts +14 -0
  16. package/src/internal/generated_proto/iron_pdf_service.d.ts.map +1 -1
  17. package/src/internal/generated_proto/iron_pdf_service.ts +14 -0
  18. package/src/internal/generated_proto/ironpdfengineproto/IronPdfService.d.ts +38 -0
  19. package/src/internal/generated_proto/ironpdfengineproto/IronPdfService.d.ts.map +1 -1
  20. package/src/internal/generated_proto/ironpdfengineproto/IronPdfService.ts +46 -0
  21. package/src/internal/generated_proto/ironpdfengineproto/PdfiumCompressImagesRequestP.d.ts +2 -0
  22. package/src/internal/generated_proto/ironpdfengineproto/PdfiumCompressImagesRequestP.d.ts.map +1 -1
  23. package/src/internal/generated_proto/ironpdfengineproto/PdfiumCompressImagesRequestP.ts +2 -0
  24. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackRequestP.d.ts +8 -0
  25. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackRequestP.d.ts.map +1 -0
  26. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackRequestP.js +4 -0
  27. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackRequestP.js.map +1 -0
  28. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackRequestP.ts +11 -0
  29. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackResultP.d.ts +12 -0
  30. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackResultP.d.ts.map +1 -0
  31. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackResultP.js +4 -0
  32. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackResultP.js.map +1 -0
  33. package/src/internal/generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackResultP.ts +15 -0
  34. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontRequestStreamP.d.ts +25 -0
  35. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontRequestStreamP.d.ts.map +1 -0
  36. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontRequestStreamP.js +4 -0
  37. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontRequestStreamP.js.map +1 -0
  38. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontRequestStreamP.ts +28 -0
  39. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontResultP.d.ts +12 -0
  40. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontResultP.d.ts.map +1 -0
  41. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontResultP.js +4 -0
  42. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontResultP.js.map +1 -0
  43. package/src/internal/generated_proto/ironpdfengineproto/PdfiumSetFormFontResultP.ts +15 -0
  44. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP.d.ts +23 -0
  45. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP.d.ts.map +1 -0
  46. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP.js +4 -0
  47. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP.js.map +1 -0
  48. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP.ts +26 -0
  49. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedRequestP.d.ts +15 -0
  50. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedRequestP.d.ts.map +1 -0
  51. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedRequestP.js +4 -0
  52. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedRequestP.js.map +1 -0
  53. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedRequestP.ts +18 -0
  54. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressionFlagsP.d.ts +30 -0
  55. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressionFlagsP.d.ts.map +1 -0
  56. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressionFlagsP.js +4 -0
  57. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressionFlagsP.js.map +1 -0
  58. package/src/internal/generated_proto/ironpdfengineproto/QPdfCompressionFlagsP.ts +33 -0
  59. package/src/internal/grpc_layer/pdfium/compress.d.ts +41 -1
  60. package/src/internal/grpc_layer/pdfium/compress.d.ts.map +1 -1
  61. package/src/internal/grpc_layer/pdfium/compress.js +220 -9
  62. package/src/internal/grpc_layer/pdfium/compress.js.map +1 -1
  63. package/src/internal/grpc_layer/pdfium/compress.ts +264 -2
  64. package/src/internal/grpc_layer/pdfium/form.d.ts +15 -0
  65. package/src/internal/grpc_layer/pdfium/form.d.ts.map +1 -0
  66. package/src/internal/grpc_layer/pdfium/form.js +99 -0
  67. package/src/internal/grpc_layer/pdfium/form.js.map +1 -0
  68. package/src/internal/grpc_layer/pdfium/form.ts +119 -0
  69. package/src/internal/grpc_layer/pdfium/formFontValidator.d.ts +26 -0
  70. package/src/internal/grpc_layer/pdfium/formFontValidator.d.ts.map +1 -0
  71. package/src/internal/grpc_layer/pdfium/formFontValidator.js +81 -0
  72. package/src/internal/grpc_layer/pdfium/formFontValidator.js.map +1 -0
  73. package/src/internal/grpc_layer/pdfium/formFontValidator.ts +86 -0
  74. package/src/internal/grpc_layer/pdfium/io.d.ts +2 -1
  75. package/src/internal/grpc_layer/pdfium/io.d.ts.map +1 -1
  76. package/src/internal/grpc_layer/pdfium/io.js +41 -36
  77. package/src/internal/grpc_layer/pdfium/io.js.map +1 -1
  78. package/src/internal/grpc_layer/pdfium/io.ts +43 -36
  79. package/src/internal/grpc_layer/pdfium/signing.d.ts +29 -2
  80. package/src/internal/grpc_layer/pdfium/signing.d.ts.map +1 -1
  81. package/src/internal/grpc_layer/pdfium/signing.js +28 -10
  82. package/src/internal/grpc_layer/pdfium/signing.js.map +1 -1
  83. package/src/internal/grpc_layer/pdfium/signing.ts +51 -11
  84. package/src/internal/image_codec.d.ts +20 -0
  85. package/src/internal/image_codec.d.ts.map +1 -0
  86. package/src/internal/image_codec.js +127 -0
  87. package/src/internal/image_codec.js.map +1 -0
  88. package/src/internal/image_codec.ts +108 -0
  89. package/src/public/compression.d.ts +92 -0
  90. package/src/public/compression.d.ts.map +1 -0
  91. package/src/public/compression.js +26 -0
  92. package/src/public/compression.js.map +1 -0
  93. package/src/public/compression.ts +107 -0
  94. package/src/public/ironpdfglobalconfig.d.ts +12 -0
  95. package/src/public/ironpdfglobalconfig.d.ts.map +1 -1
  96. package/src/public/ironpdfglobalconfig.js +7 -0
  97. package/src/public/ironpdfglobalconfig.js.map +1 -1
  98. package/src/public/ironpdfglobalconfig.ts +19 -0
  99. package/src/public/pdfDocument.d.ts +81 -0
  100. package/src/public/pdfDocument.d.ts.map +1 -1
  101. package/src/public/pdfDocument.js +212 -24
  102. package/src/public/pdfDocument.js.map +1 -1
  103. package/src/public/pdfDocument.ts +228 -28
@@ -1,10 +1,50 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  /// <reference types="node" />
4
+ import { QPdfCompressionFlagsP } from "../../generated_proto/ironpdfengineproto/QPdfCompressionFlagsP";
4
5
  import { Readable } from "stream";
5
- export declare function compressImage(id: string, imageQuality: number, scaleToVisibleSize?: boolean): Promise<void>;
6
+ import { Buffer } from "buffer";
7
+ import { AdvancedCompressionOptions } from "../../../public/compression";
8
+ export declare function compressImage(id: string, imageQuality: number, scaleToVisibleSize?: boolean, useHqSampling?: boolean, targetDpi?: number): Promise<void>;
6
9
  export declare function compressStructTree(id: string): Promise<void>;
7
10
  export declare function compressAndSaveAs(id: string, outputPath: string, imageQuality?: number): Promise<void>;
8
11
  export declare function compressInMemory(id: string, imageQuality?: number): Promise<Buffer>;
12
+ /**
13
+ * Map a user-facing {@link AdvancedCompressionOptions} onto the wire
14
+ * {@link QPdfCompressionFlagsP}.
15
+ */
16
+ export declare function toFlagsProto(options: AdvancedCompressionOptions): QPdfCompressionFlagsP;
17
+ /**
18
+ * Whether the pdfium image re-encode pass should run for these options
19
+ * (the effective target DPI is positive).
20
+ */
21
+ export declare function pdfiumWillReEncode(options: AdvancedCompressionOptions): boolean;
22
+ /**
23
+ * Apply the advanced compression pipeline to an open engine document and
24
+ * save the result to disk. Mirrors .NET
25
+ * {@code PdfDocument.CompressAndSaveAs(string, AdvancedCompressionOptions)}.
26
+ *
27
+ * Step 1 (optional) — pdfium image downsampling + re-encoding when
28
+ * {@code targetImageDpi > 0} (JpegQuality defaults to 85 when unset).
29
+ * Step 2 (optional) — struct-tree removal when {@code removeStructureTree}.
30
+ * Step 3 — qpdf {@code QPdf_Compression_CompressAndSaveAsAdvanced}.
31
+ */
32
+ export declare function compressAndSaveAsAdvanced(id: string, outputPath: string, options: AdvancedCompressionOptions, password?: string): Promise<void>;
33
+ /**
34
+ * Apply the advanced compression pipeline to byte[] input and stream the
35
+ * result back. Mirrors .NET
36
+ * {@code PdfDocument.CompressAndSaveAs(byte[], string, AdvancedCompressionOptions, ...)}.
37
+ *
38
+ * Image DPI downsampling / struct-tree removal require a loaded document, so when
39
+ * either is requested the bytes are first opened into a temporary engine document
40
+ * (which also decrypts using the password), the shared {@link applyImageAndStructPasses}
41
+ * pre-passes run, and
42
+ * the resulting plaintext bytes are streamed to the qpdf pass. The temporary document
43
+ * is always released via {@code disposePdf} in a `finally` block.
44
+ *
45
+ * Returns the compressed bytes; when {@code outputPath} is non-empty also
46
+ * writes them to disk.
47
+ */
48
+ export declare function compressAndSaveAsAdvancedFromBytes(pdfBytes: Buffer, outputPath: string, options: AdvancedCompressionOptions, password?: string): Promise<Buffer>;
9
49
  export declare function compressInMemoryStream(id: string, imageQuality?: number): Promise<Readable>;
10
50
  //# sourceMappingURL=compress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["compress.ts"],"names":[],"mappings":";;;AAOA,OAAO,EAAc,QAAQ,EAAC,MAAM,QAAQ,CAAC;AAG7C,wBAAsB,aAAa,CAClC,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,EACpB,kBAAkB,UAAQ,GACxB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,kBAAkB,CACvC,EAAE,EAAE,MAAM,GACR,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,iBAAiB,CACtC,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,MAAM,EACV,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,MAAM,EACV,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,QAAQ,CAAC,CAiCnB"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["compress.ts"],"names":[],"mappings":";;;AAMA,OAAO,EAAC,qBAAqB,EAAC,MAAM,gEAAgE,CAAC;AAKrG,OAAO,EAAc,QAAQ,EAAC,MAAM,QAAQ,CAAC;AAE7C,OAAO,EAAC,MAAM,EAAC,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAC,0BAA0B,EAAmB,MAAM,6BAA6B,CAAC;AAGzF,wBAAsB,aAAa,CAClC,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,EACpB,kBAAkB,UAAQ,EAC1B,aAAa,UAAQ,EACrB,SAAS,SAAI,GACX,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED,wBAAsB,kBAAkB,CACvC,EAAE,EAAE,MAAM,GACR,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,iBAAiB,CACtC,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,MAAM,EACV,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,0BAA0B,GAAG,qBAAqB,CAuBvF;AA0BD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAG/E;AA+BD;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAC9C,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,EACnC,QAAQ,SAAK,GACX,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kCAAkC,CACvD,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,EACnC,QAAQ,SAAK,GACX,OAAO,CAAC,MAAM,CAAC,CA0EjB;AAED,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,MAAM,EACV,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,QAAQ,CAAC,CAiCnB"}
@@ -12,20 +12,19 @@ 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.compressInMemoryStream = exports.compressInMemory = exports.compressAndSaveAs = exports.compressStructTree = exports.compressImage = void 0;
15
+ exports.compressInMemoryStream = exports.compressAndSaveAsAdvancedFromBytes = exports.compressAndSaveAsAdvanced = exports.pdfiumWillReEncode = exports.toFlagsProto = exports.compressInMemory = exports.compressAndSaveAs = exports.compressStructTree = exports.compressImage = void 0;
16
16
  const access_1 = require("../../access");
17
17
  const util_1 = require("../util");
18
18
  const stream_1 = require("stream");
19
19
  const fs_1 = __importDefault(require("fs"));
20
- function compressImage(id, imageQuality, scaleToVisibleSize = false) {
20
+ const buffer_1 = require("buffer");
21
+ const compression_1 = require("../../../public/compression");
22
+ const io_1 = require("./io");
23
+ function compressImage(id, imageQuality, scaleToVisibleSize = false, useHqSampling = false, targetDpi = 0) {
21
24
  return __awaiter(this, void 0, void 0, function* () {
22
25
  const client = yield access_1.Access.ensureConnection();
23
26
  return new Promise((resolve, reject) => {
24
- client.Pdfium_Compress_CompressImages({
25
- document: { documentId: id },
26
- scaleToVisibleSize: scaleToVisibleSize,
27
- quality: imageQuality,
28
- }, (err, value) => {
27
+ client.Pdfium_Compress_CompressImages(Object.assign({ document: { documentId: id }, scaleToVisibleSize: scaleToVisibleSize, quality: imageQuality, useHqSampling: useHqSampling }, (targetDpi > 0 ? { targetDpi: targetDpi } : {})), (err, value) => {
29
28
  if (err) {
30
29
  reject(`${err.name}/n${err.message}`);
31
30
  }
@@ -76,7 +75,7 @@ function compressAndSaveAs(id, outputPath, imageQuality) {
76
75
  reject(`${err.name}/n${err.message}`);
77
76
  });
78
77
  stream.on("end", () => {
79
- fs_1.default.writeFileSync(outputPath, Buffer.concat(buffers));
78
+ fs_1.default.writeFileSync(outputPath, buffer_1.Buffer.concat(buffers));
80
79
  resolve();
81
80
  });
82
81
  });
@@ -102,12 +101,224 @@ function compressInMemory(id, imageQuality) {
102
101
  reject(`${err.name}/n${err.message}`);
103
102
  });
104
103
  stream.on("end", () => {
105
- resolve(Buffer.concat(buffers));
104
+ resolve(buffer_1.Buffer.concat(buffers));
106
105
  });
107
106
  });
108
107
  });
109
108
  }
110
109
  exports.compressInMemory = compressInMemory;
110
+ /**
111
+ * Map a user-facing {@link AdvancedCompressionOptions} onto the wire
112
+ * {@link QPdfCompressionFlagsP}.
113
+ */
114
+ function toFlagsProto(options) {
115
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
116
+ const willReEncode = pdfiumWillReEncode(options);
117
+ const optimizeImages = !willReEncode && options.jpegQuality != null;
118
+ const flags = {
119
+ compressStreams: (_a = options.compressStreams) !== null && _a !== void 0 ? _a : true,
120
+ coalesceContents: (_b = options.coalesceContents) !== null && _b !== void 0 ? _b : true,
121
+ removeUnreferencedResources: (_c = options.removeUnreferencedResources) !== null && _c !== void 0 ? _c : true,
122
+ recompressFlate: (_d = options.recompressFlate) !== null && _d !== void 0 ? _d : true,
123
+ compressionLevel: (_e = options.compressionLevel) !== null && _e !== void 0 ? _e : 9,
124
+ objectStreams: ((_f = options.objectStreams) !== null && _f !== void 0 ? _f : compression_1.ObjectStreamMode.Generate),
125
+ decodeGeneralizedStreams: (_g = options.decodeGeneralizedStreams) !== null && _g !== void 0 ? _g : true,
126
+ optimizeImagesMinWidth: (_h = options.optimizeImagesMinWidth) !== null && _h !== void 0 ? _h : 0,
127
+ optimizeImagesMinHeight: (_j = options.optimizeImagesMinHeight) !== null && _j !== void 0 ? _j : 0,
128
+ optimizeImagesMinArea: (_k = options.optimizeImagesMinArea) !== null && _k !== void 0 ? _k : 0,
129
+ optimizeImages: optimizeImages,
130
+ };
131
+ if (!willReEncode && options.jpegQuality != null) {
132
+ flags.jpegQuality = options.jpegQuality;
133
+ }
134
+ return flags;
135
+ }
136
+ exports.toFlagsProto = toFlagsProto;
137
+ /**
138
+ * Default JPEG quality used when {@link AdvancedCompressionOptions.jpegQuality} is
139
+ * not set but image re-encoding still runs (because a target DPI is set).
140
+ */
141
+ const DEFAULT_JPEG_QUALITY = 85;
142
+ /**
143
+ * Default target image DPI used when {@link AdvancedCompressionOptions.targetImageDpi}
144
+ * is omitted (`undefined`). Mirrors the .NET / Java class default of 150, so a
145
+ * default options object (e.g. `{}`) downsamples + re-encodes images. An explicit
146
+ * `null` disables downsampling.
147
+ */
148
+ const DEFAULT_TARGET_IMAGE_DPI = 150;
149
+ /**
150
+ * Resolve the effective target DPI: `undefined` → 150 (the class default), `null` →
151
+ * disabled, otherwise the supplied value.
152
+ */
153
+ function resolveTargetImageDpi(options) {
154
+ return options.targetImageDpi === undefined
155
+ ? DEFAULT_TARGET_IMAGE_DPI
156
+ : options.targetImageDpi;
157
+ }
158
+ /**
159
+ * Whether the pdfium image re-encode pass should run for these options
160
+ * (the effective target DPI is positive).
161
+ */
162
+ function pdfiumWillReEncode(options) {
163
+ const dpi = resolveTargetImageDpi(options);
164
+ return dpi !== null && dpi > 0;
165
+ }
166
+ exports.pdfiumWillReEncode = pdfiumWillReEncode;
167
+ /**
168
+ * Shared pdfium pre-passes for the advanced pipeline, run on an open engine
169
+ * document. Optional image DPI downsampling + re-encode (JpegQuality defaults to
170
+ * {@link DEFAULT_JPEG_QUALITY} when unset, so the default options still shrink images),
171
+ * then optional struct-tree removal.
172
+ *
173
+ * `scaleToVisibleSize` is passed as `true` to match .NET's `useVisible: true` argument
174
+ * (GrpcPdfClient.CompressImages maps it to ScaleToVisibleSize).
175
+ */
176
+ function applyImageAndStructPasses(id, options) {
177
+ var _a, _b;
178
+ return __awaiter(this, void 0, void 0, function* () {
179
+ const dpi = resolveTargetImageDpi(options);
180
+ if (dpi !== null && dpi > 0) {
181
+ const quality = (_a = options.jpegQuality) !== null && _a !== void 0 ? _a : DEFAULT_JPEG_QUALITY;
182
+ yield compressImage(id, quality, true /* scaleToVisibleSize — matches .NET useVisible: true */, (_b = options.highQualityImageSubsampling) !== null && _b !== void 0 ? _b : true, dpi);
183
+ }
184
+ if (options.removeStructureTree) {
185
+ yield compressStructTree(id);
186
+ }
187
+ });
188
+ }
189
+ /**
190
+ * Apply the advanced compression pipeline to an open engine document and
191
+ * save the result to disk. Mirrors .NET
192
+ * {@code PdfDocument.CompressAndSaveAs(string, AdvancedCompressionOptions)}.
193
+ *
194
+ * Step 1 (optional) — pdfium image downsampling + re-encoding when
195
+ * {@code targetImageDpi > 0} (JpegQuality defaults to 85 when unset).
196
+ * Step 2 (optional) — struct-tree removal when {@code removeStructureTree}.
197
+ * Step 3 — qpdf {@code QPdf_Compression_CompressAndSaveAsAdvanced}.
198
+ */
199
+ function compressAndSaveAsAdvanced(id, outputPath, options, password = "") {
200
+ return __awaiter(this, void 0, void 0, function* () {
201
+ if (!options) {
202
+ throw new Error("options must not be null");
203
+ }
204
+ // Steps 1 & 2 — pdfium image re-encoding + struct-tree removal.
205
+ yield applyImageAndStructPasses(id, options);
206
+ // Step 3 — qpdf advanced pass.
207
+ const client = yield access_1.Access.ensureConnection();
208
+ return new Promise((resolve, reject) => {
209
+ const stream = client.QPdf_Compression_CompressAndSaveAsAdvanced({
210
+ document: { documentId: id },
211
+ outputPath: "",
212
+ password: password !== null && password !== void 0 ? password : "",
213
+ flags: toFlagsProto(options),
214
+ });
215
+ const buffers = [];
216
+ stream.on("data", (data) => {
217
+ if (data.exception) {
218
+ (0, util_1.handleRemoteException)(data.exception, reject);
219
+ }
220
+ else if (data.resultChunk) {
221
+ buffers.push(data.resultChunk);
222
+ }
223
+ });
224
+ stream.on("error", (err) => {
225
+ reject(`${err.name}/n${err.message}`);
226
+ });
227
+ stream.on("end", () => {
228
+ try {
229
+ fs_1.default.writeFileSync(outputPath, buffer_1.Buffer.concat(buffers));
230
+ }
231
+ catch (e) {
232
+ reject(`Failed to write compressed PDF to ${outputPath}: ${e.message}`);
233
+ return;
234
+ }
235
+ resolve();
236
+ });
237
+ });
238
+ });
239
+ }
240
+ exports.compressAndSaveAsAdvanced = compressAndSaveAsAdvanced;
241
+ /**
242
+ * Apply the advanced compression pipeline to byte[] input and stream the
243
+ * result back. Mirrors .NET
244
+ * {@code PdfDocument.CompressAndSaveAs(byte[], string, AdvancedCompressionOptions, ...)}.
245
+ *
246
+ * Image DPI downsampling / struct-tree removal require a loaded document, so when
247
+ * either is requested the bytes are first opened into a temporary engine document
248
+ * (which also decrypts using the password), the shared {@link applyImageAndStructPasses}
249
+ * pre-passes run, and
250
+ * the resulting plaintext bytes are streamed to the qpdf pass. The temporary document
251
+ * is always released via {@code disposePdf} in a `finally` block.
252
+ *
253
+ * Returns the compressed bytes; when {@code outputPath} is non-empty also
254
+ * writes them to disk.
255
+ */
256
+ function compressAndSaveAsAdvancedFromBytes(pdfBytes, outputPath, options, password = "") {
257
+ return __awaiter(this, void 0, void 0, function* () {
258
+ if (!pdfBytes || pdfBytes.length === 0) {
259
+ throw new Error("pdfBytes must not be null or empty");
260
+ }
261
+ if (!options) {
262
+ throw new Error("options must not be null");
263
+ }
264
+ let bytes = pdfBytes;
265
+ let pwd = password !== null && password !== void 0 ? password : "";
266
+ // Pre-pass: image downsampling + struct-tree removal need a loaded document.
267
+ if (pdfiumWillReEncode(options) || options.removeStructureTree) {
268
+ const tempId = yield (0, io_1.openPdfFileBuffer)(pdfBytes, { userPassword: pwd });
269
+ try {
270
+ yield applyImageAndStructPasses(tempId, options);
271
+ // Bytes are now decrypted + downsampled; the qpdf pass no longer needs the password.
272
+ bytes = yield (0, io_1.getBinaryData)(tempId);
273
+ pwd = "";
274
+ }
275
+ finally {
276
+ yield (0, io_1.disposePdf)(tempId);
277
+ }
278
+ }
279
+ const client = yield access_1.Access.ensureConnection();
280
+ return new Promise((resolve, reject) => {
281
+ const stream = client.QPdf_Compression_CompressAndSaveAsAdvancedFromBytes();
282
+ const buffers = [];
283
+ stream.on("data", (data) => {
284
+ if (data.exception) {
285
+ (0, util_1.handleRemoteException)(data.exception, reject);
286
+ }
287
+ else if (data.resultChunk) {
288
+ buffers.push(data.resultChunk);
289
+ }
290
+ });
291
+ stream.on("error", (err) => {
292
+ reject(`${err.name}/n${err.message}`);
293
+ });
294
+ stream.on("end", () => {
295
+ const result = buffer_1.Buffer.concat(buffers);
296
+ if (outputPath) {
297
+ try {
298
+ fs_1.default.writeFileSync(outputPath, result);
299
+ }
300
+ catch (e) {
301
+ reject(`Failed to write compressed PDF to ${outputPath}: ${e.message}`);
302
+ return;
303
+ }
304
+ }
305
+ resolve(result);
306
+ });
307
+ stream.write({
308
+ info: {
309
+ outputPath: outputPath !== null && outputPath !== void 0 ? outputPath : "",
310
+ password: pwd,
311
+ flags: toFlagsProto(options),
312
+ },
313
+ });
314
+ for (const chunk of (0, util_1.chunkBuffer)(bytes)) {
315
+ stream.write({ pdfBytesChunk: chunk });
316
+ }
317
+ stream.end();
318
+ });
319
+ });
320
+ }
321
+ exports.compressAndSaveAsAdvancedFromBytes = compressAndSaveAsAdvancedFromBytes;
111
322
  function compressInMemoryStream(id, imageQuality) {
112
323
  return __awaiter(this, void 0, void 0, function* () {
113
324
  const client = yield access_1.Access.ensureConnection();
@@ -1 +1 @@
1
- {"version":3,"file":"compress.js","sourceRoot":"","sources":["compress.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compress.js","sourceRoot":"","sources":["compress.ts"],"names":[],"mappings":"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"}
@@ -4,14 +4,23 @@ import {IronPdfServiceClient} from "../../generated_proto/ironpdfengineproto/Iro
4
4
  import {Access} from "../../access";
5
5
  import {EmptyResultP__Output} from "../../generated_proto/ironpdfengineproto/EmptyResultP";
6
6
  import {BytesResultStreamP__Output} from "../../generated_proto/ironpdfengineproto/BytesResultStreamP";
7
- import {handleEmptyResultP__Output} from "../util";
7
+ import {QPdfCompressionFlagsP} from "../../generated_proto/ironpdfengineproto/QPdfCompressionFlagsP";
8
+ import {
9
+ QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP
10
+ } from "../../generated_proto/ironpdfengineproto/QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP";
11
+ import {chunkBuffer, handleEmptyResultP__Output, handleRemoteException} from "../util";
8
12
  import {PassThrough, Readable} from "stream";
9
13
  import fs from "fs";
14
+ import {Buffer} from "buffer";
15
+ import {AdvancedCompressionOptions, ObjectStreamMode} from "../../../public/compression";
16
+ import {openPdfFileBuffer, getBinaryData, disposePdf} from "./io";
10
17
 
11
18
  export async function compressImage(
12
19
  id: string,
13
20
  imageQuality: number,
14
- scaleToVisibleSize = false
21
+ scaleToVisibleSize = false,
22
+ useHqSampling = false,
23
+ targetDpi = 0
15
24
  ): Promise<void> {
16
25
  const client: IronPdfServiceClient = await Access.ensureConnection();
17
26
  return new Promise(
@@ -21,6 +30,8 @@ export async function compressImage(
21
30
  document: {documentId: id},
22
31
  scaleToVisibleSize: scaleToVisibleSize,
23
32
  quality: imageQuality,
33
+ useHqSampling: useHqSampling,
34
+ ...(targetDpi > 0 ? {targetDpi: targetDpi} : {}),
24
35
  },
25
36
  (
26
37
  err: ServiceError | null,
@@ -144,6 +155,257 @@ export async function compressInMemory(
144
155
  );
145
156
  }
146
157
 
158
+ /**
159
+ * Map a user-facing {@link AdvancedCompressionOptions} onto the wire
160
+ * {@link QPdfCompressionFlagsP}.
161
+ */
162
+ export function toFlagsProto(options: AdvancedCompressionOptions): QPdfCompressionFlagsP {
163
+ const willReEncode = pdfiumWillReEncode(options);
164
+ const optimizeImages = !willReEncode && options.jpegQuality != null;
165
+
166
+ const flags: QPdfCompressionFlagsP = {
167
+ compressStreams: options.compressStreams ?? true,
168
+ coalesceContents: options.coalesceContents ?? true,
169
+ removeUnreferencedResources: options.removeUnreferencedResources ?? true,
170
+ recompressFlate: options.recompressFlate ?? true,
171
+ compressionLevel: options.compressionLevel ?? 9,
172
+ objectStreams: (options.objectStreams ?? ObjectStreamMode.Generate) as string,
173
+ decodeGeneralizedStreams: options.decodeGeneralizedStreams ?? true,
174
+ optimizeImagesMinWidth: options.optimizeImagesMinWidth ?? 0,
175
+ optimizeImagesMinHeight: options.optimizeImagesMinHeight ?? 0,
176
+ optimizeImagesMinArea: options.optimizeImagesMinArea ?? 0,
177
+ optimizeImages: optimizeImages,
178
+ };
179
+
180
+ if (!willReEncode && options.jpegQuality != null) {
181
+ flags.jpegQuality = options.jpegQuality;
182
+ }
183
+
184
+ return flags;
185
+ }
186
+
187
+ /**
188
+ * Default JPEG quality used when {@link AdvancedCompressionOptions.jpegQuality} is
189
+ * not set but image re-encoding still runs (because a target DPI is set).
190
+ */
191
+ const DEFAULT_JPEG_QUALITY = 85;
192
+
193
+ /**
194
+ * Default target image DPI used when {@link AdvancedCompressionOptions.targetImageDpi}
195
+ * is omitted (`undefined`). Mirrors the .NET / Java class default of 150, so a
196
+ * default options object (e.g. `{}`) downsamples + re-encodes images. An explicit
197
+ * `null` disables downsampling.
198
+ */
199
+ const DEFAULT_TARGET_IMAGE_DPI = 150;
200
+
201
+ /**
202
+ * Resolve the effective target DPI: `undefined` → 150 (the class default), `null` →
203
+ * disabled, otherwise the supplied value.
204
+ */
205
+ function resolveTargetImageDpi(options: AdvancedCompressionOptions): number | null {
206
+ return options.targetImageDpi === undefined
207
+ ? DEFAULT_TARGET_IMAGE_DPI
208
+ : options.targetImageDpi;
209
+ }
210
+
211
+ /**
212
+ * Whether the pdfium image re-encode pass should run for these options
213
+ * (the effective target DPI is positive).
214
+ */
215
+ export function pdfiumWillReEncode(options: AdvancedCompressionOptions): boolean {
216
+ const dpi = resolveTargetImageDpi(options);
217
+ return dpi !== null && dpi > 0;
218
+ }
219
+
220
+ /**
221
+ * Shared pdfium pre-passes for the advanced pipeline, run on an open engine
222
+ * document. Optional image DPI downsampling + re-encode (JpegQuality defaults to
223
+ * {@link DEFAULT_JPEG_QUALITY} when unset, so the default options still shrink images),
224
+ * then optional struct-tree removal.
225
+ *
226
+ * `scaleToVisibleSize` is passed as `true` to match .NET's `useVisible: true` argument
227
+ * (GrpcPdfClient.CompressImages maps it to ScaleToVisibleSize).
228
+ */
229
+ async function applyImageAndStructPasses(
230
+ id: string,
231
+ options: AdvancedCompressionOptions
232
+ ): Promise<void> {
233
+ const dpi = resolveTargetImageDpi(options);
234
+ if (dpi !== null && dpi > 0) {
235
+ const quality = options.jpegQuality ?? DEFAULT_JPEG_QUALITY;
236
+ await compressImage(
237
+ id,
238
+ quality,
239
+ true /* scaleToVisibleSize — matches .NET useVisible: true */,
240
+ options.highQualityImageSubsampling ?? true,
241
+ dpi
242
+ );
243
+ }
244
+ if (options.removeStructureTree) {
245
+ await compressStructTree(id);
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Apply the advanced compression pipeline to an open engine document and
251
+ * save the result to disk. Mirrors .NET
252
+ * {@code PdfDocument.CompressAndSaveAs(string, AdvancedCompressionOptions)}.
253
+ *
254
+ * Step 1 (optional) — pdfium image downsampling + re-encoding when
255
+ * {@code targetImageDpi > 0} (JpegQuality defaults to 85 when unset).
256
+ * Step 2 (optional) — struct-tree removal when {@code removeStructureTree}.
257
+ * Step 3 — qpdf {@code QPdf_Compression_CompressAndSaveAsAdvanced}.
258
+ */
259
+ export async function compressAndSaveAsAdvanced(
260
+ id: string,
261
+ outputPath: string,
262
+ options: AdvancedCompressionOptions,
263
+ password = ""
264
+ ): Promise<void> {
265
+ if (!options) {
266
+ throw new Error("options must not be null");
267
+ }
268
+
269
+ // Steps 1 & 2 — pdfium image re-encoding + struct-tree removal.
270
+ await applyImageAndStructPasses(id, options);
271
+
272
+ // Step 3 — qpdf advanced pass.
273
+ const client: IronPdfServiceClient = await Access.ensureConnection();
274
+
275
+ return new Promise(
276
+ (resolve: () => void, reject: (errorMsg: string) => void) => {
277
+ const stream: grpc.ClientReadableStream<BytesResultStreamP__Output> =
278
+ client.QPdf_Compression_CompressAndSaveAsAdvanced({
279
+ document: {documentId: id},
280
+ outputPath: "",
281
+ password: password ?? "",
282
+ flags: toFlagsProto(options),
283
+ });
284
+
285
+ const buffers: Buffer[] = [];
286
+ stream.on("data", (data: BytesResultStreamP__Output) => {
287
+ if (data.exception) {
288
+ handleRemoteException(data.exception, reject);
289
+ } else if (data.resultChunk) {
290
+ buffers.push(data.resultChunk);
291
+ }
292
+ });
293
+
294
+ stream.on("error", (err: Error) => {
295
+ reject(`${err.name}/n${err.message}`);
296
+ });
297
+
298
+ stream.on("end", () => {
299
+ try {
300
+ fs.writeFileSync(outputPath, Buffer.concat(buffers));
301
+ } catch (e) {
302
+ reject(
303
+ `Failed to write compressed PDF to ${outputPath}: ${(e as Error).message}`
304
+ );
305
+ return;
306
+ }
307
+ resolve();
308
+ });
309
+ }
310
+ );
311
+ }
312
+
313
+ /**
314
+ * Apply the advanced compression pipeline to byte[] input and stream the
315
+ * result back. Mirrors .NET
316
+ * {@code PdfDocument.CompressAndSaveAs(byte[], string, AdvancedCompressionOptions, ...)}.
317
+ *
318
+ * Image DPI downsampling / struct-tree removal require a loaded document, so when
319
+ * either is requested the bytes are first opened into a temporary engine document
320
+ * (which also decrypts using the password), the shared {@link applyImageAndStructPasses}
321
+ * pre-passes run, and
322
+ * the resulting plaintext bytes are streamed to the qpdf pass. The temporary document
323
+ * is always released via {@code disposePdf} in a `finally` block.
324
+ *
325
+ * Returns the compressed bytes; when {@code outputPath} is non-empty also
326
+ * writes them to disk.
327
+ */
328
+ export async function compressAndSaveAsAdvancedFromBytes(
329
+ pdfBytes: Buffer,
330
+ outputPath: string,
331
+ options: AdvancedCompressionOptions,
332
+ password = ""
333
+ ): Promise<Buffer> {
334
+ if (!pdfBytes || pdfBytes.length === 0) {
335
+ throw new Error("pdfBytes must not be null or empty");
336
+ }
337
+ if (!options) {
338
+ throw new Error("options must not be null");
339
+ }
340
+
341
+ let bytes = pdfBytes;
342
+ let pwd = password ?? "";
343
+
344
+ // Pre-pass: image downsampling + struct-tree removal need a loaded document.
345
+ if (pdfiumWillReEncode(options) || options.removeStructureTree) {
346
+ const tempId = await openPdfFileBuffer(pdfBytes, {userPassword: pwd});
347
+ try {
348
+ await applyImageAndStructPasses(tempId, options);
349
+ // Bytes are now decrypted + downsampled; the qpdf pass no longer needs the password.
350
+ bytes = await getBinaryData(tempId);
351
+ pwd = "";
352
+ } finally {
353
+ await disposePdf(tempId);
354
+ }
355
+ }
356
+
357
+ const client: IronPdfServiceClient = await Access.ensureConnection();
358
+
359
+ return new Promise(
360
+ (resolve: (_: Buffer) => void, reject: (errorMsg: string) => void) => {
361
+ const stream: grpc.ClientDuplexStream<
362
+ QPdfCompressAndSaveAsAdvancedFromBytesRequestStreamP,
363
+ BytesResultStreamP__Output
364
+ > = client.QPdf_Compression_CompressAndSaveAsAdvancedFromBytes();
365
+
366
+ const buffers: Buffer[] = [];
367
+ stream.on("data", (data: BytesResultStreamP__Output) => {
368
+ if (data.exception) {
369
+ handleRemoteException(data.exception, reject);
370
+ } else if (data.resultChunk) {
371
+ buffers.push(data.resultChunk);
372
+ }
373
+ });
374
+
375
+ stream.on("error", (err: Error) => {
376
+ reject(`${err.name}/n${err.message}`);
377
+ });
378
+
379
+ stream.on("end", () => {
380
+ const result = Buffer.concat(buffers);
381
+ if (outputPath) {
382
+ try {
383
+ fs.writeFileSync(outputPath, result);
384
+ } catch (e) {
385
+ reject(
386
+ `Failed to write compressed PDF to ${outputPath}: ${(e as Error).message}`
387
+ );
388
+ return;
389
+ }
390
+ }
391
+ resolve(result);
392
+ });
393
+
394
+ stream.write({
395
+ info: {
396
+ outputPath: outputPath ?? "",
397
+ password: pwd,
398
+ flags: toFlagsProto(options),
399
+ },
400
+ });
401
+ for (const chunk of chunkBuffer(bytes)) {
402
+ stream.write({pdfBytesChunk: chunk});
403
+ }
404
+ stream.end();
405
+ }
406
+ );
407
+ }
408
+
147
409
  export async function compressInMemoryStream(
148
410
  id: string,
149
411
  imageQuality?: number
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { Buffer } from "buffer";
4
+ /**
5
+ * Stream a font (or just a name reference) to the engine so subsequent
6
+ * form-field fills with non-ASCII values use the supplied font instead of
7
+ * triggering the automatic Tahoma/Arial fallback embed.
8
+ */
9
+ export declare function setFormFont(id: string, fontName: string, fontData: Buffer | undefined, forceEmbed: boolean): Promise<void>;
10
+ /**
11
+ * Suppress the engine's automatic Tahoma/Arial fallback embed for non-ASCII
12
+ * form-field values without registering a replacement font.
13
+ */
14
+ export declare function disableFormFontFallback(id: string): Promise<void>;
15
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["form.ts"],"names":[],"mappings":";;AACA,OAAO,EAAC,MAAM,EAAC,MAAM,QAAQ,CAAC;AAe9B;;;;GAIG;AACH,wBAAsB,WAAW,CAChC,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,UAAU,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CA0Df;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BvE"}