Class: EasyImgUtils

Inherits:
Object
  • Object
show all
Extended by:
CommandHelper
Includes:
Magick, RXFHelperModule
Defined in:
lib/easyimg_utils.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CommandHelper

list, search

Constructor Details

#initialize(img_in = nil, img_out = nil, out: img_out, working_dir: '/tmp', debug: false) ⇒ EasyImgUtils

Returns a new instance of EasyImgUtils.



86
87
88
89
90
91
92
# File 'lib/easyimg_utils.rb', line 86

def initialize(img_in=nil, img_out=nil, out: img_out, 
               working_dir: '/tmp', debug: false)

  @file_in, @file_out, @working_dir = img_in, out, working_dir    
  @debug = debug

end

Class Method Details

.calc_resize(geometry, new_geometry, force: false) ⇒ Object

e.g. calc_resize ‘1449x1932’, ‘640x480’ #=> 480x640 e.g. calc_resize ‘518x1024’, ‘*518x500’ #=> “518x1024” the asterisk denotes a guaranteed the image will be resized using x or y



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/easyimg_utils.rb', line 98

def self.calc_resize(geometry, new_geometry, force: false)
  
  xy = geometry.split('x',2)
  xy2 = new_geometry.split('x',2)

  # find any locked geometry which guarantees the resize on either x or y
  lock = xy2.find {|x| x =~ /^\*/}

  a = xy.map {|x| x[/\d+/].to_i}
  a2 = xy2.map {|x| x[/\d+/].to_i}

  i = lock ? a2.index(lock[1..-1].to_i) : a.index(a.max)

  factor = a2[i] / a[i].to_f

  s3 = a.map {|x| (x * factor).round}.join('x')    
  
end

Instance Method Details

#add_rectangle(a = [], quality: nil, color: 'green', stroke_width: 5, x1: 0, y1: 0, x2: 0, y2: 0) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/easyimg_utils.rb', line 117

def add_rectangle(a=[], quality: nil, color: 'green', stroke_width: 5, 
                  x1: 0, y1: 0, x2: 0, y2: 0)
  
  x1, y1, x2, y2 = *a if a
  read() do |img|
    gc = Magick::Draw.new
    gc.stroke('green')
    gc.stroke_width(5)
    gc.fill('transparent')
    gc.rectangle(x1, y1, x2, y2)
    gc.draw(img)
    write img, quality
  end
  
end

#add_svg(svg_file) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/easyimg_utils.rb', line 133

def add_svg(svg_file)

  img = Magick::ImageList.new
  img.read(@file_in)
  
  img.read(svg_file) do
      self.format = 'SVG'
      self.background_color = 'transparent'
  end
  
  img.flatten_images.write @file_out
  
end

#add_text(s = 'your text goes here', quality: nil) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/easyimg_utils.rb', line 147

def add_text(s='your text goes here', quality: nil)
  
  read() do |img|

    d = Draw.new
    img.annotate(d, 0,0,0,0, s) do
      d.gravity = Magick::SouthGravity
      d.pointsize = 26
      d.stroke = '#000000'
      d.fill = '#ffffff'
      d.font_weight = Magick::BoldWeight
    end
    
    write img, quality
    
  end
  
end

#animateObject



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/easyimg_utils.rb', line 166

def animate()

  anim = Magick::ImageList.new
  
  read() {|img| anim << img }    
  anim.ticks_per_second = 100
  anim.delay = 20
  
  @file_out ? anim.write(@file_out) : anim.animate
  
end

#blur(x: 0, y: 0, w: 80, h: 80, strength: 8, quality: nil) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/easyimg_utils.rb', line 178

def blur(x: 0, y: 0, w: 80, h: 80, strength: 8, quality: nil)
  
  width, height = w, h
  
  read() do |img|
    
    region = img.dispatch(x, y, width, height, 'RGB')
    face_img = Magick::Image.constitute(width, height, "RGB", region)
    img.composite!(face_img.gaussian_blur(0, strength), x, y, 
                  Magick::OverCompositeOp)
    write img, quality
    
  end
  
end

#brightness(quality: nil) ⇒ Object



194
195
196
197
198
199
# File 'lib/easyimg_utils.rb', line 194

