jimp-dev / jimp-dev/jimp

[Feature] Add optional divisor to convolute()

Open
#763 1 comment 0 reactions 0 assignees View on GitHub
enhancement help wanted solution in issue
Dominant language
TypeScript
Stars
14.7k
Forks
777
PR merge metrics
No merged PRs in 30d

Description

**Is your feature request related to a problem? Please describe.**
When searching the Internet for convolution kernels, one often finds some which normalize at the end of the calculation with division.

A typical example for a Gaussian blur might look like this:

```
| 1 4 6 4 1 |
| 4 16 24 16 4 |
| 6 24 36 24 6 |
| 4 16 24 16 4 |
| 1 4 6 4 1 | / 256
```

To find the equivalent version which doesn't include a divisor step, one would need to laboriously divide each of those integers with the divisor, resulting in something which might look like this:

```
[0.00390625, 0.015625, 0.0234375, 0.015625, 0.00390625],
[0.015625, 0.0625, 0.09375, 0.0625, 0.015625],
[0.0234375, 0.09375, 0.140625, 0.09375, 0.0234375],
[0.015625, 0.0625, 0.09375, 0.0625, 0.015625],
[0.00390625, 0.015625, 0.0234375, 0.015625, 0.00390625]
```

**Describe the solution you'd like**
What would be nice would be if the `convolute()` functions added another (optional) argument called `divisor` which defaults to `1`.

**Describe alternatives you've considered**
Noting that my app is a Node.js daemon, I was able to monkey-patch `node_modules/@jimp/plugin-color/dist/index.js` inside the `convolute()` function definition like this:
```
var ksize = (kernel.length - 1) / 2;
x = isDef(x) ? x : ksize;
y = isDef(y) ? y : ksize;
w = isDef(w) ? w : this.bitmap.width - x;
h = isDef(h) ? h : this.bitmap.height - y;
var source = this.cloneQuiet();
// Begin edit ------------------
var divisor = 256; // Imagine instead that the function accepted it as an argument
// End edit --------------------
this.scanQuiet(x, y, w, h, function (xx, yx, idx) {
var value = applyKernel(source, kernel, xx, yx);
// Begin edit ------------------
value[0] /= divisor;
value[1] /= divisor;
value[2] /= divisor;
// End edit --------------------
this.bitmap.data[idx] = this.constructor.limit255(value[0]);
this.bitmap.data[idx + 1] = this.constructor.limit255(value[1]);
this.bitmap.data[idx + 2] = this.constructor.limit255(value[2]);
});
```

It worked perfectly, normalizing the darkness/lightness of the resulting blur. Without this, it's problematic coming up with a good-looking matrix whose values sum to one (unless you have access to Matlab).

Of course, there appear to be several interfaces other than just `@jimp/plugin-color/dist` but I didn't use those.

Contributor guide

Open the contributing guide

Research direction

Start with the convolute() implementation in @jimp/plugin-color/dist/index.js and trace the other convolute interfaces mentioned in the issue. Add an optional divisor that defaults to 1 and applies to the calculated color-channel values before limiting them to 255. Done means normalized kernels such as the provided Gaussian example produce the expected brightness.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
computer-vision
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.