UNPKG

29.8 kBMarkdownView Raw
1<div align="center">
2 <img width="200" height="200"
3 src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-11/256/crayon.png">
4 <h1>Jimp</h1>
5 <p>JavaScript Image Manipulation Program</p>
6</div>
7
8The "JavaScript Image Manipulation Program" :-)
9
10An image processing library for Node written entirely in JavaScript, with zero native dependencies.
11
12The default jimp configuration.
13
14Supported types:
15
16- `@jimp/jpeg`
17- `@jimp/png`
18- `@jimp/bmp`
19- `@jimp/tiff`
20- `@jimp/gif`
21
22## Installation
23
24`npm install --save jimp`
25
26Example usage (Promise will never resolve if callback is passed):
27
28```js
29var Jimp = require('jimp');
30
31// open a file called "lenna.png"
32Jimp.read('lenna.png', (err, lenna) => {
33 if (err) throw err;
34 lenna
35 .resize(256, 256) // resize
36 .quality(60) // set JPEG quality
37 .greyscale() // set greyscale
38 .write('lena-small-bw.jpg'); // save
39});
40```
41
42Using promises:
43
44```js
45Jimp.read('lenna.png')
46 .then(lenna => {
47 return lenna
48 .resize(256, 256) // resize
49 .quality(60) // set JPEG quality
50 .greyscale() // set greyscale
51 .write('lena-small-bw.jpg'); // save
52 })
53 .catch(err => {
54 console.error(err);
55 });
56```
57
58## TypeScript Usage
59
60If you're using this library with TypeScript the method of importing slightly differs from JavaScript. You can import the library with three methods
61
62First of all using [`import = require()`](https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require) method to import it as a `commonJS` module:
63
64```ts
65import Jimp = require('jimp');
66```
67
68Alternatively you can import it with ES6 default import scheme, if you set the `esModuleInterop` compiler flag to `true` in your `tsconfig`
69
70```ts
71import Jimp from 'jimp';
72```
73
74Lastly you can import it with a synthetic default import. This requires setting the `allowSyntheticDefaultImports` compiler option to `true` in your `tsconfig`
75
76```ts
77import * as Jimp from 'jimp';
78```
79
80**Note 1**: `esModuleInterop` implicitly sets `allowSyntheticDefaultImports` to `true`
81
82**Note 2**: `allowSyntheticDefaultImports` nor `esModuleInterop` change the runtime behavior of your code at all. They are just flags that tells TypeScript you need the compatibility they offer.
83
84## Module Build
85
86If you're using a web bundles (webpack, rollup, parcel) you can benefit from using the `module` build of jimp. Using the module build will allow your bundler to understand your code better and exclude things you aren't using.
87
88```js
89import Jimp from 'jimp/es';
90```
91
92### WebPack
93
94If you're using webpack you can set `process.browser` to true and your build of jimp will exclude certain parts, making it load faster.
95
96```js
97{
98 plugins: [
99 new webpack.DefinePlugin({
100 'process.browser': 'true'
101 }),
102 ...
103 ],
104}
105```
106
107## Basic usage
108
109The static `Jimp.read` method takes the path to a file, URL, dimensions, a Jimp instance or a buffer and returns a Promise:
110
111```js
112Jimp.read('./path/to/image.jpg')
113 .then(image => {
114 // Do stuff with the image.
115 })
116 .catch(err => {
117 // Handle an exception.
118 });
119
120Jimp.read('http://www.example.com/path/to/lenna.jpg')
121 .then(image => {
122 // Do stuff with the image.
123 })
124 .catch(err => {
125 // Handle an exception.
126 });
127
128Jimp.read(jimpInstance)
129 .then(image => {
130 // Do stuff with the image.
131 })
132 .catch(err => {
133 // Handle an exception.
134 });
135
136Jimp.read(buffer)
137 .then(image => {
138 // Do stuff with the image.
139 })
140 .catch(err => {
141 // Handle an exception.
142 });
143```
144
145In some cases, you need to pass additional parameters with an image's URL. You can pass an object to the `Jimp.read` method:
146
147```js
148Jimp.read({
149 url: 'http://www.example.com/path/to/lenna.jpg', // Required!
150 headers: {},
151 ...
152})
153 .then(image => {
154 // Do stuff with the image.
155 })
156 .catch(err => {
157 // Handle an exception.
158 });
159```
160
161Jimp uses [phin](https://github.com/ethanent/phin) as it's HTTP client. Phin uses [`http.request(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_http_request_options_callback) or [`https.request(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_request_options_callback) methods for making HTTP requests. Phin parses a `url` with the `url.parse(...)` method and passes it with all the other parameters as an `options` to the [`http.request(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_http_request_options_callback) or [`https.request(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_request_options_callback) methods.
162
163Briefly speaking, you can pass any options from [`http.request(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_http_request_options_callback), [`https.request(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_request_options_callback) or even [`tls.connect(options[, callback])`](https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_connect_options_callback).
164
165Phin parses a `url` and combines it with any options you want. This behavior can be very useful when you need to pass some additional `headers`. Also, you can pass `rejectUnauthorized: false` if you don't require an SSL certificate to be valid (it helps to prevent `unable to verify the first certificate` error).
166
167The convenience method `Jimp.create` also exists. It is just a wrapper around `Jimp.read`.
168
169### Custom Constructor
170
171You might want to initialize jimp in so custom way. To do this Jimp exposes the static function `appendConstructorOption`. The appended constructor options run after all the defaults.
172
173To define a custom constructor provide a name for it, a function to call to determine if the arguments provided to jimp match your constructor, and a function called where you can construct the image however you want.
174
175```js
176Jimp.appendConstructorOption(
177 'Name of Option',
178 args => arg.hasSomeCustomThing,
179 function(resolve, reject, args) {
180 this.bitmap = customParser(args);
181 resolve();
182 }
183);
184```
185
186If you don't want to handle parsing the bitmap. For example if you want to do some sort of authentication for URL request. Jimp exposes `parseBitmap` so you can fall back to jimp to do the heavy lifting.
187
188Parse bitmap takes the raw image data in a Buffer, a path (optional), and a node style callback.
189
190```js
191Jimp.appendConstructorOption('Custom Url', options => options.url, function(
192 resolve,
193 reject,
194 options
195) {
196 phin(options, (err, res) => {
197 if (err) {
198 return reject(err);
199 }
200
201 this.parseBitmap(res.body, options.url, err => {
202 if (err) {
203 return reject(err);
204 }
205
206 resolve();
207 });
208 });
209});
210```
211
212### Methods
213
214Once the promise is fulfilled, the following methods can be called on the image:
215
216```js
217/* Resize */
218image.contain( w, h[, alignBits || mode, mode] ); // scale the image to the given width and height, some parts of the image may be letter boxed
219image.cover( w, h[, alignBits || mode, mode] ); // scale the image to the given width and height, some parts of the image may be clipped
220image.resize( w, h[, mode] ); // resize the image. Jimp.AUTO can be passed as one of the values.
221image.scale( f[, mode] ); // scale the image by the factor f
222image.scaleToFit( w, h[, mode] ); // scale the image to the largest size that fits inside the given width and height
223
224// An optional resize mode can be passed with all resize methods.
225
226/* Crop */
227image.autocrop([tolerance, frames]); // automatically crop same-color borders from image (if any), frames must be a Boolean
228image.autocrop(options); // automatically crop same-color borders from image (if any), options may contain tolerance, cropOnlyFrames, cropSymmetric, leaveBorder
229image.crop( x, y, w, h ); // crop to the given region
230
231/* Composing */
232image.blit( src, x, y, [srcx, srcy, srcw, srch] );
233 // blit the image with another Jimp image at x, y, optionally cropped.
234image.composite( src, x, y, [{ mode, opacitySource, opacityDest }] ); // composites another Jimp image over this image at x, y
235image.mask( src, x, y ); // masks the image with another Jimp image at x, y using average pixel value
236image.convolute( kernel ); // applies a convolution kernel matrix to the image or a region
237
238/* Flip and rotate */
239image.flip( horz, vert ); // flip the image horizontally or vertically
240image.mirror( horz, vert ); // an alias for flip
241image.rotate( deg[, mode] ); // rotate the image clockwise by a number of degrees. Optionally, a resize mode can be passed. If `false` is passed as the second parameter, the image width and height will not be resized.
242
243/* Colour */
244image.brightness( val ); // adjust the brighness by a value -1 to +1
245image.contrast( val ); // adjust the contrast by a value -1 to +1
246image.dither565(); // ordered dithering of the image and reduce color space to 16-bits (RGB565)
247image.greyscale(); // remove colour from the image
248image.invert(); // invert the image colours
249image.normalize(); // normalize the channels in an image
250
251/* Alpha channel */
252image.hasAlpha(); // determines if an image contains opaque pixels
253image.fade( f ); // an alternative to opacity, fades the image by a factor 0 - 1. 0 will haven no effect. 1 will turn the image
254image.opacity( f ); // multiply the alpha channel by each pixel by the factor f, 0 - 1
255image.opaque(); // set the alpha channel on every pixel to fully opaque
256image.background( hex ); // set the default new pixel colour (e.g. 0xFFFFFFFF or 0x00000000) for by some operations (e.g. image.contain and
257
258/* Blurs */
259image.gaussian( r ); // Gaussian blur the image by r pixels (VERY slow)
260image.blur( r ); // fast blur the image by r pixels
261
262/* Effects */
263image.posterize( n ); // apply a posterization effect with n level
264image.sepia(); // apply a sepia wash to the image
265image.pixelate( size[, x, y, w, h ]); // apply a pixelation effect to the image or a region
266
267/* 3D */
268image.displace( map, offset ); // displaces the image pixels based on the provided displacement map. Useful for making stereoscopic 3D images.
269```
270
271Some of these methods are irreversible, so it can be useful to perform them on a clone of the original image:
272
273```js
274image.clone(); // returns a clone of the image
275```
276
277(Contributions of more methods are welcome!)
278
279### Resize modes
280
281The default resizing algorithm uses a bilinear method as follows:
282
283```js
284image.resize(250, 250); // resize the image to 250 x 250
285image.resize(Jimp.AUTO, 250); // resize the height to 250 and scale the width accordingly
286image.resize(250, Jimp.AUTO); // resize the width to 250 and scale the height accordingly
287```
288
289Optionally, the following constants can be passed to choose a particular resizing algorithm:
290
291```js
292Jimp.RESIZE_NEAREST_NEIGHBOR;
293Jimp.RESIZE_BILINEAR;
294Jimp.RESIZE_BICUBIC;
295Jimp.RESIZE_HERMITE;
296Jimp.RESIZE_BEZIER;
297```
298
299For example:
300
301```js
302image.resize(250, 250, Jimp.RESIZE_BEZIER);
303```
304
305### Align modes
306
307The following constants can be passed to the `image.cover`, `image.contain` and `image.print` methods:
308
309```js
310Jimp.HORIZONTAL_ALIGN_LEFT;
311Jimp.HORIZONTAL_ALIGN_CENTER;
312Jimp.HORIZONTAL_ALIGN_RIGHT;
313
314Jimp.VERTICAL_ALIGN_TOP;
315Jimp.VERTICAL_ALIGN_MIDDLE;
316Jimp.VERTICAL_ALIGN_BOTTOM;
317```
318
319Where the align mode changes the position of the associated axis as described in the table below.
320
321| Align Mode | Axis Point |
322| ------------------------------ | ----------------------------------------------- |
323| `Jimp.HORIZONTAL_ALIGN_LEFT` | Positions the x-axis at the left of the image |
324| `Jimp.HORIZONTAL_ALIGN_CENTER` | Positions the x-axis at the center of the image |
325| `Jimp.HORIZONTAL_ALIGN_RIGHT` | Positions the x-axis at the right of the image |
326| `Jimp.VERTICAL_ALIGN_TOP` | Positions the y-axis at the top of the image |
327| `Jimp.VERTICAL_ALIGN_MIDDLE` | Positions the y-axis at the center of the image |
328| `Jimp.VERTICAL_ALIGN_BOTTOM` | Positions the y-axis at the bottom of the image |
329
330For example:
331
332```js
333image.contain(250, 250, Jimp.HORIZONTAL_ALIGN_LEFT | Jimp.VERTICAL_ALIGN_TOP);
334```
335
336Default align modes for `image.cover` and `image.contain` are:
337
338```js
339Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE;
340```
341
342Default align modes for `image.print` are:
343
344```js
345{
346 alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT,
347 alignmentY: Jimp.VERTICAL_ALIGN_TOP
348}
349```
350
351### Compositing and blend modes
352
353The following modes can be used for compositing two images together. mode defaults to Jimp.BLEND_SOURCE_OVER.
354
355```js
356Jimp.BLEND_SOURCE_OVER;
357Jimp.BLEND_DESTINATION_OVER;
358Jimp.BLEND_MULTIPLY;
359Jimp.BLEND_SCREEN;
360Jimp.BLEND_OVERLAY;
361Jimp.BLEND_DARKEN;
362Jimp.BLEND_LIGHTEN;
363Jimp.BLEND_HARDLIGHT;
364Jimp.BLEND_DIFFERENCE;
365Jimp.BLEND_EXCLUSION;
366```
367
368```js
369image.composite(srcImage, 100, 0, {
370 mode: Jimp.BLEND_MULTIPLY,
371 opacitySource: 0.5,
372 opacityDest: 0.9
373});
374```
375
376### Writing text
377
378Jimp supports basic typography using BMFont format (.fnt) even ones in different languages! Just find a bitmap font that is suitable [bitmap fonts](https://en.wikipedia.org/wiki/Bitmap_fonts):
379
380```js
381Jimp.loadFont(pathOrURL).then(font => {
382 // load font from .fnt file
383 image.print(font, x, y, message); // print a message on an image. message can be a any type
384 image.print(font, x, y, message, maxWidth); // print a message on an image with text wrapped at maxWidth
385});
386```
387
388Alignment modes are supported by replacing the `str` argument with an object containing `text`, `alignmentX` and `alignmentY`. `alignmentX` defaults to `Jimp.HORIZONTAL_ALIGN_LEFT` and `alignmentY` defaults to `Jimp.VERTICAL_ALIGN_TOP`.
389
390```js
391Jimp.loadFont(pathOrURL).then(font => {
392 image.print(
393 font,
394 x,
395 y,
396 {
397 text: 'Hello world!',
398 alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
399 alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
400 },
401 maxWidth,
402 maxHeight
403 ); // prints 'Hello world!' on an image, middle and center-aligned, when x = 0 and y = 0
404});
405```
406
407```js
408Jimp.loadFont(path, cb); // using a callback pattern
409```
410
411BMFont fonts are raster based and fixed in size and colour. Jimp comes with a set of fonts that can be used on images:
412
413```js
414Jimp.FONT_SANS_8_BLACK; // Open Sans, 8px, black
415Jimp.FONT_SANS_10_BLACK; // Open Sans, 10px, black
416Jimp.FONT_SANS_12_BLACK; // Open Sans, 12px, black
417Jimp.FONT_SANS_14_BLACK; // Open Sans, 14px, black
418Jimp.FONT_SANS_16_BLACK; // Open Sans, 16px, black
419Jimp.FONT_SANS_32_BLACK; // Open Sans, 32px, black
420Jimp.FONT_SANS_64_BLACK; // Open Sans, 64px, black
421Jimp.FONT_SANS_128_BLACK; // Open Sans, 128px, black
422
423Jimp.FONT_SANS_8_WHITE; // Open Sans, 8px, white
424Jimp.FONT_SANS_16_WHITE; // Open Sans, 16px, white
425Jimp.FONT_SANS_32_WHITE; // Open Sans, 32px, white
426Jimp.FONT_SANS_64_WHITE; // Open Sans, 64px, white
427Jimp.FONT_SANS_128_WHITE; // Open Sans, 128px, white
428```
429
430These can be used as follows:
431
432```js
433Jimp.loadFont(Jimp.FONT_SANS_32_BLACK).then(font => {
434 image.print(font, 10, 10, 'Hello world!');
435});
436```
437
438#### Measuring text
439
440If you need to do calculations on where to place your text jimp provides two methods that measure how wide and how tall a piece of text will be. You can use these methods to lay out multiple pieces of text in relation to each other
441
442```js
443Jimp.measureText(Jimp.FONT_SANS_32_BLACK, 'Some string'); // width of text
444Jimp.measureTextHeight(Jimp.FONT_SANS_32_BLACK, 'Some string', 100); // height of text
445```
446
447#### Staggering Text
448
449If you need to stagger text position along the x or y-axis the print method also returns the final coordinates as an argument to the callback.
450
451```js
452Jimp.loadFont(Jimp.FONT_SANS_32_BLACK).then(font => {
453 image.print(
454 font,
455 10,
456 10,
457 'Hello world that wraps!',
458 50,
459 (err, image, { x, y }) => {
460 image.print(font, x, y + 20, 'More text on another line', 50);
461 }
462 );
463});
464```
465
466Online tools are also available to convert TTF fonts to BMFont format. They can be used to create color font or sprite packs.
467
468:star: [Littera](http://kvazars.com/littera/)
469
470:star: [Hiero](https://github.com/libgdx/libgdx/wiki/Hiero)
471
472## Writing to files and buffers
473
474### Writing to files
475
476The image can be written to disk in PNG, JPEG or BMP format (based on the save path extension or if no extension is provided the original image's MIME type which, if not available, defaults to PNG) using:
477
478```js
479image.write(path, cb); // Node-style callback will be fired when write is successful
480image.writeAsync(path); // Returns Promise
481```
482
483The original extension for an image (or "png") can accessed as using `image.getExtension()`. The following will save an image using its original format:
484
485```js
486var file = 'new_name.' + image.getExtension();
487//or
488var file = 'new_name'; // with no extension
489image.write(file);
490```
491
492### Writing to Buffers
493
494A PNG, JPEG or BMP binary Buffer of an image (e.g. for storage in a database) can be generated using:
495
496```js
497image.getBuffer(mime, cb); // Node-style callback will be fired with result
498image.getBufferAsync(mime); // Returns Promise
499```
500
501For convenience, supported MIME types are available as static properties:
502
503```js
504Jimp.MIME_PNG; // "image/png"
505Jimp.MIME_JPEG; // "image/jpeg"
506Jimp.MIME_BMP; // "image/bmp"
507```
508
509If `Jimp.AUTO` is passed as the MIME type then the original MIME type for the image (or "image/png") will be used. Alternatively, `image.getMIME()` will return the original MIME type of the image (or "image/png").
510
511### Data URI
512
513A Base64 data URI can be generated in the same way as a Buffer, using:
514
515```js
516image.getBase64(mime, cb); // Node-style callback will be fired with result
517image.getBase64Async(mime); // Returns Promise
518```
519
520### PNG and JPEG quality
521
522The quality of JPEGs can be set with:
523
524```js
525image.quality(n); // set the quality of saved JPEG, 0 - 100
526```
527
528The format of PNGs can be set with:
529
530```js
531image.rgba(bool); // set whether PNGs are saved as RGBA (true, default) or RGB (false)
532image.filterType(number); // set the filter type for the saved PNG
533image.deflateLevel(number); // set the deflate level for the saved PNG
534Jimp.deflateStrategy(number); // set the deflate for the saved PNG (0-3)
535```
536
537For convenience, supported filter types are available as static properties:
538
539```js
540Jimp.PNG_FILTER_AUTO; // -1
541Jimp.PNG_FILTER_NONE; // 0
542Jimp.PNG_FILTER_SUB; // 1
543Jimp.PNG_FILTER_UP; // 2
544Jimp.PNG_FILTER_AVERAGE; // 3
545Jimp.PNG_FILTER_PATH; // 4
546```
547
548## Advanced usage
549
550### Colour manipulation
551
552Jimp supports advanced colour manipulation using a single method as follows:
553
554```js
555image.color([
556 { apply: 'hue', params: [-90] },
557 { apply: 'lighten', params: [50] },
558 { apply: 'xor', params: ['#06D'] }
559]);
560```
561
562The method supports the following modifiers:
563
564| Modifier | Description |
565| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
566| **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)) |
567| **brighten** {amount} | Brighten the color a given amount, from 0 to 100 (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
568| **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)) |
569| **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)) |
570| **saturate** {amount} | Saturate the color a given amount, from 0 to 100 (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
571| **greyscale** {amount} | Completely desaturates a color into greyscale (works through [TinyColor](https://github.com/bgrins/TinyColor)) |
572| **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)) |
573| **hue** {degree} | Alias for **spin** |
574| **mix** {color, amount} | Mixes colors by their RGB component values. Amount is opacity of overlaying color |
575| **tint** {amount} | Same as applying **mix** with white color |
576| **shade** {amount} | Same as applying **mix** with black color |
577| **xor** {color} | Treats the two colors as bitfields and applies an XOR operation to the red, green, and blue components |
578| **red** {amount} | Modify Red component by a given amount |
579| **green** {amount} | Modify Green component by a given amount |
580| **blue** {amount} | Modify Blue component by a given amount |
581
582### Convolution matrix
583
584Sum 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)
585
586Implement emboss effect:
587
588```js
589image.convolute([[-2, -1, 0], [-1, 1, 1], [0, 1, 2]]);
590```
591
592### Low-level manipulation
593
594Jimp enables low-level manipulation of images in memory through the bitmap property of each Jimp object:
595
596```js
597image.bitmap.data; // a Buffer of the raw bitmap data
598image.bitmap.width; // the width of the image
599image.bitmap.height; // the height of the image
600```
601
602This data can be manipulated directly, but remember: garbage in, garbage out.
603
604A helper method is available to scan a region of the bitmap:
605
606```js
607image.scan(x, y, w, h, f); // scan a given region of the bitmap and call the function f on every pixel
608```
609
610Example usage:
611
612```js
613image.scan(0, 0, image.bitmap.width, image.bitmap.height, function(x, y, idx) {
614 // x, y is the position of this pixel on the image
615 // idx is the position start position of this rgba tuple in the bitmap Buffer
616 // this is the image
617
618 var red = this.bitmap.data[idx + 0];
619 var green = this.bitmap.data[idx + 1];
620 var blue = this.bitmap.data[idx + 2];
621 var alpha = this.bitmap.data[idx + 3];
622
623 // rgba values run from 0 - 255
624 // e.g. this.bitmap.data[idx] = 0; // removes red from this pixel
625});
626```
627
628If you need to do something with the image at the end of the scan:
629
630```js
631image.scan(0, 0, image.bitmap.width, image.bitmap.height, function(x, y, idx) {
632 // do your stuff..
633
634 if (x == image.bitmap.width - 1 && y == image.bitmap.height - 1) {
635 // image scan finished, do your stuff
636 }
637});
638```
639
640It's possible to make an iterator scan with a `for ... of`, if you want to `break` the scan before it reaches the end, but note, that this iterator has a huge performance implication:
641
642```js
643for (const { x, y, idx, image } of image.scanIterator(
644 0,
645 0,
646 image.bitmap.width,
647 image.bitmap.height
648)) {
649}
650```
651
652A helper to locate a particular pixel within the raw bitmap buffer:
653
654```js
655image.getPixelIndex(x, y); // returns the index within image.bitmap.data
656```
657
658One of the following may be optionally passed as a third parameter to indicate a strategy for x, y positions that are outside of boundaries of the image:
659
660```js
661Jimp.EDGE_EXTEND = 1;
662Jimp.EDGE_WRAP = 2;
663Jimp.EDGE_CROP = 3;
664```
665
666Alternatively, you can manipulate individual pixels using the following these functions:
667
668```js
669image.getPixelColor(x, y); // returns the colour of that pixel e.g. 0xFFFFFFFF
670image.setPixelColor(hex, x, y); // sets the colour of that pixel
671```
672
673Two static helper functions exist to convert RGBA values into single integer (hex) values:
674
675```js
676Jimp.rgbaToInt(r, g, b, a); // e.g. converts 255, 255, 255, 255 to 0xFFFFFFFF
677Jimp.intToRGBA(hex); // e.g. converts 0xFFFFFFFF to {r: 255, g: 255, b: 255, a:255}
678```
679
680You can convert a css color (Hex, RGB, RGBA, HSL, HSLA, HSV, HSVA, Named) to its hexadecimal equivalent:
681
682```js
683Jimp.cssColorToHex(cssColor); // e.g. converts #FF00FF to 0xFF00FFFF
684```
685
686### Creating new images
687
688If you want to begin with an empty Jimp image, you can call the Jimp constructor passing the width and height of the image to create and a Node-style callback:
689
690```js
691new Jimp(256, 256, (err, image) => {
692 // this image is 256 x 256, every pixel is set to 0x00000000
693});
694```
695
696You can optionally set the pixel colour as follows:
697
698```js
699new Jimp(256, 256, 0xff0000ff, (err, image) => {
700 // this image is 256 x 256, every pixel is set to 0xFF0000FF
701});
702```
703
704Or you can use a css color format:
705
706```js
707new Jimp(256, 256, '#FF00FF', (err, image) => {
708 // this image is 256 x 256, every pixel is set to #FF00FF
709});
710```
711
712You can also initialize a new Jimp image with a raw image buffer:
713
714```js
715new Jimp({ data: buffer, width: 1280, height: 768 }, (err, image) => {
716 // this image is 1280 x 768, pixels are loaded from the given buffer.
717});
718```
719
720This can be useful for interoperating with other image processing libraries. `buffer` is expected to be four-channel (rgba) image data.
721
722## Comparing images
723
724To generate a [perceptual hash](https://en.wikipedia.org/wiki/Perceptual_hashing) of a Jimp image, based on the [pHash](http://phash.org/) algorithm, use:
725
726```js
727image.hash(); // aHgG4GgoFjA
728```
729
730By default the hash is returned as base 64. The hash can be returned at another base by passing a number from 2 to 64 to the method:
731
732```js
733image.hash(2); // 1010101011010000101010000100101010010000011001001001010011100100
734```
735
736There are 18,446,744,073,709,551,615 unique hashes. The hamming distance between the binary representation of these hashes can be used to find similar-looking images.
737
738To calculate the hamming distance between two Jimp images based on their perceptual hash use:
739
740```js
741Jimp.distance(image1, image2); // returns a number 0-1, where 0 means the two images are perceived to be identical
742```
743
744Jimp also allows the diffing of two Jimp images using [PixelMatch](https://github.com/mapbox/pixelmatch) as follows:
745
746```js
747var diff = Jimp.diff(image1, image2, threshold); // threshold ranges 0-1 (default: 0.1)
748diff.image; // a Jimp image showing differences
749diff.percent; // the proportion of different pixels (0-1), where 0 means the images are pixel identical
750```
751
752Using a mix of hamming distance and pixel diffing to compare images, the following code has a 99% success rate of detecting the same image from a random sample (with 1% false positives). The test this figure is drawn from attempts to match each image from a sample of 120 PNGs against 120 corresponding JPEGs saved at a quality setting of 60.
753
754```js
755var distance = Jimp.distance(png, jpeg); // perceived distance
756var diff = Jimp.diff(png, jpeg); // pixel difference
757
758if (distance < 0.15 || diff.percent < 0.15) {
759 // images match
760} else {
761 // not a match
762}
763```
764
765You can also calculate the raw pHash (no padding or custom base). You can then use this in `distanceFromHash` to calculate the hash distance from a loaded image.
766
767```js
768const hash1 = image1.pHash();
769const hash2 = image2.pHash();
770
771image2.distanceFromHash(hash1);
772Jimp.compareHashes(hash1, hash2); // same result as above
773```
774
775## Chaining or callbacks
776
777Most instance methods can be chained together, for example as follows:
778
779```js
780Jimp.read('lenna.png').then(image => {
781 image
782 .greyscale()
783 .scale(0.5)
784 .write('lena-half-bw.png');
785});
786```
787
788Alternatively, methods can be passed Node-style callbacks:
789
790```js
791Jimp.read('lenna.png').then(image => {
792 image.greyscale((err, image) => {
793 image.scale(0.5, (err, image) => {
794 image.write('lena-half-bw.png');
795 });
796 });
797});
798```
799
800The Node-style callback pattern allows Jimp to be used with frameworks that expect or build on the Node-style callback pattern.