image_voodoo 0.8.8 → 0.9.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: 10db8a256e32e37a28b94c9246049f7029484a49
4
- data.tar.gz: 27ec82a19aff0bc3171a2c0bff8338c1c7ef19e6
2
+ SHA256:
3
+ metadata.gz: 432be5fdc3ce35d25ccec454aec40066f07f512fdf0d45891ecc49ff28e48368
4
+ data.tar.gz: cacc16a2c686344983bab91d9467ff8a80957f22db50ab037f54553bd1004823
5
5
  SHA512:
6
- metadata.gz: 9bf960b9cd108f06ea22ba69a5f01f7d5ee3ca10dec63fe7a79cf6d2fe986f9a6753ef1969c8eabfa95af8509e0b19211b6ea7c0718d6106c42d998e255e6e36
7
- data.tar.gz: 27e8b1a524c25f7a72b3b15c3a9e37e4bf983111410a8be64d78b45c55ce133ed185ec5cf47ab527b565828d106515fdf053ccc41ee0298b1b1b6df75fc923f3
6
+ metadata.gz: 421f317327a6d6ecb7c799cd1d4bee0a8a0193ce5f9395c55c2b642387d4fb8b6f62533255b565a5698d379c5ac91d19b0c0fc9fa7776116efee90c537ecf7dd
7
+ data.tar.gz: 2fe8bfed88aaa7645ed9eb240a652a0c47c095e72043f62dddfe5effcf415c3d833a2b5f6991ad852bb9a9bd06e4bd3363742807229c7efb0b227ab0b1d123af
data/.gitignore CHANGED
@@ -1,2 +1,6 @@
1
1
  /pkg
2
2
  *~