def brightness(quality: nil)
  read() do |img|
    img2 = imglevel(-Magick::QuantumRange * 0.25, Magick::QuantumRange * 1.25, 1.0)
    write img2, quality
  end
end

#calc_resize(geometry) ⇒ Object

calculates the new geometry after a resize



203
204
205
# File 'lib/easyimg_utils.rb', line 203

def calc_resize(geometry)    
  EasyImgUtils.calc_resize(info()[:geometry], geometry)
end

#capture_screen(quality: nil) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
# File 'lib/easyimg_utils.rb', line 207

def capture_screen(quality: nil)
  
  # defaults (silent=false, frame=false, descend=false, 
  #           screen=false, borders=false)
  
  img = Magick::Image.capture(true, false, false, true, true) {
    self.filename = "root"
  }
  write img, quality
  
end

#center_crop(w = 0, h = 0, width: w, height: h, quality: nil) ⇒ Object



219
220
221
222
223
224
225
226
227
228
# File 'lib/easyimg_utils.rb', line 219

def center_crop(w=0, h=0, width: w, height: h, quality: nil)
  
  return unless w
  
  read() do |img|
    img.crop!(CenterGravity, width, height)
    write img, quality
  end
  
end

#composite(filex = nil, x: 0, y: 0, quality: nil) ⇒ Object Also known as: overlay, add_img



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/easyimg_utils.rb', line 230

def composite(filex=nil, x: 0, y: 0, quality: nil)
  
  return unless filex
  
  read() do |img|
      
    imgx = Magick::ImageList.new(filex)

    # Change the white pixels in the sign to transparent.
    imgx = imgx.matte_replace(0,0)

    img2 = Magick::Draw.new
    img2.composite(x, y, 0, 0, imgx)
    img2.draw(img)    
    
    write img, quality
  end
  
end

#contrast(level = 5) ⇒ Object

contrast level 1 low -> 10 high



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/easyimg_utils.rb', line 256

def contrast(level=5)
  
  neutral = 5
  
  return if level == neutral
      
  read() do |img|
          
    n = neutral - level
    sharpen  = n > 0 
    n.abs.times { img = img.contrast(sharpen) }
    
    write img, quality
  end
  
end

#convert(quality: nil) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/easyimg_utils.rb', line 273

def convert(quality: nil)
  
  if File.extname(@file_in) == '.webp' then      
    
    # output_format options: pam, ppm, pgm, bmp, tiff or yuv
    ext = File.extname(@file_out)[1..-1].to_sym
    puts 'ext: ' + ext.inspect if @debug
    
    if ext == :jpg then
      
      file_out = @file_out.sub(/\.jpg$/,'.png')
      WebP.decode(@file_in, file_out, output_format: :png)
      img = read(file_out)
      write img, quality
      
    else
    
      WebP.decode(@file_in, @file_out, output_format: ext)
    end
    
  else
    img = read()
    write img, quality
  end
  
end

#crop(x: 0, y: 0, w: nil, h: nil, quality: nil) ⇒ Object



300
301
302
303
304
305
306
307
308
309
# File 'lib/easyimg_utils.rb', line 300

def crop(x: 0, y: 0, w: nil, h: nil, quality: nil)
  
  return unless w
  
  read() do |img|
    img.crop!(x,y, width=w, height=h)
    write img, quality
  end
  
end

#facesObject



311
312
313
# File 'lib/easyimg_utils.rb', line 311

def faces()
  DetectFaces.new(@file_in).faces
end

#fax_effect(threshold: 0.55, quality: nil) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
# File 'lib/easyimg_utils.rb', line 315

def fax_effect(threshold: 0.55, quality: nil)

  read() do |img|
  
    # Use a threshold of 55% of MaxRGB.
    img = img.threshold(Magick::MaxRGB*threshold)      
    write img, quality
    
  end
  
end

#greyscale(quality: nil) ⇒ Object Also known as: grayscale



327
328
329
330
331
332
333
334
# File 'lib/easyimg_utils.rb', line 327

def greyscale(quality: nil)
  
  read() do |img|
    img2 = img.quantize(256, GRAYColorspace)
    write img2, quality
  end
  
end

#infoObject



338
339
340
341
342
343
344
345
346
347
348
# File 'lib/easyimg_utils.rb', line 338

