image_voodoo 0.8.7 → 0.9.1

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.
data/bin/image_voodoo CHANGED
@@ -1,86 +1,100 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #!/usr/bin/env ruby
2
4
 
3
5
  require 'optparse'
4
6
 
7
+ headless = true
5
8
  actions = []
6
9
  images = []
7
10
  original_image = nil
8
11
 
9
- opts = OptionParser.new do |opts|
10
- opts.banner = "Usage: image_voodoo [actions] image_file"
11
- opts.separator "Perform some actions on a source image."
12
-
13
- opts.separator ""
14
- opts.separator "Actions are meant to be chained. Examples:"
15
- opts.separator " # Print the dimensions"
16
- opts.separator " image_voodoo --dim small.jpg"
17
- opts.separator ""
18
- opts.separator " # Convert to a thumbnail, preview, and then save the result"
19
- opts.separator " image_voodoo --thumbnail 50 --preview --save thumb.png large.jpg"
20
- opts.separator ""
21
- opts.separator " # Convert source to 3 thumbnails, showing dimensions and"
22
- opts.separator " # previewing along the way"
23
- opts.separator " image_voodoo --dim --resize 50x50 --dim --preview --save t1.jpg"
24
- opts.separator " --pop --resize 40x40 --dim --preview --save t2.jpg"
25
- opts.separator " --pop --resize 30x30 --dim --preview --save t3.jpg image.jpg"
26
-
27
- opts.separator ""
28
- opts.separator "Actions:"
29
-
30
- opts.on("-a", "--alpha color_value", "Make color transparent in image") do |c|
31
- if c !~ /[[:xdigit:]]{6,6}/
32
- opts.usage "color_value is rrggbb in hexidecimal format"
33
- end
34
- actions << lambda {|img| img.alpha(c) }
12
+ opts = OptionParser.new do |o|
13
+ o.banner = 'Usage: image_voodoo [actions] image_file'
14
+ o.separator 'Perform actions/transformations on an image.'
15
+ o.separator ''
16
+ o.separator 'Examples:'
17
+ o.separator ' image_voodoo --dim small.jpg # Print the dimensions'
18
+ o.separator ''
19
+ o.separator ' # Make a thumbnail, preview it, and then save it.'
20
+ o.separator ' image_voodoo --thumbnail 50 --preview --save thumb.png large.jpg'
21
+ o.separator ''
22
+ o.separator ' # Make 2 thumbnails, showing dimensions and previewing them'
23
+ o.separator ' image_voodoo --dim --resize 50x50 --dim --preview --save t1.jpg'
24
+ o.separator ' --pop --resize 40x40 --dim --preview --save t2.jpg image.jpg'
25
+ o.separator ''
26
+ o.separator 'Actions:'
27
+
28
+ o.on('-a', '--alpha rrggbb', 'Make color transparent in image') do |c|
29
+ o.usage 'rrggbb is in hexidecimal format' if c !~ /[[:xdigit:]]{6,6}/
30
+ actions << ->(img) { img.alpha(c) }
31
+ end
32
+
33
+ o.on('-b', '--brightness SCALE,OFFSET', 'Adjust brightness') do |args|
34
+ scale, offset = args.split(/,/).map(&:to_f)
35
+ o.usage 'You need to specify proper scale and offset' unless scale && offset
36
+ actions << ->(img) { img.adjust_brightness(scale, offset) }
37
+ end
38
+
39
+ o.on('-B', '--border WIDTH,COLOR,STYLE', 'Add a simple border') do |args|
40
+ width, color, style = args.split(/,/)
41
+ options = { width: width, color: color, style: style }
42
+ actions << ->(img) { img.add_border(options) }
35
43
  end
36
44
 
37
- opts.on("-b", "--brightness SCALE,OFFSET", "Adjust brightness") do |args|
38
- scale, offset = args.split(/,/).map {|v| v.to_f}
39
- opts.usage "You need to specify proper scale and offset" unless scale && offset
40
- actions << lambda {|img| img.adjust_brightness(scale, offset) }
45
+ o.on('-d', '--dimensions', 'Print the image dimensions') do
46
+ actions << ->(img) { img.tap { puts "#{img.width}x#{img.height}" } }
41
47
  end
42
48
 
43
- opts.on("-B", "--border WIDTH,COLOR,STYLE", "Add a simple border") do |args|
44
- width, color, style = args.split(/,/)
45
- options = {:width => width, :color => color, :style => style }
49
+ o.on('-g', '--greyscale', 'Convert image to greyscale') do
50
+ actions << ->(img) { img.greyscale }
51
+ end
46
52
 
47
- actions << lambda {|img| img.add_border(options) }
53
+ o.on('-h', '--flip_horizontally') do
54
+ actions << ->(img) { img.flip_horizontally }
48
55
  end
49
56
 
50
- opts.on("-d", "--dimensions", "Print the image dimensions") do
51
- actions << lambda {|img| puts "#{img.width}x#{img.height}"; img }
57
+ o.on('-m', '--metadata') do
58
+ actions << ->(img) { img.tap { puts img.metadata } }
52
59
  end
