mirror of
https://github.com/lovell/sharp.git
synced 2025-12-19 07:15:08 +01:00
Add background and flatten APIs
This commit is contained in:
61
src/sharp.cc
61
src/sharp.cc
@@ -37,6 +37,12 @@ struct resize_baton {
|
||||
int angle;
|
||||
std::string err;
|
||||
bool withMetadata;
|
||||
// background
|
||||
double background_red;
|
||||
double background_green;
|
||||
double background_blue;
|
||||
// flatten
|
||||
bool flatten;
|
||||
|
||||
resize_baton():
|
||||
buffer_in_len(0),
|
||||
@@ -49,7 +55,13 @@ struct resize_baton {
|
||||
gamma(0.0),
|
||||
progressive(false),
|
||||
without_enlargement(false),
|
||||
withMetadata(false) {}
|
||||
withMetadata(false),
|
||||
// background
|
||||
background_red(0.0),
|
||||
background_green(0.0),
|
||||
background_blue(0.0),
|
||||
// flatten
|
||||
flatten(false) {}
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -490,14 +502,35 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
}
|
||||
g_object_unref(in);
|
||||
|
||||
// Flatten
|
||||
VipsImage *flattened = vips_image_new();
|
||||
// We skip non-four-band images as we haven’t tested two-channel PNGs with
|
||||
// alpha channel (yet).
|
||||
// See: https://github.com/lovell/sharp/pull/91#issuecomment-56496548
|
||||
if (baton->flatten && sharp_image_has_alpha(shrunk_on_load) && shrunk_on_load->Bands == 4) {
|
||||
VipsArrayDouble *background = vips_array_double_newv(
|
||||
3, // vector size
|
||||
baton->background_red,
|
||||
baton->background_green,
|
||||
baton->background_blue
|
||||
);
|
||||
|
||||
if (vips_flatten(shrunk_on_load, &flattened, "background", background, NULL)) {
|
||||
return resize_error(baton, shrunk_on_load);
|
||||
};
|
||||
} else {
|
||||
vips_copy(shrunk_on_load, &flattened, NULL);
|
||||
}
|
||||
g_object_unref(shrunk_on_load);
|
||||
|
||||
// Gamma encoding (darken)
|
||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
||||
VipsImage *gamma_encoded = vips_image_new();
|
||||
if (vips_gamma(shrunk_on_load, &gamma_encoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
||||
return resize_error(baton, shrunk_on_load);
|
||||
if (vips_gamma(flattened, &gamma_encoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
||||
return resize_error(baton, flattened);
|
||||
}
|
||||
g_object_unref(shrunk_on_load);
|
||||
shrunk_on_load = gamma_encoded;
|
||||
g_object_unref(flattened);
|
||||
flattened = gamma_encoded;
|
||||
}
|
||||
|
||||
// Convert to greyscale (linear, therefore after gamma encoding, if any)
|
||||
@@ -513,8 +546,8 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
VipsImage *shrunk = vips_image_new();
|
||||
if (shrink > 1) {
|
||||
// Use vips_shrink with the integral reduction
|
||||
if (vips_shrink(shrunk_on_load, &shrunk, shrink, shrink, NULL)) {
|
||||
return resize_error(baton, shrunk_on_load);
|
||||
if (vips_shrink(flattened, &shrunk, shrink, shrink, NULL)) {
|
||||
return resize_error(baton, flattened);
|
||||
}
|
||||
// Recalculate residual float based on dimensions of required vs shrunk images
|
||||
double shrunkWidth = shrunk->Xsize;
|
||||
@@ -533,9 +566,9 @@ class ResizeWorker : public NanAsyncWorker {
|
||||
residual = std::min(residualx, residualy);
|
||||
}
|
||||
} else {
|
||||
vips_copy(shrunk_on_load, &shrunk, NULL);
|
||||
vips_copy(flattened, &shrunk, NULL);
|
||||
}
|
||||
g_object_unref(shrunk_on_load);
|
||||
g_object_unref(flattened);
|
||||
|
||||
// Use vips_affine with the remaining float part
|
||||
VipsImage *affined = vips_image_new();
|
||||
@@ -772,6 +805,15 @@ NAN_METHOD(resize) {
|
||||
} else if (canvas->Equals(NanNew<String>("m"))) {
|
||||
baton->max = true;
|
||||
}
|
||||
|
||||
// Flatten
|
||||
baton->flatten = options->Get(NanNew<String>("flatten"))->BooleanValue();
|
||||
|
||||
// Background
|
||||
baton->background_red = options->Get(NanNew<String>("backgroundRed"))->NumberValue();
|
||||
baton->background_green = options->Get(NanNew<String>("backgroundGreen"))->NumberValue();
|
||||
baton->background_blue = options->Get(NanNew<String>("backgroundBlue"))->NumberValue();
|
||||
|
||||
// Other options
|
||||
baton->gravity = options->Get(NanNew<String>("gravity"))->Int32Value();
|
||||
baton->sharpen = options->Get(NanNew<String>("sharpen"))->BooleanValue();
|
||||
@@ -785,6 +827,7 @@ NAN_METHOD(resize) {
|
||||
baton->compressionLevel = options->Get(NanNew<String>("compressionLevel"))->Int32Value();
|
||||
baton->angle = options->Get(NanNew<String>("angle"))->Int32Value();
|
||||
baton->withMetadata = options->Get(NanNew<String>("withMetadata"))->BooleanValue();
|
||||
|
||||
// Output filename or __format for Buffer
|
||||
baton->output = *String::Utf8Value(options->Get(NanNew<String>("output"))->ToString());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user