mirror of
https://github.com/lovell/sharp.git
synced 2025-07-10 11:00:14 +02:00
Refactor pipeline to use common 16-bit detection methods
This commit is contained in:
parent
d1d6155fd1
commit
c42fb97419
@ -317,23 +317,26 @@ namespace sharp {
|
|||||||
|
|
||||||
return std::make_tuple(left, top);
|
return std::make_tuple(left, top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Are pixel values in this image 16-bit integer?
|
||||||
|
*/
|
||||||
|
bool Is16Bit(VipsInterpretation const interpretation) {
|
||||||
|
return interpretation == VIPS_INTERPRETATION_RGB16 || interpretation == VIPS_INTERPRETATION_GREY16;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return the image alpha maximum. Useful for combining alpha bands. scRGB
|
Return the image alpha maximum. Useful for combining alpha bands. scRGB
|
||||||
images are 0 - 1 for image data, but the alpha is 0 - 255.
|
images are 0 - 1 for image data, but the alpha is 0 - 255.
|
||||||
*/
|
*/
|
||||||
int MaximumImageAlpha(VipsInterpretation interpretation) {
|
double MaximumImageAlpha(VipsInterpretation const interpretation) {
|
||||||
if(interpretation == VIPS_INTERPRETATION_RGB16 ||
|
return Is16Bit(interpretation) ? 65535.0 : 255.0;
|
||||||
interpretation == VIPS_INTERPRETATION_GREY16) {
|
|
||||||
return (65535);
|
|
||||||
} else {
|
|
||||||
return (255);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get VIPS Boolean operatoin type from string
|
Get boolean operation type from string
|
||||||
*/
|
*/
|
||||||
VipsOperationBoolean GetBooleanOperation(std::string opStr) {
|
VipsOperationBoolean GetBooleanOperation(std::string const opStr) {
|
||||||
return static_cast<VipsOperationBoolean>(
|
return static_cast<VipsOperationBoolean>(
|
||||||
vips_enum_from_nick(nullptr, VIPS_TYPE_OPERATION_BOOLEAN, opStr.data())
|
vips_enum_from_nick(nullptr, VIPS_TYPE_OPERATION_BOOLEAN, opStr.data())
|
||||||
);
|
);
|
||||||
|
12
src/common.h
12
src/common.h
@ -117,17 +117,21 @@ namespace sharp {
|
|||||||
std::tuple<int, int> CalculateCrop(int const inWidth, int const inHeight,
|
std::tuple<int, int> CalculateCrop(int const inWidth, int const inHeight,
|
||||||
int const outWidth, int const outHeight, int const x, int const y);
|
int const outWidth, int const outHeight, int const x, int const y);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Are pixel values in this image 16-bit integer?
|
||||||
|
*/
|
||||||
|
bool Is16Bit(VipsInterpretation const interpretation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return the image alpha maximum. Useful for combining alpha bands. scRGB
|
Return the image alpha maximum. Useful for combining alpha bands. scRGB
|
||||||
images are 0 - 1 for image data, but the alpha is 0 - 255.
|
images are 0 - 1 for image data, but the alpha is 0 - 255.
|
||||||
*/
|
*/
|
||||||
int MaximumImageAlpha(VipsInterpretation interpretation);
|
double MaximumImageAlpha(VipsInterpretation const interpretation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get VIPS Boolean operatoin type from string
|
Get boolean operation type from string
|
||||||
*/
|
*/
|
||||||
VipsOperationBoolean GetBooleanOperation(std::string opStr);
|
VipsOperationBoolean GetBooleanOperation(std::string const opStr);
|
||||||
|
|
||||||
|
|
||||||
} // namespace sharp
|
} // namespace sharp
|
||||||
|
|
||||||
|
@ -162,8 +162,8 @@ namespace sharp {
|
|||||||
|
|
||||||
// the range of the mask and the image need to match .. one could be
|
// the range of the mask and the image need to match .. one could be
|
||||||
// 16-bit, one 8-bit
|
// 16-bit, one 8-bit
|
||||||
int dstMax = MaximumImageAlpha(dst.interpretation());
|
double const dstMax = MaximumImageAlpha(dst.interpretation());
|
||||||
int maskMax = MaximumImageAlpha(mask.interpretation());
|
double const maskMax = MaximumImageAlpha(mask.interpretation());
|
||||||
|
|
||||||
// combine the new mask and the existing alpha ... there are
|
// combine the new mask and the existing alpha ... there are
|
||||||
// many ways of doing this, mult is the simplest
|
// many ways of doing this, mult is the simplest
|
||||||
@ -419,7 +419,7 @@ namespace sharp {
|
|||||||
// significantly different from this
|
// significantly different from this
|
||||||
std::vector<double> background = image(0, 0);
|
std::vector<double> background = image(0, 0);
|
||||||
|
|
||||||
int max = MaximumImageAlpha(image.interpretation());
|
double const max = MaximumImageAlpha(image.interpretation());
|
||||||
|
|
||||||
// we need to smooth the image, subtract the background from every pixel, take
|
// we need to smooth the image, subtract the background from every pixel, take
|
||||||
// the absolute value of the difference, then threshold
|
// the absolute value of the difference, then threshold
|
||||||
|
@ -78,9 +78,12 @@ using sharp::IsDzZip;
|
|||||||
using sharp::IsV;
|
using sharp::IsV;
|
||||||
using sharp::FreeCallback;
|
using sharp::FreeCallback;
|
||||||
using sharp::CalculateCrop;
|
using sharp::CalculateCrop;
|
||||||
|
using sharp::Is16Bit;
|
||||||
|
using sharp::MaximumImageAlpha;
|
||||||
|
using sharp::GetBooleanOperation;
|
||||||
|
|
||||||
using sharp::counterProcess;
|
using sharp::counterProcess;
|
||||||
using sharp::counterQueue;
|
using sharp::counterQueue;
|
||||||
using sharp::GetBooleanOperation;
|
|
||||||
|
|
||||||
class PipelineWorker : public AsyncWorker {
|
class PipelineWorker : public AsyncWorker {
|
||||||
public:
|
public:
|
||||||
@ -409,13 +412,12 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate maximum alpha value based on input image pixel depth
|
// Calculate maximum alpha value based on input image pixel depth
|
||||||
bool is16Bit = (image.format() == VIPS_FORMAT_USHORT);
|
double const maxAlpha = MaximumImageAlpha(image.interpretation());
|
||||||
double maxAlpha = is16Bit ? 65535.0 : 255.0;
|
|
||||||
|
|
||||||
// Flatten image to remove alpha channel
|
// Flatten image to remove alpha channel
|
||||||
if (baton->flatten && HasAlpha(image)) {
|
if (baton->flatten && HasAlpha(image)) {
|
||||||
// Scale up 8-bit values to match 16-bit input image
|
// Scale up 8-bit values to match 16-bit input image
|
||||||
double multiplier = (image.interpretation() == VIPS_INTERPRETATION_RGB16) ? 256.0 : 1.0;
|
double const multiplier = Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
||||||
// Background colour
|
// Background colour
|
||||||
std::vector<double> background {
|
std::vector<double> background {
|
||||||
baton->background[0] * multiplier,
|
baton->background[0] * multiplier,
|
||||||
@ -471,7 +473,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
// Ensure image has an alpha channel when there is an overlay
|
// Ensure image has an alpha channel when there is an overlay
|
||||||
bool hasOverlay = baton->overlayBufferInLength > 0 || !baton->overlayFileIn.empty();
|
bool hasOverlay = baton->overlayBufferInLength > 0 || !baton->overlayFileIn.empty();
|
||||||
if (hasOverlay && !HasAlpha(image)) {
|
if (hasOverlay && !HasAlpha(image)) {
|
||||||
double multiplier = (image.interpretation() == VIPS_INTERPRETATION_RGB16) ? 256.0 : 1.0;
|
double const multiplier = Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
||||||
image = image.bandjoin(
|
image = image.bandjoin(
|
||||||
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier)
|
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier)
|
||||||
);
|
);
|
||||||
@ -481,10 +483,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
bool shouldBlur = baton->blurSigma != 0.0;
|
bool shouldBlur = baton->blurSigma != 0.0;
|
||||||
bool shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;
|
bool shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;
|
||||||
bool shouldSharpen = baton->sharpenSigma != 0.0;
|
bool shouldSharpen = baton->sharpenSigma != 0.0;
|
||||||
bool shouldThreshold = baton->threshold != 0;
|
|
||||||
bool shouldCutout = baton->overlayCutout;
|
bool shouldCutout = baton->overlayCutout;
|
||||||
bool shouldBandbool = baton->bandBoolOp < VIPS_OPERATION_BOOLEAN_LAST &&
|
|
||||||
baton->bandBoolOp >= VIPS_OPERATION_BOOLEAN_AND;
|
|
||||||
bool shouldPremultiplyAlpha = HasAlpha(image) &&
|
bool shouldPremultiplyAlpha = HasAlpha(image) &&
|
||||||
(shouldAffineTransform || shouldBlur || shouldConv || shouldSharpen || (hasOverlay && !shouldCutout));
|
(shouldAffineTransform || shouldBlur || shouldConv || shouldSharpen || (hasOverlay && !shouldCutout));
|
||||||
|
|
||||||
@ -554,7 +553,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
if (image.width() != baton->width || image.height() != baton->height) {
|
if (image.width() != baton->width || image.height() != baton->height) {
|
||||||
if (baton->canvas == Canvas::EMBED) {
|
if (baton->canvas == Canvas::EMBED) {
|
||||||
// Scale up 8-bit values to match 16-bit input image
|
// Scale up 8-bit values to match 16-bit input image
|
||||||
double multiplier = (image.interpretation() == VIPS_INTERPRETATION_RGB16) ? 256.0 : 1.0;
|
double const multiplier = Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
||||||
// Create background colour
|
// Create background colour
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
if (image.bands() > 2) {
|
if (image.bands() > 2) {
|
||||||
@ -617,7 +616,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
// Extend edges
|
// Extend edges
|
||||||
if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
|
if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
|
||||||
// Scale up 8-bit values to match 16-bit input image
|
// Scale up 8-bit values to match 16-bit input image
|
||||||
const double multiplier = (image.interpretation() == VIPS_INTERPRETATION_RGB16) ? 256.0 : 1.0;
|
double const multiplier = Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
||||||
// Create background colour
|
// Create background colour
|
||||||
std::vector<double> background {
|
std::vector<double> background {
|
||||||
baton->background[0] * multiplier,
|
baton->background[0] * multiplier,
|
||||||
@ -643,7 +642,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Threshold - must happen before blurring, due to the utility of blurring after thresholding
|
// Threshold - must happen before blurring, due to the utility of blurring after thresholding
|
||||||
if (shouldThreshold) {
|
if (baton->threshold != 0) {
|
||||||
image = Threshold(image, baton->threshold, baton->thresholdGrayscale);
|
image = Threshold(image, baton->threshold, baton->thresholdGrayscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,7 +757,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
if (shouldPremultiplyAlpha) {
|
if (shouldPremultiplyAlpha) {
|
||||||
image = image.unpremultiply(VImage::option()->set("max_alpha", maxAlpha));
|
image = image.unpremultiply(VImage::option()->set("max_alpha", maxAlpha));
|
||||||
// Cast pixel values to integer
|
// Cast pixel values to integer
|
||||||
if (is16Bit) {
|
if (Is16Bit(image.interpretation())) {
|
||||||
image = image.cast(VIPS_FORMAT_USHORT);
|
image = image.cast(VIPS_FORMAT_USHORT);
|
||||||
} else {
|
} else {
|
||||||
image = image.cast(VIPS_FORMAT_UCHAR);
|
image = image.cast(VIPS_FORMAT_UCHAR);
|
||||||
@ -776,7 +775,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert image to sRGB, if not already
|
// Convert image to sRGB, if not already
|
||||||
if (image.interpretation() == VIPS_INTERPRETATION_RGB16) {
|
if (Is16Bit(image.interpretation())) {
|
||||||
image = image.cast(VIPS_FORMAT_USHORT);
|
image = image.cast(VIPS_FORMAT_USHORT);
|
||||||
}
|
}
|
||||||
if (image.interpretation() != VIPS_INTERPRETATION_sRGB) {
|
if (image.interpretation() != VIPS_INTERPRETATION_sRGB) {
|
||||||
@ -828,7 +827,7 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply per-channel Bandbool bitwise operations after all other operations
|
// Apply per-channel Bandbool bitwise operations after all other operations
|
||||||
if (shouldBandbool) {
|
if (baton->bandBoolOp >= VIPS_OPERATION_BOOLEAN_AND && baton->bandBoolOp < VIPS_OPERATION_BOOLEAN_LAST) {
|
||||||
image = Bandbool(image, baton->bandBoolOp);
|
image = Bandbool(image, baton->bandBoolOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user