├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── docs ├── assets │ ├── css │ │ ├── main.css │ │ └── main.css.map │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ ├── main.js │ │ └── search.js ├── classes │ ├── baddestinationerror.html │ ├── imagemagickmissingerror.html │ ├── missingextensionerror.html │ ├── missingoptionserror.html │ └── unsupportederror.html ├── globals.html ├── index.html └── interfaces │ ├── ibaseoptions.html │ ├── iconvertoptions.html │ ├── icropoptions.html │ ├── idensity.html │ ├── iimagemagickcommandresult.html │ ├── iinforesult.html │ ├── irescropoptions.html │ ├── iresizeoptions.html │ ├── irotateoptions.html │ └── ithumbnailoptions.html ├── lib ├── commands │ ├── convert.js │ ├── crop.js │ ├── info.js │ ├── rescrop.js │ ├── resize.js │ ├── rotate.js │ └── thumbnail.js ├── easyimage.js ├── errors │ ├── BadDestinationError.js │ ├── ImageMagickMissingError.js │ ├── MissingExtensionError.js │ ├── MissingOptionsError.js │ └── UnsupportedError.js ├── execute.js ├── options.js └── utilities.js ├── package-lock.json ├── package.json ├── src ├── commands │ ├── convert.ts │ ├── crop.ts │ ├── info.ts │ ├── rescrop.ts │ ├── resize.ts │ ├── rotate.ts │ └── thumbnail.ts ├── easyimage.ts ├── errors │ ├── BadDestinationError.ts │ ├── ImageMagickMissingError.ts │ ├── MissingExtensionError.ts │ ├── MissingOptionsError.ts │ └── UnsupportedError.ts ├── execute.ts ├── options.ts └── utilities.ts ├── test ├── files │ ├── multiframe.gif │ ├── tall.png │ ├── test.pdf │ ├── wide.jpg │ └── wide.png └── specs │ ├── convert.spec.ts │ ├── crop.spec.ts │ ├── easyimage.spec.ts │ ├── info.spec.ts │ ├── rescrop.spec.ts │ ├── resize.spec.ts │ ├── rotate.spec.ts │ └── thumbail.spec.ts ├── tsconfig.json ├── tslint.json ├── typedoc.js └── types ├── commands ├── convert.d.ts ├── crop.d.ts ├── info.d.ts ├── rescrop.d.ts ├── resize.d.ts ├── rotate.d.ts └── thumbnail.d.ts ├── easyimage.d.ts ├── errors ├── BadDestinationError.d.ts ├── ImageMagickMissingError.d.ts ├── MissingExtensionError.d.ts ├── MissingOptionsError.d.ts └── UnsupportedError.d.ts ├── execute.d.ts ├── options.d.ts └── utilities.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.lock 3 | *.DS_Store 4 | *.swp 5 | *.out 6 | node_modules/ 7 | test/output 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.lock 3 | *.DS_Store 4 | *.swp 5 | *.out 6 | 7 | docs/ 8 | src/ 9 | node_modules/ 10 | test/ 11 | .travis.yml 12 | tsconfig.json 13 | typedoc.js 14 | tslint.json 15 | .idea/ 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: node_js 3 | node_js: 4 | - "node" 5 | - "lts/*" 6 | before_install: 7 | - npm install npm -g 8 | - sudo apt-get -y install imagemagick 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 3.0.1 - 2018-02-02 2 | ------------------ 3 | 4 | 1. Check for missing arugments before creating output directory. 5 | 6 | 3.0.0 - 2018-01-22 7 | ------------------ 8 | 9 | 1. Rewrote in typescript with ES6 10 | 2. Removed exec 11 | 3. Removed support for node 0.12 12 | 4. Fixed various bugs 13 | 5. No longer apply a gravity to `resize()` or `rescrop()` 14 | 6. All PDF's with no page definition now automatically apply "-append" 15 | 7. Added `coalesce` option to all commands 16 | 8. Added orientation to `info()` 17 | 9. Changed `resize()` to not auto-set height from width 18 | 10. Added `getImageMagickVersion()` 19 | 11. Rewrote tests to be more clear 20 | 21 | ------------------------------------------------------------------------ 22 | 23 | 2.2.1 - 2018-02-02 24 | ------------------ 25 | 26 | 1. Removed console.debug and replaced with process.stderr.write 27 | 28 | 2.2.0 - 10-01-2018 29 | ------------------ 30 | 31 | 1. Refactored to be more modular 32 | 2. Deprecated exec 33 | 3. Added execute function 34 | 4. Added ImageMagick 7 support 35 | 36 | 1.0.4 - 24-12-2014 37 | ------------------ 38 | 39 | 1. Filenames with spaces supported in `.exec()` 40 | 41 | 1.0.3 - 27-09-2014 42 | ------------------ 43 | 44 | 1. Use child_process.execFile instead of child_process.exec to prevent potential shellshock exploit 45 | 46 | 1.0.2 - 21-08-2014 47 | ------------------ 48 | 49 | 1. Remove PixelsPerCentimeter 50 | 2. Test output dir 51 | 52 | 1.0.1 - 03-08-2014 53 | ------------------ 54 | 55 | 1. Fixed potential hidden bugs - thanks to @jheusala 56 | 57 | 1.0.0 - 14-07-2014 58 | ------------------ 59 | 60 | 1. Changed to promise-based interface 61 | 2. Mocha tests 62 | 63 | 0.1.7 - 11-07-2014 64 | ------------------ 65 | 66 | 1. Thumbnail generation optimized 67 | 68 | 0.1.4 - 25-11-2013 69 | ------------------ 70 | 71 | 1. Add density info (Kevin Smith ksmth@github) 72 | 2. Made testing easier with a sample image and output directory 73 | 74 | 0.1.3 - 11-06-2012 75 | ------------------ 76 | 77 | 1. Refactored to return an error object instead of crashing the app, in case of errors 78 | 79 | 0.1.2 - 27-05-2012 80 | ------------------ 81 | 82 | 1. Unsupported files should not crash 83 | 84 | 0.1.1 - 09-05-2012 85 | ------------------ 86 | 87 | 1. Crop bug fixed 88 | 2. Fill option 89 | 90 | 0.1.0 - 18-04-2012 91 | ------------------ 92 | 93 | 1. Operations return an image object 94 | 95 | 0.0.9 - 15-04-2012 96 | ------------------ 97 | 98 | 1. Optimized info() 99 | 100 | 0.0.8 - 11-04-2012 101 | ------------------ 102 | 103 | 1. Bug in thumbnail() fixed 104 | 105 | 0.0.7 - 10-04-2012 106 | ------------------ 107 | 108 | 1. New method - thumbnail() 109 | 110 | 0.0.6 - 09-04-2012 111 | ------------------ 112 | 113 | 1. Better fix for file name issues. 114 | 2. info() bug fixed 115 | 116 | 0.0.5 - 09-04-2012 117 | ------------------ 118 | 119 | 1. File names can have more than once space 120 | 121 | 0.0.4 - 29-02-2012 122 | ------------------ 123 | 124 | 1. Fixed file name special character bug. More complicated than assumed! 125 | 126 | 0.0.3 - 29-02-2012 127 | ------------------ 128 | 129 | 1. '(' and ')' escaped in filenames 130 | 131 | 0.0.2 - 29-02-2012 132 | ------------------ 133 | 134 | 1. Fixed space character in file name bug 135 | 2. crop() will assume width and height as cropwidth and cropheight if they are not specified 136 | 137 | 0.0.1 - 28-02-2012 138 | ------------------ 139 | 140 | Initial release 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EasyImage [![NPM version](https://badge.fury.io/js/easyimage.svg)](https://badge.fury.io/js/easyimage) 2 | ========= 3 | 4 | EasyImage is a promise-based image processing module for Node.js, it is built on top of [ImageMagick](https://www.imagemagick.org/script/download.php), so make 5 | sure ImageMagick is installed on your system. 6 | 7 | ## Installation 8 | 9 | EasyImage 3 is only compatible with NodeJS 4 or greater. 10 | 11 | ``` 12 | $ npm install --save easyimage 13 | ``` 14 | 15 | For NodeJS 0.12, use [EasyImage 2](https://github.com/hacksparrow/node-easyimage/tree/v2.2.0) 16 | 17 | ``` 18 | $ npm install --save easyimage@2 19 | ``` 20 | 21 | ## Quick Start 22 | 23 | Get info about an image. 24 | 25 | ``` 26 | import {info} from "easyimage"; 27 | try { 28 | const imageInfo = await info("/path/to/image.jpg"); 29 | } catch (e) { 30 | console.log("Error: ", e); 31 | } 32 | ``` 33 | 34 | Convert an image from JPG to PNG. 35 | 36 | ``` 37 | import {convert} from "easyimage"; 38 | try { 39 | await convert({ 40 | src: "/path/to/source.jpg", 41 | dst: "/path/to/dest.png", 42 | }); 43 | } catch (e) { 44 | console.log("Error: ", e); 45 | } 46 | ``` 47 | 48 | Create a thumbnail. 49 | 50 | ``` 51 | import {thumbnail} from "easyimage"; 52 | try { 53 | const thumbnailInfo = await thumbnail({ 54 | src: "/path/to/source.jpg", 55 | width: 100, 56 | height: 100, 57 | }); 58 | 59 | console.log("Thumbnail is at: " + thumbnailInfo.path); 60 | } catch (e) { 61 | console.log("Error: ", e); 62 | } 63 | ``` 64 | 65 | ## Usage 66 | 67 | The EasyImage module is ES6 compatible. You can import just the commands that you will need. 68 | 69 | Every command which takes an options object which extends from [IBaseOptions](https://hacksparrow.github.io/node-easyimage/interfaces/ibaseoptions.html). You can use 70 | any of the parameters defined on `IBaseOptions`. For example, to prevent EasyImage from auto-orientating your image, you can pass `autoOrient: false` on any 71 | command. 72 | 73 | Every command must have a `src` parameter. If you do not specify a `dst`, then a random file will be created. Be sure to clean up randomly created files by 74 | either moving them to permanent storage, or deleting them. Some commands have other required options. 75 | 76 | See the [Docs](https://hacksparrow.github.io/node-easyimage/index.html) for all available options for each command. 77 | 78 | **convert** 79 | 80 | The [convert()](https://hacksparrow.github.io/node-easyimage/globals.html#convert) command can convert an image file from one type to another. 81 | 82 | **crop** 83 | 84 | The [crop()](https://hacksparrow.github.io/node-easyimage/globals.html#crop) command will crop an image to the specified size. 85 | 86 | **resize** 87 | 88 | The [resize()](https://hacksparrow.github.io/node-easyimage/globals.html#resize) command will resize an image to the specified size. 89 | 90 | **rescrop** 91 | 92 | The [rescrop()](https://hacksparrow.github.io/node-easyimage/globals.html#rescrop) command will resize and crop an image to the specified size. 93 | 94 | **rotate** 95 | 96 | The [rotate()](https://hacksparrow.github.io/node-easyimage/globals.html#rotate) command will rotate an image by the specified number of degrees. 97 | 98 | **thumbnail** 99 | 100 | The [thumbnail()](https://hacksparrow.github.io/node-easyimage/globals.html#thumbnail) command will create a thumbnail of the specified image. 101 | 102 | 103 | ## Helper Commands 104 | 105 | In addition to the above commands, there are three other commands available. 106 | 107 | **info** 108 | 109 | The [info()](https://hacksparrow.github.io/node-easyimage/globals.html#info) command will give you details about an image file. 110 | 111 | 112 | **execute** 113 | 114 | The [execute()]() command allows you directly run ImageMagick with your own tool and arguments. It will handle calling the appropriate ImageMagick version, and 115 | return the raw `stdout` and `stderr` to you. 116 | 117 | 118 | **getImageMagickVersion** 119 | 120 | The [getImageMagickVersion()](https://hacksparrow.github.io/node-easyimage/globals.html#getimagemagickversion) command will return the detected version of 121 | ImageMagick. 122 | 123 | 124 | ## Error Handling 125 | 126 | There are 5 different types of errors that can be thrown. 127 | 128 | - `BadDestinationError` 129 | - `ImageMagickMissingError` 130 | - `MissingExtensionError` 131 | - `MissingOptionsError` 132 | - `UnsupportedError` 133 | 134 | Which allows you to catch specific errors. 135 | 136 | ``` 137 | import {convert, MissingOptionsError} from "easyimage"; 138 | 139 | async function shouldError() { 140 | try { 141 | await convert({}); 142 | console.log("I should not show"); 143 | } catch (MissingOptionsError e) { 144 | console.log("I should show"); 145 | } catch (Error e) { 146 | console.log("I should not show either"); 147 | } 148 | } 149 | 150 | ``` 151 | 152 | ## License (MIT) 153 | 154 | Copyright (c) 2015 Hage Yaapa <[http://www.hacksparrow.com](http://www.hacksparrow.com)> 155 | 156 | Permission is hereby granted, free of charge, to any person obtaining a copy 157 | of this software and associated documentation files (the "Software"), to deal 158 | in the Software without restriction, including without limitation the rights 159 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 160 | copies of the Software, and to permit persons to whom the Software is 161 | furnished to do so, subject to the following conditions: 162 | 163 | The above copyright notice and this permission notice shall be included in 164 | all copies or substantial portions of the Software. 165 | 166 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 169 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 170 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 171 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 172 | SOFTWARE. 173 | -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /docs/classes/baddestinationerror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BadDestinationError | easyimage 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 |
42 |
43 | Menu 44 |
45 |
46 |
47 |
48 |
49 |
50 | 58 |

Class BadDestinationError

59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |

Hierarchy

67 |
    68 |
  • 69 | Error 70 |
      71 |
    • 72 | BadDestinationError 73 |
    • 74 |
    75 |
  • 76 |
77 |
78 |
79 |

Index

