easyimg_utils 0.4.3 → 0.6.3

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
2
  SHA256:
3
- metadata.gz: 4d14e8e346eadfa36ea43f336f4b8bb161e2c38e216c162d97e67439767fb84b
4
- data.tar.gz: 9f27d41d4938f8c5b4249c90566062a5841ff24d9b1bf86506b2354fe0c070a4
3
+ metadata.gz: f68eb15dfa8aa18281bb8b71b6ad4ac8e0da01c5da5424d981388cfdee8cae7f
4
+ data.tar.gz: 10d4a0d5ad92f28723c9b4d2b025952723b8566d8cc9418e0e11191c70a407fe
5
5
  SHA512:
6
- metadata.gz: 3df7e8b76c8860579e2801664a3a14dcfb24c36eeb79607c0aeb944b37183db7b5cc0905790bd38a124a63abbba2ac0f1b72ca714a6456d937fab99a5efde938
7
- data.tar.gz: 5e845353a3f9b335712cb262c5272de9b5d6a71a4fb3efa291863104d4fbe8b8bf7de90a935a2e87a5a0a0da7c4771da1fcfd42742ceee7449bc4f4bfaf96c07
6
+ metadata.gz: c900ec2015da02a1eb2178feb88418792f19c8b806d84700931e8efa7cbdfef3cfe1144154d25b04c5fd4696e29fd4864d153a4906c8d637e57c50d08e7eca64
7
+ data.tar.gz: c1bdfcc930995773ffb921ad88d261d37a91c356a21accd1f18ffbcf4997ecd7d288b2d7fd70a42e54a5f9df6195e4f78e95097281749b15b61601485a16a7a3
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/lib/easyimg_utils.rb CHANGED
@@ -3,9 +3,10 @@
3
3
  # file: easyimg_utils.rb
4
4
 
5
5
  require 'c32'
6
- require 'rxfhelper'
6
+ require 'x4ss'
7
7
  require 'rmagick'
8
8
  require 'webp_ffi'
9
+ require 'rxfhelper'
9
10
 
10
11
  # requirements:
11
12
  #
@@ -46,13 +47,16 @@ class EasyImgUtils
46
47
  extend CommandHelper
47
48
  include Magick
48
49
  include RXFHelperModule
50
+
49
51
 
50
52
  @commands = "
51
53
  * add rectangle # usage: add_rectangle(color: 'green', x1: 12, y1: 12, x2: 24, y2: 24)
52
54
  * add_svg # adds an SVG transparency overlay. usage: add_svg('/tmp/image1.svg')
53
55
  * add_text # e.g. add_text('some text')
56
+ * animate Creates an animated gif e.g. animate('/tmp/a%d.png', '/tmp/b.gif')
54
57
  * blur # e.g. blur(x: 231, y: 123, w: 85, h: 85)
55
58
  * capture_screen # takes a screenshot of the desktop
59
+ * calc_resize # e.g. EasyImgUtils.calc_resize '1449x1932', '640x480' #=> 480x640
56
60
  * center_crop # crops from the centre of an image. Usage center_crop(width, height)
57
61
  * composite # overlay a smaller image on top of an image
58
62
  * contrast # changes the intensity between lighter and darker elements
@@ -68,6 +72,7 @@ class EasyImgUtils
68
72
  * rotate_left
69
73
  * rotate_right
70
74
  * scale # Scales an image by the given factor e.g. 0.75 is 75%. see also resize
75
+ * screencast # records a screencast and saves it as animated gif. e.g. (out: '/tmp/fun.gif').screencast
71
76
  * sketch # renders an artistic sketch, ideal with simplistic photos
72
77
  * view # view the output
73
78
  * vignette # Feathers the edge of an image in a circular path
@@ -82,18 +87,32 @@ class EasyImgUtils
82
87
 
83
88
  end
84
89
 
