UNPKG

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