80 |
81 |
82 |
83 |

Constructors

84 | 87 |
88 |
89 |

Properties

90 | 96 |
97 |
98 |
99 |
100 |
101 |

Constructors

102 |
103 | 104 |

constructor

105 | 108 | 118 |
119 |
120 |
121 |

Properties

122 |
123 | 124 |

message

125 |
message: string
126 | 132 |
133 |
134 | 135 |

name

136 |
name: string
137 | 143 |
144 |
145 | 146 |

Optional stack

147 |
stack: string
148 | 155 |
156 |
157 | 158 |

Static Error

159 |
Error: ErrorConstructor
160 | 165 |
166 |
167 |
168 | 274 |
275 |
276 | 335 |
336 |

Generated using TypeDoc

337 |
338 |
339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /docs/classes/imagemagickmissingerror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ImageMagickMissingError | easyimage 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 |
42 |
43 | Menu 44 |
45 |
46 |
47 |
48 |
49 |
50 | 58 |

Class ImageMagickMissingError

59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |

Hierarchy

67 |
    68 |
  • 69 | Error 70 |
      71 |
    • 72 | ImageMagickMissingError 73 |
    • 74 |
    75 |
  • 76 |
77 |
78 |
79 |

Index

80 |
81 |
82 |
83 |

Constructors

84 | 87 |
88 |
89 |

Properties

90 | 96 |
97 |
98 |
99 |
100 |
101 |

Constructors

102 |
103 | 104 |

constructor

105 | 108 | 118 |
119 |
120 |
121 |

Properties

122 |
123 | 124 |

message

125 |
message: string
126 | 132 |
133 |
134 | 135 |

name

136 |
name: string
137 | 143 |
144 |
145 | 146 |

Optional stack

147 |
stack: string
148 | 155 |
156 |
157 | 158 |

Static Error

159 |
Error: ErrorConstructor
160 | 165 |
166 |
167 |
168 | 274 |
275 |
276 | 335 |
336 |

Generated using TypeDoc

337 |
338 |
339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /docs/classes/missingextensionerror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MissingExtensionError | easyimage 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 |
42 |
43 | Menu 44 |
45 |
46 |
47 |
48 |
49 |
50 | 58 |

Class MissingExtensionError

59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |

Hierarchy

67 |
    68 |
  • 69 | Error 70 |
      71 |
    • 72 | MissingExtensionError 73 |
    • 74 |
    75 |
  • 76 |
77 |
78 |
79 |

Index

80 |
81 |
82 |
83 |

Constructors

84 | 87 |
88 |
89 |

Properties

90 | 96 |
97 |
98 |
99 |
100 |
101 |

Constructors

102 |
103 | 104 |

constructor

105 | 108 | 124 |
125 |
126 |
127 |

Properties

128 |
129 | 130 |

message

131 |
message: string
132 | 138 |
139 |
140 | 141 |

name

142 |
name: string
143 | 149 |
150 |
151 | 152 |

Optional stack

153 |
stack: string
154 | 161 |
162 |
163 | 164 |

Static Error

165 |
Error: ErrorConstructor
166 | 171 |
172 |
173 |
174 | 280 |
281 |
282 | 341 |
342 |

Generated using TypeDoc

343 |
344 |
345 | 346 | 347 | 348 | -------------------------------------------------------------------------------- /docs/classes/unsupportederror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | UnsupportedError | easyimage 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 |
42 |
43 | Menu 44 |
45 |
46 |
47 |
48 |
49 |
50 | 58 |

Class UnsupportedError

59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |

Hierarchy

67 |
    68 |
  • 69 | Error 70 |
      71 |
    • 72 | UnsupportedError 73 |
    • 74 |
    75 |
  • 76 |
77 |
78 |
79 |

Index

80 |
81 |
82 |
83 |

Constructors

84 | 87 |
88 |
89 |

Properties

90 | 96 |
97 |
98 |
99 |
100 |
101 |

Constructors

102 |
103 | 104 |

constructor

105 | 108 | 124 |
125 |
126 |
127 |

Properties

128 |
129 | 130 |

message

131 |
message: string
132 | 138 |
139 |
140 | 141 |

name

142 |
name: string
143 | 149 |
150 |
151 | 152 |

Optional stack

153 |
stack: string
154 | 161 |
162 |
163 | 164 |

Static Error

165 |
Error: ErrorConstructor
166 | 171 |
172 |
173 |
174 | 280 |
281 |
282 | 341 |
342 |

Generated using TypeDoc

343 |
344 |
345 | 346 | 347 | 348 | -------------------------------------------------------------------------------- /docs/interfaces/idensity.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IDensity | easyimage 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 |
42 |
43 | Menu 44 |
45 |
46 |
47 |
48 |
49 |
50 | 58 |

Interface IDensity

59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |

Hierarchy

67 |
    68 |
  • 69 | IDensity 70 |
  • 71 |
72 |
73 |
74 |

Index

75 |
76 |
77 |
78 |

Properties

79 |
    80 |
  • x
  • 81 |
  • y
  • 82 |
83 |
84 |
85 |
86 |
87 |
88 |

Properties

89 |
90 | 91 |

x

92 |
x: number
93 | 98 |
99 |
100 | 101 |

y

102 |
y: number
103 | 108 |
109 |
110 |
111 | 208 |
209 |
210 | 269 |
270 |

Generated using TypeDoc

271 |
272 |
273 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /docs/interfaces/iimagemagickcommandresult.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IImageMagickCommandResult | easyimage 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 |
42 |
43 | Menu 44 |
45 |
46 |
47 |
48 |
49 |
50 | 58 |

Interface IImageMagickCommandResult

59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |

Hierarchy

67 |
    68 |
  • 69 | IImageMagickCommandResult 70 |
  • 71 |
72 |
73 |
74 |

Index

75 |
76 |
77 |
78 |

Properties

79 | 83 |
84 |
85 |
86 |
87 |
88 |

Properties

89 |
90 | 91 |

stderr

92 |
stderr: string
93 | 98 |
99 |
100 | 101 |

stdout

102 |
stdout: string
103 | 108 |
109 |
110 |
111 | 208 |
209 |
210 | 269 |
270 |

Generated using TypeDoc

