UNPKG

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