From 760550ca0d19ecba0ad1ec0fd0cfb4d8655c63f5 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Thu, 4 Jun 2020 20:29:02 +0100 Subject: [PATCH] Expose levels metadata for multi-level images #2222 --- docs/api-input.md | 1 + docs/changelog.md | 3 +++ lib/input.js | 1 + src/metadata.cc | 20 ++++++++++++++++++++ src/metadata.h | 1 + 5 files changed, 26 insertions(+) diff --git a/docs/api-input.md b/docs/api-input.md index 6f1c6bde..2ab3416f 100644 --- a/docs/api-input.md +++ b/docs/api-input.md @@ -20,6 +20,7 @@ A `Promise` is returned when `callback` is not provided. - `loop`: Number of times to loop an animated image, zero refers to a continuous loop. - `delay`: Delay in ms between each page in an animated image, provided as an array of integers. - `pagePrimary`: Number of the primary page in a HEIF image +- `levels`: Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide - `hasProfile`: Boolean indicating the presence of an embedded ICC profile - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel - `orientation`: Number value of the EXIF Orientation header, if present diff --git a/docs/changelog.md b/docs/changelog.md index a09c67d0..27cf1b0b 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -14,6 +14,9 @@ Requires libvips v8.9.1 [#2226](https://github.com/lovell/sharp/pull/2226) [@romaleev](https://github.com/romaleev) +* Expose `levels` metadata for multi-level images. + [#2222](https://github.com/lovell/sharp/issues/2222) + ### v0.25.3 - 17th May 2020 * Ensure libvips is initialised only once, improves worker thread safety. diff --git a/lib/input.js b/lib/input.js index c389d29d..0abf64c3 100644 --- a/lib/input.js +++ b/lib/input.js @@ -208,6 +208,7 @@ function _isStreamInput () { * - `loop`: Number of times to loop an animated image, zero refers to a continuous loop. * - `delay`: Delay in ms between each page in an animated image, provided as an array of integers. * - `pagePrimary`: Number of the primary page in a HEIF image + * - `levels`: Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide * - `hasProfile`: Boolean indicating the presence of an embedded ICC profile * - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel * - `orientation`: Number value of the EXIF Orientation header, if present diff --git a/src/metadata.cc b/src/metadata.cc index 25c2871c..34d0e4bc 100644 --- a/src/metadata.cc +++ b/src/metadata.cc @@ -74,6 +74,15 @@ class MetadataWorker : public Napi::AsyncWorker { if (image.get_typeof("heif-primary") == G_TYPE_INT) { baton->pagePrimary = image.get_int("heif-primary"); } + if (image.get_typeof("openslide.level-count") == VIPS_TYPE_REF_STRING) { + int const levels = std::stoi(image.get_string("openslide.level-count")); + for (int l = 0; l < levels; l++) { + std::string prefix = "openslide.level[" + std::to_string(l) + "]."; + int const width = std::stoi(image.get_string((prefix + "width").data())); + int const height = std::stoi(image.get_string((prefix + "height").data())); + baton->levels.push_back(std::pair(width, height)); + } + } baton->hasProfile = sharp::HasProfile(image); // Derived attributes baton->hasAlpha = sharp::HasAlpha(image); @@ -177,6 +186,17 @@ class MetadataWorker : public Napi::AsyncWorker { if (baton->pagePrimary > -1) { info.Set("pagePrimary", baton->pagePrimary); } + if (!baton->levels.empty()) { + int i = 0; + Napi::Array levels = Napi::Array::New(env, static_cast(baton->levels.size())); + for (std::pair const l : baton->levels) { + Napi::Object level = Napi::Object::New(env); + level.Set("width", l.first); + level.Set("height", l.second); + levels.Set(i++, level); + } + info.Set("levels", levels); + } info.Set("hasProfile", baton->hasProfile); info.Set("hasAlpha", baton->hasAlpha); if (baton->orientation > 0) { diff --git a/src/metadata.h b/src/metadata.h index abb860fb..00553085 100644 --- a/src/metadata.h +++ b/src/metadata.h @@ -39,6 +39,7 @@ struct MetadataBaton { int loop; std::vector delay; int pagePrimary; + std::vector> levels; bool hasProfile; bool hasAlpha; int orientation;