mindee 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +13 -10
  3. package/src/image/extractedImage.d.ts +4 -2
  4. package/src/image/extractedImage.js +5 -3
  5. package/src/image/imageExtractor.d.ts +13 -2
  6. package/src/image/imageExtractor.js +50 -12
  7. package/src/pdf/extractedPdf.d.ts +25 -0
  8. package/src/pdf/extractedPdf.js +65 -0
  9. package/src/pdf/pdfCompressor.js +2 -40
  10. package/src/pdf/pdfExtractor.d.ts +46 -0
  11. package/src/pdf/pdfExtractor.js +128 -0
  12. package/src/pdf/pdfOperation.d.ts +7 -0
  13. package/src/pdf/pdfOperation.js +34 -1
  14. package/src/pdf/pdfUtils.d.ts +9 -0
  15. package/src/pdf/pdfUtils.js +40 -0
  16. package/src/v1/extraction/multiReceiptsExtractor/multiReceiptsExtractor.js +6 -33
  17. package/src/v2/cli.js +9 -4
  18. package/src/v2/fileOperations/crop.d.ts +18 -0
  19. package/src/v2/fileOperations/crop.js +35 -0
  20. package/src/v2/fileOperations/cropFiles.d.ts +4 -0
  21. package/src/v2/fileOperations/cropFiles.js +5 -0
  22. package/src/v2/fileOperations/index.d.ts +1 -0
  23. package/src/v2/fileOperations/index.js +1 -0
  24. package/src/v2/fileOperations/split.d.ts +21 -0
  25. package/src/v2/fileOperations/split.js +48 -0
  26. package/src/v2/fileOperations/splitFiles.d.ts +4 -0
  27. package/src/v2/fileOperations/splitFiles.js +5 -0
  28. package/src/v2/product/crop/cropItem.d.ts +8 -0
  29. package/src/v2/product/crop/cropItem.js +9 -0
  30. package/src/v2/product/crop/cropResponse.d.ts +9 -1
  31. package/src/v2/product/crop/cropResponse.js +10 -1
  32. package/src/v2/product/split/splitRange.d.ts +6 -0
  33. package/src/v2/product/split/splitRange.js +9 -0
  34. package/src/v2/product/split/splitResponse.d.ts +7 -0
  35. package/src/v2/product/split/splitResponse.js +12 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Mindee Node.js API Library Changelog
2
2
 
3
+ ## v5.2.0 - 2026-04-14
4
+ ### Changes
5
+ * :sparkles: add support for crop operation for V2
6
+ * :sparkles: add support for split operation for V2
7
+ * :arrow_up: bump dependencies
8
+ ### Fixes
9
+ * :bug: fix quality defaulting to 4.17 (300/72) instead of 1 when extracting cropped zones
10
+ * :bug: fix split extraction not allowing for image files
11
+ * :bug: fix naming in extracted PDFs
12
+
13
+
14
+ ## v5.1.1 - 2026-03-11
15
+ ### Changes
16
+ * :heavy_minus_sign: tslib is never imported, remove from dependencies
17
+
3
18
 
4
19
  ## v5.1.0 - 2026-03-02
5
20
  ### Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindee",
3
- "version": "5.1.0",
3
+ "version": "5.2.0",
4
4
  "description": "Mindee Client Library for Node.js",
5
5
  "author": {
6
6
  "name": "Mindee",
@@ -48,10 +48,9 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "commander": "^14.0.3",
51
- "file-type": "^21.3.0",
52
- "tmp": "^0.2.3",
53
- "tslib": "^2.8.1",
54
- "undici": ">=6.23.0 <8.0.0"
51
+ "file-type": "^21.3.3",
52
+ "tmp": "^0.2.5",
53
+ "undici": ">=6.24.0 <7.0.0 || >=7.24.0 <8.0.0"
55
54
  },
56
55
  "optionalDependencies": {
57
56
  "@cantoo/pdf-lib": "^2.5.3",
@@ -60,17 +59,21 @@
60
59
  "sharp": "~0.34.5"
61
60
  },
62
61
  "devDependencies": {
62
+ "@eslint/eslintrc": "^3.3.5",
63
+ "@eslint/js": "^10.0.1",
63
64
  "@types/mocha": "^10.0.10",
64
- "@types/node": "^20.19.35",
65
+ "@types/node": "^20.19.37",
65
66
  "@types/tmp": "^0.2.6",
66
- "@typescript-eslint/eslint-plugin": "^8.56.1",
67
- "@typescript-eslint/parser": "^8.56.1",
68
- "eslint": "^9.39.3",
67
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
68
+ "@typescript-eslint/parser": "^8.58.1",
69
+ "eslint": "^10.0.3",
69
70
  "eslint-plugin-jsdoc": "^62.7.1",
71
+ "globals": "^17.4.0",
70
72
  "mocha": "^11.7.5",
71
73
  "tsc-alias": "^1.8.16",
74
+ "tslib": "^2.8.1",
72
75
  "tsx": "^4.21.0",
73
- "typedoc": "^0.28.17",
76
+ "typedoc": "^0.28.18",
74
77
  "typescript": "^5.9.3"
75
78
  },
