UNPKG

11.8 kBPlain TextView Raw
1#!/usr/bin/env node
2
3const fs = require('fs')
4const path = require('path')
5const program = require('commander')
6const imaginary = require('..')
7
8program
9 .version(imaginary.VERSION)
10
11program
12 .command('crop [image]')
13 .description('Crop any image in order to fit the given width or height pixels')
14 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
15 .option('-k, --key [code]', 'Optional imaginary server API key')
16 .option('-w, --width [pixels]', 'Image width resolution')
17 .option('-h, --height [pixels]', 'Image height resolution')
18 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
19 .option('-c, --compression [level]', 'PNG compression level', 6)
20 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
21 .option('-o, --output [path]', 'Output image file path')
22 .action(command('crop'))
23
24program
25 .command('smartcrop [image]')
26 .description('Smart crop any image in order to fit the given width or height pixels. Requires imaginary v1.0.8+')
27 .option('-s, --server [url]', 'imaginary service URL', imaginary.URL)
28 .option('-k, --key [code]', 'Optional imaginary server API key')
29 .option('-w, --width [pixels]', 'Image width resolution')
30 .option('-h, --height [pixels]', 'Image height resolution')
31 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
32 .option('-c, --compression [level]', 'PNG compression level', 6)
33 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
34 .option('-o, --output [path]', 'Output image file path')
35 .action(command('smartcrop'))
36
37program
38 .command('resize [image]')
39 .description('Resize the image to the given width or height in pixels')
40 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
41 .option('-k, --key [code]', 'Optional imaginary server API key')
42 .option('-w, --width [pixels]', 'Image width resolution')
43 .option('-h, --height [pixels]', 'Image height resolution')
44 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
45 .option('-c, --compression [level]', 'PNG compression level', 6)
46 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
47 .option('-o, --output [path]', 'Output image file path')
48 .action(command('resize'))
49
50program
51 .command('embed [image]')
52 .description('Embed the image to the given width or height in pixels')
53 .option('-k, --key [code]', 'Optional imaginary server API key')
54 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
55 .option('-w, --width [pixels]', 'Image width resolution')
56 .option('-h, --height [pixels]', 'Image height resolution')
57 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
58 .option('-c, --compression [level]', 'PNG compression level', 6)
59 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
60 .option('-o, --output [path]', 'Output image file path')
61 .action(command('embed'))
62
63program
64 .command('enlarge [image]')
65 .description('Enlarge the image to the given width and height in pixels')
66 .option('-k, --key [code]', 'Optional imaginary server API key')
67 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
68 .option('-w, --width [pixels]', 'Image width resolution')
69 .option('-h, --height [pixels]', 'Image height resolution')
70 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
71 .option('-c, --compression [level]', 'PNG compression level', 6)
72 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
73 .option('-o, --output [path]', 'Output image file path')
74 .action(command('enlarge'))
75
76program
77 .command('extract [image]')
78 .description('Extract area from an image by top/left and width/height')
79 .option('-k, --key [code]', 'Optional imaginary server API key')
80 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
81 .option('-w, --width [pixels]', 'Image width resolution')
82 .option('-h, --height [pixels]', 'Image height resolution')
83 .option('-t, --top [pixels]', 'Area top margin')
84 .option('-l, --left [pixels]', 'Area left margin')
85 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
86 .option('-c, --compression [level]', 'PNG compression level', 6)
87 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
88 .option('-o, --output [path]', 'Output image file path')
89 .action(command('extract'))
90
91program
92 .command('rotate [image]')
93 .description('Rotate the image by degrees')
94 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
95 .option('-k, --key [code]', 'Optional imaginary server API key')
96 .option('-w, --width [pixels]', 'Image width resolution')
97 .option('-h, --height [pixels]', 'Image height resolution')
98 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
99 .option('-c, --compression [level]', 'PNG compression level', 6)
100 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
101 .option('-r, --rotate [angle]', 'Image rotation angle. Must be multiple of 90. Example: 180')
102 .option('-o, --output [path]', 'Output image file path')
103 .action(command('rotate'))
104
105program
106 .command('flip [image]')
107 .description('Flip an image')
108 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
109 .option('-k, --key [code]', 'Optional imaginary server API key')
110 .option('-w, --width [pixels]', 'Image width resolution')
111 .option('-h, --height [pixels]', 'Image height resolution')
112 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
113 .option('-c, --compression [level]', 'PNG compression level', 6)
114 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
115 .option('-o, --output [path]', 'Output image file path')
116 .action(command('flip'))
117
118program
119 .command('flop [image]')
120 .description('Flop an image')
121 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
122 .option('-k, --key [code]', 'Optional imaginary server API key')
123 .option('-w, --width [pixels]', 'Image width resolution')
124 .option('-h, --height [pixels]', 'Image height resolution')
125 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
126 .option('-c, --compression [level]', 'PNG compression level', 6)
127 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
128 .option('-o, --output [path]', 'Output image file path')
129 .action(command('flop'))
130
131program
132 .command('zoom [image]')
133 .description('Zoom the image to the given width or height in pixels')
134 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
135 .option('-k, --key [code]', 'Optional imaginary server API key')
136 .option('-w, --width [pixels]', 'Image width resolution')
137 .option('-h, --height [pixels]', 'Image height resolution')
138 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
139 .option('-c, --compression [level]', 'PNG compression level', 6)
140 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
141 .option('-f, --factor [level]', 'Zoom factor level between 1-5', 1)
142 .option('-o, --output [path]', 'Output image file path')
143 .action(command('zoom'))
144
145program
146 .command('watermark [image]')
147 .description('Add a text watermark in the image')
148 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
149 .option('-k, --key [code]', 'Optional imaginary server API key')
150 .option('-w, --width [pixels]', 'Image width resolution')
151 .option('-h, --height [pixels]', 'Image height resolution')
152 .option('-q, --quality [num]', 'JPEG image quality between 1-100', 80)
153 .option('-c, --compression [level]', 'PNG compression level', 6)
154 .option('-t, --type [name]', 'Specify the image format to output. Possible values are: jpeg, png and webp')
155 .option('-x, --text [text]', 'Watermark text content. Example: copyright (c)')
156 .option('-m, --margin [num]', 'Text margin in pixels. Example: 100')
157 .option('-d, --dip [num]', 'DPI value for watermark. Example: 150')
158 .option('-y, --textwidth [num]', 'Text width for watermark. Example: 200')
159 .option('-s, --opacity [num]', 'Opacity level for watermark text. Example: 0.2')
160 .option('-r, --noreplicate', 'Disable text replication in watermark')
161 .option('-f, --font [value]', 'Watermark text font type and format. Example: sans bold 12')
162 .option('-m, --color [value]', 'Watermark text RGB decimal base color. Example: 255,200,150')
163 .option('-o, --output [path]', 'Output image file path')
164 .action(command('watermark'))
165
166program
167 .command('pipeline [image]')
168 .description('Pipeline processing based on a JSON file transformation. Requires imaginary v1.0.8+')
169 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
170 .option('-k, --key [code]', 'Optional imaginary server API key')
171 .option('-j, --json [path]', 'Operations JSON file path to use. Optionally loaded from stdin.')
172 .option('-p, --operations [json]', 'Operations JSON string to use.')
173 .option('-o, --output [path]', 'Output image file path')
174 .action(pipeline)
175
176program
177 .command('info [image]')
178 .description('Retrieve image information as JSON')
179 .option('-s, --server [url]', 'imaginary server URL', imaginary.URL)
180 .option('-k, --key [code]', 'Optional imaginary server API key')
181 .option('-o, --output [path]', 'Output image info file (JSON)')
182 .action(command('info'))
183
184program.on('--help', function () {
185 console.log(' Examples:')
186 console.log('')
187 console.log(' $ imaginary crop -w 300 -h 260 -o out.jpg image.jpg')
188 console.log(' $ imaginary smartcrop -w 300 -h 260 -o out.jpg image.jpg')
189 console.log(' $ imaginary pipeline -j operations.json -o out.jpg image.jpg')
190 console.log(' $ imaginary resize -w 300 -o out.jpg http://server.net/image.jpg')
191 console.log(' $ imaginary zoom -f 2 -w 300 -o out.jpg http://server.net/image.jpg')
192 console.log(' $ imaginary watermark --text "copyright" -o out.jpg http://server.net/image.jpg')
193 console.log('')
194})
195
196program.parse(process.argv)
197
198function command (action) {
199 return function (image, flags) {
200 const output = flags.output || path.basename(image)
201 const opts = params(flags)
202
203 imaginary(image, flags.server)[action](opts)
204 .on('error', exitWithError)
205 .pipe(fs.createWriteStream(output))
206 }
207}
208
209function pipeline (image, flags) {
210 const output = flags.output || path.basename(image)
211 const opts = params(flags)
212
213 // Load JSON operations from disk
214 if (opts.json) {
215 opts.operations = JSON.parse(fs.readFileSync(opts.json))
216 }
217
218 // Parse operations if a string if given
219 if (opts.operations && typeof opts.operations === 'string') {
220 opts.operations = JSON.parse(opts.operations)
221 }
222
223 // Validate proper input object
224 if (!Array.isArray(opts.operations)) {
225 return exitWithError('operations must be a JSON list of objects')
226 }
227
228 imaginary(image, flags.server).pipeline(opts.operations, opts)
229 .on('error', exitWithError)
230 .pipe(fs.createWriteStream(output))
231}
232
233function params (opts) {
234 const buf = {}
235
236 Object.keys(opts).forEach(function (key) {
237 if (omit(key)) {
238 buf[key] = opts[key]
239 }
240 })
241
242 return buf
243}
244
245function omit (key) {
246 const omitFields = ['output', 'server', 'options', 'parent', 'commands']
247
248 return !~omitFields.indexOf(key) &&
249 key.charAt(0) !== '_' &&
250 key.length > 2
251}
252
253function exitWithError (err) {
254 console.error('Cannot process image:', err.message || err)
255 process.exit(1)
256}