Add convolve operation for kernel-based convolution (#479)

This commit is contained in:
Matt Hirsch
2016-07-04 15:48:00 -04:00
committed by Lovell Fuller
parent ba5a8b44ed
commit b70a7d9a3b
12 changed files with 202 additions and 1 deletions

View File

@@ -2,6 +2,7 @@
#include <cmath>
#include <tuple>
#include <utility>
#include <memory>
#include <vips/vips8>
@@ -49,6 +50,7 @@ using sharp::Cutout;
using sharp::Normalize;
using sharp::Gamma;
using sharp::Blur;
using sharp::Convolve;
using sharp::Sharpen;
using sharp::EntropyCrop;
using sharp::TileCache;
@@ -464,11 +466,12 @@ class PipelineWorker : public AsyncWorker {
bool shouldAffineTransform = xresidual != 1.0 || yresidual != 1.0;
bool shouldBlur = baton->blurSigma != 0.0;
bool shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;
bool shouldSharpen = baton->sharpenSigma != 0.0;
bool shouldThreshold = baton->threshold != 0;
bool shouldCutout = baton->overlayCutout;
bool shouldPremultiplyAlpha = HasAlpha(image) &&
(shouldAffineTransform || shouldBlur || shouldSharpen || (hasOverlay && !shouldCutout));
(shouldAffineTransform || shouldBlur || shouldConv || shouldSharpen || (hasOverlay && !shouldCutout));
// Premultiply image alpha channel before all transformations to avoid
// dark fringing around bright pixels
@@ -634,6 +637,14 @@ class PipelineWorker : public AsyncWorker {
image = Blur(image, baton->blurSigma);
}
// Convolve
if (shouldConv) {
image = Convolve(image,
baton->convKernelWidth, baton->convKernelHeight,
baton->convKernelScale, baton->convKernelOffset,
baton->convKernel);
}
// Sharpen
if (shouldSharpen) {
image = Sharpen(image, baton->sharpenSigma, baton->sharpenFlat, baton->sharpenJagged);
@@ -1151,6 +1162,22 @@ NAN_METHOD(pipeline) {
} else {
baton->tileLayout = VIPS_FOREIGN_DZ_LAYOUT_DZ;
}
// Convolution Kernel
if(Has(options, New("convKernel").ToLocalChecked()).FromJust()) {
Local<Object> kernel = Get(options, New("convKernel").ToLocalChecked()).ToLocalChecked().As<Object>();
baton->convKernelWidth = attrAs<int32_t>(kernel, "width");
baton->convKernelHeight = attrAs<int32_t>(kernel, "height");
baton->convKernelScale = attrAs<double>(kernel, "scale");
baton->convKernelOffset = attrAs<double>(kernel, "offset");
size_t kernelSize = baton->convKernelWidth * baton->convKernelHeight;
baton->convKernel = std::unique_ptr<double[]>(new double[kernelSize]);
Local<Array> kdata = Get(kernel, New("kernel").ToLocalChecked()).ToLocalChecked().As<Array>();
for(unsigned int i = 0; i < kernelSize; i++) {
baton->convKernel[i] = To<double>(Get(kdata, i).ToLocalChecked()).FromJust();
}
}
// Function to notify of queue length changes
Callback *queueListener = new Callback(