mini_magick 4.7.2 → 4.13.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3f5606d4a6e91d6ad90a393da30244dc774e374b
4
- data.tar.gz: 71ff2a31e86426bfd514879b787fd530cf2717ad
2
+ SHA256:
3
+ metadata.gz: 44b0562f09fa6d0cc281ad1c4317b8e9915aa60dc6175072dc0cdc872f3d8367
4
+ data.tar.gz: 96225cd5bd66e3c0c065cb169057e196becfcdd1e0c883cb7c23f746d76bcda6
5
5
  SHA512:
6
- metadata.gz: 5b17e89081bd677cd255e377c9dd22b64bc37dc467a81f4bbd0d7fde27cc552d99f3927d23ce48c9becabe37234652cd0fdd913062316fe57c3b85a003d51ad7
7
- data.tar.gz: 32d0e633b52b6d6104fa8633db9579dbe78513a3ad997737bc1506c3cc9ddb375015afbc3423fc9ee72b3fba4c710597306c167c2094f33b792f9f9c383a6d85
6
+ metadata.gz: a39cb409419be063b9cc27fd107a361d94d3f5dbdad719ed1f472efca70650c710160494f22b18f1408df479f29836d29c2bd71262ad1988cdf22caf85a9251a
7
+ data.tar.gz: dbb5ba23b0b773a696812ec343f0d267aee1653b0ebfb61ea9560af9c4cac68352b7c936c57233913d8848a1de3c9fe02e31070a94e5f3f0d7f471e444615a55
data/README.md ADDED
@@ -0,0 +1,573 @@
1
+ # MiniMagick
2
+ [![Gem Version](https://img.shields.io/gem/v/mini_magick.svg)](http://rubygems.org/gems/mini_magick)
3
+ [![Gem Downloads](https://img.shields.io/gem/dt/mini_magick.svg)](http://rubygems.org/gems/mini_magick)
4
+ [![CI](https://github.com/minimagick/minimagick/actions/workflows/ci.yml/badge.svg)](https://github.com/minimagick/minimagick/actions/workflows/ci.yml)
5
+ [![Code Climate](https://codeclimate.com/github/minimagick/minimagick/badges/gpa.svg)](https://codeclimate.com/github/minimagick/minimagick)
6
+
7
+ A ruby wrapper for [ImageMagick](http://imagemagick.org/) or
8
+ [GraphicsMagick](http://www.graphicsmagick.org/) command line.
9
+
10
+ ## Why?
11
+
12
+ I was using [RMagick](https://github.com/rmagick/rmagick) and loving it, but it
13
+ was eating up huge amounts of memory. Even a simple script would use over 100MB
14
+ of RAM. On my local machine this wasn't a problem, but on my hosting server the
15
+ ruby apps would crash because of their 100MB memory limit.
16
+
17
+ ## Solution!
18
+
19
+ Using MiniMagick the ruby processes memory remains small (it spawns
20
+ ImageMagick's command line program mogrify which takes up some memory as well,
21
+ but is much smaller compared to RMagick). See [Thinking of switching from
22
+ RMagick?](#thinking-of-switching-from-rmagick) below.
23
+
24
+ MiniMagick gives you access to all the command line options ImageMagick has
25
+ (found [here](http://www.imagemagick.org/script/command-line-options.php)).
26
+
27
+ ## Requirements
28
+
29
+ ImageMagick or GraphicsMagick command-line tool has to be installed. You can
30
+ check if you have it installed by running
31
+
32
+ ```sh
33
+ $ magick -version
34
+ Version: ImageMagick 7.1.1-33 Q16-HDRI aarch64 22263 https://imagemagick.org
35
+ Copyright: (C) 1999 ImageMagick Studio LLC
36
+ License: https://imagemagick.org/script/license.php
37
+ Features: Cipher DPC HDRI Modules OpenMP(5.0)
38
+ Delegates (built-in): bzlib fontconfig freetype gslib heic jng jp2 jpeg jxl lcms lqr ltdl lzma openexr png ps raw tiff webp xml zlib zstd
39
+ Compiler: gcc (4.2)
40
+ ```
41
+
42
+ ## Installation
43
+
44
+ Add the gem to your Gemfile:
45
+
46
+ ```rb
47
+ gem "mini_magick"
48
+ ```
49
+
50
+ ## Information
51
+
52
+ * [API documentation](http://rubydoc.info/github/minimagick/minimagick)
53
+
54
+ ## Usage
55
+
56
+ Let's first see a basic example of resizing an image.
57
+
58
+ ```rb
59
+ require "mini_magick"
60
+
61
+ image = MiniMagick::Image.open("input.jpg")
62
+ image.path #=> "/var/folders/k7/6zx6dx6x7ys3rv3srh0nyfj00000gn/T/magick20140921-75881-1yho3zc.jpg"
63
+ image.resize "100x100"
64
+ image.format "png"
65
+ image.write "output.png"
66
+ ```
67
+
68
+ `MiniMagick::Image.open` makes a copy of the image, and further methods modify
69
+ that copy (the original stays untouched). We then
70
+ [resize](http://www.imagemagick.org/script/command-line-options.php#resize)
71
+ the image, and write it to a file. The writing part is necessary because
72
+ the copy is just temporary, it gets garbage collected when we lose reference
73
+ to the image.
74
+
75
+ `MiniMagick::Image.open` also accepts URLs, and options passed in will be
76
+ forwarded to open-uri.
77
+
78
+ ```rb
79
+ image = MiniMagick::Image.open("http://example.com/image.jpg")
80
+ image.contrast
81
+ image.write("from_internets.jpg")
82
+ ```
83
+
84
+ On the other hand, if we want the original image to actually *get* modified,
85
+ we can use `MiniMagick::Image.new`.
86
+
87
+ ```rb
88
+ image = MiniMagick::Image.new("input.jpg")
89
+ image.path #=> "input.jpg"
90
+ image.resize "100x100"
91
+ # Not calling #write, because it's not a copy
92
+ ```
93
+
94
+ ### Combine options
95
+
96
+ While using methods like `#resize` directly is convenient, if we use more
97
+ methods in this way, it quickly becomes inefficient, because it calls the
98
+ command on each methods call. `MiniMagick::Image#combine_options` takes
99
+ multiple options and from them builds one single command.
100
+
101
+ ```rb
102
+ image.combine_options do |b|
103
+ b.resize "250x200>"
104
+ b.rotate "-90"
105
+ b.flip
106
+ end # the command gets executed
107
+ ```
108
+
109
+ As a handy shortcut, `MiniMagick::Image.new` also accepts an optional block
110
+ which is used to `combine_options`.
111
+
112
+ ```rb
113
+ image = MiniMagick::Image.new("input.jpg") do |b|
114
+ b.resize "250x200>"
115
+ b.rotate "-90"
116
+ b.flip
117
+ end # the command gets executed
118
+ ```
119
+
120
+ The yielded builder is an instance of `MiniMagick::Tool::Mogrify`. To learn more
121
+ about its interface, see [Metal](#metal) below.
122
+
123
+ ### Attributes
124
+
125
+ A `MiniMagick::Image` has various handy attributes.
126
+
127
+ ```rb
128
+ image.type #=> "JPEG"
129
+ image.mime_type #=> "image/jpeg"
130
+ image.width #=> 250
131
+ image.height #=> 300
132
+ image.dimensions #=> [250, 300]
133
+ image.size #=> 3451 (in bytes)
134
+ image.colorspace #=> "DirectClass sRGB"
135
+ image.exif #=> {"DateTimeOriginal" => "2013:09:04 08:03:39", ...}
136
+ image.resolution #=> [75, 75]
137
+ image.signature #=> "60a7848c4ca6e36b8e2c5dea632ecdc29e9637791d2c59ebf7a54c0c6a74ef7e"
138
+ ```
139
+
140
+ If you need more control, you can also access [raw image
141
+ attributes](http://www.imagemagick.org/script/escape.php):
142
+
143
+ ```rb
144
+ image["%[gamma]"] # "0.9"
145
+ ```
146
+
147
+ To get the all information about the image, MiniMagick gives you a handy method
148
+ which returns the output from `identify -verbose` in hash format:
149
+
150
+ ```rb
151
+ image.data #=>
152
+ # {
153
+ # "format": "JPEG",
154
+ # "mimeType": "image/jpeg",
155
+ # "class": "DirectClass",
156
+ # "geometry": {
157
+ # "width": 200,
158
+ # "height": 276,
159
+ # "x": 0,
160
+ # "y": 0
161
+ # },
162
+ # "resolution": {
163
+ # "x": "300",
164
+ # "y": "300"
165
+ # },
166
+ # "colorspace": "sRGB",
167
+ # "channelDepth": {
168
+ # "red": 8,
169
+ # "green": 8,
170
+ # "blue": 8
171
+ # },
172
+ # "quality": 92,
173
+ # "properties": {
174
+ # "date:create": "2016-07-11T19:17:53+08:00",
175
+ # "date:modify": "2016-07-11T19:17:53+08:00",
176
+ # "exif:ColorSpace": "1",
177
+ # "exif:ExifImageLength": "276",
178
+ # "exif:ExifImageWidth": "200",
179
+ # "exif:ExifOffset": "90",
180
+ # "exif:Orientation": "1",
181
+ # "exif:ResolutionUnit": "2",
182
+ # "exif:XResolution": "300/1",
183
+ # "exif:YResolution": "300/1",
184
+ # "icc:copyright": "Copyright (c) 1998 Hewlett-Packard Company",
185
+ # "icc:description": "sRGB IEC61966-2.1",
186
+ # "icc:manufacturer": "IEC http://www.iec.ch",
187
+ # "icc:model": "IEC 61966-2.1 Default RGB colour space - sRGB",
188
+ # "jpeg:colorspace": "2",
189
+ # "jpeg:sampling-factor": "1x1,1x1,1x1",
190
+ # "signature": "1b2336f023e5be4a9f357848df9803527afacd4987ecc18c4295a272403e52c1"
191
+ # },
192
+ # ...
193
+ # }
194
+ ```
195
+
196
+ Note that `MiniMagick::Image#data` is supported only on ImageMagick 6.8.8-3 or
197
+ above, for GraphicsMagick or older versions of ImageMagick use
198
+ `MiniMagick::Image#details`.
199
+
200
+ ### Pixels
201
+
202
+ With MiniMagick you can retrieve a matrix of image pixels, where each member of
203
+ the matrix is a 3-element array of numbers between 0-255, one for each range of
204
+ the RGB color channels.
205
+
206
+ ```rb
207
+ image = MiniMagick::Image.open("image.jpg")
208
+ pixels = image.get_pixels
209
+ pixels[3][2][1] # the green channel value from the 4th-row, 3rd-column pixel
210
+ ```
211
+
212
+ It can also be called after applying transformations:
213
+
214
+ ```rb
215
+ image = MiniMagick::Image.open("image.jpg")
216
+ image.crop "20x30+10+5"
217
+ image.colorspace "Gray"
218
+ pixels = image.get_pixels
219
+ ```
220
+
221
+ ### Pixels To Image
222
+
223
+ Sometimes when you have pixels and want to create image from pixels, you can do this to form an image:
224
+ ```rb
225
+ image = MiniMagick::Image.open('/Users/rabin/input.jpg')
226
+ pixels = image.get_pixels
227
+ depth = 8
228
+ dimension = [image.width, image.height]
229
+ map = 'rgb'
230
+ image = MiniMagick::Image.get_image_from_pixels(pixels, dimension, map, depth ,'jpg')
231
+ image.write('/Users/rabin/output.jpg')
232
+
233
+ ```
234
+
235
+ In this example, the returned pixels should now have equal R, G, and B values.
236
+
237
+ ### Configuration
238
+
239
+ ```rb
240
+ MiniMagick.configure do |config|
241
+ config.cli = :graphicsmagick
242
+ config.timeout = 5
243
+ end
244
+ ```
245
+
246
+ For a complete list of configuration options, see
247
+ [Configuration](http://rubydoc.info/github/minimagick/minimagick/MiniMagick/Configuration).
248
+
249
+ ### Composite
250
+
251
+ MiniMagick also allows you to
252
+ [composite](http://www.imagemagick.org/script/composite.php) images:
253
+
254
+ ```rb
255
+ first_image = MiniMagick::Image.new("first.jpg")
256
+ second_image = MiniMagick::Image.new("second.jpg")
257
+ result = first_image.composite(second_image) do |c|
258
+ c.compose "Over" # OverCompositeOp
259
+ c.geometry "+20+20" # copy second_image onto first_image from (20, 20)
260
+ end
261
+ result.write "output.jpg"
262
+ ```
263
+
264
+ ### Layers/Frames/Pages
265
+
266
+ For multilayered images you can access its layers.
267
+
268
+ ```rb
269
+ gif.frames #=> [...]
270
+ pdf.pages #=> [...]
271
+ psd.layers #=> [...]
272
+
273
+ gif.frames.each_with_index do |frame, idx|
274
+ frame.write("frame#{idx}.jpg")
275
+ end
276
+ ```
277
+
278
+ ### Image validation
279
+
280
+ By default, MiniMagick validates images each time it's opening them. It
281
+ validates them by running `identify` on them, and see if ImageMagick finds
282
+ them valid. This adds slight overhead to the whole processing. Sometimes it's
283
+ safe to assume that all input and output images are valid by default and turn
284
+ off validation:
285
+
286
+ ```rb
287
+ MiniMagick.configure do |config|
288
+ config.validate_on_create = false
289
+ end
290
+ ```
291
+
292
+ You can test whether an image is valid:
293
+
294
+ ```rb
295
+ image.valid?
296
+ image.validate! # raises MiniMagick::Invalid if image is invalid
297
+ ```
298
+
299
+ ### Logging
300
+
301
+ You can choose to log MiniMagick commands and their execution times:
302
+
303
+ ```rb
304
+ MiniMagick.logger.level = Logger::DEBUG
305
+ ```
306
+ ```
307
+ D, [2016-03-19T07:31:36.755338 #87191] DEBUG -- : [0.01s] identify /var/folders/k7/6zx6dx6x7ys3rv3srh0nyfj00000gn/T/mini_magick20160319-87191-1ve31n1.jpg
308
+ ```
309
+
310
+ In Rails you'll probably want to set `MiniMagick.logger = Rails.logger`.
311
+
312
+ ### Switching CLIs (ImageMagick \<=\> GraphicsMagick)
313
+
314
+ Default CLI is ImageMagick, but if you want to use GraphicsMagick, you can
315
+ specify it in configuration:
316
+
317
+ ```rb
318
+ MiniMagick.configure do |config|
319
+ config.cli = :graphicsmagick # or :imagemagick or :imagemagick7
320
+ end
321
+ ```
322
+
323
+ You can also use `.with_cli` to temporary switch the CLI:
324
+
325
+ ```rb
326
+ MiniMagick.with_cli(:graphicsmagick) do
327
+ # Some processing that GraphicsMagick is better at
328
+ end
329
+ ```
330
+
331
+ **WARNING**: If you're building a multithreaded web application, you should
332
+ change the CLI only on application startup. This is because the configuration is
333
+ global, so if you change it in a controller action, other threads in the same
334
+ process will also have their CLI changed, which could lead to race conditions.
335
+
336
+ ### Metal
337
+
338
+ If you want to be close to the metal, you can use ImageMagick's command-line
339
+ tools directly.
340
+
341
+ ```rb
342
+ MiniMagick::Tool::Magick.new do |magick|
343
+ magick << "input.jpg"
344
+ magick.resize("100x100")
345
+ magick.negate
346
+ magick << "output.jpg"
347
+ end #=> `magick input.jpg -resize 100x100 -negate output.jpg`
348
+
349
+ # OR
350
+
351
+ convert = MiniMagick::Tool::Convert.new
352
+ convert << "input.jpg"
353
+ convert.resize("100x100")
354
+ convert.negate
355
+ convert << "output.jpg"
356
+ convert.call #=> `convert input.jpg -resize 100x100 -negate output.jpg`
357
+ ```
358
+
359
+ If you're on ImageMagick 7, you should probably use `MiniMagick::Tool::Magick`,
360
+ though the legacy `MiniMagick::Tool::Convert` and friends will work too. On
361
+ ImageMagick 6 `MiniMagick::Tool::Magick` won't be available, so you should
362
+ instead use `MiniMagick::Tool::Convert` and friends.
363
+
364
+ This way of using MiniMagick is highly recommended if you want to maximize
365
+ performance of your image processing. We will now show the features available.
366
+
367
+ #### Appending
368
+
369
+ The most basic way of building a command is appending strings:
370
+
371
+ ```rb
372
+ MiniMagick::Tool::Magick.new do |convert|
373
+ convert << "input.jpg"
374
+ convert.merge! ["-resize", "500x500", "-negate"]
375
+ convert << "output.jpg"
376
+ end
377
+ ```
378
+
379
+ Note that it is important that every command you would pass to the command line
380
+ has to be separated with `<<`, e.g.:
381
+
382
+ ```rb
383
+ # GOOD
384
+ convert << "-resize" << "500x500"
385
+
386
+ # BAD
387
+ convert << "-resize 500x500"
388
+ ```
389
+
390
+ Shell escaping is also handled for you. If an option has a value that has
391
+ spaces inside it, just pass it as a regular string.
392
+
393
+ ```rb
394
+ convert << "-distort"
395
+ convert << "Perspective"
396
+ convert << "0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35"
397
+ ```
398
+ ```
399
+ convert -distort Perspective '0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35'
400
+ ```
401
+
402
+ #### Methods
403
+
404
+ Instead of passing in options directly, you can use Ruby methods:
405
+
406
+ ```rb
407
+ convert.resize("500x500")
408
+ convert.rotate(90)
409
+ convert.distort("Perspective", "0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35")
410
+ ```
411
+
412
+ MiniMagick knows which options each tool has, so you will get an explicit
413
+ `NoMethodError` if you happen to have misspelled an option.
414
+
415
+ #### Chaining
416
+
417
+ Every method call returns `self`, so you can chain them to create logical groups.
418
+
419
+ ```rb
420
+ MiniMagick::Tool::Magick.new do |convert|
421
+ convert << "input.jpg"
422
+ convert.clone(0).background('gray').shadow('80x5+5+5')
423
+ convert.negate
424
+ convert << "output.jpg"
425
+ end
426
+ ```
427
+
428
+ #### "Plus" options
429
+
430
+ ```rb
431
+ MiniMagick::Tool::Magick.new do |convert|
432
+ convert << "input.jpg"
433
+ convert.repage.+
434
+ convert.distort.+("Perspective", "more args")
435
+ end
436
+ ```
437
+ ```
438
+ convert input.jpg +repage +distort Perspective 'more args'
439
+ ```
440
+
441
+ #### Stacks
442
+
443
+ ```rb
444
+ MiniMagick::Tool::Magick.new do |convert|
445
+ convert << "wand.gif"
446
+
447
+ convert.stack do |stack|
448
+ stack << "wand.gif"
449
+ stack.rotate(30)
450
+ stack.foo("bar", "baz")
451
+ end
452
+ # or
453
+ convert.stack("wand.gif", { rotate: 30, foo: ["bar", "baz"] })
454
+
455
+ convert << "images.gif"
456
+ end
457
+ ```
458
+ ```
459
+ convert wand.gif \( wand.gif -rotate 90 -foo bar baz \) images.gif
460
+ ```
461
+
462
+ #### STDIN and STDOUT
463
+
464
+ If you want to pass something to standard input, you can pass the `:stdin`
465
+ option to `#call`:
466
+
467
+ ```rb
468
+ identify = MiniMagick::Tool::Identify.new
469
+ identify.stdin # alias for "-"
470
+ identify.call(stdin: image_content)
471
+ ```
472
+
473
+ MiniMagick also has `#stdout` alias for "-" for outputting file contents to
474
+ standard output:
475
+
476
+ ```rb
477
+ content = MiniMagick::Tool::Magick.new do |convert|
478
+ convert << "input.jpg"
479
+ convert.auto_orient
480
+ convert.stdout # alias for "-"
481
+ end
482
+ ```
483
+
484
+ #### Capturing STDERR
485
+
486
+ Some MiniMagick tools such as `compare` output the result of the command on
487
+ standard error, even if the command succeeded. The result of
488
+ `MiniMagick::Tool#call` is always the standard output, but if you pass it a
489
+ block, it will yield the stdout, stderr and exit status of the command:
490
+
491
+ ```rb
492
+ compare = MiniMagick::Tool::Compare.new
493
+ # build the command
494
+ compare.call do |stdout, stderr, status|
495
+ # ...
496
+ end
497
+ ```
498
+
499
+ ## Limiting resources
500
+
501
+ ImageMagick supports a number of environment variables for controlling its
502
+ resource limits. For example, you can enforce memory or execution time limits by
503
+ setting the following variables in your application's process environment:
504
+
505
+ * `MAGICK_MEMORY_LIMIT=128MiB`
506
+ * `MAGICK_MAP_LIMIT=64MiB`
507
+ * `MAGICK_TIME_LIMIT=30`
508
+
509
+ For a full list of variables and description, see [ImageMagick's resources
510
+ documentation](http://www.imagemagick.org/script/resources.php#environment).
511
+
512
+ ## Changing temporary directory
513
+
514
+ ImageMagick allows you to change the temporary directory to process the image file:
515
+
516
+ ```rb
517
+ MiniMagick.configure do |config|
518
+ config.tmpdir = File.join(Dir.tmpdir, "/my/new/tmp_dir")
519
+ end
520
+ ```
521
+
522
+ The example directory `/my/new/tmp_dir` must exist and must be writable.
523
+
524
+ If not configured, it will default to `Dir.tmpdir`.
525
+
526
+ ## Ignoring STDERR
527
+
528
+ If you're receiving warnings from ImageMagick that you don't care about, you
529
+ can avoid them being forwarded to standard error:
530
+
531
+ ```rb
532
+ MiniMagick.configure do |config|
533
+ config.warnings = false
534
+ end
535
+ ```
536
+
537
+ ## Troubleshooting
538
+
539
+ ### Errors being raised when they shouldn't
540
+
541
+ This gem raises an error when ImageMagick returns a nonzero exit code.
542
+ Sometimes, however, ImageMagick returns nonzero exit codes when the command
543
+ actually went ok. In these cases, to avoid raising errors, you can add the
544
+ following configuration:
545
+
546
+ ```rb
547
+ MiniMagick.configure do |config|
548
+ config.whiny = false
549
+ end
550
+ ```
551
+
552
+ If you're using the tool directly, you can pass `whiny: false` value to the
553
+ constructor:
554
+
555
+ ```rb
556
+ MiniMagick::Tool::Identify.new(whiny: false) do |b|
557
+ b.help
558
+ end
559
+ ```
560
+
561
+ ## Thinking of switching from RMagick?
562
+
563
+ Unlike RMagick, MiniMagick is a much thinner wrapper around ImageMagick.
564
+
565
+ * To piece together MiniMagick commands refer to the [Mogrify
566
+ Documentation](https://imagemagick.org/script/mogrify.php). For instance
567
+ you can use the `-flop` option as `image.flop`.
568
+ * Operations on a MiniMagick image tend to happen in-place as `image.trim`,
569
+ whereas RMagick has both copying and in-place methods like `image.trim` and
570
+ `image.trim!`.
571
+ * To open files with MiniMagick you use `MiniMagick::Image.open` as you would
572
+ `Magick::Image.read`. To open a file and directly edit it, use
573
+ `MiniMagick::Image.new`.