def info()

  img = Magick::Image.ping( @file_in ).first
  {
    geometry: "%sx%s" % [img.columns, img.rows],
    mime_type: img.mime_type, format: img.format,
    quality: img.quality, filesize: img.filesize,
    filename: img.filename, created: img.properties
  }
  
end

#make_thumbnail(width = 125, height = 125) ⇒ Object Also known as: thumbnail



350
351
352
353
354
355
356
357
# File 'lib/easyimg_utils.rb', line 350

def make_thumbnail(width=125, height=125)
  
  read() do |img|
    img2 = img.thumbnail(width, height)
    write img2, quality
  end
  
end

#resize(raw_geometry = '320x240', quality: nil) ⇒ Object

defines the maximum size of an image while maintaining aspect ratio



363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/easyimg_utils.rb', line 363

def resize(raw_geometry='320x240', quality: nil)
  
  geometry = calc_resize(raw_geometry
                           )
  read() do |preview|
  
    preview.change_geometry!(geometry) do |cols, rows, img|
      img.resize!(cols, rows)
    end
    
    write preview, quality
  end
  
end

#rotate(degrees) ⇒ Object



378
379
380
381
382
383
384
385
# File 'lib/easyimg_utils.rb', line 378

def rotate(degrees)
  
  read() do |img|
    img2 = img.rotate(degrees.to_i)
    write img2, quality
  end
  
end

#rotate_180Object



387
388
389
390
391
392
393
394
# File 'lib/easyimg_utils.rb', line 387

def rotate_180()
  
  read() do |img|
    img2 = img.rotate(180)
    write img2, quality
  end
  
end

#rotate_leftObject



396
397
398
399
400
401
402
403
# File 'lib/easyimg_utils.rb', line 396

def rotate_left()
  
  read() do |img|
    img2 = img.rotate(-45)
    write img2, quality
  end
  
end

#rotate_rightObject



405
406
407
408
409
410
411
412
# File 'lib/easyimg_utils.rb', line 405

def rotate_right()
  
  read() do |img|
    img2 = img.rotate(45)
    write img2, quality    
  end
  
end

#scale(factor = 0.75, quality: nil) ⇒ Object

Scales an image by the given factor e.g. 0.75 is 75%



416
417
418
419
420
421
422
423
424
425
# File 'lib/easyimg_utils.rb', line 416

def scale(factor=0.75, quality: nil)
  
  read() do |img|
  
    img2 = img.scale(factor)      
    write img2, quality
    
  end
  
end

#screencast(duration: 6, scale: 1, window: true) ⇒ Object

Takes a screenshot every second to create an animated gif



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/easyimg_utils.rb', line 429

def screencast(duration: 6, scale: 1, window: true)
  
  fileout = @file_out.sub(/\.\w+$/,'%d.png')
  
  puts 'fileout: ' + fileout if @debug
  
  x4ss = X4ss.new fileout, mouse: true, window: true
  mode = window ? :window : :screen
  sleep 2; x4ss.record duration: duration, mode: mode
  x4ss.save
  
  fileout2 = fileout.sub(/(?=%)/,'b')
  EasyImgUtils.new(fileout, fileout2).scale(scale) unless scale == 1
  EasyImgUtils.new(fileout2, @file_out).animate
  
end

#sketch(quality: nil) ⇒ Object Also known as: drawing



446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/easyimg_utils.rb', line 446

def sketch(quality: nil)
  
  read() do |img|

    # Convert to grayscale
    sketch = img.quantize(256, Magick::GRAYColorspace)

    # Apply histogram equalization
    sketch = sketch.equalize

    sketch = sketch.sketch(0, 10, 135)
    img = img.dissolve(sketch, 0.75, 0.25)

    write img, quality
    
  end
  
end

#view(show: true) ⇒ Object



467
468
469
470
471
472
473
# File 'lib/easyimg_utils.rb', line 467

def view(show: true)
  
  return unless @file_out
  command = `feh #{@file_out}`
  run command, show
  
end

#vignette(quality: nil) ⇒ Object Also known as: feathered_around



475
476
477
478
479
480
481
482
483
484
# File 'lib/easyimg_utils.rb', line 475

def vignette(quality: nil)
  
  read() do |img|
    
    img2 = img.vignette
    write img2, quality
    
  end
  
end