90
+ # e.g. calc_resize '1449x1932', '640x480' #=> 480x640
91
+ #
92
+ def self.calc_resize(s, s2)
93
+
94
+ a = s.split('x',2).map(&:to_i).sort
95
+ a2 = s2.split('x',2).map(&:to_i).sort
96
+
97
+ factor = a2.last / a.last.to_f
98
+
99
+ a.map {|x| (x * factor).to_i}.join('x')
100
+
101
+ end
102
+
85
103
  def add_rectangle(a=[], quality: nil, color: 'green', stroke_width: 5,
86
104
  x1: 0, y1: 0, x2: 0, y2: 0)
87
105
 
88
106
  x1, y1, x2, y2 = *a if a
89
- img = read()
90
- gc = Magick::Draw.new
91
- gc.stroke('green')
92
- gc.stroke_width(5)
93
- gc.fill('transparent')
94
- gc.rectangle(x1, y1, x2, y2)
95
- gc.draw(img)
96
- write img, quality
107
+ read() do |img|
108
+ gc = Magick::Draw.new
109
+ gc.stroke('green')
110
+ gc.stroke_width(5)
111
+ gc.fill('transparent')
112
+ gc.rectangle(x1, y1, x2, y2)
113
+ gc.draw(img)
114
+ write img, quality
115
+ end
97
116
 
98
117
  end
99
118
 
@@ -113,38 +132,56 @@ class EasyImgUtils
113
132
 
114
133
  def add_text(s='your text goes here', quality: nil)
115
134
 
116
- img = read()
135
+ read() do |img|
117
136
 
118
- d = Draw.new
119
- img.annotate(d, 0,0,0,0, s) do
120
- d.gravity = Magick::SouthGravity
121
- d.pointsize = 26
122
- d.stroke = '#000000'
123
- d.fill = '#ffffff'
124
- d.font_weight = Magick::BoldWeight
137
+ d = Draw.new
138
+ img.annotate(d, 0,0,0,0, s) do
139
+ d.gravity = Magick::SouthGravity
140
+ d.pointsize = 26
141
+ d.stroke = '#000000'
142
+ d.fill = '#ffffff'
143
+ d.font_weight = Magick::BoldWeight
144
+ end
145
+
146
+ write img, quality
147
+
125
148
  end
126
149
 
127
- write img, quality
128
-
129
150
  end
130
151
 
152
+ def animate()
153
+
154
+ anim = Magick::ImageList.new
155
+
156
+ read() {|img| anim << img }
157
+ anim.ticks_per_second = 100
158
+ anim.delay = 20
159
+
160
+ @file_out ? anim.write(@file_out) : anim.animate
161
+
162
+ end
131
163
 
132
164
  def blur(x: 0, y: 0, w: 80, h: 80, strength: 8, quality: nil)
133
165
 
134
166
  width, height = w, h
135
- img = read()
136
- region = img.dispatch(x, y, width, height, 'RGB')
137
- face_img = Magick::Image.constitute(width, height, "RGB", region)
138
- img.composite!(face_img.gaussian_blur(0, strength), x, y,
139
- Magick::OverCompositeOp)
140
- write img, quality
167
+
168
+ read() do |img|
169
+
170
+ region = img.dispatch(x, y, width, height, 'RGB')
171
+ face_img = Magick::Image.constitute(width, height, "RGB", region)
172
+ img.composite!(face_img.gaussian_blur(0, strength), x, y,
173
+ Magick::OverCompositeOp)
174
+ write img, quality
175
+
176
+ end
141
177
 
142
178
  end
143
179
 
144
180
  def brightness(quality: nil)
145
- img = read()
146
- img2 = imglevel(-Magick::QuantumRange * 0.25, Magick::QuantumRange * 1.25, 1.0)
147
- write img2, quality
181
+ read() do |img|
182
+ img2 = imglevel(-Magick::QuantumRange * 0.25, Magick::QuantumRange * 1.25, 1.0)
183
+ write img2, quality
184
+ end
148
185
  end
149
186
 
150
187
  def capture_screen(quality: nil)
@@ -163,9 +200,10 @@ class EasyImgUtils
163
200
 
164
201
  return unless w
165
202
 
166
- img = read()
167
- img.crop!(CenterGravity, width, height)
168
- write img, quality
203
+ read() do |img|
204
+ img.crop!(CenterGravity, width, height)
205
+ write img, quality
206
+ end
169
207
 