3
+ Gemfile.lock
4
+ lib/image_voodoo_jars.rb
5
+ lib/com
6
+ .idea
data/.rubocop.yml ADDED
@@ -0,0 +1,165 @@
1
+ # Experiment to tweak source based on what rubocop wanted me to. I basically
2
+ # gave up and made the following exceptions. Personally, I find the tool did
3
+ # find many interesting/questionable code Qs in the project but it is soooo
4
+ # opinionated in pretty unimportant ways (like who cares how I write my
5
+ # comments, or why can't I use kind_of? or why give me a fail for a less
6
+ # readable but more performant pattern).
7
+ #
8
+ # I can obviously tweak rules (like below) but I keep hearing of people pulling
9
+ # their hair out over all the unimportant rules; I question why this project is
10
+ # "all-in" on it's rules versus leaving most of the style rules as some preset
11
+ # profiles people can opt in to.
12
+ #
13
+ # So I am committing this and I will try and run this every now and then to
14
+ # see what it thinks about what I wrote but you will not see this as a
15
+ # requirement for commits since I think by the time I configured it to my
16
+ # liking I could have finished implementing this library. Perhaps if I
17
+ # continue using this here and there I will end up with a profile I find
18
+ # acceptable? I did find value but all the piddly shit just made me angry.
19
+ # I will reflect on it some more...
20
+
21
+ # This is a Java AWT call. It is not what the tool thinks it is...which
22
+ # might be an issue for users interacting with Java from JRuby.
23
+ Lint/UselessSetterCall:
24
+ Exclude:
25
+ - 'lib/image_voodoo/awt.rb'
26
+
27
+ # This is just impossible for them to call properly. I am doing something
28
+ # like rotate_impl and it is a bunch of reasonably simple math. If you look
29
+ # for this transformation in a text book it will look like this code. Putting
30
+ # a bunch of math within different methods would get the score down but
31
+ # it would not help readability. (addendum: I did try and break it apart more
32
+ # and never reached 15 but got closer. I felt this rule is neat but the
33
+ # score really depends on what it is.
34
+ Metrics/AbcSize:
35
+ Max: 16.5
36
+
37
+ # This is triggered for correct_orientation_impl. I could put these transforms
38
+ # in a table and then execute lambdas for each orientation but this is much
39
+ # more clear.
40
+ Metrics/CyclomaticComplexity:
41
+ Max: 10
42
+
43
+ # A bunch of fields in a hash are basically generated data. Correcting them
44
+ # for column seems much too pedantic. I guess exclude is the right thing for
45
+ # an unusual file?
46
+ Layout/LineLength:
47
+ Max: 132
48
+ Exclude:
49
+ - 'lib/image_voodoo/metadata.rb'
50
+
51
+ # Metadata classes have data in them. awt.rb is big and perhaps could be
52
+ # shrunk but it is not a hard file to navigate and the cleaving points are
53
+ # not super obvious. These sorts of rules feel very arbitrary and if I have
54
+ # n highly related things and they do not fit into a more restrictive
55
+ # taxonomy why would the file being longer matter? I do understand the
56
+ # motivation here but as a default rule this feels wrong to me.
57
+ Metrics/ClassLength:
58
+ Max: 250
59
+
60
+ # I do not find this very useful. There is no performance difference and
61
+ # sometimes I want to highlight this string does not involve interpolation.
62
+ # Other times it is not worth pointing out.
63
+ Style/StringLiterals:
64
+ Enabled: false
65
+
66
+ # require 'english' is a step too far for $! which is so baked into my
67
+ # head I do not want to change :)
68
+ Style/SpecialGlobalVars:
69
+ Enabled: false
70
+
71
+ # I am grouping math and using lack of whitespace for separation.
72
+ Layout/SpaceAroundOperators:
73
+ Enabled: false
74
+
75
+ # I prefer tight assignment for opt args.
76
+ Layout/SpaceAroundEqualsInParameterDefault:
77
+ Enabled: false
78
+
79
+ # Java methods which override or implement Java method names cannot be switched
80
+ # to snake case. Do we really need this as a rule anyways? I have never seen
81
+ # a Rubyist do this as a preferred style?
82
+ Naming/MethodName:
83
+ Enabled: false
84
+
85
+ # bin/image_voodoo main options block.
86
+ Metrics/BlockLength:
87
+ Exclude:
88
+ - 'bin/image_voodoo'
89
+
90
+ # Hash rocket looks much more natural in a rakefile for its deps.
91
+ Style/HashSyntax:
92
+ Exclude:
93
+ - 'Rakefile'
94
+
95
+ # Forget it. I do parallel assignment and you will have to peel it out of
96
+ # my cold dead hands.
97
+ Style/ParallelAssignment:
98
+ Enabled: false
99
+
100
+ # FIXME: consider keywords for shapes.
101
+ # I might switch these to keyword args if I ever revisit shapes support.
102
+ # In general lots of params do suck and are hard to remember. This library
103
+ # still is supposed to work in 1.8 but I can probably soon major rev this
104
+ # and switch over to keywords.
105
+ Metrics/ParameterLists:
106
+ Exclude:
107
+ - 'lib/image_voodoo/awt/shapes.rb'
108
+
109
+ # This is complaining that 'x' and 'y' are bad names because they are less
110
+ # than 3 chars. Silly rule even if I appreciate what it is trying to
111
+ # accomplish. Interestingly, in image_voodoo I do use h for height and
112
+ # w for width. Those probably could be written out but they are so common
113
+ # I am basically opting for short-hand. This is something I rarely do except
114
+ # domain-driven code like this (x,y,h,w).
115
+ Naming/MethodParameterName:
116
+ Enabled: false
117
+
118
+ # This represents one of those frustrating dogmatic rules where if I followed
119
+ # this advice I would then violate the column length rule. I specifically
120
+ # use traditional if indented block in cases where if_mod doesn't fit.
121
+ # Gramatically, if_mod can be across two lines but I hate how that looks. The
122
+ # second solution of logical &&/|| change for a raise is alien to for all but
123
+ # assignment.
124
+ Style/IfUnlessModifier:
125
+ Enabled: false
126
+
127
+ # What the hell. Really telling people that encoding: utf-8 should not happen
128
+ # because there are no multi-byte utf-8 characters in it? Why add this noise?
129
+ Style/Encoding:
130
+ Enabled: false
131
+
132
+ # FIXME:
133
+ # This is an unknown error which I should figure out. It must be some
134
+ # StandardError (which is what nothing explicit means) but I should actually
135
+ # be more explicit here.
136
+ Style/RescueStandardError:
137
+ Exclude:
138
+ - 'lib/image_voodoo.rb'
139
+
140
+
141
+ # This was complaining metadata_impl should use @metadata_impl instead of
142
+ # @metadata. I disagree and am unsure why I need to follow this programs
143
+ # opinion on what a good name is? What is commentable is if I change the
144
+ # variable name to @gorgon it still tells me I need to use @metadata_impl.
145
+ # So if I conditionally add any state in any method it will tell me I am
146
+ # memoizing and have to use same ivar as the name of the method? Is it more
147
+ # sophisticated than that? Should I have spent 2-3 minutes trying to figure
148
+ # out how this rule was implemented? :)
149
+ Naming/MemoizedInstanceVariableName:
150
+ Enabled: false
151
+
152
+ # I have two modes of use for private. If it is a small number of individual
153
+ # methods I am explicit and inline the private. If it is a large number of
154
+ # methods especially when the name is fairly obvious that those will be private
155
+ # (like render_impl) then I use block private. Not sure telling me I can only
156
+ # use a single style is very useful.
157
+ Style/AccessModifierDeclarations:
158
+ Enabled: false
159
+
160
+ # I feel for the tiny amount of generation here a better name would not help
161
+ # me understand it better. This is one of those naming rules I feel is
162
+ # probably helpful a minority of the time. Also I have never been confused
163
+ # by what a heredoc text represents because of my heredoc terminator?
164
+ Naming/HeredocDelimiterNaming:
165
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,2 +1,17 @@
1
+ language: ruby
2
+
3
+ sudo: false
4
+
1
5
  rvm:
2
- - jruby-19mode
6
+ - jruby-head
7
+
8
+ before_install:
9
+ - mkdir rvm_tmp
10
+ - cd rvm_tmp
11
+
12
+ before_script:
13
+ - cd ..
14
+ - git clone --depth 1 https://github.com/drewnoakes/metadata-extractor-images.git ../metadata-extractor-images
15
+
16
+ install: JRUBY_OPTS=--dev jruby --dev -S bundle install --jobs=3 --retry=3
17
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/Jars.lock ADDED
@@ -0,0 +1,3 @@
1
+ org.yaml:snakeyaml:1.23:compile:
2
+ com.drewnoakes:metadata-extractor:2.11.0:compile:
3
+ com.adobe.xmp:xmpcore:5.1.3:compile:
data/Rakefile CHANGED
@@ -1,13 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler'
2
4
  require 'rake/testtask'
5
+ require 'jars/installer'
3
6
  Bundler::GemHelper.install_tasks
7
+ Bundler.setup
8
+
9
+ task :default => %i[vendor_jars test]
4
10
 
5
- task :default => :test
11
+ desc 'Vendor Jars'
12
+ task :vendor_jars do
13
+ test_file = File.expand_path File.join('lib', 'image_voodoo_jars.rb'), __dir__
14
+ Jars::Installer.vendor_jars! unless File.exist? test_file
15
+ end
6
16
 
7
- desc "Run tests"
8
- task :test do
17
+ desc 'Run tests'
18
+ task :test => :vendor_jars do
9
19
  Rake::TestTask.new do |t|
10
- t.libs << "lib:vendor"
20
+ t.libs << 'lib:vendor'
11
21
  t.test_files = FileList['test/test*.rb']
12
22
  end
13
23
  end
data/bin/image_voodoo CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #!/usr/bin/env ruby
2
4
 
3
5
  require 'optparse'
@@ -7,101 +9,91 @@ actions = []
7
9
  images = []
8
10
  original_image = nil
9
11
 
