mini_magick 4.13.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44b0562f09fa6d0cc281ad1c4317b8e9915aa60dc6175072dc0cdc872f3d8367
4
- data.tar.gz: 96225cd5bd66e3c0c065cb169057e196becfcdd1e0c883cb7c23f746d76bcda6
3
+ metadata.gz: b2a979a253bd3d26fe275850919ab3569c69ae6b2817fadf6660bbeaa9ec3e07
4
+ data.tar.gz: a1c7c90b81883cdf2c1734906ff07a72bc50c427cf35835f67818d5245e78936
5
5
  SHA512:
6
- metadata.gz: a39cb409419be063b9cc27fd107a361d94d3f5dbdad719ed1f472efca70650c710160494f22b18f1408df479f29836d29c2bd71262ad1988cdf22caf85a9251a
7
- data.tar.gz: dbb5ba23b0b773a696812ec343f0d267aee1653b0ebfb61ea9560af9c4cac68352b7c936c57233913d8848a1de3c9fe02e31070a94e5f3f0d7f471e444615a55
6
+ metadata.gz: 6cd0afcaab4af7f1f069938fef824290cdf03b5b17920594acc81c2dbb7b1c6828cb88af157e784fd27ba387cd27d2acf0fa8a5e1c3b9a02924ec11d7a4630eb
7
+ data.tar.gz: b99d1936faea4689b647d39832de3424dc1bdde6d748c0c9b0d8432dd24b6e89661690f141089d5a0a88315fcd2658a4da8c3ba2736929aeafbb4113cdc43541
data/README.md CHANGED
@@ -4,8 +4,7 @@
4
4
  [![CI](https://github.com/minimagick/minimagick/actions/workflows/ci.yml/badge.svg)](https://github.com/minimagick/minimagick/actions/workflows/ci.yml)
5
5
  [![Code Climate](https://codeclimate.com/github/minimagick/minimagick/badges/gpa.svg)](https://codeclimate.com/github/minimagick/minimagick)
6
6
 
7
- A ruby wrapper for [ImageMagick](http://imagemagick.org/) or
8
- [GraphicsMagick](http://www.graphicsmagick.org/) command line.
7
+ A ruby wrapper for [ImageMagick](http://imagemagick.org/) command line.
9
8
 
10
9
  ## Why?
11
10
 
@@ -26,8 +25,8 @@ MiniMagick gives you access to all the command line options ImageMagick has
26
25
 
27
26
  ## Requirements
28
27
 
29
- ImageMagick or GraphicsMagick command-line tool has to be installed. You can
30
- check if you have it installed by running
28
+ ImageMagick command-line tool has to be installed. You can check if you have it
29
+ installed by running
31
30
 
32
31
  ```sh
33
32
  $ magick -version
@@ -43,8 +42,8 @@ Compiler: gcc (4.2)
43
42
 
44
43
  Add the gem to your Gemfile:
45
44
 
46
- ```rb
47
- gem "mini_magick"
45
+ ```sh
46
+ $ bundle add mini_magick
48
47
  ```
49
48
 
50
49
  ## Information
@@ -73,7 +72,7 @@ the copy is just temporary, it gets garbage collected when we lose reference
73
72
  to the image.
74
73
 
75
74
  `MiniMagick::Image.open` also accepts URLs, and options passed in will be
76
- forwarded to open-uri.
75
+ forwarded to [open-uri](https://github.com/ruby/open-uri).
77
76
 
78
77
  ```rb
79
78
  image = MiniMagick::Image.open("http://example.com/image.jpg")
@@ -117,8 +116,8 @@ image = MiniMagick::Image.new("input.jpg") do |b|
117
116
  end # the command gets executed
118
117
  ```
119
118
 
120
- The yielded builder is an instance of `MiniMagick::Tool::Mogrify`. To learn more
121
- about its interface, see [Metal](#metal) below.
119
+ The yielded builder is an instance of `MiniMagick::Tool`. To learn more
120
+ about its interface, see [Tools](#tools) below.
122
121
 
123
122
  ### Attributes
124
123
 
@@ -126,7 +125,6 @@ A `MiniMagick::Image` has various handy attributes.
126
125
 
127
126
  ```rb
128
127
  image.type #=> "JPEG"
129
- image.mime_type #=> "image/jpeg"
130
128
  image.width #=> 250
131
129
  image.height #=> 300
132
130
  image.dimensions #=> [250, 300]
@@ -145,7 +143,7 @@ image["%[gamma]"] # "0.9"
145
143
  ```
146
144
 
147
145
  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:
146
+ which returns the output from `magick input.jpg json:`:
149
147
 
150
148
  ```rb
151
149
  image.data #=>
@@ -193,10 +191,6 @@ image.data #=>
193
191
  # }
194
192
  ```
195
193
 
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
194
  ### Pixels
201
195
 
202
196
  With MiniMagick you can retrieve a matrix of image pixels, where each member of
@@ -221,6 +215,7 @@ pixels = image.get_pixels
221
215
  ### Pixels To Image
222
216
 
223
217
  Sometimes when you have pixels and want to create image from pixels, you can do this to form an image:
218
+
224
219
  ```rb
225
220
  image = MiniMagick::Image.open('/Users/rabin/input.jpg')
226
221
  pixels = image.get_pixels
@@ -229,22 +224,27 @@ dimension = [image.width, image.height]
229
224
  map = 'rgb'
230
225
  image = MiniMagick::Image.get_image_from_pixels(pixels, dimension, map, depth ,'jpg')
231
226
  image.write('/Users/rabin/output.jpg')
232
-
233
227
  ```
234
228
 
235
229
  In this example, the returned pixels should now have equal R, G, and B values.
236
230
 
237
231
  ### Configuration
238
232
 
233
+ Here are the available configuration options with their default values:
234
+
239
235
  ```rb
240
236
  MiniMagick.configure do |config|
241
- config.cli = :graphicsmagick
242
- config.timeout = 5
237
+ config.timeout = nil # number of seconds IM commands may take
238
+ config.errors = true # raise errors non nonzero exit status
239
+ config.warnings = true # forward warnings to standard error
240
+ config.tmdir = Dir.tmpdir # alternative directory for tempfiles
241
+ config.logger = Logger.new($stdout) # where to log IM commands
242
+ config.cli_prefix = nil # add prefix to all IM commands
243
243
  end
244
244
  ```
245
245
 
246
- For a complete list of configuration options, see
247
- [Configuration](http://rubydoc.info/github/minimagick/minimagick/MiniMagick/Configuration).
246
+ For a more information, see
247
+ [Configuration](http://rubydoc.info/github/minimagick/minimagick/MiniMagick/Configuration) API documentation.
248
248
 
249
249
  ### Composite
250
250
 
@@ -277,19 +277,7 @@ end
277
277
 
278
278
  ### Image validation
279
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:
280
+ You can test whether an image is valid by running it through `identify`:
293
281
 
294
282
  ```rb
295
283
  image.valid?
@@ -309,67 +297,36 @@ D, [2016-03-19T07:31:36.755338 #87191] DEBUG -- : [0.01s] identify /var/folders/
309
297
 
310
298
  In Rails you'll probably want to set `MiniMagick.logger = Rails.logger`.
311
299
 
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
300
+ ## Tools
337
301
 
338
- If you want to be close to the metal, you can use ImageMagick's command-line
339
- tools directly.
302
+ If you prefer not to use the `MiniMagick::Image` abstraction, you can use ImageMagick's command-line tools directly:
340
303
 
341
304
  ```rb
342
- MiniMagick::Tool::Magick.new do |magick|
343
- magick << "input.jpg"
344
- magick.resize("100x100")
345
- magick.negate
346
- magick << "output.jpg"
305
+ MiniMagick.convert do |convert|
306
+ convert << "input.jpg"
307
+ convert.resize("100x100")
308
+ convert.negate
309
+ convert << "output.jpg"
347
310
  end #=> `magick input.jpg -resize 100x100 -negate output.jpg`
348
311
 
349
312
  # OR
350
313
 
351
- convert = MiniMagick::Tool::Convert.new
314
+ convert = MiniMagick.convert
352
315
  convert << "input.jpg"
353
316
  convert.resize("100x100")
354
317
  convert.negate
355
318
  convert << "output.jpg"
356
- convert.call #=> `convert input.jpg -resize 100x100 -negate output.jpg`
319
+ convert.call #=> `magick input.jpg -resize 100x100 -negate output.jpg`
357
320
  ```
358
321
 
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.
322
+ This way of using MiniMagick is highly recommended if you want to maximize performance of your image processing. There are class methods for each CLI tool: `animate`, `compare`, `composite`, `conjure`, `convert`, `display`, `identify`, `import`, `mogrify` and `stream`. The `MiniMagick.convert` method will use `magick` on ImageMagick 7 and `convert` on ImageMagick 6.
363
323
 
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
324
+ ### Appending
368
325
 
369
326
  The most basic way of building a command is appending strings:
370
327
 
371
328
  ```rb
372
- MiniMagick::Tool::Magick.new do |convert|
329
+ MiniMagick.convert do |convert|
373
330
  convert << "input.jpg"
374
331
  convert.merge! ["-resize", "500x500", "-negate"]
375
332
  convert << "output.jpg"
@@ -396,10 +353,10 @@ convert << "Perspective"
396
353
  convert << "0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35"
397
354
  ```
398
355
  ```
399
- convert -distort Perspective '0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35'
356
+ magick -distort Perspective '0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35'
400
357
  ```
401
358
 
402
- #### Methods
359
+ ### Methods
403
360
 
404
361
  Instead of passing in options directly, you can use Ruby methods:
405
362
 
@@ -409,15 +366,12 @@ convert.rotate(90)
409
366
  convert.distort("Perspective", "0,0,0,0 0,45,0,45 69,0,60,10 69,45,60,35")
410
367
  ```
411
368
 
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
369
+ ### Chaining
416
370
 
417
371
  Every method call returns `self`, so you can chain them to create logical groups.
418
372
 
419
373
  ```rb
420
- MiniMagick::Tool::Magick.new do |convert|
374
+ MiniMagick.convert do |convert|
421
375
  convert << "input.jpg"
422
376
  convert.clone(0).background('gray').shadow('80x5+5+5')
423
377
  convert.negate
@@ -425,23 +379,23 @@ MiniMagick::Tool::Magick.new do |convert|
425
379
  end
426
380
  ```
427
381
 
428
- #### "Plus" options
382
+ ### "Plus" options
429
383
 
430
384
  ```rb
431
- MiniMagick::Tool::Magick.new do |convert|
385
+ MiniMagick.convert do |convert|
432
386
  convert << "input.jpg"
433
387
  convert.repage.+
434
388
  convert.distort.+("Perspective", "more args")
435
389
  end
436
390
  ```
437
391
  ```
438
- convert input.jpg +repage +distort Perspective 'more args'
392
+ magick input.jpg +repage +distort Perspective 'more args'
439
393
  ```
440
394
 
441
- #### Stacks
395
+ ### Stacks
442
396
 
443
397
  ```rb
444
- MiniMagick::Tool::Magick.new do |convert|
398
+ MiniMagick.convert do |convert|
445
399
  convert << "wand.gif"
446
400
 
447
401
  convert.stack do |stack|
@@ -456,16 +410,16 @@ MiniMagick::Tool::Magick.new do |convert|
456
410
  end
457
411
  ```
458
412
  ```
459
- convert wand.gif \( wand.gif -rotate 90 -foo bar baz \) images.gif
413
+ magick wand.gif \( wand.gif -rotate 90 -foo bar baz \) images.gif
460
414
  ```
461
415
 
462
- #### STDIN and STDOUT
416
+ ### STDIN and STDOUT
463
417
 
464
418
  If you want to pass something to standard input, you can pass the `:stdin`
465
419
  option to `#call`:
466
420
 
467
421
  ```rb
468
- identify = MiniMagick::Tool::Identify.new
422
+ identify = MiniMagick.identify
469
423
  identify.stdin # alias for "-"
470
424
  identify.call(stdin: image_content)
471
425
  ```
@@ -474,14 +428,14 @@ MiniMagick also has `#stdout` alias for "-" for outputting file contents to
474
428
  standard output:
475
429
 
476
430
  ```rb
477
- content = MiniMagick::Tool::Magick.new do |convert|
431
+ content = MiniMagick.convert do |convert|
478
432
  convert << "input.jpg"
479
433
  convert.auto_orient
480
434
  convert.stdout # alias for "-"
481
435
  end
482
436
  ```
483
437
 
484
- #### Capturing STDERR
438
+ ### Capturing STDERR
485
439
 
486
440
  Some MiniMagick tools such as `compare` output the result of the command on
487
441
  standard error, even if the command succeeded. The result of
@@ -489,14 +443,30 @@ standard error, even if the command succeeded. The result of
489
443
  block, it will yield the stdout, stderr and exit status of the command:
490
444
 
491
445
  ```rb
492
- compare = MiniMagick::Tool::Compare.new
446
+ compare = MiniMagick.compare
493
447
  # build the command
494
448
  compare.call do |stdout, stderr, status|
495
449
  # ...
496
450
  end
497
451
  ```
498
452
 
499
- ## Limiting resources
453
+ ## Configuring
454
+
455
+ ### GraphicsMagick
456
+
457
+ As of MiniMagick 5+, [GraphicsMagick](http://www.graphicsmagick.org/) isn't
458
+ officially supported. However, you can still configure MiniMagick to use it:
459
+
460
+ ```rb
461
+ MiniMagick.configure do |config|
462
+ config.cli_prefix = "gm"
463
+ end
464
+ ```
465
+
466
+ Some MiniMagick features won't be supported, such as global timeout,
467
+ `MiniMagick::Image#data` and `MiniMagick::Image#exif`.
468
+
469
+ ### Limiting resources
500
470
 
501
471
  ImageMagick supports a number of environment variables for controlling its
502
472
  resource limits. For example, you can enforce memory or execution time limits by
@@ -509,7 +479,7 @@ setting the following variables in your application's process environment:
509
479
  For a full list of variables and description, see [ImageMagick's resources
510
480
  documentation](http://www.imagemagick.org/script/resources.php#environment).
511
481
 
512
- ## Changing temporary directory
482
+ ### Changing temporary directory
513
483
 
514
484
  ImageMagick allows you to change the temporary directory to process the image file:
515
485
 
@@ -523,7 +493,7 @@ The example directory `/my/new/tmp_dir` must exist and must be writable.
523
493
 
524
494
  If not configured, it will default to `Dir.tmpdir`.
525
495
 
526
- ## Ignoring STDERR
496
+ ### Ignoring STDERR
527
497
 
528
498
  If you're receiving warnings from ImageMagick that you don't care about, you
529
499
  can avoid them being forwarded to standard error:
@@ -534,9 +504,7 @@ MiniMagick.configure do |config|
534
504
  end
535
505
  ```
536
506
 
537
- ## Troubleshooting
538
-
539
- ### Errors being raised when they shouldn't
507
+ ### Avoiding raising errors
540
508
 
541
509
  This gem raises an error when ImageMagick returns a nonzero exit code.
542
510
  Sometimes, however, ImageMagick returns nonzero exit codes when the command
@@ -545,15 +513,14 @@ following configuration:
545
513
 
546
514
  ```rb
547
515
  MiniMagick.configure do |config|
548
- config.whiny = false
516
+ config.errors = false
549
517
  end
550
518
  ```
551
519
 
552
- If you're using the tool directly, you can pass `whiny: false` value to the
553
- constructor:
520
+ You can also pass `errors: false` to individual commands:
554
521
 
555
522
  ```rb
556
- MiniMagick::Tool::Identify.new(whiny: false) do |b|
523
+ MiniMagick.identify(errors: false) do |b|
557
524
  b.help
558
525
  end
559
526
  ```
@@ -4,14 +4,6 @@ require 'logger'
4
4
  module MiniMagick
5
5
  module Configuration
6
6
 
7
- ##
8
- # If you don't have the CLI tools in your PATH, you can set the path to the
9
- # executables.
10
- #
11
- attr_writer :cli_path
12
- # @private (for backwards compatibility)
13
- attr_accessor :processor_path
14
-
15
7
  ##
16
8
  # Adds a prefix to the CLI command.
17
9
  # For example, you could use `firejail` to run all commands in a sandbox.
@@ -31,16 +23,8 @@ module MiniMagick
31
23
  #
32
24
  attr_accessor :timeout
33
25
  ##
34
- # When get to `true`, it outputs each command to STDOUT in their shell
35
- # version.
36
- #
37
- # @return [Boolean]
38
- #
39
- attr_reader :debug
40
- ##
41
- # Logger for {#debug}, default is `MiniMagick::Logger.new(STDOUT)`, but
42
- # you can override it, for example if you want the logs to be written to
43
- # a file.
26
+ # Logger for commands, default is `Logger.new($stdout)`, but you can
27
+ # override it, for example if you want the logs to be written to a file.
44
28
  #
45
29
  # @return [Logger]
46
30
  #
@@ -53,31 +37,13 @@ module MiniMagick
53
37
  #
54
38
  attr_accessor :tmpdir
55
39
 
56
- ##
57
- # If set to `true`, it will `identify` every newly created image, and raise
58
- # `MiniMagick::Invalid` if the image is not valid. Useful for validating
59
- # user input, although it adds a bit of overhead. Defaults to `true`.
60
- #
61
- # @return [Boolean]
62
- #
63
- attr_accessor :validate_on_create
64
- ##
65
- # If set to `true`, it will `identify` every image that gets written (with
66
- # {MiniMagick::Image#write}), and raise `MiniMagick::Invalid` if the image
67
- # is not valid. Useful for validating that processing was successful,
68
- # although it adds a bit of overhead. Defaults to `true`.
69
- #
70
- # @return [Boolean]
71
- #
72
- attr_accessor :validate_on_write
73
-
74
40
  ##
75
41
  # If set to `false`, it will not raise errors when ImageMagick returns
76
42
  # status code different than 0. Defaults to `true`.
77
43
  #
78
44
  # @return [Boolean]
79
45
  #
80
- attr_accessor :whiny
46
+ attr_accessor :errors
81
47
 
82
48
  ##
83
49
  # If set to `false`, it will not forward warnings from ImageMagick to
@@ -86,9 +52,7 @@ module MiniMagick
86
52
 
87
53
  def self.extended(base)
88
54
  base.tmpdir = Dir.tmpdir
89
- base.validate_on_create = true
90
- base.validate_on_write = true
91
- base.whiny = true
55
+ base.errors = true
92
56
  base.logger = Logger.new($stdout).tap { |l| l.level = Logger::INFO }
93
57
  base.warnings = true
94
58
  end
@@ -97,107 +61,11 @@ module MiniMagick
97
61
  # @yield [self]
98
62
  # @example
99
63
  # MiniMagick.configure do |config|
100
- # config.cli = :graphicsmagick
101
64
  # config.timeout = 5
102
65
  # end
103
66
  #
104
67
  def configure
105
68
  yield self
106
69
  end
107
-
108
- CLI_DETECTION = {
109
- imagemagick7: "magick",
110
- imagemagick: "mogrify",
111
- graphicsmagick: "gm",
112
- }
113
-
114
- # @private (for backwards compatibility)
115
- def processor
116
- @processor ||= CLI_DETECTION.values.detect do |processor|
117
- MiniMagick::Utilities.which(processor)
118
- end
119
- end
120
-
121
- # @private (for backwards compatibility)
122
- def processor=(processor)
123
- @processor = processor.to_s
124
-
125
- unless CLI_DETECTION.value?(@processor)
126
- raise ArgumentError,
127
- "processor has to be set to either \"magick\", \"mogrify\" or \"gm\"" \
128
- ", was set to #{@processor.inspect}"
129
- end
130
- end
131
-
132
- ##
133
- # Get [ImageMagick](http://www.imagemagick.org) or
134
- # [GraphicsMagick](http://www.graphicsmagick.org).
135
- #
136
- # @return [Symbol] `:imagemagick` or `:graphicsmagick`
137
- #
138
- def cli
139
- if instance_variable_defined?("@cli")
140
- instance_variable_get("@cli")
141
- else
142
- cli = CLI_DETECTION.key(processor) or
143
- fail MiniMagick::Error, "You must have ImageMagick or GraphicsMagick installed"
144
-
145
- instance_variable_set("@cli", cli)
146
- end
147
- end
148
-
149
- ##
150
- # Set whether you want to use [ImageMagick](http://www.imagemagick.org) or
151
- # [GraphicsMagick](http://www.graphicsmagick.org).
152
- #
153
- def cli=(value)
154
- @cli = value
155
-
156
- if not CLI_DETECTION.key?(@cli)
157
- raise ArgumentError,
158
- "CLI has to be set to either :imagemagick, :imagemagick7 or :graphicsmagick" \
159
- ", was set to #{@cli.inspect}"
160
- end
161
- end
162
-
163
- ##
164
- # If you set the path of CLI tools, you can get the path of the
165
- # executables.
166
- #
167
- # @return [String]
168
- #
169
- def cli_path
170
- if instance_variable_defined?("@cli_path")
171
- instance_variable_get("@cli_path")
172
- else
173
- processor_path = instance_variable_get("@processor_path") if instance_variable_defined?("@processor_path")
174
-
175
- instance_variable_set("@cli_path", processor_path)
176
- end
177
- end
178
-
179
- ##
180
- # When set to `true`, it outputs each command to STDOUT in their shell
181
- # version.
182
- #
183
- def debug=(value)
184
- warn "MiniMagick.debug is deprecated and will be removed in MiniMagick 5. Use `MiniMagick.logger.level = Logger::DEBUG` instead."
185
- logger.level = value ? Logger::DEBUG : Logger::INFO
186
- end
187
-
188
- def shell_api=(value)
189
- warn "MiniMagick.shell_api is deprecated and will be removed in MiniMagick 5. The posix-spawn gem doesn't improve performance recent Ruby versions anymore, so support for it will be removed."
190
- @shell_api = value
191
- end
192
-
193
- def shell_api
194
- @shell_api || "open3"
195
- end
196
-
197
- # Backwards compatibility
198
- def reload_tools
199
- warn "MiniMagick.reload_tools is deprecated because it is no longer necessary"
200
- end
201
-
202
70
  end
203
71
  end