170
208
  end
171
209
 
@@ -173,18 +211,19 @@ class EasyImgUtils
173
211
 
174
212
  return unless filex
175
213
 
176
- img = read()
214
+ read() do |img|
177
215
 
178
- imgx = Magick::ImageList.new(filex)
216
+ imgx = Magick::ImageList.new(filex)
179
217
 
180
- # Change the white pixels in the sign to transparent.
181
- imgx = imgx.matte_replace(0,0)
218
+ # Change the white pixels in the sign to transparent.
219
+ imgx = imgx.matte_replace(0,0)
182
220
 
183
- img2 = Magick::Draw.new
184
- img2.composite(x, y, 0, 0, imgx)
185
- img2.draw(img)
186
-
187
- write img, quality
221
+ img2 = Magick::Draw.new
222
+ img2.composite(x, y, 0, 0, imgx)
223
+ img2.draw(img)
224
+
225
+ write img, quality
226
+ end
188
227
 
189
228
  end
190
229
 
@@ -200,13 +239,14 @@ class EasyImgUtils
200
239
 
201
240
  return if level == neutral
202
241
 
203
- img ||= read()
242
+ read() do |img|
204
243
 
205
- n = neutral - level
206
- sharpen = n > 0
207
- n.abs.times { img = img.contrast(sharpen) }
208
-
209
- write img, quality
244
+ n = neutral - level
245
+ sharpen = n > 0
246
+ n.abs.times { img = img.contrast(sharpen) }
247
+
248
+ write img, quality
249
+ end
210
250
 
211
251
  end
212
252
 
@@ -241,28 +281,31 @@ class EasyImgUtils
241
281
 
242
282
  return unless w
243
283
 
244
- img = read()
245
- img.crop!(x,y, width=w, height=h)
246
- write img, quality
284
+ read() do |img|
285
+ img.crop!(x,y, width=w, height=h)
286
+ write img, quality
287
+ end
247
288
 
248
289
  end
249
290
 
250
291
  def fax_effect(threshold: 0.55, quality: nil)
251
292
 
252
- img = read()
253
-
254
- # Use a threshold of 55% of MaxRGB.
255
- img = img.threshold(Magick::MaxRGB*threshold)
293
+ read() do |img|
256
294
 
257
- write img, quality
295
+ # Use a threshold of 55% of MaxRGB.
296
+ img = img.threshold(Magick::MaxRGB*threshold)
297
+ write img, quality
298
+
299
+ end
258
300
 
259
301
  end
260
302
 
261
303
  def greyscale(quality: nil)
262
304
 
263
- img = read()
264
- img2 = img.quantize(256, GRAYColorspace)
265
- write img2, quality
305
+ read() do |img|
306
+ img2 = img.quantize(256, GRAYColorspace)
307
+ write img2, quality
308
+ end
266
309
 
267
310
  end
268
311
 
@@ -282,9 +325,10 @@ class EasyImgUtils
282
325
 
283
326
  def make_thumbnail(width=125, height=125)
284
327
 
285
- img = read()
286
- img2 = img.thumbnail(width, height)
287
- write img2, quality
328
+ read() do |img|
329
+ img2 = img.thumbnail(width, height)
330
+ write img2, quality
331
+ end
288
332
 
289
333
  end
290
334
 
@@ -294,45 +338,50 @@ class EasyImgUtils
294
338
  #
295
339
  def resize(geometry='320x240', quality: nil)
296
340
 
297
- preview = read()
341
+ read() do |preview|
298
342
 
299
- preview.change_geometry!(geometry) do |cols, rows, img|
300
- img.resize!(cols, rows)
343
+ preview.change_geometry!(geometry) do |cols, rows, img|
344
+ img.resize!(cols, rows)
345
+ end
346
+
347
+ write preview, quality
301
348
  end
302
349
 
303
- write preview, quality
304
-
305
350
  end
306
351
 
307
352
  def rotate(degrees)
308
353
 