10
- opts = OptionParser.new do |opts|
11
- opts.banner = "Usage: image_voodoo [actions] image_file"
12
- opts.separator "Perform some actions on a source image."
13
-
14
- opts.separator ""
15
- opts.separator "Actions are meant to be chained. Examples:"
16
- opts.separator " # Print the dimensions"
17
- opts.separator " image_voodoo --dim small.jpg"
18
- opts.separator ""
19
- opts.separator " # Convert to a thumbnail, preview, and then save the result"
20
- opts.separator " image_voodoo --thumbnail 50 --preview --save thumb.png large.jpg"
21
- opts.separator ""
22
- opts.separator " # Convert source to 3 thumbnails, showing dimensions and"
23
- opts.separator " # previewing along the way"
24
- opts.separator " image_voodoo --dim --resize 50x50 --dim --preview --save t1.jpg"
25
- opts.separator " --pop --resize 40x40 --dim --preview --save t2.jpg"
26
- opts.separator " --pop --resize 30x30 --dim --preview --save t3.jpg image.jpg"
27
-
28
- opts.separator ""
29
- opts.separator "Actions:"
30
-
31
- opts.on("-a", "--alpha color_value", "Make color transparent in image") do |c|
32
- if c !~ /[[:xdigit:]]{6,6}/
33
- opts.usage "color_value is rrggbb in hexidecimal format"
34
- end
35
- actions << lambda {|img| img.alpha(c) }
36
- end
37
-
38
- opts.on("-b", "--brightness SCALE,OFFSET", "Adjust brightness") do |args|
39
- scale, offset = args.split(/,/).map {|v| v.to_f}
40
- opts.usage "You need to specify proper scale and offset" unless scale && offset
41
- actions << lambda {|img| img.adjust_brightness(scale, offset) }
42
- end
43
-
44
- opts.on("-B", "--border WIDTH,COLOR,STYLE", "Add a simple border") do |args|
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|
45
40
  width, color, style = args.split(/,/)
46
- options = {:width => width, :color => color, :style => style }
47
-
48
- actions << lambda {|img| img.add_border(options) }
41
+ options = { width: width, color: color, style: style }
42
+ actions << ->(img) { img.add_border(options) }
49
43
  end
50
44
 
51
- opts.on("-d", "--dimensions", "Print the image dimensions") do
52
- actions << lambda {|img| puts "#{img.width}x#{img.height}"; img }
45
+ o.on('-d', '--dimensions', 'Print the image dimensions') do
46
+ actions << ->(img) { img.tap { puts "#{img.width}x#{img.height}" } }
53
47
  end
54
48
 
55
- opts.on("-g", "--greyscale", "Convert image to greyscale") do
56
- actions << lambda {|img| img.greyscale }
49
+ o.on('-g', '--greyscale', 'Convert image to greyscale') do
50
+ actions << ->(img) { img.greyscale }
57
51
  end
58
52
 
59
- opts.on("-h", "--flip_horizontally") do
60
- actions << lambda {|img| img.flip_horizontally }
53
+ o.on('-h', '--flip_horizontally') do
54
+ actions << ->(img) { img.flip_horizontally }
61
55
  end
62
56
 
63
- opts.on("-m", "--metadata") do
64
- actions << lambda {|img| puts img.metadata }
57
+ o.on('-m', '--metadata') do
58
+ actions << ->(img) { img.tap { puts img.metadata } }
65
59
  end
66
60
 
67
- opts.on("-n", "--negative", "Make a negative out of the image") do
68
- actions << lambda {|img| img.negative }
61
+ o.on('-n', '--negative', 'Make a negative out of the image') do
62
+ actions << ->(img) { img.negative }
69
63
  end
70
64
 
71
- opts.on("-o", "--orient", "Rotate image to orient it based on metadata") do
72
- actions << lambda {|img| img.correct_orientation }
65
+ o.on('-o', '--orient', 'Rotate image to orient it based on metadata') do
66
+ actions << ->(img) { img.correct_orientation }
73
67
  end
74
68
 