53
60
 
54
- opts.on("-g", "--greyscale", "Convert image to greyscale") do
55
- actions << lambda {|img| img.greyscale }
61
+ o.on('-n', '--negative', 'Make a negative out of the image') do
62
+ actions << ->(img) { img.negative }
56
63
  end
57
64
 
58
- opts.on("-h", "--flip_horizontally") do
59
- actions << lambda {|img| img.flip_horizontally }
65
+ o.on('-o', '--orient', 'Rotate image to orient it based on metadata') do
66
+ actions << ->(img) { img.correct_orientation }
60
67
  end
61
68
 
62
- opts.on("-n", "--negative", "Make a negative out of the image") do
63
- actions << lambda {|img| img.negative }
69
+ o.on('-q', '--quality 0..1', Float, 'Set % of quality for lossy compression') do |quality|
70
+ actions << ->(img) { img.quality(quality) }
64
71
  end
65
72
 
66
- opts.on("-q", "--quality 0..1", Float, "Set % of quality for lossy compression") do |quality|
67
- actions << lambda {|img| img.quality(quality) }
73
+ o.on('-R', '--rotate 0..360', Float, 'Set angle to rotate image') do |angle|
74
+ actions << ->(img) { img.rotate(angle.to_f) }
68
75
  end
69
76
 
70
- opts.on("-s", "--save FILENAME", "Save the results to a new file") do |f|
71
- actions << lambda {|img| img.save(f); img }
77
+ o.on('-r', '--resize WIDTHxHEIGHT', 'Make a new resized image') do |dim|
78
+ width, height = dim.split(/x/i).map(&:to_i)
79
+ o.usage 'You need to specify proper dimensions' unless width && width > 0 && height && height > 0
80
+ actions << ->(img) { img.resize(width, height) }
72
81
  end
73
82
 
74
- opts.on("-t", "--thumbnail SIZE", Integer, "Create a thumbnail of the given size") do |size|
75
- actions << lambda {|img| img.thumbnail(size) }
83
+ o.on('-s', '--save FILENAME', 'Save the results to a new file') do |f|
84
+ actions << ->(img) { img.tap { img.save(f) } }
76
85
  end
77
86
 
78
- opts.on("-v", "--flip_vertically") do
79
- actions << lambda {|img| img.flip_vertically }
87
+ o.on('-t', '--thumbnail SIZE', Integer, 'Create a thumbnail of the given size') do |size|
88
+ actions << ->(img) { img.thumbnail(size) }
80
89
  end
81
90
 
82
- opts.on("-p", "--preview", "Preview the image. Close the frame window",
83
- "to continue, or quit the application to", "abort the action pipeline") do
91
+ o.on('-v', '--flip_vertically') { actions << ->(img) { img.flip_vertically } }
92
+
93
+ o.on('-p', '--preview',
94
+ 'Preview the image. Close the frame window',
95
+ 'to continue, or quit the application to',
96
+ 'abort the action pipeline') do
97
+ headless = false
84
98
  actions << lambda do |img|
85
99
  done = false
86
100
  img.preview { done = true }
@@ -89,38 +103,33 @@ opts = OptionParser.new do |opts|
89
103
  end
90
104
  end
91
105
 
92
- opts.on("--push", "Save the current image to be popped later") do
93
- actions << lambda {|img| images << img; img }
106
+ o.on('--push', 'Save the current image to be popped later') do
107
+ actions << ->(img) { img.tap { images << img } }
94
108
  end
95
109
 
96
- opts.on("--pop", "Revert back to the previous saved image", "or the original source image") do
97
- actions << lambda {|img| images.pop || original_image }
110
+ o.on('--pop', 'Revert back to the previous image') do
111
+ actions << -> { images.pop || original_image }
98
112
  end
99
113
 
100
- opts.on("-r", "--resize WIDTHxHEIGHT", "Create a new image with the specified", "dimensions") do |dim|
101
- width, height = dim.split(/x/i).map {|v| v.to_i}
102
- opts.usage "You need to specify proper dimensions" unless width && width > 0 && height && height > 0
103
- actions << lambda {|img| img.resize(width,height) }
114
+ o.on('-f', '--format', 'Print the image format') do
115
+ actions << ->(img) { img.tap { img.format } }
104
116
  end
105
117
 
106
- opts.on("-f", "--format", "Print the image format") do
107
- actions << lambda {|img| puts img.format; img }
108
- end
118
+ o.on_tail('-h', '--help', 'Show this message') { o.usage }
109
119
 
110
- opts.on_tail("-h", "--help", "Show this message") do
111
- puts opts
112
- exit 0
113
- end
114
-
115
- def opts.usage(msg)
116
- puts msg
120
+ def o.usage(msg=nil)
121
+ puts msg if msg
117
122
  puts self
118
123
  exit 1
119
124
  end
120
125
  end
121
126
  opts.parse!(ARGV)