309
- img = read()
310
- img2 = img.rotate(degrees.to_i)
311
- write img2, quality
354
+ read() do |img|
355
+ img2 = img.rotate(degrees.to_i)
356
+ write img2, quality
357
+ end
312
358
 
313
359
  end
314
360
 
315
361
  def rotate_180()
316
362
 
317
- img = read()
318
- img2 = img.rotate(180)
319
- write img2, quality
363
+ read() do |img|
364
+ img2 = img.rotate(180)
365
+ write img2, quality
366
+ end
320
367
 
321
368
  end
322
369
 
323
370
  def rotate_left()
324
371
 
325
- img = read()
326
- img2 = img.rotate(-45)
327
- write img2, quality
372
+ read() do |img|
373
+ img2 = img.rotate(-45)
374
+ write img2, quality
375
+ end
328
376
 
329
377
  end
330
378
 
331
379
  def rotate_right()
332
380
 
333
- img = read()
334
- img2 = img.rotate(45)
335
- write img2, quality
381
+ read() do |img|
382
+ img2 = img.rotate(45)
383
+ write img2, quality
384
+ end
336
385
 
337
386
  end
338
387
 
@@ -340,30 +389,50 @@ class EasyImgUtils
340
389
  #
341
390
  def scale(factor=0.75, quality: nil)
342
391
 
343
- img = read()
344
-
345
- img2 = img.scale(factor)
392
+ read() do |img|
346
393
 
347
- write img2, quality
394
+ img2 = img.scale(factor)
395
+ write img2, quality
396
+
397
+ end
348
398
 
349
399
  end
400
+
401
+ # Takes a screenshot every second to create an animated gif
402
+ #
403
+ def screencast(duration: 6, scale: 1, window: true)
404
+
405
+ fileout = @file_out.sub(/\.\w+$/,'%d.png')
406
+
407
+ puts 'fileout: ' + fileout if @debug
350
408
 
409
+ x4ss = X4ss.new fileout, mouse: true, window: true
410
+ mode = window ? :window : :screen
411
+ sleep 2; x4ss.record duration: duration, mode: mode
412
+ x4ss.save
351
413
 
414
+ fileout2 = fileout.sub(/(?=%)/,'b')
415
+ EasyImgUtils.new(fileout, fileout2).scale(scale) unless scale == 1
416
+ EasyImgUtils.new(fileout2, @file_out).animate
417
+
418
+ end
352
419
 
353
420
  def sketch(quality: nil)
354
421
 
355
- img = read()
422
+ read() do |img|
356
423
 
357
- # Convert to grayscale
358
- sketch = img.quantize(256, Magick::GRAYColorspace)
424
+ # Convert to grayscale
425
+ sketch = img.quantize(256, Magick::GRAYColorspace)
359
426
 
360
- # Apply histogram equalization
361
- sketch = sketch.equalize
427
+ # Apply histogram equalization
428
+ sketch = sketch.equalize
362
429
 
363
- sketch = sketch.sketch(0, 10, 135)
364
- img = img.dissolve(sketch, 0.75, 0.25)
430
+ sketch = sketch.sketch(0, 10, 135)
431
+ img = img.dissolve(sketch, 0.75, 0.25)
365
432
 
366
- write img, quality
433
+ write img, quality
434
+
435
+ end
367
436
 
368
437
  end
369
438
 
@@ -379,10 +448,12 @@ class EasyImgUtils
379
448
 
380
449
  def vignette(quality: nil)
381
450
 
382
- img = read()
383
- img2 = img.vignette
384
-
385
- write img2, quality
451
+ read() do |img|
452
+
453
+ img2 = img.vignette
454
+ write img2, quality
455
+
456
+ end
386
457
 
387
458
  end
388
459
 
@@ -391,8 +462,28 @@ class EasyImgUtils
391
462
  private
392
463
 
393
464
  def read(file=@file_in)