75
- opts.on("-q", "--quality 0..1", Float, "Set % of quality for lossy compression") do |quality|
76
- actions << lambda {|img| img.quality(quality) }
69
+ o.on('-q', '--quality 0..1', Float, 'Set % of quality for lossy compression') do |quality|
70
+ actions << ->(img) { img.quality(quality) }
77
71
  end
78
72
 
79
- opts.on("-R", "--rotate 0..360", Float, "Set angle to rotate image") do |angle|
80
- actions << lambda {|img| img.rotate(angle.to_f) }
73
+ o.on('-R', '--rotate 0..360', Float, 'Set angle to rotate image') do |angle|
74
+ actions << ->(img) { img.rotate(angle.to_f) }
81
75
  end
82
76
 
83
- opts.on("-r", "--resize WIDTHxHEIGHT", "Create a new image with the specified", "dimensions") do |dim|
84
- width, height = dim.split(/x/i).map {|v| v.to_i}
85
- opts.usage "You need to specify proper dimensions" unless width && width > 0 && height && height > 0
86
- actions << lambda {|img| img.resize(width,height) }
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) }
87
81
  end
88
82
 
89
-
90
- opts.on("-s", "--save FILENAME", "Save the results to a new file") do |f|
91
- actions << lambda {|img| img.save(f); img }
83
+ o.on('-s', '--save FILENAME', 'Save the results to a new file') do |f|
84
+ actions << ->(img) { img.tap { img.save(f) } }
92
85
  end
93
86
 
94
- opts.on("-t", "--thumbnail SIZE", Integer, "Create a thumbnail of the given size") do |size|
95
- actions << lambda {|img| img.thumbnail(size) }
87
+ o.on('-t', '--thumbnail SIZE', Integer, 'Create a thumbnail of the given size') do |size|
88
+ actions << ->(img) { img.thumbnail(size) }
96
89
  end
97
90
 
98
- opts.on("-v", "--flip_vertically") do
99
- actions << lambda {|img| img.flip_vertically }
100
- end
101
-
102
- opts.on("-p", "--preview", "Preview the image. Close the frame window",
103
- "to continue, or quit the application to", "abort the action pipeline") do
91
+ o.on('-v', '--flip_vertically') { actions << ->(img) { img.flip_vertically } }
104
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
105
97
  headless = false
106
98
  actions << lambda do |img|
107
99
  done = false
@@ -111,36 +103,33 @@ opts = OptionParser.new do |opts|
111
103
  end
112
104
  end
113
105
 
114
- opts.on("--push", "Save the current image to be popped later") do
115
- 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 } }
116
108
  end
117
109
 
118
- opts.on("--pop", "Revert back to the previous saved image", "or the original source image") do
119
- actions << lambda {|img| images.pop || original_image }
110
+ o.on('--pop', 'Revert back to the previous image') do
111
+ actions << -> { images.pop || original_image }
120
112
  end
121
113
 
122
- opts.on("-f", "--format", "Print the image format") do
123
- actions << lambda {|img| puts img.format; img }
114
+ o.on('-f', '--format', 'Print the image format') do
115
+ actions << ->(img) { img.tap { img.format } }
124
116
  end
125
117
 
126
- opts.on_tail("-h", "--help", "Show this message") do
127
- puts opts
128
- exit 0
129
- end
118
+ o.on_tail('-h', '--help', 'Show this message') { o.usage }
130
119
 
131
- def opts.usage(msg)
132
- puts msg
120
+ def o.usage(msg=nil)
121
+ puts msg if msg
133
122
  puts self
134
123
  exit 1
135
124
  end
136
125
  end
137
126
  opts.parse!(ARGV)
138
- opts.usage("You need to supply a source image filename.") unless ARGV.first
139
- 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?
140
129
 
141
130
  # For this binstub we only want to load non-headless if we are using
142
131
  # the preview feature. top of See lib/image_voodoo.rb for more info...
143
- class ImageVoodoo; NEEDS_HEAD = true; end unless headless
132
+ require 'image_voodoo/needs_head' unless headless
144
133
 
145
134
  require 'image_voodoo'
146
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
-