122
- opts.usage("You need to supply a source image filename.") unless ARGV.first
123
- opts.usage("You need to supply one or more actions.") unless actions.size > 0
127
+ opts.usage('You need to supply a source image filename.') unless ARGV.first
128
+ opts.usage('You need to supply one or more actions.') if actions.empty?
129
+
130
+ # For this binstub we only want to load non-headless if we are using
131
+ # the preview feature. top of See lib/image_voodoo.rb for more info...
132
+ require 'image_voodoo/needs_head' unless headless
124
133
 
125
134
  require 'image_voodoo'
126
135
  file_name = ARGV.first
data/image_voodoo.gemspec CHANGED
@@ -1,6 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "image_voodoo/version"
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
5
+ require 'image_voodoo/version'
4
6
 
5
7
  Gem::Specification.new do |s|
6
8
  s.name = 'image_voodoo'
@@ -12,11 +14,16 @@ Gem::Specification.new do |s|
12
14
  s.summary = 'Image manipulation in JRuby with ImageScience compatible API'
13
15
  s.description = 'Image manipulation in JRuby with ImageScience compatible API'
14
16
 
15
- s.rubyforge_project = "image_voodoo"
16
-
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ["lib", "vendor"]
21
- s.has_rdoc = true
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
20
+ s.require_paths = %w[lib vendor]
21
+
22
+ s.add_development_dependency 'jar-dependencies'
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'rubocop'
25
+ s.add_development_dependency 'ruby-maven'
26
+ s.add_development_dependency 'test-unit'
27
+
28
+ s.requirements << 'jar com.drewnoakes, metadata-extractor, 2.11.0'
22
29
  end
data/lib/image_science.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'image_voodoo'
2
4
  # HA HA...let the pin-pricking begin
3
- ImageScience = ImageVoodoo
5
+ ImageScience = ImageVoodoo
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+
5
+ # Hide in ImageVoodoo so awt.rb can see this and we will not polute global
6
+ class ImageVoodoo
7
+ java_import java.awt.image.BufferedImage
8
+
9
+ # Re-open to add convenience methods.
10
+ class BufferedImage
11
+ def each
12
+ height.times { |j| width.times { |i| yield i, j } }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+
5
+ # Hide in ImageVoodoo so awt.rb can see this and we will not polute global
6
+ class ImageVoodoo
7
+ java_import java.awt.Graphics2D
8
+
9
+ # Re-open to add convenience methods.
10
+ class Graphics2D
11
+ def draw_this_image(image)
12
+ draw_image image, 0, 0, nil
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ImageVoodoo
4
+ # (Experimental) An attempt at some primitive drawing in images.
2
5
  module Shapes
6
+ # FIXME: if image has alpha values the border shows through since it is
7
+ # a solid fill.
8
+ ##
9
+ # *AWT* (experimental) Add a border to the image and yield/return a new
10
+ # image. The following options are supported:
11
+ # - width: How thick is the border (default: 3)
12
+ # - color: Which color is the border (in rrggbb hex value)
13
+ # - style: etched, raised, plain (default: plain)
14
+ #
15
+ def add_border(options = {})
16
+ border_width = options[:width].to_i || 2
17
+ new_width, new_height = width + 2*border_width, height + 2*border_width
18
+ target = paint(BufferedImage.new(new_width, new_height, color_type)) do |g|
19
+ paint_border(g, new_width, new_height, options)
20
+ g.draw_image(@src, nil, border_width, border_width)
21
+ end
22
+ block_given? ? yield(target) : target
23
+ end
24
+
25
+ def paint_border(g, new_width, new_height, options)
26
+ g.color = hex_to_color(options[:color])
27
+ fill_method, *args = border_style(options)
28
+ g.send fill_method, 0, 0, new_width, new_height, *args
29
+ end
30
+
31
+ def border_style(options)
32
+ case (options[:style] || "").to_s
33
+ when "raised" then
34
+ [:fill3DRect, true]
35
+ when "etched" then
36
+ [:fill3DRect, false]
37
+ else
38
+ [:fill_rect]
39
+ end
40
+ end
41
+
3
42
  ##
4
43
  # *AWT* Draw a square
5
44
  #
@@ -18,14 +57,14 @@ class ImageVoodoo
18
57
  # *AWT* Draw a rounded square
19
58
  #
20
59
  def square_rounded(x, y, dim, rgb, arc_width=0, fill=true)
21
- rect_rounded(x,y, dim, dim, rgb, arc_width, arc_width, fill)
60
+ rect_rounded(x, y, dim, dim, rgb, arc_width, arc_width, fill)
22
61
  end
23
62
 
24
63
  ##
25
64
  # *AWT* Draw a rounded rectangle
26
65
  #
27
66
  def rect_rounded(x, y, width, height, rgb, arc_width=0, arc_height=0, fill=true)
28
- as_color(ImageVoodoo.hex_to_color(rgb)) do |g|
67
+ as_color(hex_to_color(rgb)) do |g|
29
68
  if fill
30
69
  g.fill_round_rect x, y, width, height, arc_width, arc_height
31
70
  else
@@ -44,4 +83,3 @@ class ImageVoodoo
44
83
  end
45
84
  end
46
85
  end
47
-