Skip to content

Commit

Permalink
Erode / dilate preliminary implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
WRidder committed Jun 6, 2019
1 parent cfa4f7d commit 213399f
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 0 deletions.
26 changes: 26 additions & 0 deletions docs/api-operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,32 @@ When a `sigma` is provided, performs a slower, more accurate Gaussian blur.
- `sigma` **[Number][1]?** a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.


- Throws **[Error][5]** Invalid parameters

Returns **Sharp**

## dilate

Dilate the image.

### Parameters

- `width` **[Number][1]?** dilate width.


- Throws **[Error][5]** Invalid parameters

Returns **Sharp**

## erode

Erode the image.

### Parameters

- `width` **[Number][1]?** erode width.


- Throws **[Error][5]** Invalid parameters

Returns **Sharp**
Expand Down
2 changes: 2 additions & 0 deletions lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ const Sharp = function (input, options) {
threshold: 0,
thresholdGrayscale: true,
trimThreshold: 0,
dilateWidth: 0,
erodeWidth: 0,
gamma: 0,
gammaOut: 0,
greyscale: false,
Expand Down
40 changes: 40 additions & 0 deletions lib/operation.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,44 @@ function blur (sigma) {
return this;
}

/**
* Dilate the image.
* @param {Number} [width] dilate width.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function dilate (width) {
if (!is.defined(width)) {
// No arguments: default to mild dilation
this.options.dilateWidth = 3;
} else if (is.integer(width) && width % 2 !== 0 && is.inRange(width, 3, 1001)) {
// Numeric argument: specific width
this.options.dilateWidth = width;
} else {
throw new Error('Invalid dilate width ' + width);
}
return this;
}

/**
* Erode the image.
* @param {Number} [width] erode width.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function erode (width) {
if (!is.defined(width)) {
// No arguments: default to mild erosion
this.options.erodeWidth = 3;
} else if (is.integer(width) && width % 2 !== 0 && is.inRange(width, 3, 1001)) {
// Numeric argument: specific width
this.options.erodeWidth = width;
} else {
throw new Error('Invalid erode width ' + width);
}
return this;
}

/**
* Merge alpha transparency channel, if any, with a background.
* @param {Object} [options]
Expand Down Expand Up @@ -481,6 +519,8 @@ module.exports = function (Sharp) {
flip,
flop,
sharpen,
erode,
dilate,
median,
blur,
flatten,
Expand Down
22 changes: 22 additions & 0 deletions src/operations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,26 @@ namespace sharp {
return image.linear(a, b);
}
}

/*
* Dilate an image
*/
VImage Dilate(VImage image, int const width) {
VImage mask = VImage::new_matrix(width, width);

return image.morph(
mask,
VIPS_OPERATION_MORPHOLOGY_DILATE).invert();
}

/*
* Dilate an image
*/
VImage Erode(VImage image, int const width) {
VImage mask = VImage::new_matrix(width, width);

return image.morph(
mask,
VIPS_OPERATION_MORPHOLOGY_ERODE).invert();
}
} // namespace sharp
10 changes: 10 additions & 0 deletions src/operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ namespace sharp {
*/
VImage Modulate(VImage image, double const brightness, double const saturation, int const hue);

/*
* Dilate an image
*/
VImage Dilate(VImage image, int const width);

/*
* Erode an image
*/
VImage Erode(VImage image, int const width);

} // namespace sharp

#endif // SRC_OPERATIONS_H_
12 changes: 12 additions & 0 deletions src/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,16 @@ class PipelineWorker : public Nan::AsyncWorker {
image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
}

// Dilate - must happen before blurring, due to the utility of dilating after thresholding
if (baton->dilateWidth != 0) {
image = sharp::Dilate(image, baton->dilateWidth);
}

// Erode - must happen before blurring, due to the utility of eroding after thresholding
if (baton->erodeWidth != 0) {
image = sharp::Erode(image, baton->erodeWidth);
}

// Blur
if (shouldBlur) {
image = sharp::Blur(image, baton->blurSigma);
Expand Down Expand Up @@ -1230,6 +1240,8 @@ NAN_METHOD(pipeline) {
baton->gammaOut = AttrTo<double>(options, "gammaOut");
baton->linearA = AttrTo<double>(options, "linearA");
baton->linearB = AttrTo<double>(options, "linearB");
baton->dilateWidth = AttrTo<int32_t>(options, "dilateWidth");
baton->erodeWidth = AttrTo<int32_t>(options, "erodeWidth");
baton->greyscale = AttrTo<bool>(options, "greyscale");
baton->normalise = AttrTo<bool>(options, "normalise");
baton->useExifOrientation = AttrTo<bool>(options, "useExifOrientation");
Expand Down
4 changes: 4 additions & 0 deletions src/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ struct PipelineBaton {
int trimOffsetTop;
double linearA;
double linearB;
int dilateWidth;
int erodeWidth;
double gamma;
double gammaOut;
bool greyscale;
Expand Down Expand Up @@ -206,6 +208,8 @@ struct PipelineBaton {
trimOffsetTop(0),
linearA(1.0),
linearB(0.0),
dilateWidth(0),
erodeWidth(0),
gamma(0.0),
greyscale(false),
normalise(false),
Expand Down
Binary file added test/fixtures/dot-and-lines.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/dilate-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/erode-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions test/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ module.exports = {

inputJPGBig: getPath('flowers.jpeg'),

inputPngDotAndLines: getPath('dot-and-lines.png'),

inputPngStripesV: getPath('stripesV.png'),
inputPngStripesH: getPath('stripesH.png'),

Expand Down
20 changes: 20 additions & 0 deletions test/unit/dilate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const assert = require('assert');

const sharp = require('../../');
const fixtures = require('../fixtures');

describe('Dilate', function () {
it('dilate 1 png', function (done) {
sharp(fixtures.inputPngDotAndLines)
.dilate(3)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format);
assert.strictEqual(100, info.width);
assert.strictEqual(100, info.height);
fixtures.assertSimilar(fixtures.expected('dilate-1.png'), data, done);
});
});
});
20 changes: 20 additions & 0 deletions test/unit/erode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const assert = require('assert');

const sharp = require('../../');
const fixtures = require('../fixtures');

describe('Erode', function () {
it('erode 1 png', function (done) {
sharp(fixtures.inputPngDotAndLines)
.erode(3)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format);
assert.strictEqual(100, info.width);
assert.strictEqual(100, info.height);
fixtures.assertSimilar(fixtures.expected('erode-1.png'), data, done);
});
});
});

0 comments on commit 213399f

Please sign in to comment.