WIP - add extractor, generate snippet_data
This commit is contained in:
21
node_modules/@jimp/plugin-color/LICENSE
generated
vendored
Normal file
21
node_modules/@jimp/plugin-color/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Oliver Moran
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
256
node_modules/@jimp/plugin-color/README.md
generated
vendored
Normal file
256
node_modules/@jimp/plugin-color/README.md
generated
vendored
Normal file
@ -0,0 +1,256 @@
|
||||
<div align="center">
|
||||
<img width="200" height="200"
|
||||
src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-11/256/crayon.png">
|
||||
<h1>@jimp/plugin-color</h1>
|
||||
<p>Jimp color methods.</p>
|
||||
</div>
|
||||
|
||||
Bitmap manipulation to adjust the color in an image.
|
||||
|
||||
## color
|
||||
|
||||
Apply multiple color modification rules
|
||||
|
||||
- @param {array} actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.color([{ apply: 'red', params: [100] }]);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
Jimp supports advanced colour manipulation using a single method as follows:
|
||||
|
||||
```js
|
||||
image.color([
|
||||
{ apply: 'hue', params: [-90] },
|
||||
{ apply: 'lighten', params: [50] },
|
||||
{ apply: 'xor', params: ['#06D'] }
|
||||
]);
|
||||
```
|
||||
|
||||
The method supports the following modifiers:
|
||||
|
||||
| Modifier | Description |
|
||||
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **lighten** {amount} | Lighten the color a given amount, from 0 to 100. Providing 100 will always return white (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **brighten** {amount} | Brighten the color a given amount, from 0 to 100 (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **darken** {amount} | Darken the color a given amount, from 0 to 100. Providing 100 will always return black (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **desaturate** {amount} | Desaturate the color a given amount, from 0 to 100. Providing 100 will is the same as calling greyscale (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **saturate** {amount} | Saturate the color a given amount, from 0 to 100 (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **greyscale** {amount} | Completely desaturates a color into greyscale (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **spin** {degree} | Spin the hue a given amount, from -360 to 360. Calling with 0, 360, or -360 will do nothing - since it sets the hue back to what it was before. (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
|
||||
| **hue** {degree} | Alias for **spin** |
|
||||
| **mix** {color, amount} | Mixes colors by their RGB component values. Amount is opacity of overlaying color |
|
||||
| **tint** {amount} | Same as applying **mix** with white color |
|
||||
| **shade** {amount} | Same as applying **mix** with black color |
|
||||
| **xor** {color} | Treats the two colors as bitfields and applies an XOR operation to the red, green, and blue components |
|
||||
| **red** {amount} | Modify Red component by a given amount |
|
||||
| **green** {amount} | Modify Green component by a given amount |
|
||||
| **blue** {amount} | Modify Blue component by a given amount |
|
||||
|
||||
## brightness
|
||||
|
||||
Adjusts the brightness of the image
|
||||
|
||||
- @param {number} val the amount to adjust the brightness, a number between -1 and +1
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.brightness(20);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## contrast
|
||||
|
||||
Adjusts the contrast of the image
|
||||
|
||||
- @param {number} val the amount to adjust the contrast, a number between -1 and +1
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.contrast(70);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## posterize
|
||||
|
||||
Apply a posterize effect
|
||||
|
||||
- @param {number} n the amount to adjust the contrast, minimum threshold is two
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.posterize(5);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## opacity
|
||||
|
||||
Multiplies the opacity of each pixel by a factor between 0 and 1
|
||||
|
||||
- @param {number} f A number, the factor by which to multiply the opacity of each pixel
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.opacity(80);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## sepia
|
||||
|
||||
Applies a sepia tone to the image
|
||||
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.sepia();
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## fade
|
||||
|
||||
Fades each pixel by a factor between 0 and 1
|
||||
|
||||
- @param {number} f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.fade(0.7);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## convolution
|
||||
|
||||
Sum neighbor pixels weighted by the kernel matrix. You can find a nice explanation with examples at [GIMP's Convolution Matrix plugin](https://docs.gimp.org/2.6/en/plug-in-convmatrix.html)
|
||||
|
||||
- @param {array} kernel a matrix to weight the neighbors sum
|
||||
- @param {string} edgeHandling (optional) define how to sum pixels from outside the border
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
// make me better
|
||||
image.convolution(weights);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## opaque
|
||||
|
||||
Set the alpha channel on every pixel to fully opaque
|
||||
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.opaque();
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## pixelate
|
||||
|
||||
Pixelates the image or a region
|
||||
|
||||
- @param {number} size the size of the pixels
|
||||
- @param {number} x (optional) the x position of the region to pixelate
|
||||
- @param {number} y (optional) the y position of the region to pixelate
|
||||
- @param {number} w (optional) the width of the region to pixelate
|
||||
- @param {number} h (optional) the height of the region to pixelate
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
image.pixelate(10);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
## convolute
|
||||
|
||||
Applies a convolution kernel to the image or a region
|
||||
|
||||
- @param {array} kernel the convolution kernel
|
||||
- @param {number} x (optional) the x position of the region to apply convolution to
|
||||
- @param {number} y (optional) the y position of the region to apply convolution to
|
||||
- @param {number} w (optional) the width of the region to apply convolution to
|
||||
- @param {number} h (optional) the height of the region to apply convolution to
|
||||
- @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
|
||||
```js
|
||||
import jimp from 'jimp';
|
||||
|
||||
async function main() {
|
||||
const image = await jimp.read('test/image.png');
|
||||
|
||||
// make me better
|
||||
image.pixelate(kernal);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
595
node_modules/@jimp/plugin-color/dist/index.js
generated
vendored
Normal file
595
node_modules/@jimp/plugin-color/dist/index.js
generated
vendored
Normal file
@ -0,0 +1,595 @@
|
||||
"use strict";
|
||||
|
||||
require("core-js/modules/es6.object.define-property");
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
|
||||
require("core-js/modules/es6.string.iterator");
|
||||
|
||||
require("core-js/modules/es6.array.from");
|
||||
|
||||
require("core-js/modules/es6.regexp.to-string");
|
||||
|
||||
require("core-js/modules/es6.date.to-string");
|
||||
|
||||
require("core-js/modules/es7.symbol.async-iterator");
|
||||
|
||||
require("core-js/modules/es6.symbol");
|
||||
|
||||
require("core-js/modules/web.dom.iterable");
|
||||
|
||||
require("core-js/modules/es6.array.for-each");
|
||||
|
||||
require("core-js/modules/es6.array.map");
|
||||
|
||||
require("core-js/modules/es6.array.is-array");
|
||||
|
||||
var _tinycolor = _interopRequireDefault(require("tinycolor2"));
|
||||
|
||||
var _utils = require("@jimp/utils");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
|
||||
|
||||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
|
||||
|
||||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
|
||||
|
||||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
|
||||
|
||||
function applyKernel(im, kernel, x, y) {
|
||||
var value = [0, 0, 0];
|
||||
var size = (kernel.length - 1) / 2;
|
||||
|
||||
for (var kx = 0; kx < kernel.length; kx += 1) {
|
||||
for (var ky = 0; ky < kernel[kx].length; ky += 1) {
|
||||
var idx = im.getPixelIndex(x + kx - size, y + ky - size);
|
||||
value[0] += im.bitmap.data[idx] * kernel[kx][ky];
|
||||
value[1] += im.bitmap.data[idx + 1] * kernel[kx][ky];
|
||||
value[2] += im.bitmap.data[idx + 2] * kernel[kx][ky];
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
var isDef = function isDef(v) {
|
||||
return typeof v !== 'undefined' && v !== null;
|
||||
};
|
||||
|
||||
function greyscale(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var grey = parseInt(0.2126 * this.bitmap.data[idx] + 0.7152 * this.bitmap.data[idx + 1] + 0.0722 * this.bitmap.data[idx + 2], 10);
|
||||
this.bitmap.data[idx] = grey;
|
||||
this.bitmap.data[idx + 1] = grey;
|
||||
this.bitmap.data[idx + 2] = grey;
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function mix(clr, clr2) {
|
||||
var p = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 50;
|
||||
return {
|
||||
r: (clr2.r - clr.r) * (p / 100) + clr.r,
|
||||
g: (clr2.g - clr.g) * (p / 100) + clr.g,
|
||||
b: (clr2.b - clr.b) * (p / 100) + clr.b
|
||||
};
|
||||
}
|
||||
|
||||
function colorFn(actions, cb) {
|
||||
var _this = this;
|
||||
|
||||
if (!actions || !Array.isArray(actions)) {
|
||||
return _utils.throwError.call(this, 'actions must be an array', cb);
|
||||
}
|
||||
|
||||
actions = actions.map(function (action) {
|
||||
if (action.apply === 'xor' || action.apply === 'mix') {
|
||||
action.params[0] = (0, _tinycolor.default)(action.params[0]).toRgb();
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var clr = {
|
||||
r: _this.bitmap.data[idx],
|
||||
g: _this.bitmap.data[idx + 1],
|
||||
b: _this.bitmap.data[idx + 2]
|
||||
};
|
||||
|
||||
var colorModifier = function colorModifier(i, amount) {
|
||||
return _this.constructor.limit255(clr[i] + amount);
|
||||
};
|
||||
|
||||
actions.forEach(function (action) {
|
||||
if (action.apply === 'mix') {
|
||||
clr = mix(clr, action.params[0], action.params[1]);
|
||||
} else if (action.apply === 'tint') {
|
||||
clr = mix(clr, {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255
|
||||
}, action.params[0]);
|
||||
} else if (action.apply === 'shade') {
|
||||
clr = mix(clr, {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0
|
||||
}, action.params[0]);
|
||||
} else if (action.apply === 'xor') {
|
||||
clr = {
|
||||
r: clr.r ^ action.params[0].r,
|
||||
g: clr.g ^ action.params[0].g,
|
||||
b: clr.b ^ action.params[0].b
|
||||
};
|
||||
} else if (action.apply === 'red') {
|
||||
clr.r = colorModifier('r', action.params[0]);
|
||||
} else if (action.apply === 'green') {
|
||||
clr.g = colorModifier('g', action.params[0]);
|
||||
} else if (action.apply === 'blue') {
|
||||
clr.b = colorModifier('b', action.params[0]);
|
||||
} else {
|
||||
var _clr;
|
||||
|
||||
if (action.apply === 'hue') {
|
||||
action.apply = 'spin';
|
||||
}
|
||||
|
||||
clr = (0, _tinycolor.default)(clr);
|
||||
|
||||
if (!clr[action.apply]) {
|
||||
return _utils.throwError.call(_this, 'action ' + action.apply + ' not supported', cb);
|
||||
}
|
||||
|
||||
clr = (_clr = clr)[action.apply].apply(_clr, _toConsumableArray(action.params)).toRgb();
|
||||
}
|
||||
});
|
||||
_this.bitmap.data[idx] = clr.r;
|
||||
_this.bitmap.data[idx + 1] = clr.g;
|
||||
_this.bitmap.data[idx + 2] = clr.b;
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
var _default = function _default() {
|
||||
return {
|
||||
/**
|
||||
* Adjusts the brightness of the image
|
||||
* @param {number} val the amount to adjust the brightness, a number between -1 and +1
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
brightness: function brightness(val, cb) {
|
||||
if (typeof val !== 'number') {
|
||||
return _utils.throwError.call(this, 'val must be numbers', cb);
|
||||
}
|
||||
|
||||
if (val < -1 || val > +1) {
|
||||
return _utils.throwError.call(this, 'val must be a number between -1 and +1', cb);
|
||||
}
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
if (val < 0.0) {
|
||||
this.bitmap.data[idx] = this.bitmap.data[idx] * (1 + val);
|
||||
this.bitmap.data[idx + 1] = this.bitmap.data[idx + 1] * (1 + val);
|
||||
this.bitmap.data[idx + 2] = this.bitmap.data[idx + 2] * (1 + val);
|
||||
} else {
|
||||
this.bitmap.data[idx] = this.bitmap.data[idx] + (255 - this.bitmap.data[idx]) * val;
|
||||
this.bitmap.data[idx + 1] = this.bitmap.data[idx + 1] + (255 - this.bitmap.data[idx + 1]) * val;
|
||||
this.bitmap.data[idx + 2] = this.bitmap.data[idx + 2] + (255 - this.bitmap.data[idx + 2]) * val;
|
||||
}
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adjusts the contrast of the image
|
||||
* @param {number} val the amount to adjust the contrast, a number between -1 and +1
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
contrast: function contrast(val, cb) {
|
||||
if (typeof val !== 'number') {
|
||||
return _utils.throwError.call(this, 'val must be numbers', cb);
|
||||
}
|
||||
|
||||
if (val < -1 || val > +1) {
|
||||
return _utils.throwError.call(this, 'val must be a number between -1 and +1', cb);
|
||||
}
|
||||
|
||||
var factor = (val + 1) / (1 - val);
|
||||
|
||||
function adjust(value) {
|
||||
value = Math.floor(factor * (value - 127) + 127);
|
||||
return value < 0 ? 0 : value > 255 ? 255 : value;
|
||||
}
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
this.bitmap.data[idx] = adjust(this.bitmap.data[idx]);
|
||||
this.bitmap.data[idx + 1] = adjust(this.bitmap.data[idx + 1]);
|
||||
this.bitmap.data[idx + 2] = adjust(this.bitmap.data[idx + 2]);
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply a posterize effect
|
||||
* @param {number} n the amount to adjust the contrast, minimum threshold is two
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
posterize: function posterize(n, cb) {
|
||||
if (typeof n !== 'number') {
|
||||
return _utils.throwError.call(this, 'n must be numbers', cb);
|
||||
}
|
||||
|
||||
if (n < 2) {
|
||||
n = 2;
|
||||
} // minimum of 2 levels
|
||||
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
this.bitmap.data[idx] = Math.floor(this.bitmap.data[idx] / 255 * (n - 1)) / (n - 1) * 255;
|
||||
this.bitmap.data[idx + 1] = Math.floor(this.bitmap.data[idx + 1] / 255 * (n - 1)) / (n - 1) * 255;
|
||||
this.bitmap.data[idx + 2] = Math.floor(this.bitmap.data[idx + 2] / 255 * (n - 1)) / (n - 1) * 255;
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes colour from the image using ITU Rec 709 luminance values
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
greyscale: greyscale,
|
||||
// Alias of greyscale for our American friends
|
||||
grayscale: greyscale,
|
||||
|
||||
/**
|
||||
* Multiplies the opacity of each pixel by a factor between 0 and 1
|
||||
* @param {number} f A number, the factor by which to multiply the opacity of each pixel
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
opacity: function opacity(f, cb) {
|
||||
if (typeof f !== 'number') return _utils.throwError.call(this, 'f must be a number', cb);
|
||||
if (f < 0 || f > 1) return _utils.throwError.call(this, 'f must be a number from 0 to 1', cb);
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var v = this.bitmap.data[idx + 3] * f;
|
||||
this.bitmap.data[idx + 3] = v;
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies a sepia tone to the image
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
sepia: function sepia(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var red = this.bitmap.data[idx];
|
||||
var green = this.bitmap.data[idx + 1];
|
||||
var blue = this.bitmap.data[idx + 2];
|
||||
red = red * 0.393 + green * 0.769 + blue * 0.189;
|
||||
green = red * 0.349 + green * 0.686 + blue * 0.168;
|
||||
blue = red * 0.272 + green * 0.534 + blue * 0.131;
|
||||
this.bitmap.data[idx] = red < 255 ? red : 255;
|
||||
this.bitmap.data[idx + 1] = green < 255 ? green : 255;
|
||||
this.bitmap.data[idx + 2] = blue < 255 ? blue : 255;
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fades each pixel by a factor between 0 and 1
|
||||
* @param {number} f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
fade: function fade(f, cb) {
|
||||
if (typeof f !== 'number') {
|
||||
return _utils.throwError.call(this, 'f must be a number', cb);
|
||||
}
|
||||
|
||||
if (f < 0 || f > 1) {
|
||||
return _utils.throwError.call(this, 'f must be a number from 0 to 1', cb);
|
||||
} // this method is an alternative to opacity (which may be deprecated)
|
||||
|
||||
|
||||
this.opacity(1 - f);
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds each element of the image to its local neighbors, weighted by the kernel
|
||||
* @param {array} kernel a matrix to weight the neighbors sum
|
||||
* @param {string} edgeHandling (optional) define how to sum pixels from outside the border
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
convolution: function convolution(kernel, edgeHandling, cb) {
|
||||
if (typeof edgeHandling === 'function' && typeof cb === 'undefined') {
|
||||
cb = edgeHandling;
|
||||
edgeHandling = null;
|
||||
}
|
||||
|
||||
if (!edgeHandling) {
|
||||
edgeHandling = this.constructor.EDGE_EXTEND;
|
||||
}
|
||||
|
||||
var newData = Buffer.from(this.bitmap.data);
|
||||
var kRows = kernel.length;
|
||||
var kCols = kernel[0].length;
|
||||
var rowEnd = Math.floor(kRows / 2);
|
||||
var colEnd = Math.floor(kCols / 2);
|
||||
var rowIni = -rowEnd;
|
||||
var colIni = -colEnd;
|
||||
var weight;
|
||||
var rSum;
|
||||
var gSum;
|
||||
var bSum;
|
||||
var ri;
|
||||
var gi;
|
||||
var bi;
|
||||
var xi;
|
||||
var yi;
|
||||
var idxi;
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
bSum = 0;
|
||||
gSum = 0;
|
||||
rSum = 0;
|
||||
|
||||
for (var row = rowIni; row <= rowEnd; row++) {
|
||||
for (var col = colIni; col <= colEnd; col++) {
|
||||
xi = x + col;
|
||||
yi = y + row;
|
||||
weight = kernel[row + rowEnd][col + colEnd];
|
||||
idxi = this.getPixelIndex(xi, yi, edgeHandling);
|
||||
|
||||
if (idxi === -1) {
|
||||
bi = 0;
|
||||
gi = 0;
|
||||
ri = 0;
|
||||
} else {
|
||||
ri = this.bitmap.data[idxi + 0];
|
||||
gi = this.bitmap.data[idxi + 1];
|
||||
bi = this.bitmap.data[idxi + 2];
|
||||
}
|
||||
|
||||
rSum += weight * ri;
|
||||
gSum += weight * gi;
|
||||
bSum += weight * bi;
|
||||
}
|
||||
}
|
||||
|
||||
if (rSum < 0) {
|
||||
rSum = 0;
|
||||
}
|
||||
|
||||
if (gSum < 0) {
|
||||
gSum = 0;
|
||||
}
|
||||
|
||||
if (bSum < 0) {
|
||||
bSum = 0;
|
||||
}
|
||||
|
||||
if (rSum > 255) {
|
||||
rSum = 255;
|
||||
}
|
||||
|
||||
if (gSum > 255) {
|
||||
gSum = 255;
|
||||
}
|
||||
|
||||
if (bSum > 255) {
|
||||
bSum = 255;
|
||||
}
|
||||
|
||||
newData[idx + 0] = rSum;
|
||||
newData[idx + 1] = gSum;
|
||||
newData[idx + 2] = bSum;
|
||||
});
|
||||
this.bitmap.data = newData;
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the alpha channel on every pixel to fully opaque
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
opaque: function opaque(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
this.bitmap.data[idx + 3] = 255;
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Pixelates the image or a region
|
||||
* @param {number} size the size of the pixels
|
||||
* @param {number} x (optional) the x position of the region to pixelate
|
||||
* @param {number} y (optional) the y position of the region to pixelate
|
||||
* @param {number} w (optional) the width of the region to pixelate
|
||||
* @param {number} h (optional) the height of the region to pixelate
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
pixelate: function pixelate(size, x, y, w, h, cb) {
|
||||
if (typeof x === 'function') {
|
||||
cb = x;
|
||||
h = null;
|
||||
w = null;
|
||||
y = null;
|
||||
x = null;
|
||||
} else {
|
||||
if (typeof size !== 'number') {
|
||||
return _utils.throwError.call(this, 'size must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(x) && typeof x !== 'number') {
|
||||
return _utils.throwError.call(this, 'x must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(y) && typeof y !== 'number') {
|
||||
return _utils.throwError.call(this, 'y must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(w) && typeof w !== 'number') {
|
||||
return _utils.throwError.call(this, 'w must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(h) && typeof h !== 'number') {
|
||||
return _utils.throwError.call(this, 'h must be a number', cb);
|
||||
}
|
||||
}
|
||||
|
||||
var kernel = [[1 / 16, 2 / 16, 1 / 16], [2 / 16, 4 / 16, 2 / 16], [1 / 16, 2 / 16, 1 / 16]];
|
||||
x = x || 0;
|
||||
y = y || 0;
|
||||
w = isDef(w) ? w : this.bitmap.width - x;
|
||||
h = isDef(h) ? h : this.bitmap.height - y;
|
||||
var source = this.cloneQuiet();
|
||||
this.scanQuiet(x, y, w, h, function (xx, yx, idx) {
|
||||
xx = size * Math.floor(xx / size);
|
||||
yx = size * Math.floor(yx / size);
|
||||
var value = applyKernel(source, kernel, xx, yx);
|
||||
this.bitmap.data[idx] = value[0];
|
||||
this.bitmap.data[idx + 1] = value[1];
|
||||
this.bitmap.data[idx + 2] = value[2];
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies a convolution kernel to the image or a region
|
||||
* @param {array} kernel the convolution kernel
|
||||
* @param {number} x (optional) the x position of the region to apply convolution to
|
||||
* @param {number} y (optional) the y position of the region to apply convolution to
|
||||
* @param {number} w (optional) the width of the region to apply convolution to
|
||||
* @param {number} h (optional) the height of the region to apply convolution to
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
convolute: function convolute(kernel, x, y, w, h, cb) {
|
||||
if (!Array.isArray(kernel)) return _utils.throwError.call(this, 'the kernel must be an array', cb);
|
||||
|
||||
if (typeof x === 'function') {
|
||||
cb = x;
|
||||
x = null;
|
||||
y = null;
|
||||
w = null;
|
||||
h = null;
|
||||
} else {
|
||||
if (isDef(x) && typeof x !== 'number') {
|
||||
return _utils.throwError.call(this, 'x must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(y) && typeof y !== 'number') {
|
||||
return _utils.throwError.call(this, 'y must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(w) && typeof w !== 'number') {
|
||||
return _utils.throwError.call(this, 'w must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(h) && typeof h !== 'number') {
|
||||
return _utils.throwError.call(this, 'h must be a number', cb);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
this.scanQuiet(x, y, w, h, function (xx, yx, idx) {
|
||||
var value = applyKernel(source, kernel, xx, yx);
|
||||
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]);
|
||||
});
|
||||
|
||||
if ((0, _utils.isNodePattern)(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply multiple color modification rules
|
||||
* @param {array} actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
color: colorFn,
|
||||
colour: colorFn
|
||||
};
|
||||
};
|
||||
|
||||
exports.default = _default;
|
||||
module.exports = exports.default;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@jimp/plugin-color/dist/index.js.map
generated
vendored
Normal file
1
node_modules/@jimp/plugin-color/dist/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
560
node_modules/@jimp/plugin-color/es/index.js
generated
vendored
Normal file
560
node_modules/@jimp/plugin-color/es/index.js
generated
vendored
Normal file
@ -0,0 +1,560 @@
|
||||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
|
||||
|
||||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
|
||||
|
||||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
|
||||
|
||||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
|
||||
|
||||
import tinyColor from 'tinycolor2';
|
||||
import { throwError, isNodePattern } from '@jimp/utils';
|
||||
|
||||
function applyKernel(im, kernel, x, y) {
|
||||
var value = [0, 0, 0];
|
||||
var size = (kernel.length - 1) / 2;
|
||||
|
||||
for (var kx = 0; kx < kernel.length; kx += 1) {
|
||||
for (var ky = 0; ky < kernel[kx].length; ky += 1) {
|
||||
var idx = im.getPixelIndex(x + kx - size, y + ky - size);
|
||||
value[0] += im.bitmap.data[idx] * kernel[kx][ky];
|
||||
value[1] += im.bitmap.data[idx + 1] * kernel[kx][ky];
|
||||
value[2] += im.bitmap.data[idx + 2] * kernel[kx][ky];
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
var isDef = function isDef(v) {
|
||||
return typeof v !== 'undefined' && v !== null;
|
||||
};
|
||||
|
||||
function greyscale(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var grey = parseInt(0.2126 * this.bitmap.data[idx] + 0.7152 * this.bitmap.data[idx + 1] + 0.0722 * this.bitmap.data[idx + 2], 10);
|
||||
this.bitmap.data[idx] = grey;
|
||||
this.bitmap.data[idx + 1] = grey;
|
||||
this.bitmap.data[idx + 2] = grey;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function mix(clr, clr2) {
|
||||
var p = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 50;
|
||||
return {
|
||||
r: (clr2.r - clr.r) * (p / 100) + clr.r,
|
||||
g: (clr2.g - clr.g) * (p / 100) + clr.g,
|
||||
b: (clr2.b - clr.b) * (p / 100) + clr.b
|
||||
};
|
||||
}
|
||||
|
||||
function colorFn(actions, cb) {
|
||||
var _this = this;
|
||||
|
||||
if (!actions || !Array.isArray(actions)) {
|
||||
return throwError.call(this, 'actions must be an array', cb);
|
||||
}
|
||||
|
||||
actions = actions.map(function (action) {
|
||||
if (action.apply === 'xor' || action.apply === 'mix') {
|
||||
action.params[0] = tinyColor(action.params[0]).toRgb();
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var clr = {
|
||||
r: _this.bitmap.data[idx],
|
||||
g: _this.bitmap.data[idx + 1],
|
||||
b: _this.bitmap.data[idx + 2]
|
||||
};
|
||||
|
||||
var colorModifier = function colorModifier(i, amount) {
|
||||
return _this.constructor.limit255(clr[i] + amount);
|
||||
};
|
||||
|
||||
actions.forEach(function (action) {
|
||||
if (action.apply === 'mix') {
|
||||
clr = mix(clr, action.params[0], action.params[1]);
|
||||
} else if (action.apply === 'tint') {
|
||||
clr = mix(clr, {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255
|
||||
}, action.params[0]);
|
||||
} else if (action.apply === 'shade') {
|
||||
clr = mix(clr, {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0
|
||||
}, action.params[0]);
|
||||
} else if (action.apply === 'xor') {
|
||||
clr = {
|
||||
r: clr.r ^ action.params[0].r,
|
||||
g: clr.g ^ action.params[0].g,
|
||||
b: clr.b ^ action.params[0].b
|
||||
};
|
||||
} else if (action.apply === 'red') {
|
||||
clr.r = colorModifier('r', action.params[0]);
|
||||
} else if (action.apply === 'green') {
|
||||
clr.g = colorModifier('g', action.params[0]);
|
||||
} else if (action.apply === 'blue') {
|
||||
clr.b = colorModifier('b', action.params[0]);
|
||||
} else {
|
||||
var _clr;
|
||||
|
||||
if (action.apply === 'hue') {
|
||||
action.apply = 'spin';
|
||||
}
|
||||
|
||||
clr = tinyColor(clr);
|
||||
|
||||
if (!clr[action.apply]) {
|
||||
return throwError.call(_this, 'action ' + action.apply + ' not supported', cb);
|
||||
}
|
||||
|
||||
clr = (_clr = clr)[action.apply].apply(_clr, _toConsumableArray(action.params)).toRgb();
|
||||
}
|
||||
});
|
||||
_this.bitmap.data[idx] = clr.r;
|
||||
_this.bitmap.data[idx + 1] = clr.g;
|
||||
_this.bitmap.data[idx + 2] = clr.b;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
export default (function () {
|
||||
return {
|
||||
/**
|
||||
* Adjusts the brightness of the image
|
||||
* @param {number} val the amount to adjust the brightness, a number between -1 and +1
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
brightness: function brightness(val, cb) {
|
||||
if (typeof val !== 'number') {
|
||||
return throwError.call(this, 'val must be numbers', cb);
|
||||
}
|
||||
|
||||
if (val < -1 || val > +1) {
|
||||
return throwError.call(this, 'val must be a number between -1 and +1', cb);
|
||||
}
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
if (val < 0.0) {
|
||||
this.bitmap.data[idx] = this.bitmap.data[idx] * (1 + val);
|
||||
this.bitmap.data[idx + 1] = this.bitmap.data[idx + 1] * (1 + val);
|
||||
this.bitmap.data[idx + 2] = this.bitmap.data[idx + 2] * (1 + val);
|
||||
} else {
|
||||
this.bitmap.data[idx] = this.bitmap.data[idx] + (255 - this.bitmap.data[idx]) * val;
|
||||
this.bitmap.data[idx + 1] = this.bitmap.data[idx + 1] + (255 - this.bitmap.data[idx + 1]) * val;
|
||||
this.bitmap.data[idx + 2] = this.bitmap.data[idx + 2] + (255 - this.bitmap.data[idx + 2]) * val;
|
||||
}
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adjusts the contrast of the image
|
||||
* @param {number} val the amount to adjust the contrast, a number between -1 and +1
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
contrast: function contrast(val, cb) {
|
||||
if (typeof val !== 'number') {
|
||||
return throwError.call(this, 'val must be numbers', cb);
|
||||
}
|
||||
|
||||
if (val < -1 || val > +1) {
|
||||
return throwError.call(this, 'val must be a number between -1 and +1', cb);
|
||||
}
|
||||
|
||||
var factor = (val + 1) / (1 - val);
|
||||
|
||||
function adjust(value) {
|
||||
value = Math.floor(factor * (value - 127) + 127);
|
||||
return value < 0 ? 0 : value > 255 ? 255 : value;
|
||||
}
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
this.bitmap.data[idx] = adjust(this.bitmap.data[idx]);
|
||||
this.bitmap.data[idx + 1] = adjust(this.bitmap.data[idx + 1]);
|
||||
this.bitmap.data[idx + 2] = adjust(this.bitmap.data[idx + 2]);
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply a posterize effect
|
||||
* @param {number} n the amount to adjust the contrast, minimum threshold is two
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
posterize: function posterize(n, cb) {
|
||||
if (typeof n !== 'number') {
|
||||
return throwError.call(this, 'n must be numbers', cb);
|
||||
}
|
||||
|
||||
if (n < 2) {
|
||||
n = 2;
|
||||
} // minimum of 2 levels
|
||||
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
this.bitmap.data[idx] = Math.floor(this.bitmap.data[idx] / 255 * (n - 1)) / (n - 1) * 255;
|
||||
this.bitmap.data[idx + 1] = Math.floor(this.bitmap.data[idx + 1] / 255 * (n - 1)) / (n - 1) * 255;
|
||||
this.bitmap.data[idx + 2] = Math.floor(this.bitmap.data[idx + 2] / 255 * (n - 1)) / (n - 1) * 255;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes colour from the image using ITU Rec 709 luminance values
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
greyscale: greyscale,
|
||||
// Alias of greyscale for our American friends
|
||||
grayscale: greyscale,
|
||||
|
||||
/**
|
||||
* Multiplies the opacity of each pixel by a factor between 0 and 1
|
||||
* @param {number} f A number, the factor by which to multiply the opacity of each pixel
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
opacity: function opacity(f, cb) {
|
||||
if (typeof f !== 'number') return throwError.call(this, 'f must be a number', cb);
|
||||
if (f < 0 || f > 1) return throwError.call(this, 'f must be a number from 0 to 1', cb);
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var v = this.bitmap.data[idx + 3] * f;
|
||||
this.bitmap.data[idx + 3] = v;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies a sepia tone to the image
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
sepia: function sepia(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
var red = this.bitmap.data[idx];
|
||||
var green = this.bitmap.data[idx + 1];
|
||||
var blue = this.bitmap.data[idx + 2];
|
||||
red = red * 0.393 + green * 0.769 + blue * 0.189;
|
||||
green = red * 0.349 + green * 0.686 + blue * 0.168;
|
||||
blue = red * 0.272 + green * 0.534 + blue * 0.131;
|
||||
this.bitmap.data[idx] = red < 255 ? red : 255;
|
||||
this.bitmap.data[idx + 1] = green < 255 ? green : 255;
|
||||
this.bitmap.data[idx + 2] = blue < 255 ? blue : 255;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fades each pixel by a factor between 0 and 1
|
||||
* @param {number} f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
fade: function fade(f, cb) {
|
||||
if (typeof f !== 'number') {
|
||||
return throwError.call(this, 'f must be a number', cb);
|
||||
}
|
||||
|
||||
if (f < 0 || f > 1) {
|
||||
return throwError.call(this, 'f must be a number from 0 to 1', cb);
|
||||
} // this method is an alternative to opacity (which may be deprecated)
|
||||
|
||||
|
||||
this.opacity(1 - f);
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds each element of the image to its local neighbors, weighted by the kernel
|
||||
* @param {array} kernel a matrix to weight the neighbors sum
|
||||
* @param {string} edgeHandling (optional) define how to sum pixels from outside the border
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
convolution: function convolution(kernel, edgeHandling, cb) {
|
||||
if (typeof edgeHandling === 'function' && typeof cb === 'undefined') {
|
||||
cb = edgeHandling;
|
||||
edgeHandling = null;
|
||||
}
|
||||
|
||||
if (!edgeHandling) {
|
||||
edgeHandling = this.constructor.EDGE_EXTEND;
|
||||
}
|
||||
|
||||
var newData = Buffer.from(this.bitmap.data);
|
||||
var kRows = kernel.length;
|
||||
var kCols = kernel[0].length;
|
||||
var rowEnd = Math.floor(kRows / 2);
|
||||
var colEnd = Math.floor(kCols / 2);
|
||||
var rowIni = -rowEnd;
|
||||
var colIni = -colEnd;
|
||||
var weight;
|
||||
var rSum;
|
||||
var gSum;
|
||||
var bSum;
|
||||
var ri;
|
||||
var gi;
|
||||
var bi;
|
||||
var xi;
|
||||
var yi;
|
||||
var idxi;
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
bSum = 0;
|
||||
gSum = 0;
|
||||
rSum = 0;
|
||||
|
||||
for (var row = rowIni; row <= rowEnd; row++) {
|
||||
for (var col = colIni; col <= colEnd; col++) {
|
||||
xi = x + col;
|
||||
yi = y + row;
|
||||
weight = kernel[row + rowEnd][col + colEnd];
|
||||
idxi = this.getPixelIndex(xi, yi, edgeHandling);
|
||||
|
||||
if (idxi === -1) {
|
||||
bi = 0;
|
||||
gi = 0;
|
||||
ri = 0;
|
||||
} else {
|
||||
ri = this.bitmap.data[idxi + 0];
|
||||
gi = this.bitmap.data[idxi + 1];
|
||||
bi = this.bitmap.data[idxi + 2];
|
||||
}
|
||||
|
||||
rSum += weight * ri;
|
||||
gSum += weight * gi;
|
||||
bSum += weight * bi;
|
||||
}
|
||||
}
|
||||
|
||||
if (rSum < 0) {
|
||||
rSum = 0;
|
||||
}
|
||||
|
||||
if (gSum < 0) {
|
||||
gSum = 0;
|
||||
}
|
||||
|
||||
if (bSum < 0) {
|
||||
bSum = 0;
|
||||
}
|
||||
|
||||
if (rSum > 255) {
|
||||
rSum = 255;
|
||||
}
|
||||
|
||||
if (gSum > 255) {
|
||||
gSum = 255;
|
||||
}
|
||||
|
||||
if (bSum > 255) {
|
||||
bSum = 255;
|
||||
}
|
||||
|
||||
newData[idx + 0] = rSum;
|
||||
newData[idx + 1] = gSum;
|
||||
newData[idx + 2] = bSum;
|
||||
});
|
||||
this.bitmap.data = newData;
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the alpha channel on every pixel to fully opaque
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
opaque: function opaque(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function (x, y, idx) {
|
||||
this.bitmap.data[idx + 3] = 255;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Pixelates the image or a region
|
||||
* @param {number} size the size of the pixels
|
||||
* @param {number} x (optional) the x position of the region to pixelate
|
||||
* @param {number} y (optional) the y position of the region to pixelate
|
||||
* @param {number} w (optional) the width of the region to pixelate
|
||||
* @param {number} h (optional) the height of the region to pixelate
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
pixelate: function pixelate(size, x, y, w, h, cb) {
|
||||
if (typeof x === 'function') {
|
||||
cb = x;
|
||||
h = null;
|
||||
w = null;
|
||||
y = null;
|
||||
x = null;
|
||||
} else {
|
||||
if (typeof size !== 'number') {
|
||||
return throwError.call(this, 'size must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(x) && typeof x !== 'number') {
|
||||
return throwError.call(this, 'x must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(y) && typeof y !== 'number') {
|
||||
return throwError.call(this, 'y must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(w) && typeof w !== 'number') {
|
||||
return throwError.call(this, 'w must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(h) && typeof h !== 'number') {
|
||||
return throwError.call(this, 'h must be a number', cb);
|
||||
}
|
||||
}
|
||||
|
||||
var kernel = [[1 / 16, 2 / 16, 1 / 16], [2 / 16, 4 / 16, 2 / 16], [1 / 16, 2 / 16, 1 / 16]];
|
||||
x = x || 0;
|
||||
y = y || 0;
|
||||
w = isDef(w) ? w : this.bitmap.width - x;
|
||||
h = isDef(h) ? h : this.bitmap.height - y;
|
||||
var source = this.cloneQuiet();
|
||||
this.scanQuiet(x, y, w, h, function (xx, yx, idx) {
|
||||
xx = size * Math.floor(xx / size);
|
||||
yx = size * Math.floor(yx / size);
|
||||
var value = applyKernel(source, kernel, xx, yx);
|
||||
this.bitmap.data[idx] = value[0];
|
||||
this.bitmap.data[idx + 1] = value[1];
|
||||
this.bitmap.data[idx + 2] = value[2];
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies a convolution kernel to the image or a region
|
||||
* @param {array} kernel the convolution kernel
|
||||
* @param {number} x (optional) the x position of the region to apply convolution to
|
||||
* @param {number} y (optional) the y position of the region to apply convolution to
|
||||
* @param {number} w (optional) the width of the region to apply convolution to
|
||||
* @param {number} h (optional) the height of the region to apply convolution to
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
convolute: function convolute(kernel, x, y, w, h, cb) {
|
||||
if (!Array.isArray(kernel)) return throwError.call(this, 'the kernel must be an array', cb);
|
||||
|
||||
if (typeof x === 'function') {
|
||||
cb = x;
|
||||
x = null;
|
||||
y = null;
|
||||
w = null;
|
||||
h = null;
|
||||
} else {
|
||||
if (isDef(x) && typeof x !== 'number') {
|
||||
return throwError.call(this, 'x must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(y) && typeof y !== 'number') {
|
||||
return throwError.call(this, 'y must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(w) && typeof w !== 'number') {
|
||||
return throwError.call(this, 'w must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(h) && typeof h !== 'number') {
|
||||
return throwError.call(this, 'h must be a number', cb);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
this.scanQuiet(x, y, w, h, function (xx, yx, idx) {
|
||||
var value = applyKernel(source, kernel, xx, yx);
|
||||
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]);
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply multiple color modification rules
|
||||
* @param {array} actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
color: colorFn,
|
||||
colour: colorFn
|
||||
};
|
||||
});
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@jimp/plugin-color/es/index.js.map
generated
vendored
Normal file
1
node_modules/@jimp/plugin-color/es/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
64
node_modules/@jimp/plugin-color/package.json
generated
vendored
Normal file
64
node_modules/@jimp/plugin-color/package.json
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"_from": "@jimp/plugin-color@^0.6.4",
|
||||
"_id": "@jimp/plugin-color@0.6.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-6Nfr2l9KSb6zH2fij8G6fQOw85TTkyRaBlqMvDmsQp/I1IlaDbXzA2C2Eh9jkQYZQDPu61B1MkmlEhJp/TUx6Q==",
|
||||
"_location": "/@jimp/plugin-color",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "@jimp/plugin-color@^0.6.4",
|
||||
"name": "@jimp/plugin-color",
|
||||
"escapedName": "@jimp%2fplugin-color",
|
||||
"scope": "@jimp",
|
||||
"rawSpec": "^0.6.4",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^0.6.4"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/@jimp/plugins"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.6.4.tgz",
|
||||
"_shasum": "d5ce139a0e665437ef9d5df7642be66f33735645",
|
||||
"_spec": "@jimp/plugin-color@^0.6.4",
|
||||
"_where": "/Users/stefanfejes/Projects/30-seconds-of-python-code/node_modules/@jimp/plugins",
|
||||
"author": "",
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"@jimp/utils": "^0.6.4",
|
||||
"core-js": "^2.5.7",
|
||||
"tinycolor2": "^1.4.1"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Bitmap manipulation to adjust the color in an image.",
|
||||
"devDependencies": {
|
||||
"@jimp/custom": "^0.6.4",
|
||||
"@jimp/test-utils": "^0.6.4",
|
||||
"@jimp/types": "^0.6.4"
|
||||
},
|
||||
"gitHead": "7c9d3c817cade88d4a20422be10670d3c1528429",
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"module": "es/index.js",
|
||||
"name": "@jimp/plugin-color",
|
||||
"peerDependencies": {
|
||||
"@jimp/custom": ">=0.3.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build:node:production && npm run build:module",
|
||||
"build:debug": "npm run build:node:debug",
|
||||
"build:module": "cross-env BABEL_ENV=module babel src -d es --source-maps --config-file ../../babel.config.js",
|
||||
"build:node": "babel src -d dist --source-maps --config-file ../../babel.config.js",
|
||||
"build:node:debug": "cross-env BABEL_ENV=development npm run build:node",
|
||||
"build:node:production": "cross-env BABEL_ENV=production npm run build:node",
|
||||
"build:watch": "npm run build:node:debug -- -- --watch --verbose",
|
||||
"test": "cross-env BABEL_ENV=test mocha --require @babel/register",
|
||||
"test:coverage": "nyc npm run test",
|
||||
"test:watch": "npm run test -- --reporter min --watch"
|
||||
},
|
||||
"version": "0.6.4"
|
||||
}
|
||||
616
node_modules/@jimp/plugin-color/src/index.js
generated
vendored
Normal file
616
node_modules/@jimp/plugin-color/src/index.js
generated
vendored
Normal file
@ -0,0 +1,616 @@
|
||||
import tinyColor from 'tinycolor2';
|
||||
import { throwError, isNodePattern } from '@jimp/utils';
|
||||
|
||||
function applyKernel(im, kernel, x, y) {
|
||||
const value = [0, 0, 0];
|
||||
const size = (kernel.length - 1) / 2;
|
||||
|
||||
for (let kx = 0; kx < kernel.length; kx += 1) {
|
||||
for (let ky = 0; ky < kernel[kx].length; ky += 1) {
|
||||
const idx = im.getPixelIndex(x + kx - size, y + ky - size);
|
||||
|
||||
value[0] += im.bitmap.data[idx] * kernel[kx][ky];
|
||||
value[1] += im.bitmap.data[idx + 1] * kernel[kx][ky];
|
||||
value[2] += im.bitmap.data[idx + 2] * kernel[kx][ky];
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const isDef = v => typeof v !== 'undefined' && v !== null;
|
||||
|
||||
function greyscale(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
const grey = parseInt(
|
||||
0.2126 * this.bitmap.data[idx] +
|
||||
0.7152 * this.bitmap.data[idx + 1] +
|
||||
0.0722 * this.bitmap.data[idx + 2],
|
||||
10
|
||||
);
|
||||
|
||||
this.bitmap.data[idx] = grey;
|
||||
this.bitmap.data[idx + 1] = grey;
|
||||
this.bitmap.data[idx + 2] = grey;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function mix(clr, clr2, p = 50) {
|
||||
return {
|
||||
r: (clr2.r - clr.r) * (p / 100) + clr.r,
|
||||
g: (clr2.g - clr.g) * (p / 100) + clr.g,
|
||||
b: (clr2.b - clr.b) * (p / 100) + clr.b
|
||||
};
|
||||
}
|
||||
|
||||
function colorFn(actions, cb) {
|
||||
if (!actions || !Array.isArray(actions)) {
|
||||
return throwError.call(this, 'actions must be an array', cb);
|
||||
}
|
||||
|
||||
actions = actions.map(action => {
|
||||
if (action.apply === 'xor' || action.apply === 'mix') {
|
||||
action.params[0] = tinyColor(action.params[0]).toRgb();
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, (x, y, idx) => {
|
||||
let clr = {
|
||||
r: this.bitmap.data[idx],
|
||||
g: this.bitmap.data[idx + 1],
|
||||
b: this.bitmap.data[idx + 2]
|
||||
};
|
||||
|
||||
const colorModifier = (i, amount) =>
|
||||
this.constructor.limit255(clr[i] + amount);
|
||||
|
||||
actions.forEach(action => {
|
||||
if (action.apply === 'mix') {
|
||||
clr = mix(clr, action.params[0], action.params[1]);
|
||||
} else if (action.apply === 'tint') {
|
||||
clr = mix(clr, { r: 255, g: 255, b: 255 }, action.params[0]);
|
||||
} else if (action.apply === 'shade') {
|
||||
clr = mix(clr, { r: 0, g: 0, b: 0 }, action.params[0]);
|
||||
} else if (action.apply === 'xor') {
|
||||
clr = {
|
||||
r: clr.r ^ action.params[0].r,
|
||||
g: clr.g ^ action.params[0].g,
|
||||
b: clr.b ^ action.params[0].b
|
||||
};
|
||||
} else if (action.apply === 'red') {
|
||||
clr.r = colorModifier('r', action.params[0]);
|
||||
} else if (action.apply === 'green') {
|
||||
clr.g = colorModifier('g', action.params[0]);
|
||||
} else if (action.apply === 'blue') {
|
||||
clr.b = colorModifier('b', action.params[0]);
|
||||
} else {
|
||||
if (action.apply === 'hue') {
|
||||
action.apply = 'spin';
|
||||
}
|
||||
|
||||
clr = tinyColor(clr);
|
||||
|
||||
if (!clr[action.apply]) {
|
||||
return throwError.call(
|
||||
this,
|
||||
'action ' + action.apply + ' not supported',
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
clr = clr[action.apply](...action.params).toRgb();
|
||||
}
|
||||
});
|
||||
|
||||
this.bitmap.data[idx] = clr.r;
|
||||
this.bitmap.data[idx + 1] = clr.g;
|
||||
this.bitmap.data[idx + 2] = clr.b;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
export default () => ({
|
||||
/**
|
||||
* Adjusts the brightness of the image
|
||||
* @param {number} val the amount to adjust the brightness, a number between -1 and +1
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
brightness(val, cb) {
|
||||
if (typeof val !== 'number') {
|
||||
return throwError.call(this, 'val must be numbers', cb);
|
||||
}
|
||||
|
||||
if (val < -1 || val > +1) {
|
||||
return throwError.call(
|
||||
this,
|
||||
'val must be a number between -1 and +1',
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
if (val < 0.0) {
|
||||
this.bitmap.data[idx] = this.bitmap.data[idx] * (1 + val);
|
||||
this.bitmap.data[idx + 1] = this.bitmap.data[idx + 1] * (1 + val);
|
||||
this.bitmap.data[idx + 2] = this.bitmap.data[idx + 2] * (1 + val);
|
||||
} else {
|
||||
this.bitmap.data[idx] =
|
||||
this.bitmap.data[idx] + (255 - this.bitmap.data[idx]) * val;
|
||||
this.bitmap.data[idx + 1] =
|
||||
this.bitmap.data[idx + 1] + (255 - this.bitmap.data[idx + 1]) * val;
|
||||
this.bitmap.data[idx + 2] =
|
||||
this.bitmap.data[idx + 2] + (255 - this.bitmap.data[idx + 2]) * val;
|
||||
}
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adjusts the contrast of the image
|
||||
* @param {number} val the amount to adjust the contrast, a number between -1 and +1
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
contrast(val, cb) {
|
||||
if (typeof val !== 'number') {
|
||||
return throwError.call(this, 'val must be numbers', cb);
|
||||
}
|
||||
|
||||
if (val < -1 || val > +1) {
|
||||
return throwError.call(
|
||||
this,
|
||||
'val must be a number between -1 and +1',
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
const factor = (val + 1) / (1 - val);
|
||||
|
||||
function adjust(value) {
|
||||
value = Math.floor(factor * (value - 127) + 127);
|
||||
|
||||
return value < 0 ? 0 : value > 255 ? 255 : value;
|
||||
}
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
this.bitmap.data[idx] = adjust(this.bitmap.data[idx]);
|
||||
this.bitmap.data[idx + 1] = adjust(this.bitmap.data[idx + 1]);
|
||||
this.bitmap.data[idx + 2] = adjust(this.bitmap.data[idx + 2]);
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply a posterize effect
|
||||
* @param {number} n the amount to adjust the contrast, minimum threshold is two
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
posterize(n, cb) {
|
||||
if (typeof n !== 'number') {
|
||||
return throwError.call(this, 'n must be numbers', cb);
|
||||
}
|
||||
|
||||
if (n < 2) {
|
||||
n = 2;
|
||||
} // minimum of 2 levels
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
this.bitmap.data[idx] =
|
||||
(Math.floor((this.bitmap.data[idx] / 255) * (n - 1)) / (n - 1)) * 255;
|
||||
this.bitmap.data[idx + 1] =
|
||||
(Math.floor((this.bitmap.data[idx + 1] / 255) * (n - 1)) / (n - 1)) *
|
||||
255;
|
||||
this.bitmap.data[idx + 2] =
|
||||
(Math.floor((this.bitmap.data[idx + 2] / 255) * (n - 1)) / (n - 1)) *
|
||||
255;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes colour from the image using ITU Rec 709 luminance values
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
greyscale,
|
||||
|
||||
// Alias of greyscale for our American friends
|
||||
grayscale: greyscale,
|
||||
|
||||
/**
|
||||
* Multiplies the opacity of each pixel by a factor between 0 and 1
|
||||
* @param {number} f A number, the factor by which to multiply the opacity of each pixel
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
opacity(f, cb) {
|
||||
if (typeof f !== 'number')
|
||||
return throwError.call(this, 'f must be a number', cb);
|
||||
if (f < 0 || f > 1)
|
||||
return throwError.call(this, 'f must be a number from 0 to 1', cb);
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
const v = this.bitmap.data[idx + 3] * f;
|
||||
this.bitmap.data[idx + 3] = v;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies a sepia tone to the image
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
sepia(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
let red = this.bitmap.data[idx];
|
||||
let green = this.bitmap.data[idx + 1];
|
||||
let blue = this.bitmap.data[idx + 2];
|
||||
|
||||
red = red * 0.393 + green * 0.769 + blue * 0.189;
|
||||
green = red * 0.349 + green * 0.686 + blue * 0.168;
|
||||
blue = red * 0.272 + green * 0.534 + blue * 0.131;
|
||||
|
||||
this.bitmap.data[idx] = red < 255 ? red : 255;
|
||||
this.bitmap.data[idx + 1] = green < 255 ? green : 255;
|
||||
this.bitmap.data[idx + 2] = blue < 255 ? blue : 255;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fades each pixel by a factor between 0 and 1
|
||||
* @param {number} f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
fade(f, cb) {
|
||||
if (typeof f !== 'number') {
|
||||
return throwError.call(this, 'f must be a number', cb);
|
||||
}
|
||||
|
||||
if (f < 0 || f > 1) {
|
||||
return throwError.call(this, 'f must be a number from 0 to 1', cb);
|
||||
}
|
||||
|
||||
// this method is an alternative to opacity (which may be deprecated)
|
||||
this.opacity(1 - f);
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds each element of the image to its local neighbors, weighted by the kernel
|
||||
* @param {array} kernel a matrix to weight the neighbors sum
|
||||
* @param {string} edgeHandling (optional) define how to sum pixels from outside the border
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
convolution(kernel, edgeHandling, cb) {
|
||||
if (typeof edgeHandling === 'function' && typeof cb === 'undefined') {
|
||||
cb = edgeHandling;
|
||||
edgeHandling = null;
|
||||
}
|
||||
|
||||
if (!edgeHandling) {
|
||||
edgeHandling = this.constructor.EDGE_EXTEND;
|
||||
}
|
||||
|
||||
const newData = Buffer.from(this.bitmap.data);
|
||||
const kRows = kernel.length;
|
||||
const kCols = kernel[0].length;
|
||||
const rowEnd = Math.floor(kRows / 2);
|
||||
const colEnd = Math.floor(kCols / 2);
|
||||
const rowIni = -rowEnd;
|
||||
const colIni = -colEnd;
|
||||
|
||||
let weight;
|
||||
let rSum;
|
||||
let gSum;
|
||||
let bSum;
|
||||
let ri;
|
||||
let gi;
|
||||
let bi;
|
||||
let xi;
|
||||
let yi;
|
||||
let idxi;
|
||||
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
bSum = 0;
|
||||
gSum = 0;
|
||||
rSum = 0;
|
||||
|
||||
for (let row = rowIni; row <= rowEnd; row++) {
|
||||
for (let col = colIni; col <= colEnd; col++) {
|
||||
xi = x + col;
|
||||
yi = y + row;
|
||||
weight = kernel[row + rowEnd][col + colEnd];
|
||||
idxi = this.getPixelIndex(xi, yi, edgeHandling);
|
||||
|
||||
if (idxi === -1) {
|
||||
bi = 0;
|
||||
gi = 0;
|
||||
ri = 0;
|
||||
} else {
|
||||
ri = this.bitmap.data[idxi + 0];
|
||||
gi = this.bitmap.data[idxi + 1];
|
||||
bi = this.bitmap.data[idxi + 2];
|
||||
}
|
||||
|
||||
rSum += weight * ri;
|
||||
gSum += weight * gi;
|
||||
bSum += weight * bi;
|
||||
}
|
||||
}
|
||||
|
||||
if (rSum < 0) {
|
||||
rSum = 0;
|
||||
}
|
||||
|
||||
if (gSum < 0) {
|
||||
gSum = 0;
|
||||
}
|
||||
|
||||
if (bSum < 0) {
|
||||
bSum = 0;
|
||||
}
|
||||
|
||||
if (rSum > 255) {
|
||||
rSum = 255;
|
||||
}
|
||||
|
||||
if (gSum > 255) {
|
||||
gSum = 255;
|
||||
}
|
||||
|
||||
if (bSum > 255) {
|
||||
bSum = 255;
|
||||
}
|
||||
|
||||
newData[idx + 0] = rSum;
|
||||
newData[idx + 1] = gSum;
|
||||
newData[idx + 2] = bSum;
|
||||
});
|
||||
|
||||
this.bitmap.data = newData;
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the alpha channel on every pixel to fully opaque
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
opaque(cb) {
|
||||
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
|
||||
x,
|
||||
y,
|
||||
idx
|
||||
) {
|
||||
this.bitmap.data[idx + 3] = 255;
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Pixelates the image or a region
|
||||
* @param {number} size the size of the pixels
|
||||
* @param {number} x (optional) the x position of the region to pixelate
|
||||
* @param {number} y (optional) the y position of the region to pixelate
|
||||
* @param {number} w (optional) the width of the region to pixelate
|
||||
* @param {number} h (optional) the height of the region to pixelate
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
pixelate(size, x, y, w, h, cb) {
|
||||
if (typeof x === 'function') {
|
||||
cb = x;
|
||||
h = null;
|
||||
w = null;
|
||||
y = null;
|
||||
x = null;
|
||||
} else {
|
||||
if (typeof size !== 'number') {
|
||||
return throwError.call(this, 'size must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(x) && typeof x !== 'number') {
|
||||
return throwError.call(this, 'x must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(y) && typeof y !== 'number') {
|
||||
return throwError.call(this, 'y must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(w) && typeof w !== 'number') {
|
||||
return throwError.call(this, 'w must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(h) && typeof h !== 'number') {
|
||||
return throwError.call(this, 'h must be a number', cb);
|
||||
}
|
||||
}
|
||||
|
||||
const kernel = [
|
||||
[1 / 16, 2 / 16, 1 / 16],
|
||||
[2 / 16, 4 / 16, 2 / 16],
|
||||
[1 / 16, 2 / 16, 1 / 16]
|
||||
];
|
||||
|
||||
x = x || 0;
|
||||
y = y || 0;
|
||||
w = isDef(w) ? w : this.bitmap.width - x;
|
||||
h = isDef(h) ? h : this.bitmap.height - y;
|
||||
|
||||
const source = this.cloneQuiet();
|
||||
|
||||
this.scanQuiet(x, y, w, h, function(xx, yx, idx) {
|
||||
xx = size * Math.floor(xx / size);
|
||||
yx = size * Math.floor(yx / size);
|
||||
|
||||
const value = applyKernel(source, kernel, xx, yx);
|
||||
|
||||
this.bitmap.data[idx] = value[0];
|
||||
this.bitmap.data[idx + 1] = value[1];
|
||||
this.bitmap.data[idx + 2] = value[2];
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies a convolution kernel to the image or a region
|
||||
* @param {array} kernel the convolution kernel
|
||||
* @param {number} x (optional) the x position of the region to apply convolution to
|
||||
* @param {number} y (optional) the y position of the region to apply convolution to
|
||||
* @param {number} w (optional) the width of the region to apply convolution to
|
||||
* @param {number} h (optional) the height of the region to apply convolution to
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
convolute(kernel, x, y, w, h, cb) {
|
||||
if (!Array.isArray(kernel))
|
||||
return throwError.call(this, 'the kernel must be an array', cb);
|
||||
|
||||
if (typeof x === 'function') {
|
||||
cb = x;
|
||||
x = null;
|
||||
y = null;
|
||||
w = null;
|
||||
h = null;
|
||||
} else {
|
||||
if (isDef(x) && typeof x !== 'number') {
|
||||
return throwError.call(this, 'x must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(y) && typeof y !== 'number') {
|
||||
return throwError.call(this, 'y must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(w) && typeof w !== 'number') {
|
||||
return throwError.call(this, 'w must be a number', cb);
|
||||
}
|
||||
|
||||
if (isDef(h) && typeof h !== 'number') {
|
||||
return throwError.call(this, 'h must be a number', cb);
|
||||
}
|
||||
}
|
||||
|
||||
const 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;
|
||||
|
||||
const source = this.cloneQuiet();
|
||||
|
||||
this.scanQuiet(x, y, w, h, function(xx, yx, idx) {
|
||||
const value = applyKernel(source, kernel, xx, yx);
|
||||
|
||||
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]);
|
||||
});
|
||||
|
||||
if (isNodePattern(cb)) {
|
||||
cb.call(this, null, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply multiple color modification rules
|
||||
* @param {array} actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
|
||||
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
|
||||
* @returns {Jimp }this for chaining of methods
|
||||
*/
|
||||
color: colorFn,
|
||||
colour: colorFn
|
||||
});
|
||||
49
node_modules/@jimp/plugin-color/test/color.test.js
generated
vendored
Normal file
49
node_modules/@jimp/plugin-color/test/color.test.js
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
import { Jimp, donutJGD } from '@jimp/test-utils';
|
||||
import configure from '@jimp/custom';
|
||||
|
||||
import color from '../src';
|
||||
|
||||
const jimp = configure({ plugins: [color] }, Jimp);
|
||||
|
||||
describe('canvas color transformation', () => {
|
||||
const redDonutJGD = donutJGD(0x00000000, 0xff000088, 0xff0000ff);
|
||||
|
||||
it('can apply more than one color transformation', async () => {
|
||||
const image = await jimp.read(redDonutJGD);
|
||||
const newJGD = image
|
||||
.color([
|
||||
{ apply: 'hue', params: [-180] },
|
||||
{ apply: 'lighten', params: [25] }
|
||||
])
|
||||
.getJGDSync();
|
||||
|
||||
newJGD.should.be.sameJGD(donutJGD(0x40404000, 0x80ffff88, 0x80ffffff));
|
||||
});
|
||||
|
||||
it('lighten', async () => {
|
||||
const image = await jimp.read(redDonutJGD);
|
||||
|
||||
image
|
||||
.color([{ apply: 'lighten', params: [25] }])
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(donutJGD(0x40404000, 0xff808088, 0xff8080ff));
|
||||
});
|
||||
|
||||
it('brighten', async () => {
|
||||
const image = await jimp.read(redDonutJGD);
|
||||
|
||||
image
|
||||
.color([{ apply: 'brighten', params: [25] }])
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(donutJGD(0x40404000, 0xff404088, 0xff4040ff));
|
||||
});
|
||||
|
||||
it('spin hue', async () => {
|
||||
const image = await jimp.read(redDonutJGD);
|
||||
|
||||
image
|
||||
.color([{ apply: 'hue', params: [150] }])
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(donutJGD(0x00000000, 0x00ff8088, 0x00ff80ff));
|
||||
});
|
||||
});
|
||||
184
node_modules/@jimp/plugin-color/test/convolution.test.js
generated
vendored
Normal file
184
node_modules/@jimp/plugin-color/test/convolution.test.js
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
import { Jimp, mkJGD, getTestDir } from '@jimp/test-utils';
|
||||
import configure from '@jimp/custom';
|
||||
import types from '@jimp/types';
|
||||
|
||||
import color from '../src';
|
||||
|
||||
const jimp = configure({ types: [types], plugins: [color] }, Jimp);
|
||||
|
||||
describe('Convolution', function() {
|
||||
this.timeout(15000);
|
||||
|
||||
const imgs = [
|
||||
jimp.read(
|
||||
mkJGD(
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22888822',
|
||||
'22888822',
|
||||
'22888822',
|
||||
'22888822',
|
||||
'22222222',
|
||||
'22222222'
|
||||
)
|
||||
),
|
||||
jimp.read(
|
||||
mkJGD(
|
||||
'88222222',
|
||||
'88222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222'
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
let imgMid;
|
||||
let imgTopLeft; // stores the Jimp instances of the JGD images above.
|
||||
|
||||
before(done => {
|
||||
Promise.all(imgs)
|
||||
.then(imgs => {
|
||||
imgMid = imgs[0];
|
||||
imgTopLeft = imgs[1];
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
const sharpM = [[-1, -1, 0], [-1, 1, 1], [0, 1, 1]];
|
||||
|
||||
it('3x3 sharp matrix on EDGE_EXTEND', done => {
|
||||
imgMid
|
||||
.clone()
|
||||
.convolution(sharpM)
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(
|
||||
mkJGD(
|
||||
'22222222',
|
||||
'28EEE822',
|
||||
'2EFFF802',
|
||||
'2EF88002',
|
||||
'2EF88002',
|
||||
'28800002',
|
||||
'22000002',
|
||||
'22222222'
|
||||
),
|
||||
'Mid light block'
|
||||
);
|
||||
imgTopLeft
|
||||
.clone()
|
||||
.convolution(sharpM)
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(
|
||||
mkJGD(
|
||||
'80022222',
|
||||
'00022222',
|
||||
'00022222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222'
|
||||
),
|
||||
'Top left light block'
|
||||
);
|
||||
done();
|
||||
});
|
||||
|
||||
it('3x3 sharp matrix on EDGE_WRAP', done => {
|
||||
imgMid
|
||||
.clone()
|
||||
.convolution(sharpM, jimp.EDGE_WRAP)
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(
|
||||
mkJGD(
|
||||
'66666666',
|
||||
'28EEE822',
|
||||
'2EFFF802',
|
||||
'2EF88002',
|
||||
'2EF88002',
|
||||
'28800002',
|
||||
'22000002',
|
||||
'22222222'
|
||||
),
|
||||
'Mid light block'
|
||||
);
|
||||
imgTopLeft
|
||||
.clone()
|
||||
.convolution(sharpM, jimp.EDGE_WRAP)
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(
|
||||
mkJGD(
|
||||
'FC06666F',
|
||||
'80022228',
|
||||
'00022222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'22222222',
|
||||
'E8222228'
|
||||
),
|
||||
'Top left light block'
|
||||
);
|
||||
done();
|
||||
});
|
||||
|
||||
it('3x3 sharp matrix on EDGE_CROP', done => {
|
||||
imgMid
|
||||
.clone()
|
||||
.convolution(sharpM, jimp.EDGE_CROP)
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(
|
||||
mkJGD(
|
||||
'86666662',
|
||||
'68EEE820',
|
||||
'6EFFF800',
|
||||
'6EF88000',
|
||||
'6EF88000',
|
||||
'68800000',
|
||||
'62000000',
|
||||
'20000000'
|
||||
),
|
||||
'Mid light block'
|
||||
);
|
||||
imgTopLeft
|
||||
.clone()
|
||||
.convolution(sharpM, jimp.EDGE_CROP)
|
||||
.getJGDSync()
|
||||
.should.be.sameJGD(
|
||||
mkJGD(
|
||||
'FC066662',
|
||||
'C0022220',
|
||||
'00022220',
|
||||
'62222220',
|
||||
'62222220',
|
||||
'62222220',
|
||||
'62222220',
|
||||
'20000000'
|
||||
),
|
||||
'Top left light block'
|
||||
);
|
||||
done();
|
||||
});
|
||||
|
||||
it('new pixel value is greater than 255', async () => {
|
||||
const expectedImg = await jimp.read(
|
||||
getTestDir(__dirname) + '/images/qr-convoluted.png'
|
||||
);
|
||||
const image = await jimp.read(getTestDir(__dirname) + '/images/qr.jpg');
|
||||
|
||||
image
|
||||
.convolution([
|
||||
[0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 1, 0, 1, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0]
|
||||
])
|
||||
.bitmap.data.should.be.deepEqual(expectedImg.bitmap.data);
|
||||
});
|
||||
});
|
||||
BIN
node_modules/@jimp/plugin-color/test/images/qr-convoluted.png
generated
vendored
Normal file
BIN
node_modules/@jimp/plugin-color/test/images/qr-convoluted.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 151 KiB |
BIN
node_modules/@jimp/plugin-color/test/images/qr.jpg
generated
vendored
Normal file
BIN
node_modules/@jimp/plugin-color/test/images/qr.jpg
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
Reference in New Issue
Block a user