Add background and flatten APIs

This commit is contained in:
Daniel Gasienica
2014-09-12 19:53:58 -07:00
parent 513b07ddcf
commit 6145231936
6 changed files with 164 additions and 15 deletions

View File

@@ -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 havent 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());