271 |
272 |
273 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /lib/commands/convert.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var tslib_1 = require("tslib"); 4 | /* 5 | EasyImage 6 | 7 | EasyImage is a promise-based image processing module 8 | for Node.js, it is built on top of ImageMagick, so 9 | make sure ImageMagick is installed on your system. 10 | 11 | Copyright (c) 2015 Hage Yaapa 12 | Maintained by Kevin Gravier 13 | 14 | MIT License 15 | */ 16 | var Bluebird = require("bluebird"); 17 | var execute_1 = require("../execute"); 18 | var utilities_1 = require("../utilities"); 19 | var info_1 = require("./info"); 20 | Promise = Promise || Bluebird; 21 | /** 22 | * Converts an image from one format to another. 23 | * 24 | * @param {IConvertOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | function convert(options) { 28 | return tslib_1.__awaiter(this, void 0, void 0, function () { 29 | var args; 30 | return tslib_1.__generator(this, function (_a) { 31 | switch (_a.label) { 32 | case 0: 33 | utilities_1.applyDefaultsToBaseOptions(options); 34 | utilities_1.checkForMissingOptions(options, ["src"]); 35 | return [4 /*yield*/, utilities_1.ensureDestinationDirectoryExists(options)]; 36 | case 1: 37 | _a.sent(); 38 | args = [options.src]; 39 | utilities_1.applyBaseOptionsToArgs(options, args); 40 | args.push(options.dst); 41 | return [4 /*yield*/, execute_1.execute("convert", args)]; 42 | case 2: 43 | _a.sent(); 44 | return [2 /*return*/, info_1.info(options.dst)]; 45 | } 46 | }); 47 | }); 48 | } 49 | exports.convert = convert; 50 | -------------------------------------------------------------------------------- /lib/commands/crop.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var execute_1 = require("../execute"); 18 | var utilities_1 = require("../utilities"); 19 | var info_1 = require("./info"); 20 | Promise = Promise || Bluebird; 21 | /** 22 | * Crops an image. 23 | * 24 | * @param {ICropOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | function crop(options) { 28 | return tslib_1.__awaiter(this, void 0, void 0, function () { 29 | var args, cropDefinition; 30 | return tslib_1.__generator(this, function (_a) { 31 | switch (_a.label) { 32 | case 0: 33 | utilities_1.applyDefaultsToBaseOptions(options); 34 | upgradeCropOptions(options); 35 | applyDefaultsToCropOptions(options); 36 | utilities_1.checkForMissingOptions(options, ["src", "cropWidth"]); 37 | return [4 /*yield*/, utilities_1.ensureDestinationDirectoryExists(options)]; 38 | case 1: 39 | _a.sent(); 40 | args = [options.src]; 41 | utilities_1.applyBaseOptionsToArgs(options, args); 42 | cropDefinition = "" + options.cropWidth; 43 | if (options.cropHeight) { 44 | cropDefinition += "x" + options.cropHeight; 45 | } 46 | cropDefinition += "+" + options.x + "+" + options.y; 47 | if (options.gravity) { 48 | args.push("-gravity", options.gravity); 49 | } 50 | args.push("-crop", cropDefinition, options.dst); 51 | return [4 /*yield*/, execute_1.execute("convert", args)]; 52 | case 2: 53 | _a.sent(); 54 | return [2 /*return*/, info_1.info(options.dst)]; 55 | } 56 | }); 57 | }); 58 | } 59 | exports.crop = crop; 60 | function upgradeCropOptions(options) { 61 | if (!options.cropWidth && options.cropwidth) { 62 | options.cropWidth = options.cropwidth; 63 | } 64 | if (!options.cropHeight && options.cropheight) { 65 | options.cropHeight = options.cropheight; 66 | } 67 | } 68 | function applyDefaultsToCropOptions(options) { 69 | if (!options.cropHeight) { 70 | options.cropHeight = options.cropWidth; 71 | } 72 | if (!options.x) { 73 | options.x = 0; 74 | } 75 | if (!options.y) { 76 | options.y = 0; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/commands/info.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var UnsupportedError_1 = require("../errors/UnsupportedError"); 18 | var execute_1 = require("../execute"); 19 | Promise = Promise || Bluebird; 20 | /** 21 | * Returns information about an image. 22 | * 23 | * @param {string} filePath Path to the image file. 24 | * @returns {Bluebird} 25 | */ 26 | function info(filePath) { 27 | return tslib_1.__awaiter(this, void 0, void 0, function () { 28 | var numberOfFrames, args, _a, stdout, stderr, temp, result; 29 | return tslib_1.__generator(this, function (_b) { 30 | switch (_b.label) { 31 | case 0: return [4 /*yield*/, getNumberOfFrames(filePath)]; 32 | case 1: 33 | numberOfFrames = _b.sent(); 34 | args = ["-format", "%m %z %w %h %b %x %y %[orientation] %f"]; 35 | if (numberOfFrames > 1) { 36 | args.push(filePath + "[0]"); 37 | } 38 | else { 39 | args.push(filePath); 40 | } 41 | return [4 /*yield*/, execute_1.execute("identify", args)]; 42 | case 2: 43 | _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; 44 | if (stdout === "") { 45 | throw new UnsupportedError_1.UnsupportedError("ImageMagick returned unexpected data."); 46 | } 47 | temp = stdout 48 | .replace(/PixelsPerInch/g, "") 49 | .replace(/PixelsPerCentimeter/g, "") 50 | .split(/\s+/g); 51 | // All fields not found 52 | if (temp.length < 8) { 53 | throw new UnsupportedError_1.UnsupportedError("ImageMagick returned unexpected data."); 54 | } 55 | result = { 56 | density: { 57 | x: parseFloat(temp[5]), 58 | y: parseFloat(temp[6]) 59 | }, 60 | depth: parseInt(temp[1], 10), 61 | frames: numberOfFrames, 62 | height: parseInt(temp[3], 10), 63 | name: temp.slice(8).join(" ").replace(/(\r\n|\n|\r)/gm, "").trim(), 64 | orientation: temp[7], 65 | path: filePath, 66 | size: parseSize(temp[4]), 67 | type: temp[0].toLowerCase(), 68 | width: parseInt(temp[2], 10) 69 | }; 70 | if (stderr) { 71 | result.warnings = stderr; 72 | } 73 | return [2 /*return*/, result]; 74 | } 75 | }); 76 | }); 77 | } 78 | exports.info = info; 79 | function getNumberOfFrames(filePath) { 80 | return tslib_1.__awaiter(this, void 0, void 0, function () { 81 | var args, _a, stdout, stderr; 82 | return tslib_1.__generator(this, function (_b) { 83 | switch (_b.label) { 84 | case 0: 85 | args = ["-format", "%n\n", "" + filePath]; 86 | return [4 /*yield*/, execute_1.execute("identify", args)]; 87 | case 1: 88 | _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; 89 | if (stdout === "") { 90 | throw new UnsupportedError_1.UnsupportedError("ImageMagick returned unexpected data."); 91 | } 92 | return [2 /*return*/, parseInt(stdout.split("\n")[0], 10)]; 93 | } 94 | }); 95 | }); 96 | } 97 | var units = { 98 | B: 1, 99 | GB: 1000000000, 100 | KB: 1000, 101 | MB: 1000000, 102 | TB: 1000000000000 103 | }; 104 | function parseSize(sizeString) { 105 | var rx = /^(\d*\.?\d*)([KMGT]?B)$/; // regex for extract the float value and its unit 106 | var sizeArray = rx.exec(sizeString); 107 | return parseFloat(sizeArray[1]) * units[sizeArray[2]]; 108 | } 109 | -------------------------------------------------------------------------------- /lib/commands/rescrop.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var execute_1 = require("../execute"); 18 | var utilities_1 = require("../utilities"); 19 | var info_1 = require("./info"); 20 | Promise = Promise || Bluebird; 21 | /** 22 | * Resizes and crops an image. 23 | * 24 | * @param {IResCropOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | function rescrop(options) { 28 | return tslib_1.__awaiter(this, void 0, void 0, function () { 29 | var args, resizeDefinition, cropDefinition; 30 | return tslib_1.__generator(this, function (_a) { 31 | switch (_a.label) { 32 | case 0: 33 | utilities_1.applyDefaultsToBaseOptions(options); 34 | upgradeCropOptions(options); 35 | applyDefaultsToRescropOptions(options); 36 | utilities_1.checkForMissingOptions(options, ["src", "cropWidth", "width"]); 37 | return [4 /*yield*/, utilities_1.ensureDestinationDirectoryExists(options)]; 38 | case 1: 39 | _a.sent(); 40 | args = [options.src]; 41 | utilities_1.applyBaseOptionsToArgs(options, args); 42 | resizeDefinition = "" + options.width; 43 | if (options.height) { 44 | resizeDefinition += "x" + options.height; 45 | } 46 | if (options.ignoreAspectRatio) { 47 | resizeDefinition += "!"; 48 | } 49 | if (options.onlyDownscale) { 50 | if (/^win/.test(process.platform)) { 51 | resizeDefinition += "^>"; 52 | } 53 | else { 54 | resizeDefinition += ">"; 55 | } 56 | } 57 | cropDefinition = "" + options.cropWidth; 58 | if (options.cropHeight) { 59 | cropDefinition += "x" + options.cropHeight; 60 | } 61 | cropDefinition += "+" + options.x + "+" + options.y; 62 | if (options.gravity) { 63 | args.push("-gravity", options.gravity); 64 | } 65 | args.push("-resize", resizeDefinition, "-crop", cropDefinition, options.dst); 66 | return [4 /*yield*/, execute_1.execute("convert", args)]; 67 | case 2: 68 | _a.sent(); 69 | return [2 /*return*/, info_1.info(options.dst)]; 70 | } 71 | }); 72 | }); 73 | } 74 | exports.rescrop = rescrop; 75 | function upgradeCropOptions(options) { 76 | if (!options.cropWidth && options.cropwidth) { 77 | options.cropWidth = options.cropwidth; 78 | } 79 | if (!options.cropHeight && options.cropheight) { 80 | options.cropHeight = options.cropheight; 81 | } 82 | } 83 | function applyDefaultsToRescropOptions(options) { 84 | if (!options.cropHeight) { 85 | options.cropHeight = options.cropWidth; 86 | } 87 | if (!options.x) { 88 | options.x = 0; 89 | } 90 | if (!options.y) { 91 | options.y = 0; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/commands/resize.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var execute_1 = require("../execute"); 18 | var utilities_1 = require("../utilities"); 19 | var info_1 = require("./info"); 20 | Promise = Promise || Bluebird; 21 | /** 22 | * Resizes an image. 23 | * 24 | * @param {IResizeOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | function resize(options) { 28 | return tslib_1.__awaiter(this, void 0, void 0, function () { 29 | var args, resizeDefinition; 30 | return tslib_1.__generator(this, function (_a) { 31 | switch (_a.label) { 32 | case 0: 33 | utilities_1.applyDefaultsToBaseOptions(options); 34 | applyDefaultsToResizeOptions(options); 35 | utilities_1.checkForMissingOptions(options, ["src", "width"]); 36 | return [4 /*yield*/, utilities_1.ensureDestinationDirectoryExists(options)]; 37 | case 1: 38 | _a.sent(); 39 | args = [options.src]; 40 | utilities_1.applyBaseOptionsToArgs(options, args); 41 | resizeDefinition = "" + options.width; 42 | if (options.height) { 43 | resizeDefinition += "x" + options.height; 44 | } 45 | if (options.ignoreAspectRatio) { 46 | resizeDefinition += "!"; 47 | } 48 | if (options.onlyDownscale) { 49 | if (/^win/.test(process.platform)) { 50 | resizeDefinition += "^>"; 51 | } 52 | else { 53 | resizeDefinition += ">"; 54 | } 55 | } 56 | args.push("-resize", resizeDefinition, options.dst); 57 | return [4 /*yield*/, execute_1.execute("convert", args)]; 58 | case 2: 59 | _a.sent(); 60 | return [2 /*return*/, info_1.info(options.dst)]; 61 | } 62 | }); 63 | }); 64 | } 65 | exports.resize = resize; 66 | function applyDefaultsToResizeOptions(options) { 67 | if (options.ignoreAspectRatio === undefined) { 68 | options.ignoreAspectRatio = false; 69 | } 70 | if (options.onlyDownscale === undefined) { 71 | options.onlyDownscale = false; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/commands/rotate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var execute_1 = require("../execute"); 18 | var utilities_1 = require("../utilities"); 19 | var info_1 = require("./info"); 20 | Promise = Promise || Bluebird; 21 | /** 22 | * Rotates an image by a specified number of degrees. 23 | * 24 | * @param {IRotateOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | function rotate(options) { 28 | return tslib_1.__awaiter(this, void 0, void 0, function () { 29 | var args; 30 | return tslib_1.__generator(this, function (_a) { 31 | switch (_a.label) { 32 | case 0: 33 | utilities_1.applyDefaultsToBaseOptions(options); 34 | utilities_1.checkForMissingOptions(options, ["src", "degree"]); 35 | return [4 /*yield*/, utilities_1.ensureDestinationDirectoryExists(options)]; 36 | case 1: 37 | _a.sent(); 38 | args = [options.src]; 39 | utilities_1.applyBaseOptionsToArgs(options, args); 40 | args.push("-rotate", options.degree.toString(), options.dst); 41 | return [4 /*yield*/, execute_1.execute("convert", args)]; 42 | case 2: 43 | _a.sent(); 44 | return [2 /*return*/, info_1.info(options.dst)]; 45 | } 46 | }); 47 | }); 48 | } 49 | exports.rotate = rotate; 50 | -------------------------------------------------------------------------------- /lib/commands/thumbnail.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var execute_1 = require("../execute"); 18 | var utilities_1 = require("../utilities"); 19 | var info_1 = require("./info"); 20 | Promise = Promise || Bluebird; 21 | /** 22 | * Creates a thumbnail of an image. 23 | * 24 | * @param {IThumbnailOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | function thumbnail(options) { 28 | return tslib_1.__awaiter(this, void 0, void 0, function () { 29 | var infoData, args; 30 | return tslib_1.__generator(this, function (_a) { 31 | switch (_a.label) { 32 | case 0: 33 | utilities_1.applyDefaultsToBaseOptions(options); 34 | return [4 /*yield*/, applyDefaultsToThumbnailOptions(options)]; 35 | case 1: 36 | _a.sent(); 37 | utilities_1.checkForMissingOptions(options, ["src", "width", "height"]); 38 | return [4 /*yield*/, utilities_1.ensureDestinationDirectoryExists(options)]; 39 | case 2: 40 | _a.sent(); 41 | return [4 /*yield*/, info_1.info(options.src)]; 42 | case 3: 43 | infoData = _a.sent(); 44 | args = [options.src]; 45 | utilities_1.applyBaseOptionsToArgs(options, args); 46 | if (options.gravity) { 47 | args.push("-gravity", options.gravity); 48 | } 49 | args.push("-interpolate", options.interpolate); 50 | args.push("-strip"); 51 | if (infoData.width > infoData.height) { 52 | args.push("-thumbnail", "x" + options.height); 53 | } 54 | else { 55 | args.push("-thumbnail", options.width + "x"); 56 | } 57 | args.push("-crop", options.width + "x" + options.height + "+" + options.x + "+" + options.y); 58 | args.push(options.dst); 59 | return [4 /*yield*/, execute_1.execute("convert", args)]; 60 | case 4: 61 | _a.sent(); 62 | return [2 /*return*/, info_1.info(options.dst)]; 63 | } 64 | }); 65 | }); 66 | } 67 | exports.thumbnail = thumbnail; 68 | function applyDefaultsToThumbnailOptions(options) { 69 | return tslib_1.__awaiter(this, void 0, void 0, function () { 70 | var availableVersion; 71 | return tslib_1.__generator(this, function (_a) { 72 | switch (_a.label) { 73 | case 0: 74 | if (!options.x) { 75 | options.x = 0; 76 | } 77 | if (!options.y) { 78 | options.y = 0; 79 | } 80 | if (!!options.interpolate) return [3 /*break*/, 2]; 81 | return [4 /*yield*/, execute_1.getImageMagickVersion()]; 82 | case 1: 83 | availableVersion = _a.sent(); 84 | switch (availableVersion) { 85 | case 6: 86 | options.interpolate = "bicubic"; 87 | break; 88 | case 7: 89 | options.interpolate = "catrom"; 90 | break; 91 | } 92 | _a.label = 2; 93 | case 2: return [2 /*return*/]; 94 | } 95 | }); 96 | }); 97 | } 98 | -------------------------------------------------------------------------------- /lib/easyimage.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | tslib_1.__exportStar(require("./execute"), exports); 17 | tslib_1.__exportStar(require("./commands/info"), exports); 18 | tslib_1.__exportStar(require("./commands/crop"), exports); 19 | tslib_1.__exportStar(require("./commands/convert"), exports); 20 | tslib_1.__exportStar(require("./commands/resize"), exports); 21 | tslib_1.__exportStar(require("./commands/rotate"), exports); 22 | tslib_1.__exportStar(require("./commands/rescrop"), exports); 23 | tslib_1.__exportStar(require("./commands/thumbnail"), exports); 24 | tslib_1.__exportStar(require("./errors/BadDestinationError"), exports); 25 | tslib_1.__exportStar(require("./errors/ImageMagickMissingError"), exports); 26 | tslib_1.__exportStar(require("./errors/MissingExtensionError"), exports); 27 | tslib_1.__exportStar(require("./errors/MissingOptionsError"), exports); 28 | tslib_1.__exportStar(require("./errors/UnsupportedError"), exports); 29 | -------------------------------------------------------------------------------- /lib/errors/BadDestinationError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var BadDestinationError = /** @class */ (function (_super) { 17 | tslib_1.__extends(BadDestinationError, _super); 18 | function BadDestinationError() { 19 | return _super.call(this, "`dst` directory could not be created") || this; 20 | } 21 | return BadDestinationError; 22 | }(Error)); 23 | exports.BadDestinationError = BadDestinationError; 24 | -------------------------------------------------------------------------------- /lib/errors/ImageMagickMissingError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var ImageMagickMissingError = /** @class */ (function (_super) { 17 | tslib_1.__extends(ImageMagickMissingError, _super); 18 | function ImageMagickMissingError() { 19 | return _super.call(this, "ImageMagick not found") || this; 20 | } 21 | return ImageMagickMissingError; 22 | }(Error)); 23 | exports.ImageMagickMissingError = ImageMagickMissingError; 24 | -------------------------------------------------------------------------------- /lib/errors/MissingExtensionError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var MissingExtensionError = /** @class */ (function (_super) { 17 | tslib_1.__extends(MissingExtensionError, _super); 18 | function MissingExtensionError(srcFile) { 19 | return _super.call(this, srcFile + " does not have an extension") || this; 20 | } 21 | return MissingExtensionError; 22 | }(Error)); 23 | exports.MissingExtensionError = MissingExtensionError; 24 | -------------------------------------------------------------------------------- /lib/errors/MissingOptionsError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var MissingOptionsError = /** @class */ (function (_super) { 17 | tslib_1.__extends(MissingOptionsError, _super); 18 | function MissingOptionsError(options) { 19 | return _super.call(this, "Missing " + options.map(function (o) { return "`" + o + "`"; }).join(", ") + " from options") || this; 20 | } 21 | return MissingOptionsError; 22 | }(Error)); 23 | exports.MissingOptionsError = MissingOptionsError; 24 | -------------------------------------------------------------------------------- /lib/errors/UnsupportedError.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var UnsupportedError = /** @class */ (function (_super) { 17 | tslib_1.__extends(UnsupportedError, _super); 18 | function UnsupportedError(err) { 19 | return _super.call(this, "The issued command is unsupported: " + err) || this; 20 | } 21 | return UnsupportedError; 22 | }(Error)); 23 | exports.UnsupportedError = UnsupportedError; 24 | -------------------------------------------------------------------------------- /lib/execute.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var tslib_1 = require("tslib"); 16 | var Bluebird = require("bluebird"); 17 | var child_process_1 = require("child_process"); 18 | var ImageMagickMissingError_1 = require("./errors/ImageMagickMissingError"); 19 | var UnsupportedError_1 = require("./errors/UnsupportedError"); 20 | Promise = Promise || Bluebird; 21 | var availableImageMagickVersion = null; 22 | /** 23 | * Executes a command with arguments and returns the stdout and stderr. 24 | * 25 | * @param {string} command the command to run (convert, identify, etc). 26 | * @param {string[]} args 27 | * @returns {Promise} 28 | */ 29 | function execute(command, args) { 30 | return tslib_1.__awaiter(this, void 0, void 0, function () { 31 | var version; 32 | return tslib_1.__generator(this, function (_a) { 33 | switch (_a.label) { 34 | case 0: return [4 /*yield*/, getImageMagickVersion()]; 35 | case 1: 36 | version = _a.sent(); 37 | if (version === 7) { 38 | args.unshift(command); 39 | command = "magick"; 40 | } 41 | try { 42 | return [2 /*return*/, execFilePromised(command, args)]; 43 | } 44 | catch (err) { 45 | throw new UnsupportedError_1.UnsupportedError(err); 46 | } 47 | return [2 /*return*/]; 48 | } 49 | }); 50 | }); 51 | } 52 | exports.execute = execute; 53 | /** 54 | * Returns the latest available version of ImageMagick 55 | * 56 | * @param {boolean} fresh Do not used previously found version 57 | * @returns {Promise} 58 | */ 59 | function getImageMagickVersion(fresh) { 60 | return tslib_1.__awaiter(this, void 0, void 0, function () { 61 | return tslib_1.__generator(this, function (_a) { 62 | switch (_a.label) { 63 | case 0: 64 | if (!fresh && availableImageMagickVersion !== null) { 65 | return [2 /*return*/, availableImageMagickVersion]; 66 | } 67 | return [4 /*yield*/, hasMagicKCommand()]; 68 | case 1: 69 | if (!_a.sent()) return [3 /*break*/, 2]; 70 | availableImageMagickVersion = 7; 71 | return [3 /*break*/, 4]; 72 | case 2: return [4 /*yield*/, hasConvertCommand()]; 73 | case 3: 74 | if (_a.sent()) { 75 | availableImageMagickVersion = 6; 76 | } 77 | _a.label = 4; 78 | case 4: 79 | if (availableImageMagickVersion === null) { 80 | throw new ImageMagickMissingError_1.ImageMagickMissingError(); 81 | } 82 | return [2 /*return*/, availableImageMagickVersion]; 83 | } 84 | }); 85 | }); 86 | } 87 | exports.getImageMagickVersion = getImageMagickVersion; 88 | function hasMagicKCommand() { 89 | return tslib_1.__awaiter(this, void 0, void 0, function () { 90 | var stdout, e_1; 91 | return tslib_1.__generator(this, function (_a) { 92 | switch (_a.label) { 93 | case 0: 94 | _a.trys.push([0, 2, , 3]); 95 | return [4 /*yield*/, execFilePromised("magick", ["-version"])]; 96 | case 1: 97 | stdout = (_a.sent()).stdout; 98 | return [2 /*return*/, /ImageMagick/.test(stdout)]; 99 | case 2: 100 | e_1 = _a.sent(); 101 | return [2 /*return*/, false]; 102 | case 3: return [2 /*return*/]; 103 | } 104 | }); 105 | }); 106 | } 107 | function hasConvertCommand() { 108 | return tslib_1.__awaiter(this, void 0, void 0, function () { 109 | var stdout, e_2; 110 | return tslib_1.__generator(this, function (_a) { 111 | switch (_a.label) { 112 | case 0: 113 | _a.trys.push([0, 2, , 3]); 114 | return [4 /*yield*/, execFilePromised("convert", ["-version"])]; 115 | case 1: 116 | stdout = (_a.sent()).stdout; 117 | return [2 /*return*/, /ImageMagick/.test(stdout)]; 118 | case 2: 119 | e_2 = _a.sent(); 120 | return [2 /*return*/, false]; 121 | case 3: return [2 /*return*/]; 122 | } 123 | }); 124 | }); 125 | } 126 | function execFilePromised(command, args) { 127 | return tslib_1.__awaiter(this, void 0, void 0, function () { 128 | return tslib_1.__generator(this, function (_a) { 129 | return [2 /*return*/, new Promise(function (resolve, reject) { 130 | child_process_1.execFile(command, args, function (err, stdout, stderr) { 131 | if (err) { 132 | return reject(err); 133 | } 134 | return resolve({ stdout: stdout, stderr: stderr }); 135 | }); 136 | })]; 137 | }); 138 | }); 139 | } 140 | -------------------------------------------------------------------------------- /lib/options.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | -------------------------------------------------------------------------------- /lib/utilities.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | EasyImage 4 | 5 | EasyImage is a promise-based image processing module 6 | for Node.js, it is built on top of ImageMagick, so 7 | make sure ImageMagick is installed on your system. 8 | 9 | Copyright (c) 2015 Hage Yaapa 10 | Maintained by Kevin Gravier 11 | 12 | MIT License 13 | */ 14 | exports.__esModule = true; 15 | var Bluebird = require("bluebird"); 16 | var fs_1 = require("fs"); 17 | var mkdirp = require("mkdirp"); 18 | var nanoid = require("nanoid"); 19 | var os_1 = require("os"); 20 | var path_1 = require("path"); 21 | var BadDestinationError_1 = require("./errors/BadDestinationError"); 22 | var MissingExtensionError_1 = require("./errors/MissingExtensionError"); 23 | var MissingOptionsError_1 = require("./errors/MissingOptionsError"); 24 | Promise = Promise || Bluebird; 25 | function ensureDestinationDirectoryExists(options) { 26 | if (!options.dst) { 27 | return Promise.reject(new MissingOptionsError_1.MissingOptionsError(["dst"])); 28 | } 29 | return new Promise(function (resolve, reject) { 30 | var targetDirectory = path_1.dirname(options.dst); 31 | fs_1.exists(targetDirectory, function (doesExist) { 32 | if (doesExist) { 33 | resolve(); 34 | } 35 | else { 36 | mkdirp(targetDirectory, function (err, wasMade) { 37 | if (err) { 38 | return reject(err); 39 | } 40 | if (wasMade) { 41 | resolve(); 42 | } 43 | else { 44 | reject(new BadDestinationError_1.BadDestinationError()); 45 | } 46 | }); 47 | } 48 | }); 49 | }); 50 | } 51 | exports.ensureDestinationDirectoryExists = ensureDestinationDirectoryExists; 52 | function applyDefaultsToBaseOptions(options) { 53 | if (!options.hasOwnProperty("autoOrient")) { 54 | options.autoOrient = true; 55 | } 56 | if (!options.hasOwnProperty("dst")) { 57 | options.dst = makeTemporaryFile(options.src); 58 | } 59 | } 60 | exports.applyDefaultsToBaseOptions = applyDefaultsToBaseOptions; 61 | function applyBaseOptionsToArgs(options, args) { 62 | if (options.flatten && options.background) { 63 | args.push("-flatten", "-background", options.background); 64 | } 65 | else if (options.background) { 66 | args.push("-background", options.background, "-flatten"); 67 | } 68 | if (options.autoOrient) { 69 | args.push("-auto-orient"); 70 | } 71 | if (options.coalesce) { 72 | args.push("-coalesce"); 73 | } 74 | if (options.quality) { 75 | args.push("-quality", options.quality.toString()); 76 | } 77 | if (path_1.extname(options.src) === ".pdf") { 78 | args.push("-append"); 79 | } 80 | } 81 | exports.applyBaseOptionsToArgs = applyBaseOptionsToArgs; 82 | function checkForMissingOptions(options, requiredArgs) { 83 | var missingArgs = []; 84 | for (var _i = 0, requiredArgs_1 = requiredArgs; _i < requiredArgs_1.length; _i++) { 85 | var requiredArg = requiredArgs_1[_i]; 86 | if (!options.hasOwnProperty(requiredArg)) { 87 | missingArgs.push(requiredArg); 88 | } 89 | } 90 | if (missingArgs.length) { 91 | var args = missingArgs.filter(function (v) { return typeof v === "string"; }); 92 | throw new MissingOptionsError_1.MissingOptionsError(args); 93 | } 94 | } 95 | exports.checkForMissingOptions = checkForMissingOptions; 96 | function makeTemporaryFile(sourceFile) { 97 | var extension = path_1.extname(sourceFile); 98 | if (!extension) { 99 | throw new MissingExtensionError_1.MissingExtensionError(sourceFile); 100 | } 101 | var fileName = nanoid(8); 102 | return os_1.tmpdir() + "/EasyImage-" + fileName + extension; 103 | } 104 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easyimage", 3 | "version": "3.1.1", 4 | "description": "A promise-based, user-friendly module for processing images in Node.js", 5 | "license": "MIT", 6 | "main": "lib/easyimage.js", 7 | "types": "types/easyimage.d.ts", 8 | "scripts": { 9 | "test": "npm run lint && npm run mocha", 10 | "lint": "tslint -c tslint.json src/**/*.ts test/specs/*.ts", 11 | "mocha": "mocha -r ts-node/register --timeout 5000 test/specs/*spec.ts", 12 | "build": "npm run clean && npm run src && npm run doc", 13 | "doc": "typedoc src/execute.ts src/options.ts src/commands/* src/errors/*", 14 | "src": "tsc", 15 | "clean": "rimraf ./docs/* && rimraf ./lib/*" 16 | }, 17 | "author": { 18 | "name": "Hage Yaapa", 19 | "email": "captain@hacksparrow.com" 20 | }, 21 | "maintainers": [ 22 | { 23 | "name": "Kevin Gravier", 24 | "email": "kevin@mrkmg.com", 25 | "web": "https://github.com/mrkmg" 26 | } 27 | ], 28 | "keywords": [ 29 | "imagemagick", 30 | "image", 31 | "graphics", 32 | "process", 33 | "convert", 34 | "resize", 35 | "crop", 36 | "thumbnail", 37 | "promise" 38 | ], 39 | "repository": { 40 | "type": "git", 41 | "url": "https://github.com/hacksparrow/node-easyimage.git" 42 | }, 43 | "dependencies": { 44 | "bluebird": "^3.5.1", 45 | "mkdirp": "^0.5.0", 46 | "nanoid": "^1.0.2", 47 | "tslib": "^1.8.1", 48 | "typescript": "^3.3.0" 49 | }, 50 | "devDependencies": { 51 | "@types/bluebird": "^3.5.19", 52 | "@types/chai": "^4.1.0", 53 | "@types/chai-as-promised": "^7.1.0", 54 | "@types/mkdirp": "^0.5.2", 55 | "@types/mocha": "^2.2.46", 56 | "@types/nanoid": "^1.0.0", 57 | "@types/node": "=4", 58 | "@types/rimraf": "^2.0.2", 59 | "@types/sinon": "^4.1.3", 60 | "@types/sinon-chai": "^2.7.29", 61 | "chai": "^4.1.2", 62 | "chai-as-promised": "^7.1.1", 63 | "mocha": "^4.1.0", 64 | "rimraf": "^2.6.2", 65 | "sinon": "^4.1.6", 66 | "sinon-chai": "^2.14.0", 67 | "ts-node": "^4.1.0", 68 | "tslint": "^5.9.1", 69 | "typedoc": "^0.14.2" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/commands/convert.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | import * as Bluebird from "bluebird"; 14 | import {execute} from "../execute"; 15 | import {IBaseOptions} from "../options"; 16 | import {applyBaseOptionsToArgs, applyDefaultsToBaseOptions, checkForMissingOptions, ensureDestinationDirectoryExists} from "../utilities"; 17 | import {IInfoResult, info} from "./info"; 18 | 19 | Promise = Promise || Bluebird as any; 20 | 21 | /** 22 | * Converts an image from one format to another. 23 | * 24 | * @param {IConvertOptions} options 25 | * @returns {Bluebird} 26 | */ 27 | export async function convert(options: IConvertOptions): Promise { 28 | applyDefaultsToBaseOptions(options); 29 | checkForMissingOptions(options, ["src"]); 30 | 31 | await ensureDestinationDirectoryExists(options); 32 | 33 | const args: string[] = [options.src]; 34 | 35 | applyBaseOptionsToArgs(options, args); 36 | 37 | args.push(options.dst); 38 | 39 | await execute("convert", args); 40 | return info(options.dst); 41 | } 42 | 43 | // tslint:disable-next-line 44 | export interface IConvertOptions extends IBaseOptions { 45 | } 46 | -------------------------------------------------------------------------------- /src/commands/crop.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {execute} from "../execute"; 16 | import {IBaseOptions} from "../options"; 17 | import {applyBaseOptionsToArgs, applyDefaultsToBaseOptions, checkForMissingOptions, ensureDestinationDirectoryExists} from "../utilities"; 18 | import {IInfoResult, info} from "./info"; 19 | 20 | Promise = Promise || Bluebird as any; 21 | 22 | /** 23 | * Crops an image. 24 | * 25 | * @param {ICropOptions} options 26 | * @returns {Bluebird} 27 | */ 28 | export async function crop(options: ICropOptions): Promise { 29 | applyDefaultsToBaseOptions(options); 30 | upgradeCropOptions(options); 31 | applyDefaultsToCropOptions(options); 32 | 33 | checkForMissingOptions(options, ["src", "cropWidth"]); 34 | 35 | await ensureDestinationDirectoryExists(options); 36 | 37 | const args: string[] = [options.src]; 38 | 39 | applyBaseOptionsToArgs(options, args); 40 | 41 | let cropDefinition = `${options.cropWidth}`; 42 | if (options.cropHeight) { 43 | cropDefinition += `x${options.cropHeight}`; 44 | } 45 | cropDefinition += `+${options.x}+${options.y}`; 46 | 47 | if (options.gravity) { 48 | args.push("-gravity", options.gravity); 49 | } 50 | 51 | args.push("-crop", cropDefinition, options.dst); 52 | 53 | await execute("convert", args); 54 | return info(options.dst); 55 | } 56 | 57 | export interface ICropOptions extends IBaseOptions { 58 | /** 59 | * Width of cropped image. 60 | */ 61 | cropWidth: number; 62 | 63 | /** 64 | * Height of cropped image. 65 | * @default cropWidth 66 | */ 67 | cropHeight?: number; 68 | 69 | /** 70 | * Width of cropped image. 71 | * @deprecated 72 | */ 73 | cropwidth?: number; 74 | 75 | /** 76 | * Height of cropped image. 77 | * @deprecated 78 | */ 79 | cropheight?: number; 80 | 81 | /** 82 | * Gravity for crop. 83 | * @see https://www.imagemagick.org/script/command-line-options.php#gravity 84 | */ 85 | gravity?: string; 86 | 87 | /** 88 | * Left distance of crop 89 | * @default 0 90 | */ 91 | x?: number; 92 | 93 | /** 94 | * Top distance of crop 95 | * @default 0 96 | */ 97 | y?: number; 98 | } 99 | 100 | function upgradeCropOptions(options: ICropOptions) { 101 | if (!options.cropWidth && options.cropwidth) { 102 | options.cropWidth = options.cropwidth; 103 | } 104 | 105 | if (!options.cropHeight && options.cropheight) { 106 | options.cropHeight = options.cropheight; 107 | } 108 | } 109 | 110 | function applyDefaultsToCropOptions(options: ICropOptions) { 111 | if (!options.cropHeight) { 112 | options.cropHeight = options.cropWidth; 113 | } 114 | if (!options.x) { 115 | options.x = 0; 116 | } 117 | if (!options.y) { 118 | options.y = 0; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/commands/info.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {UnsupportedError} from "../errors/UnsupportedError"; 16 | import {execute} from "../execute"; 17 | 18 | Promise = Promise || Bluebird as any; 19 | 20 | /** 21 | * Returns information about an image. 22 | * 23 | * @param {string} filePath Path to the image file. 24 | * @returns {Bluebird} 25 | */ 26 | export async function info(filePath: string): Promise { 27 | const numberOfFrames = await getNumberOfFrames(filePath); 28 | 29 | const args = ["-format", "%m %z %w %h %b %x %y %[orientation] %f"]; 30 | 31 | if (numberOfFrames > 1) { 32 | args.push(`${filePath}[0]`); 33 | } else { 34 | args.push(filePath); 35 | } 36 | 37 | const {stdout, stderr} = await execute("identify", args); 38 | 39 | if (stdout === "") { 40 | throw new UnsupportedError("ImageMagick returned unexpected data."); 41 | } 42 | 43 | const temp = stdout 44 | .replace(/PixelsPerInch/g, "") 45 | .replace(/PixelsPerCentimeter/g, "") 46 | .split(/\s+/g); 47 | 48 | // All fields not found 49 | if (temp.length < 8) { 50 | throw new UnsupportedError("ImageMagick returned unexpected data."); 51 | } 52 | 53 | const result: IInfoResult = { 54 | density: { 55 | x: parseFloat(temp[5]), 56 | y: parseFloat(temp[6]), 57 | }, 58 | depth: parseInt(temp[1], 10), 59 | frames: numberOfFrames, 60 | height: parseInt(temp[3], 10), 61 | name: temp.slice(8).join(" ").replace(/(\r\n|\n|\r)/gm, "").trim(), 62 | orientation: temp[7], 63 | path: filePath, 64 | size: parseSize(temp[4]), 65 | type: temp[0].toLowerCase(), 66 | width: parseInt(temp[2], 10), 67 | }; 68 | 69 | if (stderr) { 70 | result.warnings = stderr; 71 | } 72 | 73 | return result; 74 | } 75 | 76 | async function getNumberOfFrames(filePath: string) { 77 | const args = ["-format", "%n\n", `${filePath}`]; 78 | 79 | const {stdout, stderr} = await execute("identify", args); 80 | 81 | if (stdout === "") { 82 | throw new UnsupportedError("ImageMagick returned unexpected data."); 83 | } 84 | 85 | return parseInt(stdout.split("\n")[0], 10); 86 | } 87 | 88 | export interface IInfoResult { 89 | /** 90 | * Type of file. 91 | */ 92 | type: string; 93 | 94 | /** 95 | * The number of bits in a color sample within a pixel. 96 | */ 97 | depth: number; 98 | 99 | /** 100 | * The width of the image. 101 | */ 102 | width: number; 103 | 104 | /** 105 | * The height of the image. 106 | */ 107 | height: number; 108 | 109 | /** 110 | * The filesize of the image in bytes. 111 | */ 112 | size: number; 113 | 114 | /** 115 | * The density of the image. 116 | */ 117 | density: IDensity; 118 | 119 | /** 120 | * The filename (excluding the path) of the image. 121 | */ 122 | name: string; 123 | 124 | /** 125 | * The path to the image. 126 | */ 127 | path: string; 128 | 129 | /** 130 | * Orientation of the image. 131 | */ 132 | orientation: string; 133 | 134 | /** 135 | * Number of frames in image. 136 | */ 137 | frames: number; 138 | 139 | /** 140 | * Any warnings that ImageMagick may have output. 141 | */ 142 | warnings?: string; 143 | } 144 | 145 | export interface IDensity { 146 | x: number; 147 | y: number; 148 | } 149 | 150 | const units = { 151 | B: 1, 152 | GB: 1000000000, 153 | KB: 1000, 154 | MB: 1000000, 155 | TB: 1000000000000, 156 | }; 157 | 158 | function parseSize(sizeString: string) { 159 | const rx = /^(\d*\.?\d*)([KMGT]?B)$/; // regex for extract the float value and its unit 160 | const sizeArray = rx.exec(sizeString); 161 | 162 | return parseFloat(sizeArray[1]) * (units as any)[sizeArray[2]]; 163 | } 164 | -------------------------------------------------------------------------------- /src/commands/rescrop.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {execute} from "../execute"; 16 | import {applyBaseOptionsToArgs, applyDefaultsToBaseOptions, checkForMissingOptions, ensureDestinationDirectoryExists} from "../utilities"; 17 | import {ICropOptions} from "./crop"; 18 | import {IInfoResult, info} from "./info"; 19 | import {IResizeOptions} from "./resize"; 20 | 21 | Promise = Promise || Bluebird as any; 22 | 23 | /** 24 | * Resizes and crops an image. 25 | * 26 | * @param {IResCropOptions} options 27 | * @returns {Bluebird} 28 | */ 29 | export async function rescrop(options: IResCropOptions): Promise { 30 | applyDefaultsToBaseOptions(options); 31 | upgradeCropOptions(options); 32 | applyDefaultsToRescropOptions(options); 33 | 34 | checkForMissingOptions(options, ["src", "cropWidth", "width"]); 35 | 36 | await ensureDestinationDirectoryExists(options); 37 | 38 | const args: string[] = [options.src]; 39 | 40 | applyBaseOptionsToArgs(options, args); 41 | 42 | let resizeDefinition = `${options.width}`; 43 | 44 | if (options.height) { 45 | resizeDefinition += `x${options.height}`; 46 | } 47 | if (options.ignoreAspectRatio) { resizeDefinition += "!"; } 48 | if (options.onlyDownscale) { 49 | if (/^win/.test(process.platform)) { 50 | resizeDefinition += "^>"; 51 | } else { 52 | resizeDefinition += ">"; 53 | } 54 | } 55 | 56 | let cropDefinition = `${options.cropWidth}`; 57 | if (options.cropHeight) { 58 | cropDefinition += `x${options.cropHeight}`; 59 | } 60 | cropDefinition += `+${options.x}+${options.y}`; 61 | 62 | if (options.gravity) { 63 | args.push("-gravity", options.gravity); 64 | } 65 | 66 | args.push("-resize", resizeDefinition, "-crop", cropDefinition, options.dst); 67 | 68 | await execute("convert", args); 69 | return info(options.dst); 70 | } 71 | 72 | export interface IResCropOptions extends ICropOptions, IResizeOptions { 73 | 74 | } 75 | 76 | function upgradeCropOptions(options: ICropOptions) { 77 | if (!options.cropWidth && options.cropwidth) { 78 | options.cropWidth = options.cropwidth; 79 | } 80 | 81 | if (!options.cropHeight && options.cropheight) { 82 | options.cropHeight = options.cropheight; 83 | } 84 | } 85 | 86 | function applyDefaultsToRescropOptions(options: IResCropOptions) { 87 | if (!options.cropHeight) { 88 | options.cropHeight = options.cropWidth; 89 | } 90 | if (!options.x) { 91 | options.x = 0; 92 | } 93 | if (!options.y) { 94 | options.y = 0; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/commands/resize.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {execute} from "../execute"; 16 | import {IBaseOptions} from "../options"; 17 | import {applyBaseOptionsToArgs, applyDefaultsToBaseOptions, checkForMissingOptions, ensureDestinationDirectoryExists} from "../utilities"; 18 | import {IInfoResult, info} from "./info"; 19 | 20 | Promise = Promise || Bluebird as any; 21 | 22 | /** 23 | * Resizes an image. 24 | * 25 | * @param {IResizeOptions} options 26 | * @returns {Bluebird} 27 | */ 28 | export async function resize(options: IResizeOptions): Promise { 29 | applyDefaultsToBaseOptions(options); 30 | applyDefaultsToResizeOptions(options); 31 | 32 | checkForMissingOptions(options, ["src", "width"]); 33 | 34 | await ensureDestinationDirectoryExists(options); 35 | 36 | const args: string[] = [options.src]; 37 | applyBaseOptionsToArgs(options, args); 38 | 39 | let resizeDefinition = `${options.width}`; 40 | 41 | if (options.height) { 42 | resizeDefinition += `x${options.height}`; 43 | } 44 | if (options.ignoreAspectRatio) { resizeDefinition += "!"; } 45 | if (options.onlyDownscale) { 46 | if (/^win/.test(process.platform)) { 47 | resizeDefinition += "^>"; 48 | } else { 49 | resizeDefinition += ">"; 50 | } 51 | } 52 | 53 | args.push("-resize", resizeDefinition, options.dst); 54 | 55 | await execute("convert", args); 56 | return info(options.dst); 57 | } 58 | 59 | export interface IResizeOptions extends IBaseOptions { 60 | /** 61 | * Width of resized image. 62 | */ 63 | width: number; 64 | 65 | /** 66 | * Height of resized image. 67 | * @default cropWidth 68 | */ 69 | height?: number; 70 | 71 | /** 72 | * Ignore aspect ratio when resizing. 73 | * @default false 74 | */ 75 | ignoreAspectRatio?: boolean; 76 | 77 | /** 78 | * Only reduce the size of the image. Do not increase it. 79 | * @default false 80 | */ 81 | onlyDownscale?: boolean; 82 | } 83 | 84 | function applyDefaultsToResizeOptions(options: IResizeOptions) { 85 | if (options.ignoreAspectRatio === undefined) { 86 | options.ignoreAspectRatio = false; 87 | } 88 | 89 | if (options.onlyDownscale === undefined) { 90 | options.onlyDownscale = false; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/commands/rotate.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {execute} from "../execute"; 16 | import {IBaseOptions} from "../options"; 17 | import {applyBaseOptionsToArgs, applyDefaultsToBaseOptions, checkForMissingOptions, ensureDestinationDirectoryExists} from "../utilities"; 18 | import {IInfoResult, info} from "./info"; 19 | 20 | Promise = Promise || Bluebird as any; 21 | 22 | /** 23 | * Rotates an image by a specified number of degrees. 24 | * 25 | * @param {IRotateOptions} options 26 | * @returns {Bluebird} 27 | */ 28 | export async function rotate(options: IRotateOptions): Promise { 29 | applyDefaultsToBaseOptions(options); 30 | 31 | checkForMissingOptions(options, ["src", "degree"]); 32 | 33 | await ensureDestinationDirectoryExists(options); 34 | 35 | const args: string[] = [options.src]; 36 | 37 | applyBaseOptionsToArgs(options, args); 38 | 39 | args.push("-rotate", options.degree.toString(), options.dst); 40 | 41 | await execute("convert", args); 42 | return info(options.dst); 43 | } 44 | 45 | export interface IRotateOptions extends IBaseOptions { 46 | /** 47 | * Number of degrees to rotate the image. 48 | */ 49 | degree: number; 50 | } 51 | -------------------------------------------------------------------------------- /src/commands/thumbnail.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {execute, getImageMagickVersion} from "../execute"; 16 | import {IBaseOptions} from "../options"; 17 | import {applyBaseOptionsToArgs, applyDefaultsToBaseOptions, checkForMissingOptions, ensureDestinationDirectoryExists} from "../utilities"; 18 | import {IInfoResult, info} from "./info"; 19 | 20 | Promise = Promise || Bluebird as any; 21 | 22 | /** 23 | * Creates a thumbnail of an image. 24 | * 25 | * @param {IThumbnailOptions} options 26 | * @returns {Bluebird} 27 | */ 28 | export async function thumbnail(options: IThumbnailOptions): Promise { 29 | applyDefaultsToBaseOptions(options); 30 | await applyDefaultsToThumbnailOptions(options); 31 | 32 | checkForMissingOptions(options, ["src", "width", "height"]); 33 | 34 | await ensureDestinationDirectoryExists(options); 35 | 36 | const infoData = await info(options.src); 37 | 38 | const args: string[] = [options.src]; 39 | 40 | applyBaseOptionsToArgs(options, args); 41 | 42 | if (options.gravity) { 43 | args.push("-gravity", options.gravity); 44 | } 45 | 46 | args.push("-interpolate", options.interpolate); 47 | args.push("-strip"); 48 | 49 | if (infoData.width > infoData.height) { 50 | args.push("-thumbnail", `x${options.height}`); 51 | } else { 52 | args.push("-thumbnail", `${options.width}x`); 53 | } 54 | 55 | args.push("-crop", `${options.width}x${options.height}+${options.x}+${options.y}`); 56 | args.push(options.dst); 57 | 58 | await execute("convert", args); 59 | return info(options.dst); 60 | } 61 | 62 | export interface IThumbnailOptions extends IBaseOptions { 63 | /** 64 | * Height of thumbnail. 65 | */ 66 | height: number; 67 | 68 | /** 69 | * Width of thumbnail. 70 | */ 71 | width: number; 72 | 73 | /** 74 | * Gravity for sizing. 75 | * @see https://www.imagemagick.org/script/command-line-options.php#gravity 76 | */ 77 | gravity?: string; 78 | 79 | /** 80 | * X offset for thumbnail. 81 | */ 82 | x?: number; 83 | 84 | /** 85 | * Y offset for thumbnail. 86 | */ 87 | y?: number; 88 | 89 | /** 90 | * Interpolate the thumbnail. 91 | */ 92 | interpolate?: string; 93 | } 94 | 95 | async function applyDefaultsToThumbnailOptions(options: IThumbnailOptions) { 96 | if (!options.x) { 97 | options.x = 0; 98 | } 99 | if (!options.y) { 100 | options.y = 0; 101 | } 102 | if (!options.interpolate) { 103 | const availableVersion = await getImageMagickVersion(); 104 | switch (availableVersion) { 105 | case 6: 106 | options.interpolate = "bicubic"; 107 | break; 108 | case 7: 109 | options.interpolate = "catrom"; 110 | break; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/easyimage.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export * from "./execute"; 15 | export * from "./commands/info"; 16 | export * from "./commands/crop"; 17 | export * from "./commands/convert"; 18 | export * from "./commands/resize"; 19 | export * from "./commands/rotate"; 20 | export * from "./commands/rescrop"; 21 | export * from "./commands/thumbnail"; 22 | 23 | export * from "./errors/BadDestinationError"; 24 | export * from "./errors/ImageMagickMissingError"; 25 | export * from "./errors/MissingExtensionError"; 26 | export * from "./errors/MissingOptionsError"; 27 | export * from "./errors/UnsupportedError"; 28 | -------------------------------------------------------------------------------- /src/errors/BadDestinationError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export class BadDestinationError extends Error { 15 | constructor() { 16 | super("`dst` directory could not be created"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/errors/ImageMagickMissingError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export class ImageMagickMissingError extends Error { 15 | constructor() { 16 | super("ImageMagick not found"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/errors/MissingExtensionError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export class MissingExtensionError extends Error { 15 | constructor(srcFile: string) { 16 | super(`${srcFile} does not have an extension`); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/errors/MissingOptionsError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export class MissingOptionsError extends Error { 15 | constructor(options: string[]) { 16 | super(`Missing ${options.map((o) => "`" + o + "`").join(", ")} from options`); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/errors/UnsupportedError.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export class UnsupportedError extends Error { 15 | constructor(err: string) { 16 | super(`The issued command is unsupported: ${err}`); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/execute.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import { execFile } from "child_process"; 16 | import {ImageMagickMissingError} from "./errors/ImageMagickMissingError"; 17 | import {UnsupportedError} from "./errors/UnsupportedError"; 18 | 19 | Promise = Promise || Bluebird as any; 20 | 21 | let availableImageMagickVersion: number = null; 22 | 23 | /** 24 | * Executes a command with arguments and returns the stdout and stderr. 25 | * 26 | * @param {string} command the command to run (convert, identify, etc). 27 | * @param {string[]} args 28 | * @returns {Promise} 29 | */ 30 | export async function execute(command: string, args: string[]): Promise { 31 | const version = await getImageMagickVersion(); 32 | 33 | if (version === 7) { 34 | args.unshift(command); 35 | command = "magick"; 36 | } 37 | 38 | try { 39 | return execFilePromised(command, args); 40 | } catch (err) { 41 | throw new UnsupportedError(err); 42 | } 43 | } 44 | 45 | /** 46 | * Returns the latest available version of ImageMagick 47 | * 48 | * @param {boolean} fresh Do not used previously found version 49 | * @returns {Promise} 50 | */ 51 | export async function getImageMagickVersion(fresh?: boolean) { 52 | if (!fresh && availableImageMagickVersion !== null) { 53 | return availableImageMagickVersion; 54 | } 55 | 56 | if (await hasMagicKCommand()) { 57 | availableImageMagickVersion = 7; 58 | } else if (await hasConvertCommand()) { 59 | availableImageMagickVersion = 6; 60 | } 61 | 62 | if (availableImageMagickVersion === null) { 63 | throw new ImageMagickMissingError(); 64 | } 65 | 66 | return availableImageMagickVersion; 67 | } 68 | 69 | export interface IImageMagickCommandResult { 70 | stdout: string; 71 | stderr: string; 72 | } 73 | 74 | async function hasMagicKCommand() { 75 | try { 76 | const {stdout} = await execFilePromised("magick", ["-version"]); 77 | return /ImageMagick/.test(stdout); 78 | } catch (e) { 79 | return false; 80 | } 81 | } 82 | 83 | async function hasConvertCommand() { 84 | try { 85 | const {stdout} = await execFilePromised("convert", ["-version"]); 86 | return /ImageMagick/.test(stdout); 87 | } catch (e) { 88 | return false; 89 | } 90 | } 91 | 92 | interface IExecFileResult { 93 | stdout: string; 94 | stderr: string; 95 | } 96 | 97 | async function execFilePromised(command: string, args?: string[]): Promise { 98 | return new Promise((resolve, reject) => { 99 | execFile(command, args, (err: Error, stdout: string, stderr: string) => { 100 | if (err) { 101 | return reject(err); 102 | } 103 | 104 | return resolve({stdout, stderr}); 105 | }); 106 | }); 107 | } 108 | -------------------------------------------------------------------------------- /src/options.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | export interface IBaseOptions { 15 | /** 16 | * Source file. 17 | */ 18 | src: string; 19 | 20 | /** 21 | * Destination file. 22 | * @default A temporary file 23 | */ 24 | dst?: string; 25 | 26 | /** 27 | * Auto orientate the image. 28 | * @default true 29 | */ 30 | autoOrient?: boolean; 31 | 32 | /** 33 | * Applies the "-coalesce" option. 34 | * @default false 35 | * @see https://www.imagemagick.org/script/command-line-options.php#coalesce 36 | */ 37 | coalesce?: boolean; 38 | 39 | /** 40 | * Flatten the resulting image. 41 | * @default false 42 | */ 43 | flatten?: boolean; 44 | 45 | /** 46 | * Apply a background color. 47 | */ 48 | background?: string; 49 | 50 | /** 51 | * Set the output quality. 52 | * @type number 1-100 53 | */ 54 | quality?: number; 55 | } 56 | -------------------------------------------------------------------------------- /src/utilities.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as Bluebird from "bluebird"; 15 | import {exists} from "fs"; 16 | import * as mkdirp from "mkdirp"; 17 | import nanoid = require("nanoid"); 18 | import {tmpdir} from "os"; 19 | import {dirname, extname} from "path"; 20 | import {BadDestinationError} from "./errors/BadDestinationError"; 21 | import {MissingExtensionError} from "./errors/MissingExtensionError"; 22 | import {MissingOptionsError} from "./errors/MissingOptionsError"; 23 | import {IBaseOptions} from "./options"; 24 | 25 | Promise = Promise || Bluebird as any; 26 | 27 | export function ensureDestinationDirectoryExists(options: IBaseOptions) { 28 | if (!options.dst) { 29 | return Promise.reject(new MissingOptionsError(["dst"])); 30 | } 31 | 32 | return new Promise((resolve, reject) => { 33 | const targetDirectory = dirname(options.dst); 34 | 35 | exists(targetDirectory, (doesExist) => { 36 | if (doesExist) { 37 | resolve(); 38 | } else { 39 | mkdirp(targetDirectory, (err: Error, wasMade) => { 40 | if (err) { 41 | return reject(err); 42 | } 43 | 44 | if (wasMade) { 45 | resolve(); 46 | } else { 47 | reject(new BadDestinationError()); 48 | } 49 | }); 50 | } 51 | }); 52 | }); 53 | } 54 | 55 | export function applyDefaultsToBaseOptions(options: IBaseOptions) { 56 | if (!options.hasOwnProperty("autoOrient")) { 57 | options.autoOrient = true; 58 | } 59 | 60 | if (!options.hasOwnProperty("dst")) { 61 | options.dst = makeTemporaryFile(options.src); 62 | } 63 | } 64 | 65 | export function applyBaseOptionsToArgs(options: IBaseOptions, args: string[]) { 66 | if (options.flatten && options.background) { 67 | args.push("-flatten", "-background", options.background); 68 | } else if (options.background) { 69 | args.push("-background", options.background, "-flatten"); 70 | } 71 | 72 | if (options.autoOrient) { 73 | args.push("-auto-orient"); 74 | } 75 | 76 | if (options.coalesce) { 77 | args.push("-coalesce"); 78 | } 79 | 80 | if (options.quality) { 81 | args.push("-quality", options.quality.toString()); 82 | } 83 | 84 | if (extname(options.src) === ".pdf") { 85 | args.push("-append"); 86 | } 87 | } 88 | 89 | export function checkForMissingOptions(options: T, requiredArgs: Array) { 90 | const missingArgs: Array = []; 91 | 92 | for (const requiredArg of requiredArgs) { 93 | if (!options.hasOwnProperty(requiredArg)) { 94 | missingArgs.push(requiredArg); 95 | } 96 | } 97 | 98 | if (missingArgs.length) { 99 | const args = missingArgs.filter((v) => typeof v === "string") as string[]; 100 | throw new MissingOptionsError(args); 101 | } 102 | } 103 | 104 | function makeTemporaryFile(sourceFile: string) { 105 | const extension = extname(sourceFile); 106 | if (!extension) { 107 | throw new MissingExtensionError(sourceFile); 108 | } 109 | const fileName = nanoid(8); 110 | return `${tmpdir()}/EasyImage-${fileName}${extension}`; 111 | } 112 | -------------------------------------------------------------------------------- /test/files/multiframe.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/test/files/multiframe.gif -------------------------------------------------------------------------------- /test/files/tall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/test/files/tall.png -------------------------------------------------------------------------------- /test/files/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/test/files/test.pdf -------------------------------------------------------------------------------- /test/files/wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/test/files/wide.jpg -------------------------------------------------------------------------------- /test/files/wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hacksparrow/node-easyimage/0126a498cab9b13ef1435aed152e7647526a5202/test/files/wide.png -------------------------------------------------------------------------------- /test/specs/convert.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import {mkdir, unlink} from "fs"; 17 | import "mocha"; 18 | import * as rimraf from "rimraf"; 19 | 20 | import {convert} from "../../src/commands/convert"; 21 | 22 | chai.use(chaiAsPromised); 23 | chai.should(); 24 | 25 | const files = `${__dirname}/../files`; 26 | const output = `${__dirname}/../output`; 27 | 28 | describe("convert command", () => { 29 | beforeEach((done: () => void) => { 30 | try { 31 | mkdir(output, () => done()); 32 | } catch (e) { 33 | done(); 34 | } 35 | }); 36 | 37 | afterEach((done: () => void) => { 38 | rimraf(output, done); 39 | }); 40 | 41 | describe("with image source", () => { 42 | it("should convert to image", async () => { 43 | const info = await convert({ 44 | dst: `${output}/test.png`, 45 | src: `${files}/wide.jpg`, 46 | }); 47 | 48 | info.should.be.an("object"); 49 | info.should.have.property("type"); 50 | info.should.have.property("name"); 51 | info.type.should.be.equal("png"); 52 | info.name.should.be.equal("test.png"); 53 | }); 54 | 55 | it("should convert to pdf", async () => { 56 | const info = await convert({ 57 | dst: `${output}/test.pdf`, 58 | src: `${files}/wide.jpg`, 59 | }); 60 | 61 | info.should.be.an("object"); 62 | info.should.have.property("type"); 63 | info.should.have.property("name"); 64 | info.type.should.be.equal("pdf"); 65 | info.name.should.be.equal("test.pdf"); 66 | }); 67 | }); 68 | 69 | describe("with pdf source", () => { 70 | it("should convert one page to image", async () => { 71 | const info = await convert({ 72 | dst: `${output}/test.png`, 73 | src: `${files}/test.pdf[1]`, 74 | }); 75 | 76 | info.should.be.an("object"); 77 | info.should.have.property("type"); 78 | info.should.have.property("name"); 79 | info.should.have.property("height"); 80 | info.type.should.be.equal("png"); 81 | info.name.should.be.equal("test.png"); 82 | info.height.should.be.equal(792); 83 | 84 | }); 85 | 86 | it("should convert all pages to image", async () => { 87 | const info = await convert({ 88 | dst: `${output}/test.png`, 89 | src: `${files}/test.pdf`, 90 | }); 91 | 92 | info.should.be.an("object"); 93 | info.should.have.property("type"); 94 | info.should.have.property("name"); 95 | info.should.have.property("height"); 96 | info.type.should.be.equal("png"); 97 | info.name.should.be.equal("test.png"); 98 | info.height.should.be.equal(1584); 99 | }); 100 | }); 101 | 102 | describe("to temporary file", () => { 103 | let fullPath: string = null; 104 | afterEach((done: () => void) => { 105 | if (fullPath) { 106 | unlink(fullPath, done); 107 | fullPath = null; 108 | } 109 | }); 110 | 111 | it("should create temporary dst file", async () => { 112 | const info = await convert({ 113 | src: `${files}/wide.jpg`, 114 | }); 115 | 116 | fullPath = info.path; 117 | 118 | info.should.be.an("object"); 119 | info.should.have.property("type"); 120 | info.should.have.property("name"); 121 | info.type.should.be.equal("jpeg"); 122 | // tslint:disable-next-line 123 | /EasyImage-.+\.jpg/.test(info.name).should.be.true; 124 | }); 125 | }); 126 | }); 127 | -------------------------------------------------------------------------------- /test/specs/crop.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import {mkdir} from "fs"; 17 | import "mocha"; 18 | import * as rimraf from "rimraf"; 19 | 20 | import {crop} from "../../src/commands/crop"; 21 | 22 | chai.use(chaiAsPromised); 23 | chai.should(); 24 | 25 | const files = `${__dirname}/../files`; 26 | const output = `${__dirname}/../output`; 27 | 28 | describe("crop command", () => { 29 | beforeEach((done: () => void) => { 30 | try { 31 | mkdir(output, done); 32 | } catch (e) { 33 | done(); 34 | } 35 | }); 36 | 37 | afterEach((done: () => void) => { 38 | rimraf(output, done); 39 | }); 40 | 41 | describe("to square (only cropWidth)", () => { 42 | it("should crop an image to smaller size", async () => { 43 | const info = await crop({ 44 | cropWidth: 50, 45 | dst: `${output}/test.png`, 46 | src: `${files}/wide.png`, 47 | }); 48 | 49 | info.width.should.be.equal(50); 50 | info.height.should.be.equal(50); 51 | }); 52 | 53 | it("shouldn't crop to larger", async () => { 54 | const info = await crop({ 55 | cropWidth: 500, 56 | dst: `${output}/test.png`, 57 | src: `${files}/wide.png`, 58 | }); 59 | 60 | info.width.should.be.equal(400); 61 | info.height.should.be.equal(200); 62 | }); 63 | }); 64 | 65 | describe("to rectangle (both cropWidth and cropHeight)", () => { 66 | it("should crop an image to smaller size", async () => { 67 | const info = await crop({ 68 | cropHeight: 75, 69 | cropWidth: 50, 70 | dst: `${output}/test.png`, 71 | src: `${files}/wide.png`, 72 | }); 73 | 74 | info.width.should.be.equal(50); 75 | info.height.should.be.equal(75); 76 | }); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /test/specs/easyimage.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import "mocha"; 17 | import * as EasyImage from "../../src/easyimage"; 18 | 19 | chai.use(chaiAsPromised); 20 | chai.should(); 21 | 22 | describe("EasyImage Global", () => { 23 | it("should be an object", () => { 24 | EasyImage.should.be.an("object"); 25 | }); 26 | 27 | it("should export helper functions", () => { 28 | EasyImage.should.have.property("execute"); 29 | EasyImage.should.have.property("getImageMagickVersion"); 30 | 31 | EasyImage.execute.should.be.a("function"); 32 | EasyImage.getImageMagickVersion.should.be.a("function"); 33 | }); 34 | 35 | it("should export commands", () => { 36 | EasyImage.should.have.property("convert"); 37 | EasyImage.should.have.property("crop"); 38 | EasyImage.should.have.property("info"); 39 | EasyImage.should.have.property("rescrop"); 40 | EasyImage.should.have.property("resize"); 41 | EasyImage.should.have.property("rotate"); 42 | 43 | EasyImage.convert.should.be.a("function"); 44 | EasyImage.crop.should.be.a("function"); 45 | EasyImage.info.should.be.a("function"); 46 | EasyImage.rescrop.should.be.a("function"); 47 | EasyImage.resize.should.be.a("function"); 48 | EasyImage.rotate.should.be.a("function"); 49 | 50 | }); 51 | 52 | it("should export error constructors", () => { 53 | EasyImage.should.have.property("BadDestinationError"); 54 | EasyImage.should.have.property("ImageMagickMissingError"); 55 | EasyImage.should.have.property("MissingExtensionError"); 56 | EasyImage.should.have.property("MissingOptionsError"); 57 | EasyImage.should.have.property("UnsupportedError"); 58 | 59 | EasyImage.BadDestinationError.should.be.a("function"); 60 | EasyImage.ImageMagickMissingError.should.be.a("function"); 61 | EasyImage.MissingExtensionError.should.be.a("function"); 62 | EasyImage.MissingOptionsError.should.be.a("function"); 63 | EasyImage.UnsupportedError.should.be.a("function"); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/specs/info.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import "mocha"; 17 | 18 | import {info} from "../../src/commands/info"; 19 | 20 | chai.use(chaiAsPromised); 21 | chai.should(); 22 | 23 | const files = `${__dirname}/../files`; 24 | 25 | describe("info command", () => { 26 | 27 | it("should return all fields", async () => { 28 | const fileInfo = await info(`${files}/wide.png`); 29 | 30 | fileInfo.should.be.an("object"); 31 | fileInfo.should.have.property("type"); 32 | fileInfo.should.have.property("depth"); 33 | fileInfo.should.have.property("width"); 34 | fileInfo.should.have.property("height"); 35 | fileInfo.should.have.property("size"); 36 | fileInfo.should.have.property("density"); 37 | fileInfo.should.have.property("orientation"); 38 | fileInfo.should.have.property("name"); 39 | fileInfo.should.have.property("path"); 40 | fileInfo.should.have.property("frames"); 41 | fileInfo.density.should.have.property("x"); 42 | fileInfo.density.should.have.property("y"); 43 | }); 44 | 45 | it("should get details for png", async () => { 46 | const fileInfo = await info(`${files}/wide.png`); 47 | 48 | fileInfo.type.should.equal("png"); 49 | fileInfo.depth.should.equal(8); 50 | fileInfo.width.should.equal(400); 51 | fileInfo.height.should.equal(200); 52 | fileInfo.size.should.closeTo(3565, 10); 53 | fileInfo.density.x.should.equal(28.35); 54 | fileInfo.density.y.should.equal(28.35); 55 | fileInfo.orientation.should.equal("Undefined"); 56 | fileInfo.name.should.equal("wide.png"); 57 | fileInfo.path.should.equal(`${files}/wide.png`); 58 | fileInfo.frames.should.equal(1); 59 | }); 60 | 61 | it("should work with a multi-frame gif", async () => { 62 | const fileInfo = await info(`${files}/multiframe.gif`); 63 | 64 | fileInfo.type.should.equal("gif"); 65 | fileInfo.depth.should.equal(8); 66 | fileInfo.width.should.equal(972); 67 | fileInfo.height.should.equal(730); 68 | fileInfo.size.should.closeTo(2045510, 1000); 69 | fileInfo.density.x.should.equal(72); 70 | fileInfo.density.y.should.equal(72); 71 | fileInfo.orientation.should.equal("Undefined"); 72 | fileInfo.name.should.equal("multiframe.gif"); 73 | fileInfo.path.should.equal(`${files}/multiframe.gif`); 74 | fileInfo.frames.should.equal(5); 75 | }); 76 | 77 | it("should work with a pdf", async () => { 78 | const fileInfo = await info(`${files}/test.pdf`); 79 | 80 | fileInfo.type.should.equal("pdf"); 81 | fileInfo.depth.should.equal(16); 82 | fileInfo.width.should.equal(612); 83 | fileInfo.height.should.equal(792); 84 | fileInfo.size.should.closeTo(6497, 100); 85 | fileInfo.density.x.should.equal(72); 86 | fileInfo.density.y.should.equal(72); 87 | fileInfo.orientation.should.equal("Undefined"); 88 | fileInfo.name.should.equal("test.pdf"); 89 | fileInfo.path.should.equal(`${files}/test.pdf`); 90 | fileInfo.frames.should.equal(2); 91 | }); 92 | }); 93 | -------------------------------------------------------------------------------- /test/specs/rescrop.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import {mkdir} from "fs"; 17 | import "mocha"; 18 | import * as rimraf from "rimraf"; 19 | 20 | import {rescrop} from "../../src/commands/rescrop"; 21 | 22 | chai.use(chaiAsPromised); 23 | chai.should(); 24 | 25 | const files = `${__dirname}/../files`; 26 | const output = `${__dirname}/../output`; 27 | 28 | describe("rescrop command", () => { 29 | beforeEach((done: () => void) => { 30 | try { 31 | mkdir(output, done); 32 | } catch (e) { 33 | done(); 34 | } 35 | }); 36 | 37 | afterEach((done: () => void) => { 38 | rimraf(output, done); 39 | }); 40 | 41 | it("should resize and crop an image", async () => { 42 | const info = await rescrop({ 43 | cropWidth: 50, 44 | dst: `${output}/wide.png`, 45 | height: 100, 46 | src: `${files}/wide.png`, 47 | width: 100, 48 | }); 49 | 50 | info.width.should.equal(50); 51 | info.height.should.equal(50); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/specs/resize.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import {mkdir} from "fs"; 17 | import "mocha"; 18 | import * as rimraf from "rimraf"; 19 | 20 | import {resize} from "../../src/commands/resize"; 21 | 22 | chai.use(chaiAsPromised); 23 | chai.should(); 24 | 25 | const files = `${__dirname}/../files`; 26 | const output = `${__dirname}/../output`; 27 | 28 | describe("resize command", () => { 29 | beforeEach((done: () => void) => { 30 | try { 31 | mkdir(output, done); 32 | } catch (e) { 33 | done(); 34 | } 35 | }); 36 | 37 | afterEach((done: () => void) => { 38 | rimraf(output, done); 39 | }); 40 | 41 | describe("with keeping aspect ratio", async () => { 42 | describe("with only width", () => { 43 | it("should make smaller image", async () => { 44 | const wideInfo = await resize({ 45 | dst: `${output}/wide.png`, 46 | src: `${files}/wide.png`, 47 | width: 50, 48 | }); 49 | const tallInfo = await resize({ 50 | dst: `${output}/tall.png`, 51 | src: `${files}/tall.png`, 52 | width: 50, 53 | }); 54 | 55 | wideInfo.width.should.equal(50); 56 | wideInfo.height.should.equal(25); 57 | 58 | tallInfo.width.should.equal(50); 59 | tallInfo.height.should.equal(100); 60 | }); 61 | 62 | it("should make larger image", async () => { 63 | const wideInfo = await resize({ 64 | dst: `${output}/wide.png`, 65 | src: `${files}/wide.png`, 66 | width: 500, 67 | }); 68 | const tallInfo = await resize({ 69 | dst: `${output}/tall.png`, 70 | src: `${files}/tall.png`, 71 | width: 500, 72 | }); 73 | 74 | wideInfo.width.should.equal(500); 75 | wideInfo.height.should.equal(250); 76 | 77 | tallInfo.width.should.equal(500); 78 | tallInfo.height.should.equal(1000); 79 | }); 80 | }); 81 | 82 | describe("with width and height", () => { 83 | it("should make smaller image", async () => { 84 | const wideInfo = await resize({ 85 | dst: `${output}/wide.png`, 86 | height: 100, 87 | src: `${files}/wide.png`, 88 | width: 100, 89 | }); 90 | const tallInfo = await resize({ 91 | dst: `${output}/tall.png`, 92 | height: 100, 93 | src: `${files}/tall.png`, 94 | width: 100, 95 | }); 96 | 97 | wideInfo.width.should.equal(100); 98 | wideInfo.height.should.equal(50); 99 | 100 | tallInfo.width.should.equal(50); 101 | tallInfo.height.should.equal(100); 102 | }); 103 | 104 | it("should make larger image", async () => { 105 | const wideInfo = await resize({ 106 | dst: `${output}/wide.png`, 107 | height: 500, 108 | src: `${files}/wide.png`, 109 | width: 500, 110 | }); 111 | const tallInfo = await resize({ 112 | dst: `${output}/tall.png`, 113 | height: 500, 114 | src: `${files}/tall.png`, 115 | width: 500, 116 | }); 117 | 118 | wideInfo.width.should.equal(500); 119 | wideInfo.height.should.equal(250); 120 | 121 | tallInfo.width.should.equal(250); 122 | tallInfo.height.should.equal(500); 123 | }); 124 | }); 125 | }); 126 | 127 | describe("without keeping aspect ratio", async () => { 128 | describe("with width and height", () => { 129 | it("should make smaller image", async () => { 130 | const wideInfo = await resize({ 131 | dst: `${output}/wide.png`, 132 | height: 100, 133 | ignoreAspectRatio: true, 134 | src: `${files}/wide.png`, 135 | width: 100, 136 | }); 137 | const tallInfo = await resize({ 138 | dst: `${output}/tall.png`, 139 | height: 100, 140 | ignoreAspectRatio: true, 141 | src: `${files}/tall.png`, 142 | width: 100, 143 | }); 144 | 145 | wideInfo.width.should.equal(100); 146 | wideInfo.height.should.equal(100); 147 | 148 | tallInfo.width.should.equal(100); 149 | tallInfo.height.should.equal(100); 150 | }); 151 | 152 | it("should make larger image", async () => { 153 | const wideInfo = await resize({ 154 | dst: `${output}/wide.png`, 155 | height: 500, 156 | ignoreAspectRatio: true, 157 | src: `${files}/wide.png`, 158 | width: 500, 159 | }); 160 | const tallInfo = await resize({ 161 | dst: `${output}/tall.png`, 162 | height: 500, 163 | ignoreAspectRatio: true, 164 | src: `${files}/tall.png`, 165 | width: 500, 166 | }); 167 | 168 | wideInfo.width.should.equal(500); 169 | wideInfo.height.should.equal(500); 170 | 171 | tallInfo.width.should.equal(500); 172 | tallInfo.height.should.equal(500); 173 | }); 174 | }); 175 | }); 176 | 177 | describe("with only downscaling", () => { 178 | it("should make a smaller image", async () => { 179 | const wideInfo = await resize({ 180 | dst: `${output}/wide.png`, 181 | height: 50, 182 | onlyDownscale: true, 183 | src: `${files}/wide.png`, 184 | width: 50, 185 | }); 186 | const tallInfo = await resize({ 187 | dst: `${output}/tall.png`, 188 | height: 50, 189 | onlyDownscale: true, 190 | src: `${files}/tall.png`, 191 | width: 50, 192 | }); 193 | 194 | wideInfo.width.should.equal(50); 195 | wideInfo.height.should.equal(25); 196 | 197 | tallInfo.width.should.equal(25); 198 | tallInfo.height.should.equal(50); 199 | }); 200 | 201 | it("shouldn't make larger image", async () => { 202 | const wideInfo = await resize({ 203 | dst: `${output}/wide.png`, 204 | height: 500, 205 | onlyDownscale: true, 206 | src: `${files}/wide.png`, 207 | width: 500, 208 | }); 209 | const tallInfo = await resize({ 210 | dst: `${output}/tall.png`, 211 | height: 500, 212 | onlyDownscale: true, 213 | src: `${files}/tall.png`, 214 | width: 500, 215 | }); 216 | 217 | wideInfo.width.should.equal(400); 218 | wideInfo.height.should.equal(200); 219 | 220 | tallInfo.width.should.equal(200); 221 | tallInfo.height.should.equal(400); 222 | }); 223 | }); 224 | }); 225 | -------------------------------------------------------------------------------- /test/specs/rotate.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import {mkdir} from "fs"; 17 | import "mocha"; 18 | import * as rimraf from "rimraf"; 19 | 20 | import {rotate} from "../../src/commands/rotate"; 21 | 22 | chai.use(chaiAsPromised); 23 | chai.should(); 24 | 25 | const files = `${__dirname}/../files`; 26 | const output = `${__dirname}/../output`; 27 | 28 | describe("rotate command", () => { 29 | beforeEach((done: () => void) => { 30 | try { 31 | mkdir(output, done); 32 | } catch (e) { 33 | done(); 34 | } 35 | }); 36 | 37 | afterEach((done: () => void) => { 38 | rimraf(output, done); 39 | }); 40 | 41 | it("should rotate an image", async () => { 42 | const info = await rotate({ 43 | degree: 90, 44 | dst: `${output}/wide.png`, 45 | src: `${files}/wide.png`, 46 | }); 47 | 48 | info.width.should.equal(200); 49 | info.height.should.equal(400); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/specs/thumbail.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | EasyImage 3 | 4 | EasyImage is a promise-based image processing module 5 | for Node.js, it is built on top of ImageMagick, so 6 | make sure ImageMagick is installed on your system. 7 | 8 | Copyright (c) 2015 Hage Yaapa 9 | Maintained by Kevin Gravier 10 | 11 | MIT License 12 | */ 13 | 14 | import * as chai from "chai"; 15 | import * as chaiAsPromised from "chai-as-promised"; 16 | import {mkdir} from "fs"; 17 | import "mocha"; 18 | import * as rimraf from "rimraf"; 19 | 20 | import {thumbnail} from "../../src/commands/thumbnail"; 21 | 22 | chai.use(chaiAsPromised); 23 | chai.should(); 24 | 25 | const files = `${__dirname}/../files`; 26 | const output = `${__dirname}/../output`; 27 | 28 | describe("thumbnail command", () => { 29 | beforeEach((done: () => void) => { 30 | try { 31 | mkdir(output, done); 32 | } catch (e) { 33 | done(); 34 | } 35 | }); 36 | 37 | afterEach((done: () => void) => { 38 | rimraf(output, done); 39 | }); 40 | 41 | it("should create a thumbnail", async () => { 42 | const info = await thumbnail({ 43 | dst: `${output}/wide.png`, 44 | height: 100, 45 | src: `${files}/wide.png`, 46 | width: 100, 47 | }); 48 | 49 | info.width.should.equal(100); 50 | info.height.should.equal(100); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitAny": true, 5 | "preserveConstEnums": true, 6 | "declaration": true, 7 | "declarationDir": "./types", 8 | "sourceMap": false, 9 | "outDir": "./lib", 10 | "skipLibCheck": true, 11 | "importHelpers": true, 12 | "lib": ["ES2015"] 13 | }, 14 | "include": ["./src/**/*"], 15 | "exclude": ["node_modules"] 16 | } 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": ["tslint:recommended"], 4 | "jsRules": {}, 5 | "rules": { 6 | "max-line-length": false 7 | }, 8 | "rulesDirectory": [] 9 | } 10 | -------------------------------------------------------------------------------- /typedoc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "out": "docs", 3 | "mode": "file", 4 | "excludeNotExported": true, 5 | "excludeExternals": true, 6 | "gitRevision": "master" 7 | }; 8 | -------------------------------------------------------------------------------- /types/commands/convert.d.ts: -------------------------------------------------------------------------------- 1 | import { IBaseOptions } from "../options"; 2 | import { IInfoResult } from "./info"; 3 | /** 4 | * Converts an image from one format to another. 5 | * 6 | * @param {IConvertOptions} options 7 | * @returns {Bluebird} 8 | */ 9 | export declare function convert(options: IConvertOptions): Promise; 10 | export interface IConvertOptions extends IBaseOptions { 11 | } 12 | -------------------------------------------------------------------------------- /types/commands/crop.d.ts: -------------------------------------------------------------------------------- 1 | import { IBaseOptions } from "../options"; 2 | import { IInfoResult } from "./info"; 3 | /** 4 | * Crops an image. 5 | * 6 | * @param {ICropOptions} options 7 | * @returns {Bluebird} 8 | */ 9 | export declare function crop(options: ICropOptions): Promise; 10 | export interface ICropOptions extends IBaseOptions { 11 | /** 12 | * Width of cropped image. 13 | */ 14 | cropWidth: number; 15 | /** 16 | * Height of cropped image. 17 | * @default cropWidth 18 | */ 19 | cropHeight?: number; 20 | /** 21 | * Width of cropped image. 22 | * @deprecated 23 | */ 24 | cropwidth?: number; 25 | /** 26 | * Height of cropped image. 27 | * @deprecated 28 | */ 29 | cropheight?: number; 30 | /** 31 | * Gravity for crop. 32 | * @see https://www.imagemagick.org/script/command-line-options.php#gravity 33 | */ 34 | gravity?: string; 35 | /** 36 | * Left distance of crop 37 | * @default 0 38 | */ 39 | x?: number; 40 | /** 41 | * Top distance of crop 42 | * @default 0 43 | */ 44 | y?: number; 45 | } 46 | -------------------------------------------------------------------------------- /types/commands/info.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns information about an image. 3 | * 4 | * @param {string} filePath Path to the image file. 5 | * @returns {Bluebird} 6 | */ 7 | export declare function info(filePath: string): Promise; 8 | export interface IInfoResult { 9 | /** 10 | * Type of file. 11 | */ 12 | type: string; 13 | /** 14 | * The number of bits in a color sample within a pixel. 15 | */ 16 | depth: number; 17 | /** 18 | * The width of the image. 19 | */ 20 | width: number; 21 | /** 22 | * The height of the image. 23 | */ 24 | height: number; 25 | /** 26 | * The filesize of the image in bytes. 27 | */ 28 | size: number; 29 | /** 30 | * The density of the image. 31 | */ 32 | density: IDensity; 33 | /** 34 | * The filename (excluding the path) of the image. 35 | */ 36 | name: string; 37 | /** 38 | * The path to the image. 39 | */ 40 | path: string; 41 | /** 42 | * Orientation of the image. 43 | */ 44 | orientation: string; 45 | /** 46 | * Number of frames in image. 47 | */ 48 | frames: number; 49 | /** 50 | * Any warnings that ImageMagick may have output. 51 | */ 52 | warnings?: string; 53 | } 54 | export interface IDensity { 55 | x: number; 56 | y: number; 57 | } 58 | -------------------------------------------------------------------------------- /types/commands/rescrop.d.ts: -------------------------------------------------------------------------------- 1 | import { ICropOptions } from "./crop"; 2 | import { IInfoResult } from "./info"; 3 | import { IResizeOptions } from "./resize"; 4 | /** 5 | * Resizes and crops an image. 6 | * 7 | * @param {IResCropOptions} options 8 | * @returns {Bluebird} 9 | */ 10 | export declare function rescrop(options: IResCropOptions): Promise; 11 | export interface IResCropOptions extends ICropOptions, IResizeOptions { 12 | } 13 | -------------------------------------------------------------------------------- /types/commands/resize.d.ts: -------------------------------------------------------------------------------- 1 | import { IBaseOptions } from "../options"; 2 | import { IInfoResult } from "./info"; 3 | /** 4 | * Resizes an image. 5 | * 6 | * @param {IResizeOptions} options 7 | * @returns {Bluebird} 8 | */ 9 | export declare function resize(options: IResizeOptions): Promise; 10 | export interface IResizeOptions extends IBaseOptions { 11 | /** 12 | * Width of resized image. 13 | */ 14 | width: number; 15 | /** 16 | * Height of resized image. 17 | * @default cropWidth 18 | */ 19 | height?: number; 20 | /** 21 | * Ignore aspect ratio when resizing. 22 | * @default false 23 | */ 24 | ignoreAspectRatio?: boolean; 25 | /** 26 | * Only reduce the size of the image. Do not increase it. 27 | * @default false 28 | */ 29 | onlyDownscale?: boolean; 30 | } 31 | -------------------------------------------------------------------------------- /types/commands/rotate.d.ts: -------------------------------------------------------------------------------- 1 | import { IBaseOptions } from "../options"; 2 | import { IInfoResult } from "./info"; 3 | /** 4 | * Rotates an image by a specified number of degrees. 5 | * 6 | * @param {IRotateOptions} options 7 | * @returns {Bluebird} 8 | */ 9 | export declare function rotate(options: IRotateOptions): Promise; 10 | export interface IRotateOptions extends IBaseOptions { 11 | /** 12 | * Number of degrees to rotate the image. 13 | */ 14 | degree: number; 15 | } 16 | -------------------------------------------------------------------------------- /types/commands/thumbnail.d.ts: -------------------------------------------------------------------------------- 1 | import { IBaseOptions } from "../options"; 2 | import { IInfoResult } from "./info"; 3 | /** 4 | * Creates a thumbnail of an image. 5 | * 6 | * @param {IThumbnailOptions} options 7 | * @returns {Bluebird} 8 | */ 9 | export declare function thumbnail(options: IThumbnailOptions): Promise; 10 | export interface IThumbnailOptions extends IBaseOptions { 11 | /** 12 | * Height of thumbnail. 13 | */ 14 | height: number; 15 | /** 16 | * Width of thumbnail. 17 | */ 18 | width: number; 19 | /** 20 | * Gravity for sizing. 21 | * @see https://www.imagemagick.org/script/command-line-options.php#gravity 22 | */ 23 | gravity?: string; 24 | /** 25 | * X offset for thumbnail. 26 | */ 27 | x?: number; 28 | /** 29 | * Y offset for thumbnail. 30 | */ 31 | y?: number; 32 | /** 33 | * Interpolate the thumbnail. 34 | */ 35 | interpolate?: string; 36 | } 37 | -------------------------------------------------------------------------------- /types/easyimage.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./execute"; 2 | export * from "./commands/info"; 3 | export * from "./commands/crop"; 4 | export * from "./commands/convert"; 5 | export * from "./commands/resize"; 6 | export * from "./commands/rotate"; 7 | export * from "./commands/rescrop"; 8 | export * from "./commands/thumbnail"; 9 | export * from "./errors/BadDestinationError"; 10 | export * from "./errors/ImageMagickMissingError"; 11 | export * from "./errors/MissingExtensionError"; 12 | export * from "./errors/MissingOptionsError"; 13 | export * from "./errors/UnsupportedError"; 14 | -------------------------------------------------------------------------------- /types/errors/BadDestinationError.d.ts: -------------------------------------------------------------------------------- 1 | export declare class BadDestinationError extends Error { 2 | constructor(); 3 | } 4 | -------------------------------------------------------------------------------- /types/errors/ImageMagickMissingError.d.ts: -------------------------------------------------------------------------------- 1 | export declare class ImageMagickMissingError extends Error { 2 | constructor(); 3 | } 4 | -------------------------------------------------------------------------------- /types/errors/MissingExtensionError.d.ts: -------------------------------------------------------------------------------- 1 | export declare class MissingExtensionError extends Error { 2 | constructor(srcFile: string); 3 | } 4 | -------------------------------------------------------------------------------- /types/errors/MissingOptionsError.d.ts: -------------------------------------------------------------------------------- 1 | export declare class MissingOptionsError extends Error { 2 | constructor(options: string[]); 3 | } 4 | -------------------------------------------------------------------------------- /types/errors/UnsupportedError.d.ts: -------------------------------------------------------------------------------- 1 | export declare class UnsupportedError extends Error { 2 | constructor(err: string); 3 | } 4 | -------------------------------------------------------------------------------- /types/execute.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Executes a command with arguments and returns the stdout and stderr. 3 | * 4 | * @param {string} command the command to run (convert, identify, etc). 5 | * @param {string[]} args 6 | * @returns {Promise} 7 | */ 8 | export declare function execute(command: string, args: string[]): Promise; 9 | /** 10 | * Returns the latest available version of ImageMagick 11 | * 12 | * @param {boolean} fresh Do not used previously found version 13 | * @returns {Promise} 14 | */ 15 | export declare function getImageMagickVersion(fresh?: boolean): Promise; 16 | export interface IImageMagickCommandResult { 17 | stdout: string; 18 | stderr: string; 19 | } 20 | -------------------------------------------------------------------------------- /types/options.d.ts: -------------------------------------------------------------------------------- 1 | export interface IBaseOptions { 2 | /** 3 | * Source file. 4 | */ 5 | src: string; 6 | /** 7 | * Destination file. 8 | * @default A temporary file 9 | */ 10 | dst?: string; 11 | /** 12 | * Auto orientate the image. 13 | * @default true 14 | */ 15 | autoOrient?: boolean; 16 | /** 17 | * Applies the "-coalesce" option. 18 | * @default false 19 | * @see https://www.imagemagick.org/script/command-line-options.php#coalesce 20 | */ 21 | coalesce?: boolean; 22 | /** 23 | * Flatten the resulting image. 24 | * @default false 25 | */ 26 | flatten?: boolean; 27 | /** 28 | * Apply a background color. 29 | */ 30 | background?: string; 31 | /** 32 | * Set the output quality. 33 | * @type number 1-100 34 | */ 35 | quality?: number; 36 | } 37 | -------------------------------------------------------------------------------- /types/utilities.d.ts: -------------------------------------------------------------------------------- 1 | import { IBaseOptions } from "./options"; 2 | export declare function ensureDestinationDirectoryExists(options: IBaseOptions): Promise<{}>; 3 | export declare function applyDefaultsToBaseOptions(options: IBaseOptions): void; 4 | export declare function applyBaseOptionsToArgs(options: IBaseOptions, args: string[]): void; 5 | export declare function checkForMissingOptions(options: T, requiredArgs: Array): void; 6 | --------------------------------------------------------------------------------