76
79
  "keywords": [
@@ -5,8 +5,10 @@ import { BufferInput } from "../input/index.js";
5
5
  */
6
6
  export declare class ExtractedImage {
7
7
  buffer: Buffer;
8
- protected internalFileName: string;
9
- protected constructor(buffer: Uint8Array, fileName: string);
8
+ filename: string;
9
+ pageId?: number;
10
+ elementId?: number;
11
+ constructor(buffer: Uint8Array, fileName: string, pageId?: number, elementId?: number);
10
12
  /**
11
13
  * Saves the document to a file.
12
14
  *
@@ -10,9 +10,11 @@ import { loadOptionalDependency } from "../dependency/index.js";
10
10
  * Generic class for image extraction
11
11
  */
12
12
  export class ExtractedImage {
13
- constructor(buffer, fileName) {
13
+ constructor(buffer, fileName, pageId, elementId) {
14
14
  this.buffer = Buffer.from(buffer);
15
- this.internalFileName = fileName;
15
+ this.filename = fileName;
16
+ this.pageId = pageId;
17
+ this.elementId = elementId;
16
18
  }
17
19
  /**
18
20
  * Saves the document to a file.
@@ -93,7 +95,7 @@ export class ExtractedImage {
93
95
  asSource() {
94
96
  return new BufferInput({
95
97
  buffer: this.buffer,
96
- filename: this.internalFileName,
98
+ filename: this.filename,
97
99
  });
98
100
  }
99
101
  }
@@ -1,9 +1,20 @@
1
- import type * as pdfLibTypes from "@cantoo/pdf-lib";
2
1
  import { Polygon } from "../geometry/index.js";
2
+ import { ExtractedImage } from "../image/extractedImage.js";
3
+ import { LocalInputSource } from "../input/index.js";
4
+ import type * as pdfLibTypes from "@cantoo/pdf-lib";
5
+ /**
6
+ * Extracts elements from a PDF document based on a list of bounding boxes.
7
+ * @param inputSource The input source to extract from.
8
+ * @param polygonsPerPage List of polygons to extract from per page.
9
+ * @param quality JPEG quality of extracted images.
10
+ */
11
+ export declare function extractImagesFromPolygon(inputSource: LocalInputSource, polygonsPerPage: Map<number, Polygon[]>, quality?: number): Promise<ExtractedImage[]>;
3
12
  /**
4
13
  * Extracts elements from a page based off of a list of bounding boxes.
5
14
  *
6
15
  * @param pdfPage PDF Page to extract from.
7
16
  * @param polygons List of coordinates to pull the elements from.
17
+ * @param asImage Whether to return the extracted elements as images.
18
+ * @param quality JPEG quality of extracted images, given as number between 0 and 1.
8
19
  */
9
- export declare function extractFromPage(pdfPage: pdfLibTypes.PDFPage, polygons: Polygon[]): Promise<Uint8Array<ArrayBufferLike>[]>;
20
+ export declare function extractFromPage(pdfPage: pdfLibTypes.PDFPage, polygons: Polygon[], asImage?: boolean, quality?: number): Promise<Uint8Array<ArrayBufferLike>[]>;
@@ -1,44 +1,76 @@
1
+ import { loadOptionalDependency } from "../dependency/index.js";
2
+ import { MindeeImageError } from "../errors/index.js";
1
3
  import { getMinMaxX, getMinMaxY } from "../geometry/index.js";
2
4
  import { adjustForRotation } from "../geometry/polygonUtils.js";
3
- import { loadOptionalDependency } from "../dependency/index.js";
5
+ import { ExtractedImage } from "../image/extractedImage.js";
6
+ import { logger } from "../logger.js";
7
+ import { createPdfFromInputSource } from "../pdf/pdfOperation.js";
8
+ import { rasterizePage } from "../pdf/pdfUtils.js";
4
9
  let pdfLib = null;
5
10
  async function getPdfLib() {
6
11
  if (!pdfLib) {
7
- const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Text Embedding");
12
+ const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Image Extraction");
8
13
  pdfLib = pdfLibImport.default || pdfLibImport;
9
14
  }
10
15
  return pdfLib;
11
16
  }
17
+ /**
18
+ * Extracts elements from a PDF document based on a list of bounding boxes.
19
+ * @param inputSource The input source to extract from.
20
+ * @param polygonsPerPage List of polygons to extract from per page.
21
+ * @param quality JPEG quality of extracted images.
22
+ */
23
+ export async function extractImagesFromPolygon(inputSource, polygonsPerPage, quality) {
24
+ const allExtractedImages = [];
25
+ const pdfDoc = await createPdfFromInputSource(inputSource);
26
+ for (const [pageId, polygons] of polygonsPerPage) {
27
+ logger.debug(`Extracting images from page ${pageId}`);
28
+ const pdfPage = pdfDoc.getPage(pageId);
29
+ const extractions = (await extractFromPage(pdfPage, polygons, true, quality));
30
+ const extractedImages = extractions.map((v, i) => new ExtractedImage(v, inputSource.filename + `_page${pageId}-${i}.jpg`, pageId, i));
31
+ allExtractedImages.push(...extractedImages);
32
+ }
33
+ return allExtractedImages;
34
+ }
12
35
  /**
13
36
  * Extracts elements from a page based off of a list of bounding boxes.
14
37
  *
15
38
  * @param pdfPage PDF Page to extract from.
16
39
  * @param polygons List of coordinates to pull the elements from.
40
+ * @param asImage Whether to return the extracted elements as images.
41
+ * @param quality JPEG quality of extracted images, given as number between 0 and 1.
17
42
  */
18
- export async function extractFromPage(pdfPage, polygons) {
43
+ export async function extractFromPage(pdfPage, polygons, asImage = false, quality) {
19
44
  const pdfLib = await getPdfLib();
20
45
  const { width, height } = pdfPage.getSize();
21
46
  const extractedElements = [];
22
- // Manual upscale.
23
- // Fixes issues with the OCR.
24
- const qualityScale = 300 / 72;
47
+ if (quality && (quality < 0)) {
48
+ throw new MindeeImageError("Quality must be a number between 0 and 1");
49
+ }
50
+ if (quality && quality > 1) {
51
+ logger.warn("Quality is greater than 1, this operation will apply a manual upscale on the output." +
52
+ " Use only if you know what you are doing.");
53
+ }
54
+ const qualityScale = quality ?? 1;
25
55
  const orientation = pdfPage.getRotation().angle;
56
+ const sourceDoc = pdfPage.doc;
57
+ const pageIndex = sourceDoc.getPages().indexOf(pdfPage);
26
58
  for (const origPolygon of polygons) {
27
- const polygon = adjustForRotation(origPolygon, orientation);
59
+ logger.debug(`Extracting image with polygon: ${origPolygon.toString()}`);
28
60
  const tempPdf = await pdfLib.PDFDocument.create();
61
+ const [copiedPage] = await tempPdf.copyPages(sourceDoc, [pageIndex]);
62
+ const polygon = adjustForRotation(origPolygon, orientation);
29
63
  const newWidth = width * (getMinMaxX(polygon).max - getMinMaxX(polygon).min);
30
64
  const newHeight = height * (getMinMaxY(polygon).max - getMinMaxY(polygon).min);
31
- const cropped = await tempPdf.embedPage(pdfPage, {
65
+ const cropped = await tempPdf.embedPage(copiedPage, {
32
66
  left: getMinMaxX(polygon).min * width,
33
67
  right: getMinMaxX(polygon).max * width,
34
68
  top: height - (getMinMaxY(polygon).min * height),
35
69
  bottom: height - (getMinMaxY(polygon).max * height),
36
70
  });
37
- // Determine the final page dimensions based on orientation
38
71
  let finalWidth;
39
72
  let finalHeight;
40
73
  if (orientation === 90 || orientation === 270) {
41
- // For 90/270 rotations, swap width and height
42
74
  finalWidth = newHeight * qualityScale;
43
75
  finalHeight = newWidth * qualityScale;
44
76
  }
@@ -52,8 +84,8 @@ export async function extractFromPage(pdfPage, polygons) {
52
84
  y: 0,
53
85
  width: finalWidth,
54
86
  height: finalHeight,
87
+ color: pdfLib.rgb(1, 1, 1),
55
88
  });
56
- // Draw the cropped page with rotation applied
57
89
  if (orientation === 0) {
58
90
  samplePage.drawPage(cropped, {
59
91
  width: newWidth * qualityScale,
@@ -87,7 +119,13 @@ export async function extractFromPage(pdfPage, polygons) {
87
119
  rotate: pdfLib.degrees(90),
88
120
  });
89
121
  }
90
- extractedElements.push(await tempPdf.save());
122
+ const pdfBuffer = Buffer.from(await tempPdf.save());
123
+ if (asImage) {
124
+ extractedElements.push(await rasterizePage(pdfBuffer, 0, 100));
125
+ }
126
+ else {
127
+ extractedElements.push(pdfBuffer);
128
+ }
91
129
  }
92
130
  return extractedElements;
93
131
  }
@@ -0,0 +1,25 @@
1
+ import { BufferInput } from "../input/index.js";
2
+ import { Buffer } from "node:buffer";
3
+ export declare class ExtractedPdf {
4
+ readonly buffer: Buffer;
5
+ readonly filename: string;
6
+ readonly pageCount: number;
7
+ constructor(pdfData: Buffer<ArrayBufferLike>, filename: string, pageCount: number);
8
+ /**
9
+ * Saves the document to a file.
10
+ *
11
+ * @param outputPath Path to save the file to.
12
+ */
13
+ saveToFileAsync(outputPath: string): Promise<void>;
14
+ /**
15
+ * Saves the document to a file synchronously.
16
+ * @param outputPath
17
+ */
18
+ saveToFile(outputPath: string): void;
19
+ /**
20
+ * Return the file as a Mindee-compatible BufferInput source.
21
+ *
22
+ * @returns A BufferInput source.
23
+ */
24
+ asSource(): BufferInput;
25
+ }
@@ -0,0 +1,65 @@
1
+ import path from "node:path";
2
+ import { BufferInput, MIMETYPES } from "../input/index.js";
3
+ import { MindeeError } from "../errors/index.js";
4
+ import { writeFile } from "fs/promises";
5
+ import { logger } from "../logger.js";
6
+ import { writeFileSync } from "node:fs";
7
+ export class ExtractedPdf {
8
+ constructor(pdfData, filename, pageCount) {
9
+ this.buffer = pdfData;
10
+ this.filename = filename;
11
+ this.pageCount = pageCount;
12
+ }
13
+ /**
14
+ * Saves the document to a file.
15
+ *
16
+ * @param outputPath Path to save the file to.
17
+ */
18
+ async saveToFileAsync(outputPath) {
19
+ const fileExt = path.extname(outputPath).toLowerCase();
20
+ if (fileExt !== ".pdf" && !MIMETYPES.has(fileExt)) {
21
+ outputPath += ".pdf";
22
+ }
23
+ try {
24
+ await writeFile(path.resolve(outputPath), this.buffer);
25
+ logger.info(`File saved successfully to ${path.resolve(outputPath)}.`);
26
+ }
27
+ catch (e) {
28
+ if (e instanceof TypeError) {
29
+ throw new MindeeError("Invalid path/filename provided.");
30
+ }
31
+ else {
32
+ throw e;
33
+ }
34
+ }
35
+ }
36
+ /**
37
+ * Saves the document to a file synchronously.
38
+ * @param outputPath
39
+ */
40
+ saveToFile(outputPath) {
41
+ try {
42
+ writeFileSync(path.resolve(outputPath), this.buffer);
43
+ logger.info(`File saved successfully to ${path.resolve(outputPath)}.`);
44
+ }
45
+ catch (e) {
46
+ if (e instanceof TypeError) {
47
+ throw new MindeeError("Invalid path/filename provided.");
48
+ }
49
+ else {
50
+ throw e;
51
+ }
52
+ }
53
+ }
54
+ /**
55
+ * Return the file as a Mindee-compatible BufferInput source.
56
+ *
57
+ * @returns A BufferInput source.
58
+ */
59
+ asSource() {
60
+ return new BufferInput({
61
+ buffer: this.buffer,
62
+ filename: this.filename,
63
+ });
64
+ }
65
+ }
@@ -1,9 +1,7 @@
1
1
  import { logger } from "../logger.js";
2
- import tmp from "tmp";
3
- import * as fs from "node:fs";
4
2
  import { compressImage } from "../image/index.js";
5
3
  import { loadOptionalDependency } from "../dependency/index.js";
6
- import { extractTextFromPdf, hasSourceText } from "./pdfUtils.js";
4
+ import { extractTextFromPdf, hasSourceText, rasterizePage } from "./pdfUtils.js";
7
5
  let pdfLib = null;
8
6
  async function getPdfLib() {
9
7
  if (!pdfLib) {
@@ -105,7 +103,7 @@ async function compressPagesWithQuality(pdfData, extractedPdfInfo, imageQuality,
105
103
  for (let i = 0; i < extractedPdfInfo.pages.length; i++) {
106
104
  const page = pdfDoc.getPages()[i];
107
105
  const rasterizedPage = await rasterizePage(pdfData, i + 1, imageQuality);
108
- const compressedImage = await compressImage(Buffer.from(rasterizedPage, "binary"), imageQuality);
106
+ const compressedImage = await compressImage(rasterizedPage, imageQuality);
109
107
  if (!disableSourceText) {
110
108
  await addTextToPdfPage(page, extractedText);
111
109
  }
@@ -187,42 +185,6 @@ async function getFontFromName(fontName) {
187
185
  }
188
186
  return font;
189
187
  }
190
- /**
191
- * Rasterizes a PDF page.
192
- *
193
- * @param pdfData Buffer representation of the entire PDF file.
194
- * @param index Index of the page to rasterize.
195
- * @param quality Quality to apply during rasterization.
196
- */
197
- async function rasterizePage(pdfData, index, quality = 85) {
198
- const popplerImport = await loadOptionalDependency("node-poppler", "Image Processing");
199
- const poppler = popplerImport.default || popplerImport;
200
- const popplerInstance = new poppler.Poppler();
201
- const tmpPdf = tmp.fileSync();
202
- const tempPdfPath = tmpPdf.name;
203
- const antialiasOption = "best";
204
- try {
205
- await fs.promises.writeFile(tempPdfPath, pdfData);
206
- const options = {
207
- antialias: antialiasOption,
208
- firstPageToConvert: index,
209
- lastPageToConvert: index,
210
- jpegFile: true,
211
- jpegOptions: `quality=${quality}`,
212
- singleFile: true
213
- };
214
- const jpegBuffer = await popplerInstance.pdfToCairo(tempPdfPath, undefined, options);
215
- await fs.promises.unlink(tempPdfPath);
216
- return jpegBuffer;
217
- }
218
- catch (error) {
219
- logger.error("Error rasterizing PDF:", error);
220
- throw error;
221
- }
222
- finally {
223
- tmpPdf.removeCallback();
224
- }
225
- }
226
188
  /**
227
189
  * Performs linear interpolation between two numbers.
228
190
  * @param start The starting value.
@@ -0,0 +1,46 @@
1
+ import { LocalInputSource } from "../input/index.js";
2
+ import { ExtractedPdf } from "../pdf/extractedPdf.js";
3
+ export declare class PdfExtractor {
4
+ /**
5
+ * Buffer containing the PDF data.
6
+ * @private
7
+ */
8
+ private sourcePdf;
9
+ /**
10
+ * Filename of the PDF.
11
+ * @private
12
+ */
13
+ private filename;
14
+ /**
15
+ * Input document.
16
+ * @private
17
+ */
18
+ private readonly inputDocument;
19
+ /**
20
+ * Whether the extractor has been initialized.
21
+ * @private
22
+ */
23
+ private initialized;
24
+ /**
25
+ * PDF library instance.
26
+ * @private
27
+ */
28
+ private pdfLib;
29
+ /**
30
+ * List of extracted PDFs.
31
+ * @private
32
+ */
33
+ private extractedPdfs;
34
+ constructor(inputDocument: string | LocalInputSource);
35
+ init(): Promise<void>;
36
+ /**
37
+ * Gets the number of pages in the PDF.
38
+ * @returns The number of pages in the PDF.
39
+ */
40
+ getPageCount(): Promise<number>;
41
+ /**
42
+ * Extracts pages from the PDF.
43
+ * @param pageIndexes
44
+ */
45
+ extractSubDocuments(pageIndexes: number[][]): Promise<ExtractedPdf[]>;
46
+ }
@@ -0,0 +1,128 @@
1
+ import { PageOptionsOperation, PathInput } from "../input/index.js";
2
+ import { logger } from "../logger.js";
3
+ import path from "path";
4
+ import { loadOptionalDependency } from "../dependency/index.js";
5
+ import { MindeeInputSourceError, MindeePdfError } from "../errors/index.js";
6
+ import { ExtractedPdf } from "../pdf/extractedPdf.js";
7
+ import { createPdfFromInputSource, extractPages } from "../pdf/pdfOperation.js";
8
+ let pdfLib = null;
9
+ async function getPdfLib() {
10
+ if (!pdfLib) {
11
+ const pdfLibImport = await loadOptionalDependency("@cantoo/pdf-lib", "Text Embedding");
12
+ pdfLib = pdfLibImport.default || pdfLibImport;
13
+ }
14
+ return pdfLib;
15
+ }
16
+ export class PdfExtractor {
17
+ constructor(inputDocument) {
18
+ /**
19
+ * Buffer containing the PDF data.
20
+ * @private
21
+ */
22
+ this.sourcePdf = null;
23
+ /**
24
+ * Filename of the PDF.
25
+ * @private
26
+ */
27
+ this.filename = null;
28
+ /**
29
+ * Whether the extractor has been initialized.
30
+ * @private
31
+ */
32
+ this.initialized = false;
33
+ /**
34
+ * PDF library instance.
35
+ * @private
36
+ */
37
+ this.pdfLib = null;
38
+ /**
39
+ * List of extracted PDFs.
40
+ * @private
41
+ */
42
+ this.extractedPdfs = null;
43
+ this.inputDocument = inputDocument;
44
+ }
45
+ async init() {
46
+ this.pdfLib = await getPdfLib();
47
+ if (typeof this.inputDocument === "string") {
48
+ logger.debug(`Loading from path: ${this.inputDocument}`);
49
+ try {
50
+ const tempPathInput = new PathInput({ inputPath: this.inputDocument });
51
+ await tempPathInput.init();
52
+ if (tempPathInput.isPdf()) {
53
+ this.sourcePdf = tempPathInput.fileObject;
54
+ }
55
+ else {
56
+ const pdfObject = await createPdfFromInputSource(tempPathInput);
57
+ this.sourcePdf = Buffer.from(await pdfObject.save());
58
+ }
59
+ }
60
+ catch {
61
+ throw new MindeeInputSourceError("Couldn't generate PDF from input.");
62
+ }
63
+ this.filename = path.basename(this.inputDocument);
64
+ }
65
+ else {
66
+ logger.debug(`Loading document: ${this.inputDocument.filename}`);
67
+ await this.inputDocument.init();
68
+ if (this.inputDocument.isPdf()) {
69
+ this.sourcePdf = this.inputDocument.fileObject;
70
+ }
71
+ else {
72
+ const pdfObject = await createPdfFromInputSource(this.inputDocument);
73
+ const arrayBuffer = await pdfObject.save();
74
+ this.sourcePdf = Buffer.from(arrayBuffer);
75
+ }
76
+ this.filename = this.inputDocument.filename;
77
+ }
78
+ this.initialized = true;
79
+ if (!this.sourcePdf) {
80
+ throw new MindeePdfError("Could not load PDF source.");
81
+ }
82
+ }
83
+ /**
84
+ * Gets the number of pages in the PDF.
85
+ * @returns The number of pages in the PDF.
86
+ */
87
+ async getPageCount() {
88
+ if (!this.initialized) {
89
+ await this.init();
90
+ }
91
+ const currentPdf = await this.pdfLib.PDFDocument.load(this.sourcePdf, {
92
+ ignoreEncryption: true,
93
+ password: ""
94
+ });
95
+ return currentPdf.getPageCount();
96
+ }
97
+ /**
98
+ * Extracts pages from the PDF.
99
+ * @param pageIndexes
100
+ */
101
+ async extractSubDocuments(pageIndexes) {
102
+ if (this.extractedPdfs && this.extractedPdfs.length > 0) {
103
+ return this.extractedPdfs;
104
+ }
105
+ if (!this.initialized) {
106
+ await this.init();
107
+ }
108
+ this.extractedPdfs = [];
109
+ for (const pageRange of pageIndexes) {
110
+ logger.debug(`Extracting pages ${pageRange.join(", ")}`);
111
+ if (pageRange.length === 0) {
112
+ throw new MindeeInputSourceError("Empty indexes not allowed for extraction.");
113
+ }
114
+ const pageOptions = {
115
+ pageIndexes: pageRange,
116
+ operation: PageOptionsOperation.KeepOnly,
117
+ onMinPages: 1,
118
+ };
119
+ const splitName = path.basename(this.filename, path.extname(this.filename));
120
+ const startPage = String(pageRange[0] + 1).padStart(3, "0");
121
+ const endPage = String(pageRange[pageRange.length - 1] + 1).padStart(3, "0");
122
+ const fieldFilename = `${splitName}_page_${startPage}-${endPage}.pdf`;
123
+ const page = await extractPages(this.sourcePdf, pageOptions);
124
+ this.extractedPdfs.push(new ExtractedPdf(page.file, fieldFilename, pageRange.length));
125
+ }
126
+ return this.extractedPdfs;
127
+ }
128
+ }
@@ -1,4 +1,6 @@
1
+ import type * as pdfLibTypes from "@cantoo/pdf-lib";
1
2
  import { PageOptions } from "../input/pageOptions.js";
3
+ import { LocalInputSource } from "../input/index.js";
2
4
  export interface SplitPdf {
3
5
  file: Buffer;
4
6
  totalPagesRemoved: number;
@@ -16,3 +18,8 @@ export declare function extractPages(file: Buffer, pageOptions: PageOptions): Pr
16
18
  * @returns the number of pages in the file.
17
19
  */
18
20
  export declare function countPages(file: Buffer): Promise<number>;
21
+ /**
22
+ * Creates a PDF from a local file. Converts images to PDFs if needed.
23
+ * @param inputSource The input source to create a PDF from.
24
+ */
25
+ export declare function createPdfFromInputSource(inputSource: LocalInputSource): Promise<pdfLibTypes.PDFDocument>;
@@ -1,6 +1,6 @@
1
1
  import { errorHandler } from "../errors/handler.js";
2
2
  import { PageOptionsOperation } from "../input/pageOptions.js";
3
- import { MindeeError } from "../errors/index.js";
3
+ import { MindeeError, MindeeInputSourceError } from "../errors/index.js";
4
4
  import { logger } from "../logger.js";
5
5
  import { loadOptionalDependency } from "../dependency/index.js";
6
6
  let pdfLib = null;
@@ -84,3 +84,36 @@ export async function countPages(file) {
84
84
  });
85
85
  return currentPdf.getPageCount();
86
86
  }
87
+ /**
88
+ * Creates a PDF from a local file. Converts images to PDFs if needed.
89
+ * @param inputSource The input source to create a PDF from.
90
+ */
91
+ export async function createPdfFromInputSource(inputSource) {
92
+ const pdfLib = await getPdfLib();
93
+ let pdfDoc;
94
+ if (!["image/jpeg", "image/jpg", "image/png", "application/pdf"].includes(inputSource.mimeType)) {
95
+ throw new MindeeInputSourceError('Unsupported file type "' +
96
+ inputSource.mimeType +
97
+ '" Currently supported types are .png, .jpg and .pdf');
98
+ }
99
+ else if (inputSource.isPdf()) {
100
+ pdfDoc = await pdfLib.PDFDocument.load(inputSource.fileObject, {
101
+ ignoreEncryption: true,
102
+ password: ""
103
+ });
104
+ }
105
+ else {
106
+ pdfDoc = await pdfLib.PDFDocument.create();
107
+ let image;
108
+ if (inputSource.mimeType === "image/png") {
109
+ image = await pdfDoc.embedPng(inputSource.fileObject);
110
+ }
111
+ else {
112
+ image = await pdfDoc.embedJpg(inputSource.fileObject);
113
+ }
114
+ const imageDims = image.scale(1);
115
+ const pageImage = pdfDoc.addPage([imageDims.width, imageDims.height]);
116
+ pageImage.drawImage(image);
117
+ }
118
+ return pdfDoc;
119
+ }
@@ -28,3 +28,12 @@ export declare function extractTextFromPdf(pdfBuffer: Buffer): Promise<Extracted
28
28
  * @returns A Promise containing a boolean indicating if the PDF has source text.
29
29
  */
30
30
  export declare function hasSourceText(pdfData: Buffer): Promise<boolean>;
31
+ /**
32
+ * Rasterizes a PDF page.
33
+ *
34
+ * @param pdfData Buffer representation of the entire PDF file.
35
+ * @param index Index of the page to rasterize.
36
+ * @param quality Quality to apply during rasterization.
37
+ * @return Buffer containing the rasterized image data.
38
+ */
39
+ export declare function rasterizePage(pdfData: Buffer, index: number, quality?: number): Promise<Buffer>;
@@ -1,5 +1,8 @@
1
+ import tmp from "tmp";
2
+ import * as fs from "node:fs";
1
3
  import { MindeePdfError } from "../errors/index.js";
2
4
  import { loadOptionalDependency } from "../dependency/index.js";
5
+ import { logger } from "../logger.js";
3
6
  function getConcatenatedText(pages) {
4
7
  return pages.flatMap(page => page.content.map(item => item.str)).join(" ");
5
8
  }
@@ -51,3 +54,40 @@ export async function hasSourceText(pdfData) {
51
54
  const text = await extractTextFromPdf(pdfData);
52
55
  return text.getConcatenatedText().trim().length > 0;
53
56
  }
57
+ /**
58
+ * Rasterizes a PDF page.
59
+ *
60
+ * @param pdfData Buffer representation of the entire PDF file.
61
+ * @param index Index of the page to rasterize.
62
+ * @param quality Quality to apply during rasterization.
63
+ * @return Buffer containing the rasterized image data.
64
+ */
65
+ export async function rasterizePage(pdfData, index, quality = 85) {
66
+ const popplerImport = await loadOptionalDependency("node-poppler", "Image Processing");
67
+ const poppler = popplerImport.default || popplerImport;
68
+ const popplerInstance = new poppler.Poppler();
69
+ const tmpPdf = tmp.fileSync();
70
+ const tempPdfPath = tmpPdf.name;
71
+ const antialiasOption = "best";
72
+ try {
73
+ await fs.promises.writeFile(tempPdfPath, pdfData);
74
+ const options = {
75
+ antialias: antialiasOption,
76
+ firstPageToConvert: index,
77
+ lastPageToConvert: index,
78
+ jpegFile: true,
79
+ jpegOptions: `quality=${quality}`,
80
+ singleFile: true
81
+ };
82
+ const jpegBuffer = await popplerInstance.pdfToCairo(tempPdfPath, undefined, options);
83
+ await fs.promises.unlink(tempPdfPath);
84
+ return Buffer.from(jpegBuffer, "binary");
85
+ }
86
+ catch (error) {
87
+ logger.error("Error rasterizing PDF:", error);
88
+ throw error;
89
+ }
90
+ finally {
91
+ tmpPdf.removeCallback();
92
+ }
93
+ }
@@ -1,4 +1,5 @@
1
- import { MindeeError, MindeeInputSourceError } from "../../../errors/index.js";
1
+ import { MindeeError } from "../../../errors/index.js";
2
+ import { createPdfFromInputSource } from "../../../pdf/pdfOperation.js";
2
3
  import { ExtractedMultiReceiptImage } from "../../../v1/extraction/index.js";
3
4
  import { extractFromPage } from "../../../image/index.js";
4
5
  import { loadOptionalDependency } from "../../../dependency/index.js";
@@ -20,42 +21,14 @@ async function getPdfLib() {
20
21
  * pages.
21
22
  */
22
23
  async function extractReceiptsFromPage(pdfPage, boundingBoxes, pageId) {
23
- const extractedReceiptsRaw = await extractFromPage(pdfPage, boundingBoxes);
24
+ const manualUpscaleFactor = 300 / 72;
25
+ const extractedReceiptsRaw = await extractFromPage(pdfPage, boundingBoxes, false, manualUpscaleFactor);
24
26
  const extractedReceipts = [];
25
27
  for (let i = 0; i < extractedReceiptsRaw.length; i++) {
26
28
  extractedReceipts.push(new ExtractedMultiReceiptImage(extractedReceiptsRaw[i], pageId, i));
27
29
  }
28
30
  return extractedReceipts;
29
31
  }
30
- async function loadPdfDoc(inputFile) {
31
- const pdfLib = await getPdfLib();
32
- let pdfDoc;
33
- if (!["image/jpeg", "image/jpg", "image/png", "application/pdf"].includes(inputFile.mimeType)) {
34
- throw new MindeeInputSourceError('Unsupported file type "' +
35
- inputFile.mimeType +
36
- '" Currently supported types are .png, .jpg and .pdf');
37
- }
38
- else if (inputFile.isPdf()) {
39
- pdfDoc = await pdfLib.PDFDocument.load(inputFile.fileObject, {
40
- ignoreEncryption: true,
41
- password: ""
42
- });
43
- }
44
- else {
45
- pdfDoc = await pdfLib.PDFDocument.create();
46
- let image;
47
- if (inputFile.mimeType === "image/png") {
48
- image = await pdfDoc.embedPng(inputFile.fileObject);
49
- }
50
- else {
51
- image = await pdfDoc.embedJpg(inputFile.fileObject);
52
- }
53
- const imageDims = image.scale(1);
54
- const pageImage = pdfDoc.addPage([imageDims.width, imageDims.height]);
55
- pageImage.drawImage(image);
56
- }
57
- return pdfDoc;
58
- }
59
32
  /**
60
33
  * Extracts individual receipts from multi-receipts documents.
61
34
  *
@@ -69,9 +42,9 @@ export async function extractReceipts(inputFile, inference) {
69
42
  if (!inference.prediction.receipts) {
70
43
  throw new MindeeError("No possible receipts candidates found for MultiReceipts extraction.");
71
44
  }
72
- const pdfDoc = await loadPdfDoc(inputFile);
45
+ const pdfDoc = await createPdfFromInputSource(inputFile);
73
46
  for (let pageId = 0; pageId < pdfDoc.getPageCount(); pageId++) {
74
- const [page] = await pdfDoc.copyPages(pdfDoc, [pageId]);
47
+ const page = pdfDoc.getPage(pageId);
75
48
  page.setRotation(pdfLib.degrees(inference.pages[pageId].orientation?.value ?? 0));
76
49
  const receiptPositions = inference.pages[pageId].prediction.receipts.map((receipt) => receipt.boundingBox);
77
50
  const extractedReceipts = await extractReceiptsFromPage(page, receiptPositions, pageId);
package/src/v2/cli.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Command } from "commander";
2
- import { Client } from "./client.js";
3
- import { PathInput } from "../input/index.js";
4
2
  import * as console from "console";
3
+ import { Client, PathInput, UrlInput } from "../index.js";
5
4
  import { Classification, Crop, Extraction, Ocr, Split, } from "../v2/product/index.js";
6
5
  const program = new Command();
7
6
  //
@@ -15,7 +14,13 @@ function initClient(options) {
15
14
  }
16
15
  async function enqueueAndGetInference(product, inputPath, options) {
17
16
  const mindeeClient = initClient(options);
18
- const inputSource = new PathInput({ inputPath: inputPath });
17
+ let inputSource;
18
+ if (inputPath.startsWith("https://")) {
19
+ inputSource = new UrlInput({ url: inputPath });
20
+ }
21
+ else {
22
+ inputSource = new PathInput({ inputPath: inputPath });
23
+ }
19
24
  const response = await mindeeClient.enqueueAndGetResult(product, inputSource, { modelId: options.model }, {
20
25
  initialDelaySec: 2,
21
26
  delaySec: 1.5,
@@ -36,7 +41,7 @@ function printResponse(document) {
36
41
  //
37
42
  function addMainOptions(prog) {
38
43
  prog.requiredOption("-m, --model <model_id>", "Model ID (required)");
39
- prog.argument("<input_path>", "full path to the file");
44
+ prog.argument("<input_path>", "full path or URL to the file");
40
45
  }
41
46
  export function cli() {
42
47
  program.name("mindee")
@@ -0,0 +1,18 @@
1
+ import { LocalInputSource } from "../../input/index.js";
2
+ import { CropItem } from "../../v2/product/crop/index.js";
3
+ import { CropFiles } from "../../v2/fileOperations/cropFiles.js";
4
+ import { ExtractedImage } from "../../image/index.js";
5
+ /**
6
+ * Extracts a single specified crop from a given input source.
7
+ * @param inputSource Local input source.
8
+ * @param crop Crop to extract.
9
+ */
10
+ export declare function extractSingleCrop(inputSource: LocalInputSource, crop: CropItem): Promise<ExtractedImage>;
11
+ /**
12
+ * Extracts a list of crops from a document.
13
+ * @param inputSource Local input source.
14
+ * @param crops List of crops to extract.
15
+ * @param quality JPEG quality of extracted images.
16
+ * @return a list of extracted files, as a CropFiles object.
17
+ */
18
+ export declare function extractCrops(inputSource: LocalInputSource, crops: CropItem[], quality?: number): Promise<CropFiles>;
@@ -0,0 +1,35 @@
1
+ import { MindeeError } from "../../errors/index.js";
2
+ import { extractImagesFromPolygon } from "../../image/imageExtractor.js";
3
+ import { CropFiles } from "../../v2/fileOperations/cropFiles.js";
4
+ import { logger } from "../../logger.js";
5
+ /**
6
+ * Extracts a single specified crop from a given input source.
7
+ * @param inputSource Local input source.
8
+ * @param crop Crop to extract.
9
+ */
10
+ export async function extractSingleCrop(inputSource, crop) {
11
+ return (await extractCrops(inputSource, [crop]))[0];
12
+ }
13
+ /**
14
+ * Extracts a list of crops from a document.
15
+ * @param inputSource Local input source.
16
+ * @param crops List of crops to extract.
17
+ * @param quality JPEG quality of extracted images.
18
+ * @return a list of extracted files, as a CropFiles object.
19
+ */
20
+ export async function extractCrops(inputSource, crops, quality) {
21
+ if (crops.length === 0) {
22
+ throw new MindeeError("No crop indexes provided.");
23
+ }
24
+ logger.debug("Extracting crops: " + crops.join(", "));
25
+ const polygonsByPage = new Map();
26
+ for (const crop of crops) {
27
+ const pageId = crop.location.page;
28
+ if (!polygonsByPage.has(pageId)) {
29
+ polygonsByPage.set(pageId, []);
30
+ }
31
+ polygonsByPage.get(pageId).push(crop.location.polygon);
32
+ }
33
+ const extractedCrops = await extractImagesFromPolygon(inputSource, polygonsByPage, quality);
34
+ return new CropFiles(...extractedCrops);
35
+ }
@@ -0,0 +1,4 @@
1
+ import { ExtractedImage } from "../../image/index.js";
2
+ export declare class CropFiles extends Array<ExtractedImage> {
3
+ constructor(...items: ExtractedImage[]);
4
+ }
@@ -0,0 +1,5 @@
1
+ export class CropFiles extends Array {
2
+ constructor(...items) {
3
+ super(...items);
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { LocalInputSource } from "../../input/index.js";
2
+ import { SplitFiles } from "../../v2/fileOperations/splitFiles.js";
3
+ /**
4
+ * Extracts a single specified split from a
5
+ * @param inputSource
6
+ * @param split
7
+ */
8
+ export declare function extractSingleSplit(inputSource: LocalInputSource, split: number[]): Promise<SplitFiles>;
9
+ /**
10
+ * Extracts splits as complete PDFs from the document.
11
+ * @param inputSource Local input source.
12
+ * @param splits List of sub-lists of pages to keep.
13
+ * @return a list of extracted files.
14
+ * @throws MindeeError if no indexes are provided.
15
+ */
16
+ export declare function extractSplits(inputSource: LocalInputSource, splits: number[][]): Promise<SplitFiles>;
17
+ /**
18
+ * Expands a range of pages into a list of page indexes.
19
+ * @param range start and end of the page range
20
+ */
21
+ export declare function expandRange(range: [number, number]): number[];
@@ -0,0 +1,48 @@
1
+ import { MindeeError } from "../../errors/index.js";
2
+ import { PdfExtractor } from "../../pdf/pdfExtractor.js";
3
+ import { SplitFiles } from "../../v2/fileOperations/splitFiles.js";
4
+ import { logger } from "../../logger.js";
5
+ import { ExtractedPdf } from "../../pdf/extractedPdf.js";
6
+ /**
7
+ * Extracts a single specified split from a
8
+ * @param inputSource
9
+ * @param split
10
+ */
11
+ export async function extractSingleSplit(inputSource, split) {
12
+ return await extractSplits(inputSource, [split]);
13
+ }
14
+ /**
15
+ * Extracts splits as complete PDFs from the document.
16
+ * @param inputSource Local input source.
17
+ * @param splits List of sub-lists of pages to keep.
18
+ * @return a list of extracted files.
19
+ * @throws MindeeError if no indexes are provided.
20
+ */
21
+ export async function extractSplits(inputSource, splits) {
22
+ const pageGroups = splits.filter(e => e.length > 0);
23
+ if (pageGroups.length === 0) {
24
+ throw new MindeeError("No valid split indexes provided.");
25
+ }
26
+ logger.debug("Extracting splits: " + splits.join(", "));
27
+ const pdfExtractor = new PdfExtractor(inputSource);
28
+ await pdfExtractor.init();
29
+ if (splits.length === 0) {
30
+ return new SplitFiles();
31
+ }
32
+ const pageCount = await pdfExtractor.getPageCount();
33
+ if (splits.length === 1 && splits[0].at(-1) === pageCount - 1) {
34
+ return new SplitFiles(new ExtractedPdf(inputSource.fileObject, inputSource.filename, pageCount));
35
+ }
36
+ const subDocuments = await pdfExtractor.extractSubDocuments(pageGroups);
37
+ return new SplitFiles(...subDocuments);
38
+ }
39
+ /**
40
+ * Expands a range of pages into a list of page indexes.
41
+ * @param range start and end of the page range
42
+ */
43
+ export function expandRange(range) {
44
+ if (range[0] > range[1]) {
45
+ throw new MindeeError("Invalid page range provided.");
46
+ }
47
+ return Array.from({ length: range[1] - range[0] + 1 }, (_, i) => range[0] + i);
48
+ }
@@ -0,0 +1,4 @@
1
+ import { ExtractedPdf } from "../../pdf/extractedPdf.js";
2
+ export declare class SplitFiles extends Array<ExtractedPdf> {
3
+ constructor(...args: ExtractedPdf[]);
4
+ }
@@ -0,0 +1,5 @@
1
+ export class SplitFiles extends Array {
2
+ constructor(...args) {
3
+ super(...args);
4
+ }
5
+ }
@@ -1,8 +1,16 @@
1
1
  import { FieldLocation } from "../../../v2/parsing/inference/field/index.js";
2
2
  import { StringDict } from "../../../parsing/index.js";
3
+ import { LocalInputSource } from "../../../input/index.js";
4
+ import { ExtractedImage } from "../../../image/index.js";
3
5
  export declare class CropItem {
4
6
  objectType: string;
5
7
  location: FieldLocation;
6
8
  constructor(serverResponse: StringDict);
7
9
  toString(): string;
10
+ /**
11
+ * Extracts a single crop from an input.
12
+ * @param inputSource The input file to extract from.
13
+ * @param quality Optional quality parameter for image extraction, default is undefined (full quality).
14
+ */
15
+ extractFromFile(inputSource: LocalInputSource, quality?: number): Promise<ExtractedImage>;
8
16
  }
@@ -1,4 +1,5 @@
1
1
  import { FieldLocation } from "../../../v2/parsing/inference/field/index.js";
2
+ import { extractCrops } from "../../../v2/fileOperations/crop.js";
2
3
  export class CropItem {
3
4
  constructor(serverResponse) {
4
5
  this.objectType = serverResponse["object_type"];
@@ -7,4 +8,12 @@ export class CropItem {
7
8
  toString() {
8
9
  return `* :Location: ${this.location}\n :Object Type: ${this.objectType}`;
9
10
  }
11
+ /**
12
+ * Extracts a single crop from an input.
13
+ * @param inputSource The input file to extract from.
14
+ * @param quality Optional quality parameter for image extraction, default is undefined (full quality).
15
+ */
16
+ async extractFromFile(inputSource, quality = 1) {
17
+ return (await extractCrops(inputSource, [this], quality))[0];
18
+ }
10
19
  }
@@ -1,6 +1,8 @@
1
+ import { LocalInputSource } from "../../../input/index.js";
1
2
  import { StringDict } from "../../../parsing/stringDict.js";
2
- import { CropInference } from "./cropInference.js";
3
+ import { CropFiles } from "../../../v2/fileOperations/cropFiles.js";
3
4
  import { BaseResponse } from "../../../v2/parsing/index.js";
5
+ import { CropInference } from "./cropInference.js";
4
6
  export declare class CropResponse extends BaseResponse {
5
7
  /**
6
8
  * Response for a crop utility inference.
@@ -10,4 +12,10 @@ export declare class CropResponse extends BaseResponse {
10
12
  * @param serverResponse JSON response from the server.
11
13
  */
12
14
  constructor(serverResponse: StringDict);
15
+ /**
16
+ * Extracts all crops from an input.
17
+ * @param inputSource The input file to extract from.
18
+ * @param quality Optional quality parameter for image extraction, default is undefined (full quality).
19
+ */
20
+ extractFromFile(inputSource: LocalInputSource, quality?: number): Promise<CropFiles>;
13
21
  }
@@ -1,5 +1,6 @@
1
- import { CropInference } from "./cropInference.js";
1
+ import { extractCrops } from "../../../v2/fileOperations/crop.js";
2
2
  import { BaseResponse } from "../../../v2/parsing/index.js";
3
+ import { CropInference } from "./cropInference.js";
3
4
  export class CropResponse extends BaseResponse {
4
5
  /**
5
6
  * @param serverResponse JSON response from the server.
@@ -8,4 +9,12 @@ export class CropResponse extends BaseResponse {
8
9
  super(serverResponse);
9
10
  this.inference = new CropInference(serverResponse["inference"]);
10
11
  }
12
+ /**
13
+ * Extracts all crops from an input.
14
+ * @param inputSource The input file to extract from.
15
+ * @param quality Optional quality parameter for image extraction, default is undefined (full quality).
16
+ */
17
+ async extractFromFile(inputSource, quality = 1) {
18
+ return await extractCrops(inputSource, this.inference.result.crops, quality);
19
+ }
11
20
  }
@@ -1,4 +1,5 @@
1
1
  import { StringDict } from "../../../parsing/index.js";
2
+ import { LocalInputSource } from "../../../input/index.js";
2
3
  /**
3
4
  * Split inference result.
4
5
  */
@@ -14,4 +15,9 @@ export declare class SplitRange {
14
15
  documentType: string;
15
16
  constructor(serverResponse: StringDict);
16
17
  toString(): string;
18
+ /**
19
+ * Extracts a single split from the input file.
20
+ * @param inputSource The input file to extract from.
21
+ */
22
+ extractFromFile(inputSource: LocalInputSource): Promise<import("../../../pdf/extractedPdf.js").ExtractedPdf>;
17
23
  }
@@ -1,3 +1,4 @@
1
+ import { expandRange, extractSplits } from "../../../v2/fileOperations/split.js";
1
2
  /**
2
3
  * Split inference result.
3
4
  */
@@ -10,4 +11,12 @@ export class SplitRange {
10
11
  const pageRange = this.pageRange.join(",");
11
12
  return `* :Page Range: ${pageRange}\n :Document Type: ${this.documentType}`;
12
13
  }
14
+ /**
15
+ * Extracts a single split from the input file.
16
+ * @param inputSource The input file to extract from.
17
+ */
18
+ async extractFromFile(inputSource) {
19
+ const pageRange = [expandRange(this.pageRange)];
20
+ return (await extractSplits(inputSource, pageRange))[0];
21
+ }
13
22
  }
@@ -1,6 +1,8 @@
1
1
  import { StringDict } from "../../../parsing/stringDict.js";
2
2
  import { SplitInference } from "./splitInference.js";
3
3
  import { BaseResponse } from "../../../v2/parsing/index.js";
4
+ import { LocalInputSource } from "../../../input/index.js";
5
+ import { SplitFiles } from "../../../v2/fileOperations/splitFiles.js";
4
6
  export declare class SplitResponse extends BaseResponse {
5
7
  /**
6
8
  * Response for an OCR utility inference.
@@ -10,4 +12,9 @@ export declare class SplitResponse extends BaseResponse {
10
12
  * @param serverResponse JSON response from the server.
11
13
  */
12
14
  constructor(serverResponse: StringDict);
15
+ /**
16
+ * Extracts all splits from an input PDF.
17
+ * @param inputSource The input file to extract from.
18
+ */
19
+ extractFromFile(inputSource: LocalInputSource): Promise<SplitFiles>;
13
20
  }
@@ -1,5 +1,6 @@
1
1
  import { SplitInference } from "./splitInference.js";
2
2
  import { BaseResponse } from "../../../v2/parsing/index.js";
3
+ import { expandRange, extractSplits } from "../../../v2/fileOperations/split.js";
3
4
  export class SplitResponse extends BaseResponse {
4
5
  /**
5
6
  * @param serverResponse JSON response from the server.
@@ -8,4 +9,15 @@ export class SplitResponse extends BaseResponse {
8
9
  super(serverResponse);
9
10
  this.inference = new SplitInference(serverResponse["inference"]);
10
11
  }
12
+ /**
13
+ * Extracts all splits from an input PDF.
14
+ * @param inputSource The input file to extract from.
15
+ */
16
+ async extractFromFile(inputSource) {
17
+ const splits = [];
18
+ for (const split of this.inference.result.splits) {
19
+ splits.push(expandRange(split.pageRange));
20
+ }
21
+ return await extractSplits(inputSource, splits);
22
+ }
11
23
  }