@clearmist-labs/comic-archive-handler 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/API.md CHANGED
@@ -58,6 +58,7 @@ Converts an archive to `zip`, `rar`, `tar`, `asar`, or `7z`. Entries are copied
58
58
  - `options.image?: { format: ImageOutputFormat; options?: ImageConvertOptions }` - Re-encode image entries while converting the archive.
59
59
  - `options.image.format` - `'webp'`, `'jpg'`, or `'png'`.
60
60
  - `options.image.options` - Image format options described under [`convertImageBuffer`](#convertimagebuffer).
61
+ - `options.image.concurrency?: number | (() => number)` - How many images to convert at once. Defaults to `1`. A function is called again before each conversion starts, so the limit can follow the caller's load while the archive is converted. Entry order in the output is unchanged. See [`setImageConcurrency`](#setimageconcurrencythreads) for how this interacts with libuv's threadpool.
61
62
  - `options.metadata?: Partial<Record<MetadataSchema, ComicMetadata>>` - Replaces the source's embedded comic metadata. The source's `ComicInfo.xml`/`MetronInfo.xml` entries are dropped (an ASAR source's header metadata is never copied), then each given schema is written as an ASAR header key when the target is `asar`, or as a root-level `ComicInfo.xml`/`MetronInfo.xml` entry otherwise. Without it, an ASAR source's header metadata is not carried into the output.
62
63
 
63
64
  **Example**
@@ -121,6 +122,21 @@ for await (const entry of cah.readArchiveEntries(comicBuffer)) {
121
122
  }
122
123
  ```
123
124
 
125
+ ### `readArchiveImageInfo(input)`
126
+
127
+ Returns `{ name, path, width, height, type }` for every image entry in an archive, in archive iteration order. Image entries are identified by extension (see `isImagePath`), and non-image entries are skipped without being read. `name` is the file name without its directory, and `type` is the format detected from the entry's contents rather than its extension (`jpeg`, `png`, `gif`, `webp`, `tiff`, `bmp`, and so on). When an entry's contents are not a readable image, `width`, `height`, and `type` are `null`.
128
+
129
+ **Options**
130
+
131
+ - `input: ArchiveInput` - A filesystem path or archive `Buffer`.
132
+
133
+ **Example**
134
+
135
+ ```js
136
+ const images = await cah.readArchiveImageInfo(comicBuffer);
137
+ console.log(images[0]); // { name: 'P00001.jpg', path: 'pages/P00001.jpg', width: 1988, height: 3056, type: 'jpeg' }
138
+ ```
139
+
124
140
  ### `renameArchiveImagesSequentially(input, options?)`
125
141
 
126
142
  Renames image entries in natural-sort order to `P#####.<extension>`, while leaving other entries unchanged.
@@ -438,6 +454,7 @@ Re-encodes image entries in an archive and updates their extensions. Non-image e
438
454
  - `options.webp`, `options.jpeg`, `options.png` - Format-specific options listed under [`convertImageBuffer`](#convertimagebuffer).
439
455
  - `options.tempDir?: string` - Temporary staging directory for ASAR or 7z operations.
440
456
  - `options.output?: string | Writable` - Output destination. Without it, returns a `Buffer`.
457
+ - `options.concurrency?: number | (() => number)` - How many images to convert at once, as for `convertArchive`'s `options.image.concurrency`. Defaults to `1`.
441
458
 
442
459
  **Example**
443
460
 
@@ -448,6 +465,22 @@ const webpArchive = await cah.convertArchiveImages(comicBuffer, 'webp', {
448
465
  });
449
466
  ```
450
467
 
468
+ ### `setImageConcurrency(threads)`
469
+
470
+ Sets how many libvips threads process each image and returns the value now in effect. The setting is process-wide and covers every image operation in this package. When you already parallelize across images (for example one worker thread per core), pass `1` so each image doesn't also fan out across every core. sharp's default is the CPU core count, except on glibc Linux without jemalloc, where it is already `1`.
471
+
472
+ Image work runs on libuv's threadpool, which is shared by every worker thread in the process and defaults to 4 threads. To run more than 4 images at once, raise `UV_THREADPOOL_SIZE` before the process first uses the threadpool. Each image in flight (for example each of `convertArchive`'s `options.image.concurrency` conversions) holds one threadpool thread until it finishes, and a single image uses up to `threads` libvips threads on top of that.
473
+
474
+ **Options**
475
+
476
+ - `threads: number` - libvips threads per image.
477
+
478
+ **Example**
479
+
480
+ ```js
481
+ cah.setImageConcurrency(1);
482
+ ```
483
+
451
484
  ### `IMAGE_EXTENSIONS`
452
485
 
453
486
  Readonly list of recognized image extensions: `jpg`, `jpeg`, `png`, `gif`, `webp`, `bmp`, `tiff`, and `tif`.
@@ -490,6 +523,34 @@ Returns whether an archive entry path has an extension in `IMAGE_EXTENSIONS`.
490
523
  if (cah.isImagePath('P00001.jpg')) console.log('page image');
491
524
  ```
492
525
 
526
+ ### `readImageInfo(image)`
527
+
528
+ Reads an image's format and pixel dimensions from its header without decoding it, returning `{ width, height, type }`. Returns `null` when the buffer is not a readable image.
529
+
530
+ **Options**
531
+
532
+ - `image: Buffer` - Image bytes.
533
+
534
+ **Example**
535
+
536
+ ```js
537
+ const info = await cah.readImageInfo(imageBytes); // { width: 1988, height: 3056, type: 'jpeg' }
538
+ ```
539
+
540
+ ### `readImageDimensions(image)`
541
+
542
+ Like `readImageInfo`, but returns only `{ width, height }`.
543
+
544
+ **Options**
545
+
546
+ - `image: Buffer` - Image bytes.
547
+
548
+ **Example**
549
+
550
+ ```js
551
+ const { width, height } = await cah.readImageDimensions(imageBytes);
552
+ ```
553
+
493
554
  ## Perceptual hashing
494
555
 
495
556
  ### `computeImagePHash(image)`
@@ -677,6 +738,9 @@ The following types are exported for TypeScript consumers.
677
738
  - `MetadataValidationResult` - `{ valid: boolean; issues: MetadataValidationIssue[] }`, returned by `validateMetadataXml`.
678
739
  - `MetadataValidationIssue` - `{ message: string; line?: number }`.
679
740
  - `ExtractArchiveOptions` - `{ tempDir?: string }`.
741
+ - `ArchiveImageInfo` - `{ name, path, width, height, type }`, returned by `readArchiveImageInfo`. `width`, `height`, and `type` are `null` for unreadable images.
742
+ - `ImageDimensions` - `{ width: number; height: number }`.
743
+ - `ImageInfo` - `ImageDimensions & { type: string }`, returned by `readImageInfo`.
680
744
  - `WritableArchiveType` - `'zip' | 'tar' | 'asar' | '7z'`.
681
745
  - `BenchmarkArchiveOptions` - `{ tempDir?, reportsDir?, creationIterations?, seekSamples?, imageFormats?, image? }`; see [`benchmarkArchive`](#benchmarkarchivefilepath-options).
682
746
  - `BenchmarkVariantResult` - One generated variant's stats: `{ archiveType, imageFormat, fileName, filePath, fileSizeBytes, pageCount, avgImageSizeBytes, avgCreationMs, avgSeekMs }`. `avgImageSizeBytes` (average size of one converted page) depends only on `imageFormat`, not `archiveType`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clearmist-labs/comic-archive-handler",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Detect, convert, and manipulate comic book archives: container conversion, edit metadata, image re-encoding, perceptual + content hashing.",
5
5
  "keywords": [
6
6
  "7z",