image_voodoo 0.1 → 0.2
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 +20 -6
- data/lib/image_voodoo/version.rb +2 -2
- data/lib/image_voodoo.rb +88 -34
- metadata +2 -2
data/bin/image_voodoo
CHANGED
@@ -27,16 +27,30 @@ opts = OptionParser.new do |opts|
|
|
27
27
|
opts.separator ""
|
28
28
|
opts.separator "Actions:"
|
29
29
|
|
30
|
+
opts.on("-b", "--brightness SCALE,OFFSET", "Adjust brightness") do |args|
|
31
|
+
scale, offset = args.split(/\,/i).map {|v| v.to_f}
|
32
|
+
opts.usage "You need to specify proper scale and offset" unless scale && offset
|
33
|
+
actions << lambda {|img| img.adjust_brightness(scale, offset) }
|
34
|
+
end
|
35
|
+
|
30
36
|
opts.on("-d", "--dimensions", "Print the image dimensions") do
|
31
37
|
actions << lambda {|img| puts "#{img.width}x#{img.height}"; img }
|
32
38
|
end
|
33
39
|
|
40
|
+
opts.on("-g", "--greyscale", "Convert image to greyscale") do
|
41
|
+
actions << lambda {|img| img.greyscale }
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("-n", "--negative", "Make a negative out of the image") do
|
45
|
+
actions << lambda {|img| img.negative }
|
46
|
+
end
|
47
|
+
|
34
48
|
opts.on("-s", "--save FILENAME", "Save the results to a new file") do |f|
|
35
49
|
actions << lambda {|img| img.save(f); img }
|
36
50
|
end
|
37
51
|
|
38
52
|
opts.on("-t", "--thumbnail SIZE", Integer, "Create a thumbnail of the given size") do |size|
|
39
|
-
actions << lambda {|img|
|
53
|
+
actions << lambda {|img| img.thumbnail(size) }
|
40
54
|
end
|
41
55
|
|
42
56
|
opts.on("-p", "--preview", "Preview the image. Close the frame window",
|
@@ -60,7 +74,7 @@ opts = OptionParser.new do |opts|
|
|
60
74
|
opts.on("-r", "--resize WIDTHxHEIGHT", "Create a new image with the specified", "dimensions") do |dim|
|
61
75
|
width, height = dim.split(/x/i).map {|v| v.to_i}
|
62
76
|
opts.usage "You need to specify proper dimensions" unless width && width > 0 && height && height > 0
|
63
|
-
actions << lambda {|img|
|
77
|
+
actions << lambda {|img| img.resize(width,height) }
|
64
78
|
end
|
65
79
|
|
66
80
|
opts.on_tail("-h", "--help", "Show this message") do
|
@@ -79,11 +93,11 @@ opts.usage("You need to supply a source image filename.") unless ARGV.first
|
|
79
93
|
opts.usage("You need to supply one or more actions.") unless actions.size > 0
|
80
94
|
|
81
95
|
require 'image_voodoo'
|
82
|
-
|
96
|
+
file_name = ARGV.first
|
97
|
+
method = file_name =~ /^http:/ ? :from_url : :with_image
|
98
|
+
ImageVoodoo.send(method, file_name) do |img|
|
83
99
|
original_image = img
|
84
|
-
actions.each
|
85
|
-
img = act.call(img)
|
86
|
-
end
|
100
|
+
actions.each { |act| img = act.call(img) }
|
87
101
|
end
|
88
102
|
# Be sure we exit out of swing
|
89
103
|
java.lang.System.exit(0)
|
data/lib/image_voodoo/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
class ImageVoodoo
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
2
|
+
VERSION = "0.2"
|
3
|
+
end
|
data/lib/image_voodoo.rb
CHANGED
@@ -12,30 +12,39 @@
|
|
12
12
|
# end
|
13
13
|
# end
|
14
14
|
class ImageVoodoo
|
15
|
-
VERSION = "0.1"
|
16
|
-
|
17
15
|
include Java
|
18
16
|
|
19
17
|
import java.awt.RenderingHints
|
18
|
+
import java.awt.color.ColorSpace
|
20
19
|
import java.awt.geom.AffineTransform
|
20
|
+
import java.awt.image.ByteLookupTable
|
21
|
+
import java.awt.image.ColorConvertOp
|
22
|
+
import java.awt.image.LookupOp
|
23
|
+
import java.awt.image.RescaleOp
|
21
24
|
import java.awt.image.BufferedImage
|
22
|
-
import javax.imageio.ImageIO
|
23
|
-
import javax.swing.JFrame
|
24
|
-
|
25
25
|
JFile = java.io.File
|
26
26
|
BAIS = java.io.ByteArrayInputStream
|
27
27
|
BAOS = java.io.ByteArrayOutputStream
|
28
|
+
import javax.imageio.ImageIO
|
29
|
+
import javax.swing.JFrame
|
30
|
+
|
31
|
+
NEGATIVE_OP = LookupOp.new(ByteLookupTable.new(0, (0...254).to_a.reverse.to_java(:byte)), nil)
|
32
|
+
GREY_OP = ColorConvertOp.new(ColorSpace.getInstance(ColorSpace::CS_GRAY), nil)
|
28
33
|
|
29
34
|
class JImagePanel < javax.swing.JPanel
|
30
|
-
def initialize(image, x, y)
|
35
|
+
def initialize(image, x=0, y=0)
|
31
36
|
super()
|
32
37
|
@image, @x, @y = image, x, y
|
33
38
|
end
|
39
|
+
def image=(image)
|
40
|
+
@image = image
|
41
|
+
invalidate
|
42
|
+
end
|
34
43
|
def getPreferredSize
|
35
44
|
java.awt.Dimension.new(@image.width, @image.height)
|
36
45
|
end
|
37
46
|
def paintComponent(graphics)
|
38
|
-
graphics.drawImage(@image, @x, @y, nil)
|
47
|
+
graphics.drawImage(@image.to_java, @x, @y, nil)
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
@@ -43,13 +52,22 @@ class ImageVoodoo
|
|
43
52
|
@src = src
|
44
53
|
end
|
45
54
|
|
55
|
+
# Foreach pixel new_pixel = pixel * scale + offset
|
56
|
+
def adjust_brightness(scale, offset)
|
57
|
+
image = ImageVoodoo.new internal_transform(RescaleOp.new(scale, offset, nil))
|
58
|
+
block_given? ? yield(image) : image
|
59
|
+
end
|
60
|
+
|
46
61
|
def cropped_thumbnail(size)
|
47
62
|
l, t, r, b, half = 0, 0, width, height, (width - height).abs / 2
|
48
63
|
l, r = half, half + height if width > height
|
49
64
|
t, b = half, half + width if height > width
|
50
65
|
|
51
|
-
with_crop(l, t, r, b) do |
|
52
|
-
|
66
|
+
with_crop(l, t, r, b) do |image|
|
67
|
+
image.thumbnail(size) do |thumb|
|
68
|
+
target = ImageVoodoo.new target
|
69
|
+
block_given? ? yield(target) : target
|
70
|
+
end
|
53
71
|
end
|
54
72
|
end
|
55
73
|
|
@@ -61,35 +79,35 @@ class ImageVoodoo
|
|
61
79
|
@src.width
|
62
80
|
end
|
63
81
|
|
82
|
+
def to_java
|
83
|
+
@src
|
84
|
+
end
|
85
|
+
|
86
|
+
def negative
|
87
|
+
image = ImageVoodoo.new internal_transform(NEGATIVE_OP)
|
88
|
+
block_given? ? yield(image) : image
|
89
|
+
end
|
90
|
+
|
64
91
|
def resize(width, height)
|
65
|
-
target = BufferedImage.new(width, height,
|
92
|
+
target = BufferedImage.new(width, height, color_type)
|
66
93
|
graphics = target.graphics
|
67
94
|
graphics.set_rendering_hint(RenderingHints::KEY_INTERPOLATION,
|
68
95
|
RenderingHints::VALUE_INTERPOLATION_BICUBIC)
|
69
|
-
|
70
96
|
w_scale = width.to_f / @src.width
|
71
97
|
h_scale = height.to_f / @src.height
|
72
|
-
|
73
98
|
transform = AffineTransform.get_scale_instance w_scale, h_scale
|
74
|
-
|
75
99
|
graphics.draw_rendered_image @src, transform
|
76
100
|
graphics.dispose
|
77
101
|
|
78
|
-
|
102
|
+
target = ImageVoodoo.new target
|
103
|
+
block_given? ? yield(target) : target
|
79
104
|
rescue NativeException => ne
|
80
105
|
raise ArgumentError, ne.message
|
81
106
|
end
|
82
107
|
|
83
108
|
def greyscale
|
84
|
-
|
85
|
-
|
86
|
-
graphics.set_rendering_hint(RenderingHints::KEY_INTERPOLATION,
|
87
|
-
RenderingHints::VALUE_INTERPOLATION_BICUBIC)
|
88
|
-
|
89
|
-
graphics.draw_rendered_image @src, nil
|
90
|
-
graphics.dispose
|
91
|
-
|
92
|
-
yield ImageVoodoo.new(target)
|
109
|
+
image = ImageVoodoo.new internal_transform(GREY_OP)
|
110
|
+
block_given? ? yield(image) : image
|
93
111
|
end
|
94
112
|
|
95
113
|
def save(file)
|
@@ -112,7 +130,7 @@ class ImageVoodoo
|
|
112
130
|
frame = JFrame.new("Preview")
|
113
131
|
frame.add_window_listener WindowClosed.new(block)
|
114
132
|
frame.set_bounds 0, 0, width + 20, height + 40
|
115
|
-
frame.add JImagePanel.new(
|
133
|
+
frame.add JImagePanel.new(self, 10, 10)
|
116
134
|
frame.visible = true
|
117
135
|
end
|
118
136
|
|
@@ -122,31 +140,67 @@ class ImageVoodoo
|
|
122
140
|
String.from_java_bytes(out.to_byte_array)
|
123
141
|
end
|
124
142
|
|
143
|
+
def scale(ratio)
|
144
|
+
new_width = (width * ratio).to_i
|
145
|
+
new_height = (height * ratio).to_i
|
146
|
+
resize(new_width, new_height) do |image|
|
147
|
+
target = ImageVoodoo.new image
|
148
|
+
block_given? ? yield(target) : target
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
125
152
|
def thumbnail(size)
|
126
|
-
scale
|
127
|
-
new_width = (width * scale).to_i
|
128
|
-
new_height = (height * scale).to_i
|
129
|
-
resize(new_width, new_height) {|image| yield image }
|
153
|
+
scale(size.to_f / (width > height ? width : height))
|
130
154
|
end
|
131
155
|
|
132
156
|
def with_crop(left, top, right, bottom)
|
133
|
-
|
134
|
-
yield
|
157
|
+
image = ImageVoodoo.new(@src.get_subimage(left, top, right-left, bottom-top))
|
158
|
+
block_given? ? yield(image) : image
|
159
|
+
end
|
160
|
+
|
161
|
+
# TODO: Figure out how to determine whether source has alpha or not
|
162
|
+
def self.from_url(source)
|
163
|
+
url = java.net.URL.new(source)
|
164
|
+
image = java.awt.Toolkit.default_toolkit.create_image(url)
|
165
|
+
tracker = java.awt.MediaTracker.new(java.awt.Label.new(""))
|
166
|
+
tracker.addImage(image, 0);
|
167
|
+
tracker.waitForID(0)
|
168
|
+
target = BufferedImage.new(image.getWidth, image.getHeight, BufferedImage::TYPE_INT_RGB)
|
169
|
+
graphics = target.graphics
|
170
|
+
graphics.drawImage(image, 0, 0, nil)
|
171
|
+
graphics.dispose
|
172
|
+
target = ImageVoodoo.new target
|
173
|
+
block_given? ? yield(target) : target
|
174
|
+
rescue java.io.IOException, java.net.MalformedURLException
|
175
|
+
raise ArgumentError.new "Trouble retrieving image: #{$!.message}"
|
135
176
|
end
|
136
177
|
|
137
178
|
def self.with_image(file)
|
138
179
|
readers = ImageIO.getImageReadersBySuffix(File.extname(file)[1..-1])
|
139
180
|
raise TypeError, "unrecognized format for #{file}" unless readers.hasNext
|
140
|
-
image = ImageIO.read(JFile.new(file))
|
141
|
-
yield
|
181
|
+
image = ImageVoodoo.new ImageIO.read(JFile.new(file))
|
182
|
+
block_given? ? yield(image) : image
|
142
183
|
rescue NativeException => ne
|
143
184
|
nil
|
144
185
|
end
|
145
186
|
|
146
187
|
def self.with_bytes(bytes)
|
147
188
|
bytes = bytes.to_java_bytes if String === bytes
|
189
|
+
image = ImageVoodoo.new ImageIO.read(BAIS.new(bytes))
|
190
|
+
block_given? ? yield(image) : image
|
191
|
+
end
|
148
192
|
|
149
|
-
|
150
|
-
|
193
|
+
private
|
194
|
+
def color_type
|
195
|
+
return BufferedImage::TYPE_INT_ARGB if @src.color_model.has_alpha
|
196
|
+
BufferedImage::TYPE_INT_RGB
|
197
|
+
end
|
198
|
+
|
199
|
+
def internal_transform(operation, target=BufferedImage.new(width, height, color_type))
|
200
|
+
graphics = target.graphics
|
201
|
+
graphics.drawImage(@src, 0, 0, nil)
|
202
|
+
graphics.drawImage(operation.filter(target, nil), 0, 0, nil)
|
203
|
+
graphics.dispose
|
204
|
+
target
|
151
205
|
end
|
152
206
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_voodoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.2"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Enebo, Charles Nutter and JRuby contributors
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-05-19 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|