Compare commits

...

2 Commits

Author SHA1 Message Date
Lovell Fuller
852c7f8663 Clean up internal naming of format-specific input options 2025-06-17 13:24:55 +01:00
Lovell Fuller
e286e2bff9 Build format-specific input options in a single function 2025-06-17 10:15:40 +01:00
4 changed files with 60 additions and 102 deletions

View File

@ -30,7 +30,7 @@ const inputStreamParameters = [
// Format-specific // Format-specific
'jp2', 'openSlide', 'pdf', 'raw', 'svg', 'tiff', 'jp2', 'openSlide', 'pdf', 'raw', 'svg', 'tiff',
// Deprecated // Deprecated
'failOnError', 'level', 'pdfBackground', 'subifd' 'failOnError', 'openSlideLevel', 'pdfBackground', 'tiffSubifd'
]; ];
/** /**
@ -246,14 +246,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
// OpenSlide specific options // OpenSlide specific options
if (is.object(inputOptions.openSlide) && is.defined(inputOptions.openSlide.level)) { if (is.object(inputOptions.openSlide) && is.defined(inputOptions.openSlide.level)) {
if (is.integer(inputOptions.openSlide.level) && is.inRange(inputOptions.openSlide.level, 0, 256)) { if (is.integer(inputOptions.openSlide.level) && is.inRange(inputOptions.openSlide.level, 0, 256)) {
inputDescriptor.level = inputOptions.openSlide.level; inputDescriptor.openSlideLevel = inputOptions.openSlide.level;
} else { } else {
throw is.invalidParameterError('openSlide.level', 'integer between 0 and 256', inputOptions.openSlide.level); throw is.invalidParameterError('openSlide.level', 'integer between 0 and 256', inputOptions.openSlide.level);
} }
} else if (is.defined(inputOptions.level)) { } else if (is.defined(inputOptions.level)) {
// Deprecated // Deprecated
if (is.integer(inputOptions.level) && is.inRange(inputOptions.level, 0, 256)) { if (is.integer(inputOptions.level) && is.inRange(inputOptions.level, 0, 256)) {
inputDescriptor.level = inputOptions.level; inputDescriptor.openSlideLevel = inputOptions.level;
} else { } else {
throw is.invalidParameterError('level', 'integer between 0 and 256', inputOptions.level); throw is.invalidParameterError('level', 'integer between 0 and 256', inputOptions.level);
} }
@ -261,14 +261,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
// TIFF specific options // TIFF specific options
if (is.object(inputOptions.tiff) && is.defined(inputOptions.tiff.subifd)) { if (is.object(inputOptions.tiff) && is.defined(inputOptions.tiff.subifd)) {
if (is.integer(inputOptions.tiff.subifd) && is.inRange(inputOptions.tiff.subifd, -1, 100000)) { if (is.integer(inputOptions.tiff.subifd) && is.inRange(inputOptions.tiff.subifd, -1, 100000)) {
inputDescriptor.subifd = inputOptions.tiff.subifd; inputDescriptor.tiffSubifd = inputOptions.tiff.subifd;
} else { } else {
throw is.invalidParameterError('tiff.subifd', 'integer between -1 and 100000', inputOptions.tiff.subifd); throw is.invalidParameterError('tiff.subifd', 'integer between -1 and 100000', inputOptions.tiff.subifd);
} }
} else if (is.defined(inputOptions.subifd)) { } else if (is.defined(inputOptions.subifd)) {
// Deprecated // Deprecated
if (is.integer(inputOptions.subifd) && is.inRange(inputOptions.subifd, -1, 100000)) { if (is.integer(inputOptions.subifd) && is.inRange(inputOptions.subifd, -1, 100000)) {
inputDescriptor.subifd = inputOptions.subifd; inputDescriptor.tiffSubifd = inputOptions.subifd;
} else { } else {
throw is.invalidParameterError('subifd', 'integer between -1 and 100000', inputOptions.subifd); throw is.invalidParameterError('subifd', 'integer between -1 and 100000', inputOptions.subifd);
} }

View File

@ -109,12 +109,12 @@ namespace sharp {
descriptor->svgHighBitdepth = AttrAsBool(input, "svgHighBitdepth"); descriptor->svgHighBitdepth = AttrAsBool(input, "svgHighBitdepth");
} }
// Multi-level input (OpenSlide) // Multi-level input (OpenSlide)
if (HasAttr(input, "level")) { if (HasAttr(input, "openSlideLevel")) {
descriptor->level = AttrAsUint32(input, "level"); descriptor->openSlideLevel = AttrAsUint32(input, "openSlideLevel");
} }
// subIFD (OME-TIFF) // subIFD (OME-TIFF)
if (HasAttr(input, "subifd")) { if (HasAttr(input, "subifd")) {
descriptor->subifd = AttrAsInt32(input, "subifd"); descriptor->tiffSubifd = AttrAsInt32(input, "tiffSubifd");
} }
// // PDF background color // // PDF background color
if (HasAttr(input, "pdfBackground")) { if (HasAttr(input, "pdfBackground")) {
@ -394,6 +394,48 @@ namespace sharp {
imageType == ImageType::HEIF; imageType == ImageType::HEIF;
} }
/*
Format-specific options builder
*/
vips::VOption* GetOptionsForImageType(ImageType imageType, InputDescriptor *descriptor) {
vips::VOption *option = VImage::option()
->set("access", descriptor->access)
->set("fail_on", descriptor->failOn);
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
option->set("unlimited", true);
}
if (ImageTypeSupportsPage(imageType)) {
option->set("n", descriptor->pages);
option->set("page", descriptor->page);
}
switch (imageType) {
case ImageType::SVG:
option->set("dpi", descriptor->density)
->set("stylesheet", descriptor->svgStylesheet.data())
->set("high_bitdepth", descriptor->svgHighBitdepth);
break;
case ImageType::TIFF:
option->set("tiffSubifd", descriptor->tiffSubifd);
break;
case ImageType::PDF:
option->set("dpi", descriptor->density)
->set("background", descriptor->pdfBackground);
break;
case ImageType::OPENSLIDE:
option->set("openSlideLevel", descriptor->openSlideLevel);
break;
case ImageType::JP2:
option->set("oneshot", descriptor->jp2Oneshot);
break;
case ImageType::MAGICK:
option->set("density", std::to_string(descriptor->density).data());
break;
default:
break;
}
return option;
}
/* /*
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data) Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
*/ */
@ -420,38 +462,7 @@ namespace sharp {
imageType = DetermineImageType(descriptor->buffer, descriptor->bufferLength); imageType = DetermineImageType(descriptor->buffer, descriptor->bufferLength);
if (imageType != ImageType::UNKNOWN) { if (imageType != ImageType::UNKNOWN) {
try { try {
vips::VOption *option = VImage::option() vips::VOption *option = GetOptionsForImageType(imageType, descriptor);
->set("access", descriptor->access)
->set("fail_on", descriptor->failOn);
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
option->set("unlimited", true);
}
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
option->set("dpi", descriptor->density);
}
if (imageType == ImageType::MAGICK) {
option->set("density", std::to_string(descriptor->density).data());
}
if (ImageTypeSupportsPage(imageType)) {
option->set("n", descriptor->pages);
option->set("page", descriptor->page);
}
if (imageType == ImageType::SVG) {
option->set("stylesheet", descriptor->svgStylesheet.data());
option->set("high_bitdepth", descriptor->svgHighBitdepth);
}
if (imageType == ImageType::OPENSLIDE) {
option->set("level", descriptor->level);
}
if (imageType == ImageType::TIFF) {
option->set("subifd", descriptor->subifd);
}
if (imageType == ImageType::PDF) {
option->set("background", descriptor->pdfBackground);
}
if (imageType == ImageType::JP2) {
option->set("oneshot", descriptor->jp2Oneshot);
}
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option); image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) { if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
image = SetDensity(image, descriptor->density); image = SetDensity(image, descriptor->density);
@ -534,34 +545,7 @@ namespace sharp {
} }
if (imageType != ImageType::UNKNOWN) { if (imageType != ImageType::UNKNOWN) {
try { try {
vips::VOption *option = VImage::option() vips::VOption *option = GetOptionsForImageType(imageType, descriptor);
->set("access", descriptor->access)
->set("fail_on", descriptor->failOn);
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
option->set("unlimited", true);
}
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
option->set("dpi", descriptor->density);
}
if (imageType == ImageType::MAGICK) {
option->set("density", std::to_string(descriptor->density).data());
}
if (ImageTypeSupportsPage(imageType)) {
option->set("n", descriptor->pages);
option->set("page", descriptor->page);
}
if (imageType == ImageType::OPENSLIDE) {
option->set("level", descriptor->level);
}
if (imageType == ImageType::TIFF) {
option->set("subifd", descriptor->subifd);
}
if (imageType == ImageType::PDF) {
option->set("background", descriptor->pdfBackground);
}
if (imageType == ImageType::JP2) {
option->set("oneshot", descriptor->jp2Oneshot);
}
image = VImage::new_from_file(descriptor->file.data(), option); image = VImage::new_from_file(descriptor->file.data(), option);
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) { if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
image = SetDensity(image, descriptor->density); image = SetDensity(image, descriptor->density);

View File

@ -50,8 +50,6 @@ namespace sharp {
bool rawPremultiplied; bool rawPremultiplied;
int pages; int pages;
int page; int page;
int level;
int subifd;
int createChannels; int createChannels;
int createWidth; int createWidth;
int createHeight; int createHeight;
@ -79,6 +77,8 @@ namespace sharp {
VipsAlign joinValign; VipsAlign joinValign;
std::string svgStylesheet; std::string svgStylesheet;
bool svgHighBitdepth; bool svgHighBitdepth;
int tiffSubifd;
int openSlideLevel;
std::vector<double> pdfBackground; std::vector<double> pdfBackground;
bool jp2Oneshot; bool jp2Oneshot;
@ -100,8 +100,6 @@ namespace sharp {
rawPremultiplied(false), rawPremultiplied(false),
pages(1), pages(1),
page(0), page(0),
level(0),
subifd(-1),
createChannels(0), createChannels(0),
createWidth(0), createWidth(0),
createHeight(0), createHeight(0),
@ -124,6 +122,8 @@ namespace sharp {
joinHalign(VIPS_ALIGN_LOW), joinHalign(VIPS_ALIGN_LOW),
joinValign(VIPS_ALIGN_LOW), joinValign(VIPS_ALIGN_LOW),
svgHighBitdepth(false), svgHighBitdepth(false),
tiffSubifd(-1),
openSlideLevel(0),
pdfBackground{ 255.0, 255.0, 255.0, 255.0 }, pdfBackground{ 255.0, 255.0, 255.0, 255.0 },
jp2Oneshot(false) {} jp2Oneshot(false) {}
}; };
@ -221,14 +221,9 @@ namespace sharp {
ImageType DetermineImageType(char const *file); ImageType DetermineImageType(char const *file);
/* /*
Does this image type support multiple pages? Format-specific options builder
*/ */
bool ImageTypeSupportsPage(ImageType imageType); vips::VOption* GetOptionsForImageType(ImageType imageType, InputDescriptor *descriptor);
/*
Does this image type support removal of safety limits?
*/
bool ImageTypeSupportsUnlimited(ImageType imageType);
/* /*
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data) Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)

View File

@ -241,11 +241,7 @@ class PipelineWorker : public Napi::AsyncWorker {
// factor for jpegload*, a double scale factor for webpload*, // factor for jpegload*, a double scale factor for webpload*,
// pdfload* and svgload* // pdfload* and svgload*
if (jpegShrinkOnLoad > 1) { if (jpegShrinkOnLoad > 1) {
vips::VOption *option = VImage::option() vips::VOption *option = GetOptionsForImageType(inputImageType, baton->input)->set("shrink", jpegShrinkOnLoad);
->set("access", access)
->set("shrink", jpegShrinkOnLoad)
->set("unlimited", baton->input->unlimited)
->set("fail_on", baton->input->failOn);
if (baton->input->buffer != nullptr) { if (baton->input->buffer != nullptr) {
// Reload JPEG buffer // Reload JPEG buffer
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength); VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
@ -256,14 +252,8 @@ class PipelineWorker : public Napi::AsyncWorker {
image = VImage::jpegload(const_cast<char*>(baton->input->file.data()), option); image = VImage::jpegload(const_cast<char*>(baton->input->file.data()), option);
} }
} else if (scale != 1.0) { } else if (scale != 1.0) {
vips::VOption *option = VImage::option() vips::VOption *option = GetOptionsForImageType(inputImageType, baton->input)->set("scale", scale);
->set("access", access)
->set("scale", scale)
->set("fail_on", baton->input->failOn);
if (inputImageType == sharp::ImageType::WEBP) { if (inputImageType == sharp::ImageType::WEBP) {
option->set("n", baton->input->pages);
option->set("page", baton->input->page);
if (baton->input->buffer != nullptr) { if (baton->input->buffer != nullptr) {
// Reload WebP buffer // Reload WebP buffer
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength); VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
@ -274,11 +264,6 @@ class PipelineWorker : public Napi::AsyncWorker {
image = VImage::webpload(const_cast<char*>(baton->input->file.data()), option); image = VImage::webpload(const_cast<char*>(baton->input->file.data()), option);
} }
} else if (inputImageType == sharp::ImageType::SVG) { } else if (inputImageType == sharp::ImageType::SVG) {
option->set("unlimited", baton->input->unlimited);
option->set("dpi", baton->input->density);
option->set("stylesheet", baton->input->svgStylesheet.data());
option->set("high_bitdepth", baton->input->svgHighBitdepth);
if (baton->input->buffer != nullptr) { if (baton->input->buffer != nullptr) {
// Reload SVG buffer // Reload SVG buffer
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength); VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
@ -293,11 +278,6 @@ class PipelineWorker : public Napi::AsyncWorker {
throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled"); throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
} }
} else if (inputImageType == sharp::ImageType::PDF) { } else if (inputImageType == sharp::ImageType::PDF) {
option->set("n", baton->input->pages);
option->set("page", baton->input->page);
option->set("dpi", baton->input->density);
option->set("background", baton->input->pdfBackground);
if (baton->input->buffer != nullptr) { if (baton->input->buffer != nullptr) {
// Reload PDF buffer // Reload PDF buffer
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength); VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
@ -307,7 +287,6 @@ class PipelineWorker : public Napi::AsyncWorker {
// Reload PDF file // Reload PDF file
image = VImage::pdfload(const_cast<char*>(baton->input->file.data()), option); image = VImage::pdfload(const_cast<char*>(baton->input->file.data()), option);
} }
sharp::SetDensity(image, baton->input->density); sharp::SetDensity(image, baton->input->density);
} }
} else { } else {