Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MR414N-ID
GitHub Repository: MR414N-ID/botku2
Path: blob/master/node_modules/@jimp/core/es/index.js
1126 views
1
"use strict";
2
3
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
4
5
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
6
7
Object.defineProperty(exports, "__esModule", {
8
value: true
9
});
10
exports.addConstants = addConstants;
11
exports.addJimpMethods = addJimpMethods;
12
exports.jimpEvMethod = jimpEvMethod;
13
exports.jimpEvChange = jimpEvChange;
14
Object.defineProperty(exports, "addType", {
15
enumerable: true,
16
get: function get() {
17
return MIME.addType;
18
}
19
});
20
exports["default"] = void 0;
21
22
var _construct2 = _interopRequireDefault(require("@babel/runtime/helpers/construct"));
23
24
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
25
26
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
27
28
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
29
30
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
31
32
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
33
34
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
35
36
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
37
38
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
39
40
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
41
42
var _fs = _interopRequireDefault(require("fs"));
43
44
var _path = _interopRequireDefault(require("path"));
45
46
var _events = _interopRequireDefault(require("events"));
47
48
var _utils = require("@jimp/utils");
49
50
var _anyBase = _interopRequireDefault(require("any-base"));
51
52
var _mkdirp = _interopRequireDefault(require("mkdirp"));
53
54
var _pixelmatch = _interopRequireDefault(require("pixelmatch"));
55
56
var _tinycolor = _interopRequireDefault(require("tinycolor2"));
57
58
var _phash = _interopRequireDefault(require("./modules/phash"));
59
60
var _request = _interopRequireDefault(require("./request"));
61
62
var _composite = _interopRequireDefault(require("./composite"));
63
64
var _promisify = _interopRequireDefault(require("./utils/promisify"));
65
66
var MIME = _interopRequireWildcard(require("./utils/mime"));
67
68
var _imageBitmap = require("./utils/image-bitmap");
69
70
var constants = _interopRequireWildcard(require("./constants"));
71
72
var alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_'; // an array storing the maximum string length of hashes at various bases
73
// 0 and 1 do not exist as possible hash lengths
74
75
var maxHashLength = [NaN, NaN];
76
77
for (var i = 2; i < 65; i++) {
78
var maxHash = (0, _anyBase["default"])(_anyBase["default"].BIN, alphabet.slice(0, i))(new Array(64 + 1).join('1'));
79
maxHashLength.push(maxHash.length);
80
} // no operation
81
82
83
function noop() {} // error checking methods
84
85
86
function isArrayBuffer(test) {
87
return Object.prototype.toString.call(test).toLowerCase().indexOf('arraybuffer') > -1;
88
} // Prepare a Buffer object from the arrayBuffer. Necessary in the browser > node conversion,
89
// But this function is not useful when running in node directly
90
91
92
function bufferFromArrayBuffer(arrayBuffer) {
93
var buffer = Buffer.alloc(arrayBuffer.byteLength);
94
var view = new Uint8Array(arrayBuffer);
95
96
for (var _i = 0; _i < buffer.length; ++_i) {
97
buffer[_i] = view[_i];
98
}
99
100
return buffer;
101
}
102
103
function loadFromURL(options, cb) {
104
(0, _request["default"])(options, function (err, response, data) {
105
if (err) {
106
return cb(err);
107
}
108
109
if ('headers' in response && 'location' in response.headers) {
110
options.url = response.headers.location;
111
return loadFromURL(options, cb);
112
}
113
114
if ((0, _typeof2["default"])(data) === 'object' && Buffer.isBuffer(data)) {
115
return cb(null, data);
116
}
117
118
var msg = 'Could not load Buffer from <' + options.url + '> ' + '(HTTP: ' + response.statusCode + ')';
119
return new Error(msg);
120
});
121
}
122
123
function loadBufferFromPath(src, cb) {
124
if (_fs["default"] && typeof _fs["default"].readFile === 'function' && !src.match(/^(http|ftp)s?:\/\/./)) {
125
_fs["default"].readFile(src, cb);
126
} else {
127
loadFromURL({
128
url: src
129
}, cb);
130
}
131
}
132
133
function isRawRGBAData(obj) {
134
return obj && (0, _typeof2["default"])(obj) === 'object' && typeof obj.width === 'number' && typeof obj.height === 'number' && (Buffer.isBuffer(obj.data) || obj.data instanceof Uint8Array || typeof Uint8ClampedArray === 'function' && obj.data instanceof Uint8ClampedArray) && (obj.data.length === obj.width * obj.height * 4 || obj.data.length === obj.width * obj.height * 3);
135
}
136
137
function makeRGBABufferFromRGB(buffer) {
138
if (buffer.length % 3 !== 0) {
139
throw new Error('Buffer length is incorrect');
140
}
141
142
var rgbaBuffer = Buffer.allocUnsafe(buffer.length / 3 * 4);
143
var j = 0;
144
145
for (var _i2 = 0; _i2 < buffer.length; _i2++) {
146
rgbaBuffer[j] = buffer[_i2];
147
148
if ((_i2 + 1) % 3 === 0) {
149
rgbaBuffer[++j] = 255;
150
}
151
152
j++;
153
}
154
155
return rgbaBuffer;
156
}
157
158
var emptyBitmap = {
159
data: null,
160
width: null,
161
height: null
162
};
163
/**
164
* Jimp constructor (from a file)
165
* @param path a path to the image
166
* @param {function(Error, Jimp)} cb (optional) a function to call when the image is parsed to a bitmap
167
*/
168
169
/**
170
* Jimp constructor (from a url with options)
171
* @param options { url, otherOptions}
172
* @param {function(Error, Jimp)} cb (optional) a function to call when the image is parsed to a bitmap
173
*/
174
175
/**
176
* Jimp constructor (from another Jimp image or raw image data)
177
* @param image a Jimp image to clone
178
* @param {function(Error, Jimp)} cb a function to call when the image is parsed to a bitmap
179
*/
180
181
/**
182
* Jimp constructor (from a Buffer)
183
* @param data a Buffer containing the image data
184
* @param {function(Error, Jimp)} cb a function to call when the image is parsed to a bitmap
185
*/
186
187
/**
188
* Jimp constructor (to generate a new image)
189
* @param w the width of the image
190
* @param h the height of the image
191
* @param {function(Error, Jimp)} cb (optional) a function to call when the image is parsed to a bitmap
192
*/
193
194
/**
195
* Jimp constructor (to generate a new image)
196
* @param w the width of the image
197
* @param h the height of the image
198
* @param background color to fill the image with
199
* @param {function(Error, Jimp)} cb (optional) a function to call when the image is parsed to a bitmap
200
*/
201
202
var Jimp =
203
/*#__PURE__*/
204
function (_EventEmitter) {
205
(0, _inherits2["default"])(Jimp, _EventEmitter);
206
207
// An object representing a bitmap in memory, comprising:
208
// - data: a buffer of the bitmap data
209
// - width: the width of the image in pixels
210
// - height: the height of the image in pixels
211
// Default colour to use for new pixels
212
// Default MIME is PNG
213
// Exif data for the image
214
// Whether Transparency supporting formats will be exported as RGB or RGBA
215
function Jimp() {
216
var _this;
217
218
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
219
args[_key] = arguments[_key];
220
}
221
222
(0, _classCallCheck2["default"])(this, Jimp);
223
_this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(Jimp).call(this));
224
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "bitmap", emptyBitmap);
225
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_background", 0x00000000);
226
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_originalMime", Jimp.MIME_PNG);
227
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_exif", null);
228
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_rgba", true);
229
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "writeAsync", function (path) {
230
return (0, _promisify["default"])(_this.write, (0, _assertThisInitialized2["default"])(_this), path);
231
});
232
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getBase64Async", function (mime) {
233
return (0, _promisify["default"])(_this.getBase64, (0, _assertThisInitialized2["default"])(_this), mime);
234
});
235
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getBuffer", _imageBitmap.getBuffer);
236
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getBufferAsync", _imageBitmap.getBufferAsync);
237
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getPixelColour", _this.getPixelColor);
238
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "setPixelColour", _this.setPixelColor);
239
var jimpInstance = (0, _assertThisInitialized2["default"])(_this);
240
var cb = noop;
241
242
if (isArrayBuffer(args[0])) {
243
args[0] = bufferFromArrayBuffer(args[0]);
244
}
245
246
function finish() {
247
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
248
args[_key2] = arguments[_key2];
249
}
250
251
var err = args[0];
252
var evData = err || {};
253
evData.methodName = 'constructor';
254
setTimeout(function () {
255
var _cb;
256
257
// run on next tick.
258
if (err && cb === noop) {
259
jimpInstance.emitError('constructor', err);
260
} else if (!err) {
261
jimpInstance.emitMulti('constructor', 'initialized');
262
}
263
264
(_cb = cb).call.apply(_cb, [jimpInstance].concat(args));
265
}, 1);
266
}
267
268
if (typeof args[0] === 'number' && typeof args[1] === 'number' || parseInt(args[0], 10) && parseInt(args[1], 10)) {
269
// create a new image
270
var w = parseInt(args[0], 10);
271
var h = parseInt(args[1], 10);
272
cb = args[2]; // with a hex color
273
274
if (typeof args[2] === 'number') {
275
_this._background = args[2];
276
cb = args[3];
277
} // with a css color
278
279
280
if (typeof args[2] === 'string') {
281
_this._background = Jimp.cssColorToHex(args[2]);
282
cb = args[3];
283
}
284
285
if (typeof cb === 'undefined') {
286
cb = noop;
287
}
288
289
if (typeof cb !== 'function') {
290
return (0, _possibleConstructorReturn2["default"])(_this, _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), 'cb must be a function', finish));
291
}
292
293
_this.bitmap = {
294
data: Buffer.alloc(w * h * 4),
295
width: w,
296
height: h
297
};
298
299
for (var _i3 = 0; _i3 < _this.bitmap.data.length; _i3 += 4) {
300
_this.bitmap.data.writeUInt32BE(_this._background, _i3);
301
}
302
303
finish(null, (0, _assertThisInitialized2["default"])(_this));
304
} else if ((0, _typeof2["default"])(args[0]) === 'object' && args[0].url) {
305
cb = args[1] || noop;
306
307
if (typeof cb !== 'function') {
308
return (0, _possibleConstructorReturn2["default"])(_this, _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), 'cb must be a function', finish));
309
}
310
311
loadFromURL(args[0], function (err, data) {
312
if (err) {
313
return _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), err, finish);
314
}
315
316
_this.parseBitmap(data, args[0].url, finish);
317
});
318
} else if (args[0] instanceof Jimp) {
319
// clone an existing Jimp
320
var original = args[0];
321
cb = args[1];
322
323
if (typeof cb === 'undefined') {
324
cb = noop;
325
}
326
327
if (typeof cb !== 'function') {
328
return (0, _possibleConstructorReturn2["default"])(_this, _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), 'cb must be a function', finish));
329
}
330
331
_this.bitmap = {
332
data: Buffer.from(original.bitmap.data),
333
width: original.bitmap.width,
334
height: original.bitmap.height
335
};
336
_this._quality = original._quality;
337
_this._deflateLevel = original._deflateLevel;
338
_this._deflateStrategy = original._deflateStrategy;
339
_this._filterType = original._filterType;
340
_this._rgba = original._rgba;
341
_this._background = original._background;
342
_this._originalMime = original._originalMime;
343
finish(null, (0, _assertThisInitialized2["default"])(_this));
344
} else if (isRawRGBAData(args[0])) {
345
var imageData = args[0];
346
cb = args[1] || noop;
347
var isRGBA = imageData.width * imageData.height * 4 === imageData.data.length;
348
var buffer = isRGBA ? Buffer.from(imageData.data) : makeRGBABufferFromRGB(imageData.data);
349
_this.bitmap = {
350
data: buffer,
351
width: imageData.width,
352
height: imageData.height
353
};
354
finish(null, (0, _assertThisInitialized2["default"])(_this));
355
} else if (typeof args[0] === 'string') {
356
// read from a path
357
var path = args[0];
358
cb = args[1];
359
360
if (typeof cb === 'undefined') {
361
cb = noop;
362
}
363
364
if (typeof cb !== 'function') {
365
return (0, _possibleConstructorReturn2["default"])(_this, _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), 'cb must be a function', finish));
366
}
367
368
loadBufferFromPath(path, function (err, data) {
369
if (err) {
370
return _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), err, finish);
371
}
372
373
_this.parseBitmap(data, path, finish);
374
});
375
} else if ((0, _typeof2["default"])(args[0]) === 'object' && Buffer.isBuffer(args[0])) {
376
// read from a buffer
377
var data = args[0];
378
cb = args[1];
379
380
if (typeof cb !== 'function') {
381
return (0, _possibleConstructorReturn2["default"])(_this, _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), 'cb must be a function', finish));
382
}
383
384
_this.parseBitmap(data, null, finish);
385
} else {
386
// Allow client libs to add new ways to build a Jimp object.
387
// Extra constructors must be added by `Jimp.appendConstructorOption()`
388
cb = args[args.length - 1];
389
390
if (typeof cb !== 'function') {
391
// TODO: try to solve the args after cb problem.
392
cb = args[args.length - 2];
393
394
if (typeof cb !== 'function') {
395
cb = noop;
396
}
397
}
398
399
var extraConstructor = Jimp.__extraConstructors.find(function (c) {
400
return c.test.apply(c, args);
401
});
402
403
if (extraConstructor) {
404
new Promise(function (resolve, reject) {
405
var _extraConstructor$run;
406
407
return (_extraConstructor$run = extraConstructor.run).call.apply(_extraConstructor$run, [(0, _assertThisInitialized2["default"])(_this), resolve, reject].concat(args));
408
}).then(function () {
409
return finish(null, (0, _assertThisInitialized2["default"])(_this));
410
})["catch"](finish);
411
} else {
412
return (0, _possibleConstructorReturn2["default"])(_this, _utils.throwError.call((0, _assertThisInitialized2["default"])(_this), 'No matching constructor overloading was found. ' + 'Please see the docs for how to call the Jimp constructor.', finish));
413
}
414
}
415
416
return _this;
417
}
418
/**
419
* Parse a bitmap with the loaded image types.
420
*
421
* @param {Buffer} data raw image data
422
* @param {string} path optional path to file
423
* @param {function(Error, Jimp)} finish (optional) a callback for when complete
424
* @memberof Jimp
425
*/
426
427
428
(0, _createClass2["default"])(Jimp, [{
429
key: "parseBitmap",
430
value: function parseBitmap(data, path, finish) {
431
_imageBitmap.parseBitmap.call(this, data, null, finish);
432
}
433
/**
434
* Sets the type of the image (RGB or RGBA) when saving in a format that supports transparency (default is RGBA)
435
* @param {boolean} bool A Boolean, true to use RGBA or false to use RGB
436
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
437
* @returns {Jimp} this for chaining of methods
438
*/
439
440
}, {
441
key: "rgba",
442
value: function rgba(bool, cb) {
443
if (typeof bool !== 'boolean') {
444
return _utils.throwError.call(this, 'bool must be a boolean, true for RGBA or false for RGB', cb);
445
}
446
447
this._rgba = bool;
448
449
if ((0, _utils.isNodePattern)(cb)) {
450
cb.call(this, null, this);
451
}
452
453
return this;
454
}
455
/**
456
* Emit for multiple listeners
457
* @param {string} methodName name of the method to emit an error for
458
* @param {string} eventName name of the eventName to emit an error for
459
* @param {object} data to emit
460
*/
461
462
}, {
463
key: "emitMulti",
464
value: function emitMulti(methodName, eventName) {
465
var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
466
data = Object.assign(data, {
467
methodName: methodName,
468
eventName: eventName
469
});
470
this.emit('any', data);
471
472
if (methodName) {
473
this.emit(methodName, data);
474
}
475
476
this.emit(eventName, data);
477
}
478
}, {
479
key: "emitError",
480
value: function emitError(methodName, err) {
481
this.emitMulti(methodName, 'error', err);
482
}
483
/**
484
* Get the current height of the image
485
* @return {number} height of the image
486
*/
487
488
}, {
489
key: "getHeight",
490
value: function getHeight() {
491
return this.bitmap.height;
492
}
493
/**
494
* Get the current width of the image
495
* @return {number} width of the image
496
*/
497
498
}, {
499
key: "getWidth",
500
value: function getWidth() {
501
return this.bitmap.width;
502
}
503
/**
504
* Nicely format Jimp object when sent to the console e.g. console.log(image)
505
* @returns {string} pretty printed
506
*/
507
508
}, {
509
key: "inspect",
510
value: function inspect() {
511
return '<Jimp ' + (this.bitmap === emptyBitmap ? 'pending...' : this.bitmap.width + 'x' + this.bitmap.height) + '>';
512
}
513
/**
514
* Nicely format Jimp object when converted to a string
515
* @returns {string} pretty printed
516
*/
517
518
}, {
519
key: "toString",
520
value: function toString() {
521
return '[object Jimp]';
522
}
523
/**
524
* Returns the original MIME of the image (default: "image/png")
525
* @returns {string} the MIME
526
*/
527
528
}, {
529
key: "getMIME",
530
value: function getMIME() {
531
var mime = this._originalMime || Jimp.MIME_PNG;
532
return mime;
533
}
534
/**
535
* Returns the appropriate file extension for the original MIME of the image (default: "png")
536
* @returns {string} the file extension
537
*/
538
539
}, {
540
key: "getExtension",
541
value: function getExtension() {
542
var mime = this.getMIME();
543
return MIME.getExtension(mime);
544
}
545
/**
546
* Writes the image to a file
547
* @param {string} path a path to the destination file
548
* @param {function(Error, Jimp)} cb (optional) a function to call when the image is saved to disk
549
* @returns {Jimp} this for chaining of methods
550
*/
551
552
}, {
553
key: "write",
554
value: function write(path, cb) {
555
var _this2 = this;
556
557
if (!_fs["default"] || !_fs["default"].createWriteStream) {
558
throw new Error('Cant access the filesystem. You can use the getBase64 method.');
559
}
560
561
if (typeof path !== 'string') {
562
return _utils.throwError.call(this, 'path must be a string', cb);
563
}
564
565
if (typeof cb === 'undefined') {
566
cb = noop;
567
}
568
569
if (typeof cb !== 'function') {
570
return _utils.throwError.call(this, 'cb must be a function', cb);
571
}
572
573
var mime = MIME.getType(path) || this.getMIME();
574
575
var pathObj = _path["default"].parse(path);
576
577
if (pathObj.dir) {
578
_mkdirp["default"].sync(pathObj.dir);
579
}
580
581
this.getBuffer(mime, function (err, buffer) {
582
if (err) {
583
return _utils.throwError.call(_this2, err, cb);
584
}
585
586
var stream = _fs["default"].createWriteStream(path);
587
588
stream.on('open', function () {
589
stream.write(buffer);
590
stream.end();
591
}).on('error', function (err) {
592
return _utils.throwError.call(_this2, err, cb);
593
});
594
stream.on('finish', function () {
595
cb.call(_this2, null, _this2);
596
});
597
});
598
return this;
599
}
600
}, {
601
key: "getBase64",
602
603
/**
604
* Converts the image to a base 64 string
605
* @param {string} mime the mime type of the image data to be created
606
* @param {function(Error, Jimp)} cb a Node-style function to call with the buffer as the second argument
607
* @returns {Jimp} this for chaining of methods
608
*/
609
value: function getBase64(mime, cb) {
610
if (mime === Jimp.AUTO) {
611
// allow auto MIME detection
612
mime = this.getMIME();
613
}
614
615
if (typeof mime !== 'string') {
616
return _utils.throwError.call(this, 'mime must be a string', cb);
617
}
618
619
if (typeof cb !== 'function') {
620
return _utils.throwError.call(this, 'cb must be a function', cb);
621
}
622
623
this.getBuffer(mime, function (err, data) {
624
if (err) {
625
return _utils.throwError.call(this, err, cb);
626
}
627
628
var src = 'data:' + mime + ';base64,' + data.toString('base64');
629
cb.call(this, null, src);
630
});
631
return this;
632
}
633
}, {
634
key: "hash",
635
636
/**
637
* Generates a perceptual hash of the image <https://en.wikipedia.org/wiki/Perceptual_hashing>. And pads the string. Can configure base.
638
* @param {number} base (optional) a number between 2 and 64 representing the base for the hash (e.g. 2 is binary, 10 is decimal, 16 is hex, 64 is base 64). Defaults to 64.
639
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
640
* @returns {string} a string representing the hash
641
*/
642
value: function hash(base, cb) {
643
base = base || 64;
644
645
if (typeof base === 'function') {
646
cb = base;
647
base = 64;
648
}
649
650
if (typeof base !== 'number') {
651
return _utils.throwError.call(this, 'base must be a number', cb);
652
}
653
654
if (base < 2 || base > 64) {
655
return _utils.throwError.call(this, 'base must be a number between 2 and 64', cb);
656
}
657
658
var hash = this.pHash();
659
hash = (0, _anyBase["default"])(_anyBase["default"].BIN, alphabet.slice(0, base))(hash);
660
661
while (hash.length < maxHashLength[base]) {
662
hash = '0' + hash; // pad out with leading zeros
663
}
664
665
if ((0, _utils.isNodePattern)(cb)) {
666
cb.call(this, null, hash);
667
}
668
669
return hash;
670
}
671
/**
672
* Calculates the perceptual hash
673
* @returns {number} the perceptual hash
674
*/
675
676
}, {
677
key: "pHash",
678
value: function pHash() {
679
var pHash = new _phash["default"]();
680
return pHash.getHash(this);
681
}
682
/**
683
* Calculates the hamming distance of the current image and a hash based on their perceptual hash
684
* @param {hash} compareHash hash to compare to
685
* @returns {number} a number ranging from 0 to 1, 0 means they are believed to be identical
686
*/
687
688
}, {
689
key: "distanceFromHash",
690
value: function distanceFromHash(compareHash) {
691
var pHash = new _phash["default"]();
692
var currentHash = pHash.getHash(this);
693
return pHash.distance(currentHash, compareHash);
694
}
695
/**
696
* Converts the image to a buffer
697
* @param {string} mime the mime type of the image buffer to be created
698
* @param {function(Error, Jimp)} cb a Node-style function to call with the buffer as the second argument
699
* @returns {Jimp} this for chaining of methods
700
*/
701
702
}, {
703
key: "getPixelIndex",
704
705
/**
706
* Returns the offset of a pixel in the bitmap buffer
707
* @param {number} x the x coordinate
708
* @param {number} y the y coordinate
709
* @param {string} edgeHandling (optional) define how to sum pixels from outside the border
710
* @param {number} cb (optional) a callback for when complete
711
* @returns {number} the index of the pixel or -1 if not found
712
*/
713
value: function getPixelIndex(x, y, edgeHandling, cb) {
714
var xi;
715
var yi;
716
717
if (typeof edgeHandling === 'function' && typeof cb === 'undefined') {
718
cb = edgeHandling;
719
edgeHandling = null;
720
}
721
722
if (!edgeHandling) {
723
edgeHandling = Jimp.EDGE_EXTEND;
724
}
725
726
if (typeof x !== 'number' || typeof y !== 'number') {
727
return _utils.throwError.call(this, 'x and y must be numbers', cb);
728
} // round input
729
730
731
x = Math.round(x);
732
y = Math.round(y);
733
xi = x;
734
yi = y;
735
736
if (edgeHandling === Jimp.EDGE_EXTEND) {
737
if (x < 0) xi = 0;
738
if (x >= this.bitmap.width) xi = this.bitmap.width - 1;
739
if (y < 0) yi = 0;
740
if (y >= this.bitmap.height) yi = this.bitmap.height - 1;
741
}
742
743
if (edgeHandling === Jimp.EDGE_WRAP) {
744
if (x < 0) {
745
xi = this.bitmap.width + x;
746
}
747
748
if (x >= this.bitmap.width) {
749
xi = x % this.bitmap.width;
750
}
751
752
if (y < 0) {
753
xi = this.bitmap.height + y;
754
}
755
756
if (y >= this.bitmap.height) {
757
yi = y % this.bitmap.height;
758
}
759
}
760
761
var i = this.bitmap.width * yi + xi << 2; // if out of bounds index is -1
762
763
if (xi < 0 || xi >= this.bitmap.width) {
764
i = -1;
765
}
766
767
if (yi < 0 || yi >= this.bitmap.height) {
768
i = -1;
769
}
770
771
if ((0, _utils.isNodePattern)(cb)) {
772
cb.call(this, null, i);
773
}
774
775
return i;
776
}
777
/**
778
* Returns the hex colour value of a pixel
779
* @param {number} x the x coordinate
780
* @param {number} y the y coordinate
781
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
782
* @returns {number} the color of the pixel
783
*/
784
785
}, {
786
key: "getPixelColor",
787
value: function getPixelColor(x, y, cb) {
788
if (typeof x !== 'number' || typeof y !== 'number') return _utils.throwError.call(this, 'x and y must be numbers', cb); // round input
789
790
x = Math.round(x);
791
y = Math.round(y);
792
var idx = this.getPixelIndex(x, y);
793
var hex = this.bitmap.data.readUInt32BE(idx);
794
795
if ((0, _utils.isNodePattern)(cb)) {
796
cb.call(this, null, hex);
797
}
798
799
return hex;
800
}
801
}, {
802
key: "setPixelColor",
803
804
/**
805
* Returns the hex colour value of a pixel
806
* @param {number} hex color to set
807
* @param {number} x the x coordinate
808
* @param {number} y the y coordinate
809
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
810
* @returns {number} the index of the pixel or -1 if not found
811
*/
812
value: function setPixelColor(hex, x, y, cb) {
813
if (typeof hex !== 'number' || typeof x !== 'number' || typeof y !== 'number') return _utils.throwError.call(this, 'hex, x and y must be numbers', cb); // round input
814
815
x = Math.round(x);
816
y = Math.round(y);
817
var idx = this.getPixelIndex(x, y);
818
this.bitmap.data.writeUInt32BE(hex, idx);
819
820
if ((0, _utils.isNodePattern)(cb)) {
821
cb.call(this, null, this);
822
}
823
824
return this;
825
}
826
}, {
827
key: "hasAlpha",
828
829
/**
830
* Determine if the image contains opaque pixels.
831
* @return {boolean} hasAlpha whether the image contains opaque pixels
832
*/
833
value: function hasAlpha() {
834
for (var yIndex = 0; yIndex < this.bitmap.height; yIndex++) {
835
for (var xIndex = 0; xIndex < this.bitmap.width; xIndex++) {
836
var idx = this.bitmap.width * yIndex + xIndex << 2;
837
var alpha = this.bitmap.data[idx + 3];
838
839
if (alpha !== 0xff) {
840
return true;
841
}
842
}
843
}
844
845
return false;
846
}
847
/**
848
* Iterate scan through a region of the bitmap
849
* @param {number} x the x coordinate to begin the scan at
850
* @param {number} y the y coordinate to begin the scan at
851
* @param w the width of the scan region
852
* @param h the height of the scan region
853
* @returns {IterableIterator<{x: number, y: number, idx: number, image: Jimp}>}
854
*/
855
856
}, {
857
key: "scanIterator",
858
value: function scanIterator(x, y, w, h) {
859
if (typeof x !== 'number' || typeof y !== 'number') {
860
return _utils.throwError.call(this, 'x and y must be numbers');
861
}
862
863
if (typeof w !== 'number' || typeof h !== 'number') {
864
return _utils.throwError.call(this, 'w and h must be numbers');
865
}
866
867
return (0, _utils.scanIterator)(this, x, y, w, h);
868
}
869
}]);
870
return Jimp;
871
}(_events["default"]);
872
873
function addConstants(constants) {
874
var jimpInstance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Jimp;
875
Object.entries(constants).forEach(function (_ref) {
876
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
877
name = _ref2[0],
878
value = _ref2[1];
879
880
jimpInstance[name] = value;
881
});
882
}
883
884
function addJimpMethods(methods) {
885
var jimpInstance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Jimp;
886
Object.entries(methods).forEach(function (_ref3) {
887
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
888
name = _ref4[0],
889
value = _ref4[1];
890
891
jimpInstance.prototype[name] = value;
892
});
893
}
894
895
addConstants(constants);
896
addJimpMethods({
897
composite: _composite["default"]
898
});
899
Jimp.__extraConstructors = [];
900
/**
901
* Allow client libs to add new ways to build a Jimp object.
902
* @param {string} name identify the extra constructor.
903
* @param {function} test a function that returns true when it accepts the arguments passed to the main constructor.
904
* @param {function} run where the magic happens.
905
*/
906
907
Jimp.appendConstructorOption = function (name, test, run) {
908
Jimp.__extraConstructors.push({
909
name: name,
910
test: test,
911
run: run
912
});
913
};
914
/**
915
* Read an image from a file or a Buffer. Takes the same args as the constructor
916
* @returns {Promise} a promise
917
*/
918
919
920
Jimp.read = function () {
921
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
922
args[_key3] = arguments[_key3];
923
}
924
925
return new Promise(function (resolve, reject) {
926
(0, _construct2["default"])(Jimp, args.concat([function (err, image) {
927
if (err) reject(err);else resolve(image);
928
}]));
929
});
930
};
931
932
Jimp.create = Jimp.read;
933
/**
934
* A static helper method that converts RGBA values to a single integer value
935
* @param {number} r the red value (0-255)
936
* @param {number} g the green value (0-255)
937
* @param {number} b the blue value (0-255)
938
* @param {number} a the alpha value (0-255)
939
* @param {function(Error, Jimp)} cb (optional) A callback for when complete
940
* @returns {number} an single integer colour value
941
*/
942
943
Jimp.rgbaToInt = function (r, g, b, a, cb) {
944
if (typeof r !== 'number' || typeof g !== 'number' || typeof b !== 'number' || typeof a !== 'number') {
945
return _utils.throwError.call(this, 'r, g, b and a must be numbers', cb);
946
}
947
948
if (r < 0 || r > 255) {
949
return _utils.throwError.call(this, 'r must be between 0 and 255', cb);
950
}
951
952
if (g < 0 || g > 255) {
953
_utils.throwError.call(this, 'g must be between 0 and 255', cb);
954
}
955
956
if (b < 0 || b > 255) {
957
return _utils.throwError.call(this, 'b must be between 0 and 255', cb);
958
}
959
960
if (a < 0 || a > 255) {
961
return _utils.throwError.call(this, 'a must be between 0 and 255', cb);
962
}
963
964
r = Math.round(r);
965
b = Math.round(b);
966
g = Math.round(g);
967
a = Math.round(a);
968
var i = r * Math.pow(256, 3) + g * Math.pow(256, 2) + b * Math.pow(256, 1) + a * Math.pow(256, 0);
969
970
if ((0, _utils.isNodePattern)(cb)) {
971
cb.call(this, null, i);
972
}
973
974
return i;
975
};
976
/**
977
* A static helper method that converts RGBA values to a single integer value
978
* @param {number} i a single integer value representing an RGBA colour (e.g. 0xFF0000FF for red)
979
* @param {function(Error, Jimp)} cb (optional) A callback for when complete
980
* @returns {object} an object with the properties r, g, b and a representing RGBA values
981
*/
982
983
984
Jimp.intToRGBA = function (i, cb) {
985
if (typeof i !== 'number') {
986
return _utils.throwError.call(this, 'i must be a number', cb);
987
}
988
989
var rgba = {};
990
rgba.r = Math.floor(i / Math.pow(256, 3));
991
rgba.g = Math.floor((i - rgba.r * Math.pow(256, 3)) / Math.pow(256, 2));
992
rgba.b = Math.floor((i - rgba.r * Math.pow(256, 3) - rgba.g * Math.pow(256, 2)) / Math.pow(256, 1));
993
rgba.a = Math.floor((i - rgba.r * Math.pow(256, 3) - rgba.g * Math.pow(256, 2) - rgba.b * Math.pow(256, 1)) / Math.pow(256, 0));
994
995
if ((0, _utils.isNodePattern)(cb)) {
996
cb.call(this, null, rgba);
997
}
998
999
return rgba;
1000
};
1001
/**
1002
* Converts a css color (Hex, 8-digit (RGBA) Hex, RGB, RGBA, HSL, HSLA, HSV, HSVA, Named) to a hex number
1003
* @param {string} cssColor a number
1004
* @returns {number} a hex number representing a color
1005
*/
1006
1007
1008
Jimp.cssColorToHex = function (cssColor) {
1009
cssColor = cssColor || 0; // 0, null, undefined, NaN
1010
1011
if (typeof cssColor === 'number') return Number(cssColor);
1012
return parseInt((0, _tinycolor["default"])(cssColor).toHex8(), 16);
1013
};
1014
/**
1015
* Limits a number to between 0 or 255
1016
* @param {number} n a number
1017
* @returns {number} the number limited to between 0 or 255
1018
*/
1019
1020
1021
Jimp.limit255 = function (n) {
1022
n = Math.max(n, 0);
1023
n = Math.min(n, 255);
1024
return n;
1025
};
1026
/**
1027
* Diffs two images and returns
1028
* @param {Jimp} img1 a Jimp image to compare
1029
* @param {Jimp} img2 a Jimp image to compare
1030
* @param {number} threshold (optional) a number, 0 to 1, the smaller the value the more sensitive the comparison (default: 0.1)
1031
* @returns {object} an object { percent: percent similar, diff: a Jimp image highlighting differences }
1032
*/
1033
1034
1035
Jimp.diff = function (img1, img2) {
1036
var threshold = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.1;
1037
if (!(img1 instanceof Jimp) || !(img2 instanceof Jimp)) return _utils.throwError.call(this, 'img1 and img2 must be an Jimp images');
1038
var bmp1 = img1.bitmap;
1039
var bmp2 = img2.bitmap;
1040
1041
if (bmp1.width !== bmp2.width || bmp1.height !== bmp2.height) {
1042
if (bmp1.width * bmp1.height > bmp2.width * bmp2.height) {
1043
// img1 is bigger
1044
img1 = img1.cloneQuiet().resize(bmp2.width, bmp2.height);
1045
} else {
1046
// img2 is bigger (or they are the same in area)
1047
img2 = img2.cloneQuiet().resize(bmp1.width, bmp1.height);
1048
}
1049
}
1050
1051
if (typeof threshold !== 'number' || threshold < 0 || threshold > 1) {
1052
return _utils.throwError.call(this, 'threshold must be a number between 0 and 1');
1053
}
1054
1055
var diff = new Jimp(bmp1.width, bmp1.height, 0xffffffff);
1056
var numDiffPixels = (0, _pixelmatch["default"])(bmp1.data, bmp2.data, diff.bitmap.data, diff.bitmap.width, diff.bitmap.height, {
1057
threshold: threshold
1058
});
1059
return {
1060
percent: numDiffPixels / (diff.bitmap.width * diff.bitmap.height),
1061
image: diff
1062
};
1063
};
1064
/**
1065
* Calculates the hamming distance of two images based on their perceptual hash
1066
* @param {Jimp} img1 a Jimp image to compare
1067
* @param {Jimp} img2 a Jimp image to compare
1068
* @returns {number} a number ranging from 0 to 1, 0 means they are believed to be identical
1069
*/
1070
1071
1072
Jimp.distance = function (img1, img2) {
1073
var phash = new _phash["default"]();
1074
var hash1 = phash.getHash(img1);
1075
var hash2 = phash.getHash(img2);
1076
return phash.distance(hash1, hash2);
1077
};
1078
/**
1079
* Calculates the hamming distance of two images based on their perceptual hash
1080
* @param {hash} hash1 a pHash
1081
* @param {hash} hash2 a pHash
1082
* @returns {number} a number ranging from 0 to 1, 0 means they are believed to be identical
1083
*/
1084
1085
1086
Jimp.compareHashes = function (hash1, hash2) {
1087
var phash = new _phash["default"]();
1088
return phash.distance(hash1, hash2);
1089
};
1090
/**
1091
* Compute color difference
1092
* 0 means no difference, 1 means maximum difference.
1093
* @param {number} rgba1: first color to compare.
1094
* @param {number} rgba2: second color to compare.
1095
* Both parameters must be an color object {r:val, g:val, b:val, a:val}
1096
* Where `a` is optional and `val` is an integer between 0 and 255.
1097
* @returns {number} float between 0 and 1.
1098
*/
1099
1100
1101
Jimp.colorDiff = function (rgba1, rgba2) {
1102
var pow = function pow(n) {
1103
return Math.pow(n, 2);
1104
};
1105
1106
var max = Math.max;
1107
var maxVal = 255 * 255 * 3;
1108
1109
if (rgba1.a !== 0 && !rgba1.a) {
1110
rgba1.a = 255;
1111
}
1112
1113
if (rgba2.a !== 0 && !rgba2.a) {
1114
rgba2.a = 255;
1115
}
1116
1117
return (max(pow(rgba1.r - rgba2.r), pow(rgba1.r - rgba2.r - rgba1.a + rgba2.a)) + max(pow(rgba1.g - rgba2.g), pow(rgba1.g - rgba2.g - rgba1.a + rgba2.a)) + max(pow(rgba1.b - rgba2.b), pow(rgba1.b - rgba2.b - rgba1.a + rgba2.a))) / maxVal;
1118
};
1119
/**
1120
* Helper to create Jimp methods that emit events before and after its execution.
1121
* @param {string} methodName The name to be appended to Jimp prototype.
1122
* @param {string} evName The event name to be called.
1123
* It will be prefixed by `before-` and emitted when on method call.
1124
* It will be appended by `ed` and emitted after the method run.
1125
* @param {function} method A function implementing the method itself.
1126
* It will also create a quiet version that will not emit events, to not
1127
* mess the user code with many `changed` event calls. You can call with
1128
* `methodName + "Quiet"`.
1129
*
1130
* The emitted event comes with a object parameter to the listener with the
1131
* `methodName` as one attribute.
1132
*/
1133
1134
1135
function jimpEvMethod(methodName, evName, method) {
1136
var evNameBefore = 'before-' + evName;
1137
var evNameAfter = evName.replace(/e$/, '') + 'ed';
1138
1139
Jimp.prototype[methodName] = function () {
1140
var wrappedCb;
1141
1142
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
1143
args[_key4] = arguments[_key4];
1144
}
1145
1146
var cb = args[method.length - 1];
1147
var jimpInstance = this;
1148
1149
if (typeof cb === 'function') {
1150
wrappedCb = function wrappedCb() {
1151
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
1152
args[_key5] = arguments[_key5];
1153
}
1154
1155
var err = args[0],
1156
data = args[1];
1157
1158
if (err) {
1159
jimpInstance.emitError(methodName, err);
1160
} else {
1161
jimpInstance.emitMulti(methodName, evNameAfter, (0, _defineProperty2["default"])({}, methodName, data));
1162
}
1163
1164
cb.apply(this, args);
1165
};
1166
1167
args[args.length - 1] = wrappedCb;
1168
} else {
1169
wrappedCb = false;
1170
}
1171
1172
this.emitMulti(methodName, evNameBefore);
1173
var result;
1174
1175
try {
1176
result = method.apply(this, args);
1177
1178
if (!wrappedCb) {
1179
this.emitMulti(methodName, evNameAfter, (0, _defineProperty2["default"])({}, methodName, result));
1180
}
1181
} catch (error) {
1182
error.methodName = methodName;
1183
this.emitError(methodName, error);
1184
}
1185
1186
return result;
1187
};
1188
1189
Jimp.prototype[methodName + 'Quiet'] = method;
1190
}
1191
/**
1192
* Creates a new image that is a clone of this one.
1193
* @param {function(Error, Jimp)} cb (optional) A callback for when complete
1194
* @returns the new image
1195
*/
1196
1197
1198
jimpEvMethod('clone', 'clone', function (cb) {
1199
var clone = new Jimp(this);
1200
1201
if ((0, _utils.isNodePattern)(cb)) {
1202
cb.call(clone, null, clone);
1203
}
1204
1205
return clone;
1206
});
1207
/**
1208
* Simplify jimpEvMethod call for the common `change` evName.
1209
* @param {string} methodName name of the method
1210
* @param {function} method to watch changes for
1211
*/
1212
1213
function jimpEvChange(methodName, method) {
1214
jimpEvMethod(methodName, 'change', method);
1215
}
1216
/**
1217
* Sets the type of the image (RGB or RGBA) when saving as PNG format (default is RGBA)
1218
* @param b A Boolean, true to use RGBA or false to use RGB
1219
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
1220
* @returns {Jimp} this for chaining of methods
1221
*/
1222
1223
1224
jimpEvChange('background', function (hex, cb) {
1225
if (typeof hex !== 'number') {
1226
return _utils.throwError.call(this, 'hex must be a hexadecimal rgba value', cb);
1227
}
1228
1229
this._background = hex;
1230
1231
if ((0, _utils.isNodePattern)(cb)) {
1232
cb.call(this, null, this);
1233
}
1234
1235
return this;
1236
});
1237
/**
1238
* Scans through a region of the bitmap, calling a function for each pixel.
1239
* @param {number} x the x coordinate to begin the scan at
1240
* @param {number} y the y coordinate to begin the scan at
1241
* @param w the width of the scan region
1242
* @param h the height of the scan region
1243
* @param f a function to call on even pixel; the (x, y) position of the pixel
1244
* and the index of the pixel in the bitmap buffer are passed to the function
1245
* @param {function(Error, Jimp)} cb (optional) a callback for when complete
1246
* @returns {Jimp} this for chaining of methods
1247
*/
1248
1249
jimpEvChange('scan', function (x, y, w, h, f, cb) {
1250
if (typeof x !== 'number' || typeof y !== 'number') {
1251
return _utils.throwError.call(this, 'x and y must be numbers', cb);
1252
}
1253
1254
if (typeof w !== 'number' || typeof h !== 'number') {
1255
return _utils.throwError.call(this, 'w and h must be numbers', cb);
1256
}
1257
1258
if (typeof f !== 'function') {
1259
return _utils.throwError.call(this, 'f must be a function', cb);
1260
}
1261
1262
var result = (0, _utils.scan)(this, x, y, w, h, f);
1263
1264
if ((0, _utils.isNodePattern)(cb)) {
1265
cb.call(this, null, result);
1266
}
1267
1268
return result;
1269
});
1270
1271
if (process.env.ENVIRONMENT === 'BROWSER') {
1272
// For use in a web browser or web worker
1273
1274
/* global self */
1275
var gl;
1276
1277
if (typeof window !== 'undefined' && (typeof window === "undefined" ? "undefined" : (0, _typeof2["default"])(window)) === 'object') {
1278
gl = window;
1279
}
1280
1281
if (typeof self !== 'undefined' && (typeof self === "undefined" ? "undefined" : (0, _typeof2["default"])(self)) === 'object') {
1282
gl = self;
1283
}
1284
1285
gl.Jimp = Jimp;
1286
gl.Buffer = Buffer;
1287
}
1288
1289
var _default = Jimp;
1290
exports["default"] = _default;
1291
//# sourceMappingURL=index.js.map
1292