Build format-specific input options in a single function

This commit is contained in:
Lovell Fuller 2025-06-17 10:15:40 +01:00
parent 76995deefa
commit e286e2bff9
3 changed files with 45 additions and 90 deletions

View File

@ -395,31 +395,9 @@ namespace sharp {
} }
/* /*
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data) Format-specific options builder
*/ */
std::tuple<VImage, ImageType> OpenInput(InputDescriptor *descriptor) { vips::VOption* GetOptionsForImageType(ImageType imageType, InputDescriptor *descriptor) {
VImage image;
ImageType imageType;
if (descriptor->isBuffer) {
if (descriptor->rawChannels > 0) {
// Raw, uncompressed pixel data
bool const is8bit = vips_band_format_is8bit(descriptor->rawDepth);
image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength,
descriptor->rawWidth, descriptor->rawHeight, descriptor->rawChannels, descriptor->rawDepth);
if (descriptor->rawChannels < 3) {
image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_GREY16;
} else {
image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_RGB16;
}
if (descriptor->rawPremultiplied) {
image = image.unpremultiply();
}
imageType = ImageType::RAW;
} else {
// Compressed data
imageType = DetermineImageType(descriptor->buffer, descriptor->bufferLength);
if (imageType != ImageType::UNKNOWN) {
try {
vips::VOption *option = VImage::option() vips::VOption *option = VImage::option()
->set("access", descriptor->access) ->set("access", descriptor->access)
->set("fail_on", descriptor->failOn); ->set("fail_on", descriptor->failOn);
@ -452,6 +430,36 @@ namespace sharp {
if (imageType == ImageType::JP2) { if (imageType == ImageType::JP2) {
option->set("oneshot", descriptor->jp2Oneshot); option->set("oneshot", descriptor->jp2Oneshot);
} }
return option;
}
/*
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
*/
std::tuple<VImage, ImageType> OpenInput(InputDescriptor *descriptor) {
VImage image;
ImageType imageType;
if (descriptor->isBuffer) {
if (descriptor->rawChannels > 0) {
// Raw, uncompressed pixel data
bool const is8bit = vips_band_format_is8bit(descriptor->rawDepth);
image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength,
descriptor->rawWidth, descriptor->rawHeight, descriptor->rawChannels, descriptor->rawDepth);
if (descriptor->rawChannels < 3) {
image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_GREY16;
} else {
image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_RGB16;
}
if (descriptor->rawPremultiplied) {
image = image.unpremultiply();
}
imageType = ImageType::RAW;
} else {
// Compressed data
imageType = DetermineImageType(descriptor->buffer, descriptor->bufferLength);
if (imageType != ImageType::UNKNOWN) {
try {
vips::VOption *option = GetOptionsForImageType(imageType, descriptor);
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 +542,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

@ -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 {