394
- data, type = RXFHelper.read(file)
395
- Magick::Image.from_blob(data).first
465
+
466
+ files = if file =~ /%d/ then
467
+
468
+ regfilepath = file.sub('%d','(\d+)')
469
+ globfilepath = file.sub('%d','*')
470
+
471
+ a = Dir[globfilepath]
472
+ puts 'a: ' + a.inspect if @debug
473
+ a.sort_by {|x| Regexp.new(regfilepath).match(x).captures[0].to_i }
474
+
475
+ else
476
+ [file]
477
+ end
478
+
479
+ files.each do |filex|
480
+
481
+ @filex_in = filex
482
+ data, type = RXFHelper.read(filex)
483
+ yield(Magick::Image.from_blob(data).first)
484
+
485
+ end
486
+
396
487
  end
397
488
 
398
489
  def run(command, show=false)
@@ -410,19 +501,27 @@ class EasyImgUtils
410
501
 
411
502
  return img.to_blob unless @file_out
412
503
 
413
- if @file_out =~ /^dfs:/ then
504
+ file_out = if @file_out =~ /%d/ then
505
+ regpath = @file_in.sub('%d','(\d+)')
506
+ n = @filex_in[/#{regpath}/,1]
507
+ @file_out.sub('%d',n)
508
+ else
509
+ @file_out
510
+ end
511
+
512
+ if file_out =~ /^dfs:/ then
414
513
 
415
- outfile = File.join(@working_dir, File.basename(@file_out))
514
+ outfile = File.join(@working_dir, File.basename(file_out))
416
515
 
417
516
  img.write outfile do
418
517
  self.quality = quality.to_i if quality
419
518
  end
420
519
 
421
- FileX.cp outfile, @file_out
520
+ FileX.cp outfile, file_out
422
521
 
423
522
  else
424
523
 
425
- img.write @file_out do
524
+ img.write file_out do
426
525
  self.quality = quality.to_i if quality
427
526
  end
428
527
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easyimg_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,7 +35,7 @@ cert_chain:
35
35
  KY48n99T12IOioQ4ghCO1L/UAg2taLOcZbMv4WpV1p9bXKhnrow81zeogZjjiNGS
36
36
  OmTAjCfyGFPC/1eXnSV5Smv8
37
37
  -----END CERTIFICATE-----
38
- date: 2020-05-12 00:00:00.000000000 Z
38
+ date: 2021-03-20 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rmagick
@@ -43,62 +43,82 @@ dependencies:
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '4.1'
46
+ version: '4.2'
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: 4.1.2
49
+ version: 4.2.2
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: '4.1'
56
+ version: '4.2'
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 4.1.2
59
+ version: 4.2.2
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rxfhelper
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: '0.9'
66
+ version: '1.1'
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 0.9.4
69
+ version: 1.1.3
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '0.9'
76
+ version: '1.1'
77
77
  - - ">="
78
78
  - !ruby/object:Gem::Version
79
- version: 0.9.4
79
+ version: 1.1.3
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: webp-ffi
82
82
  requirement: !ruby/object:Gem::Requirement
83
83
  requirements:
84
84
  - - "~>"
85
85
  - !ruby/object:Gem::Version
86
- version: '0.2'
86
+ version: '0.3'
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 0.2.7
89
+ version: 0.3.1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.3'
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 0.3.1
100
+ - !ruby/object:Gem::Dependency
101
+ name: x4ss
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 0.2.0
94
107
  - - "~>"
95
108
  - !ruby/object:Gem::Version
96
109
  version: '0.2'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
97
114
  - - ">="
98
115
  - !ruby/object:Gem::Version
99
- version: 0.2.7
116
+ version: 0.2.0
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '0.2'
100
120
  description:
101
- email: james@jamesrobertson.eu
121
+ email: digital.robertson@gmail.com
102
122
  executables: []
103
123
  extensions: []
104
124
  extra_rdoc_files: []
@@ -123,7 +143,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
143
  - !ruby/object:Gem::Version
124
144
  version: '0'
125
145
  requirements: []
126
- rubygems_version: 3.0.3
146
+ rubyforge_project:
147
+ rubygems_version: 2.7.10
127
148
  signing_key:
128
149
  specification_version: 4
129
150
  summary: Makes manipulating images from 1 line of code easier.
metadata.gz.sig CHANGED
Binary file