image_voodoo 0.8.8 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +115 -0
- data/.travis.yml +7 -0
- data/Rakefile +2 -2
- data/bin/image_voodoo +71 -84
- data/image_voodoo.gemspec +6 -5
- data/lib/image_science.rb +1 -1
- data/lib/image_voodoo.rb +41 -93
- data/lib/image_voodoo/awt.rb +156 -153
- data/lib/image_voodoo/awt/core_ext/buffered_image.rb +13 -0
- data/lib/image_voodoo/awt/core_ext/graphics2d.rb +17 -0
- data/lib/image_voodoo/awt/shapes.rb +39 -3
- data/lib/image_voodoo/gae.rb +10 -6
- data/lib/image_voodoo/metadata.rb +115 -89
- data/lib/image_voodoo/needs_head.rb +1 -0
- data/lib/image_voodoo/version.rb +1 -1
- data/samples/bench.rb +29 -36
- data/samples/file_view.rb +2 -1
- data/samples/{in-memory.rb → in_memory.rb} +0 -0
- data/test/test_image_science.rb +32 -74
- data/test/test_image_voodoo.rb +82 -0
- data/test/test_metadata.rb +23 -16
- data/test/test_shapes.rb +21 -0
- data/tools/gen.rb +31 -27
- metadata +15 -8
@@ -0,0 +1 @@
|
|
1
|
+
class ImageVoodoo; NEEDS_HEAD = true; end
|
data/lib/image_voodoo/version.rb
CHANGED
data/samples/bench.rb
CHANGED
@@ -6,59 +6,52 @@ require 'rubygems'
|
|
6
6
|
require 'image_science'
|
7
7
|
|
8
8
|
max = (ARGV.shift || 100).to_i
|
9
|
-
ext = ARGV.shift ||
|
10
|
-
|
9
|
+
ext = ARGV.shift || 'png'
|
11
10
|
file = "blah_big.#{ext}"
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
unless File.exist?(file)
|
13
|
+
if RbConfig::CONFIG['host_os'] =~ /darwin/i
|
14
|
+
puts 'taking screenshot for thumbnailing benchmarks'
|
15
|
+
system "screencapture -SC #{file}"
|
16
|
+
elsif RbConfig::CONFIG['host_os'] =~ /linux/i
|
17
|
+
puts 'taking screenshot for thumbnailing benchmarks'
|
18
|
+
system "gnome-screenshot -f #{file}"
|
19
|
+
else
|
20
|
+
abort "You need to save an image to #{file} since we cannot generate one"
|
21
|
+
end
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
img.save(file)
|
23
|
-
end
|
24
|
+
if ext != 'png'
|
25
|
+
ImageScience.with_image(file.sub(/#{ext}$/, 'png')) { |img| img.save(file) }
|
26
|
+
end
|
24
27
|
|
25
28
|
puts "# of iterations = #{max}"
|
26
|
-
Benchmark
|
27
|
-
x.report(
|
28
|
-
for i in 0..max do
|
29
|
-
# do nothing
|
30
|
-
end
|
31
|
-
}
|
29
|
+
Benchmark.bm(20) do |x|
|
30
|
+
x.report('null_time') { max.times {} }
|
32
31
|
|
33
|
-
x.report(
|
34
|
-
|
32
|
+
x.report('cropped') do
|
33
|
+
max.times do
|
35
34
|
ImageScience.with_image(file) do |img|
|
36
|
-
img.cropped_thumbnail(100)
|
37
|
-
thumb.save("blah_cropped.#{ext}")
|
38
|
-
end
|
35
|
+
img.cropped_thumbnail(100) { |thumb| thumb.save("blah_cropped.#{ext}") }
|
39
36
|
end
|
40
37
|
end
|
41
|
-
|
38
|
+
end
|
42
39
|
|
43
|
-
x.report(
|
44
|
-
|
40
|
+
x.report('proportional') do
|
41
|
+
max.times do
|
45
42
|
ImageScience.with_image(file) do |img|
|
46
|
-
img.thumbnail(100)
|
47
|
-
thumb.save("blah_thumb.#{ext}")
|
48
|
-
end
|
43
|
+
img.thumbnail(100) { |thumb| thumb.save("blah_thumb.#{ext}") }
|
49
44
|
end
|
50
45
|
end
|
51
|
-
|
46
|
+
end
|
52
47
|
|
53
|
-
x.report(
|
54
|
-
|
48
|
+
x.report('resize') do
|
49
|
+
max.times do
|
55
50
|
ImageScience.with_image(file) do |img|
|
56
|
-
img.resize(200, 200)
|
57
|
-
resize.save("blah_resize.#{ext}")
|
58
|
-
end
|
51
|
+
img.resize(200, 200) { |resize| resize.save("blah_resize.#{ext}") }
|
59
52
|
end
|
60
53
|
end
|
61
|
-
|
54
|
+
end
|
62
55
|
end
|
63
56
|
|
64
57
|
# File.unlink(*Dir["blah*#{ext}"])
|
data/samples/file_view.rb
CHANGED
File without changes
|
data/test/test_image_science.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
require 'test/unit/testcase'
|
2
|
-
require 'test/unit' if $
|
2
|
+
require 'test/unit' if $PROGRAM_NAME == __FILE__
|
3
3
|
require 'image_science'
|
4
4
|
|
5
5
|
class TestImageScience < Test::Unit::TestCase
|
6
|
-
def deny
|
6
|
+
def deny(x)
|
7
|
+
assert !x
|
8
|
+
end
|
9
|
+
|
10
|
+
def similar_image?(w, h, img)
|
11
|
+
assert_kind_of ImageScience, img
|
12
|
+
assert_equal h, img.height
|
13
|
+
assert_equal w, img.width
|
14
|
+
end
|
7
15
|
|
8
16
|
def setup
|
9
17
|
@path = 'test/pix.png'
|
@@ -17,118 +25,68 @@ class TestImageScience < Test::Unit::TestCase
|
|
17
25
|
|
18
26
|
def test_class_with_image
|
19
27
|
ImageScience.with_image @path do |img|
|
20
|
-
|
21
|
-
assert_equal @h, img.height
|
22
|
-
assert_equal @w, img.width
|
28
|
+
similar_image? @w, @h, img
|
23
29
|
assert img.save(@tmppath)
|
24
30
|
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
ImageScience.with_image @tmppath do |img|
|
29
|
-
assert_kind_of ImageScience, img
|
30
|
-
assert_equal @h, img.height
|
31
|
-
assert_equal @w, img.width
|
32
|
-
end
|
32
|
+
ImageScience.with_image(@tmppath) { |img| similar_image? @w, @h, img }
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_class_with_image_missing
|
36
36
|
assert_raises ArgumentError do
|
37
|
-
ImageScience.with_image
|
38
|
-
flunk
|
39
|
-
end
|
37
|
+
ImageScience.with_image("#{@path}nope") { flunk }
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
43
41
|
def test_class_with_image_missing_with_img_extension
|
44
42
|
assert_raises ArgumentError do
|
45
|
-
ImageScience.with_image("nope#{@path}")
|
46
|
-
flunk
|
47
|
-
end
|
43
|
+
ImageScience.with_image("nope#{@path}") { flunk }
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
51
47
|
def test_class_with_image_return_nil_on_bogus_image
|
52
|
-
File.open(@tmppath,
|
53
|
-
assert_nil ImageScience.with_image(@tmppath)
|
54
|
-
flunk
|
55
|
-
end
|
48
|
+
File.open(@tmppath, 'w') { |f| f << 'bogus image file' }
|
49
|
+
assert_nil ImageScience.with_image(@tmppath) { flunk }
|
56
50
|
end
|
57
51
|
|
58
52
|
def test_resize
|
59
53
|
ImageScience.with_image @path do |img|
|
60
|
-
img.resize(25, 25)
|
61
|
-
assert thumb.save(@tmppath)
|
62
|
-
end
|
54
|
+
img.resize(25, 25) { |thumb| assert thumb.save(@tmppath) }
|
63
55
|
end
|
64
56
|
|
65
|
-
|
66
|
-
|
67
|
-
ImageScience.with_image @tmppath do |img|
|
68
|
-
assert_kind_of ImageScience, img
|
69
|
-
assert_equal 25, img.height
|
70
|
-
assert_equal 25, img.width
|
71
|
-
end
|
57
|
+
ImageScience.with_image(@tmppath) { |img| similar_image? 25, 25, img }
|
72
58
|
end
|
73
59
|
|
74
60
|
def test_resize_floats
|
75
61
|
ImageScience.with_image @path do |img|
|
76
|
-
img.resize(25.2, 25.7)
|
77
|
-
assert thumb.save(@tmppath)
|
78
|
-
end
|
62
|
+
img.resize(25.2, 25.7) { |thumb| assert thumb.save(@tmppath) }
|
79
63
|
end
|
80
64
|
|
81
|
-
|
82
|
-
|
83
|
-
ImageScience.with_image @tmppath do |img|
|
84
|
-
assert_kind_of ImageScience, img
|
85
|
-
assert_equal 25, img.height
|
86
|
-
assert_equal 25, img.width
|
87
|
-
end
|
65
|
+
ImageScience.with_image(@tmppath) { |img| similar_image? 25, 25, img }
|
88
66
|
end
|
89
67
|
|
90
68
|
def test_resize_zero
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
assert thumb.save(@tmppath)
|
69
|
+
[[0, 25], [25, 0], [0, 0]].each do |w, h|
|
70
|
+
assert_raises ArgumentError do
|
71
|
+
ImageScience.with_image @path do |img|
|
72
|
+
img.resize(w, h) { |thumb| assert thumb.save(@tmppath) }
|
95
73
|
end
|
96
74
|
end
|
97
|
-
end
|
98
75
|
|
99
|
-
|
100
|
-
|
101
|
-
assert_raises ArgumentError do
|
102
|
-
ImageScience.with_image @path do |img|
|
103
|
-
img.resize(25, 0) do |thumb|
|
104
|
-
assert thumb.save(@tmppath)
|
105
|
-
end
|
106
|
-
end
|
76
|
+
deny File.exist?(@tmppath)
|
107
77
|
end
|
108
|
-
|
109
|
-
deny File.exists?(@tmppath)
|
110
78
|
end
|
111
79
|
|
112
80
|
def test_resize_negative
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
assert thumb.save(@tmppath)
|
81
|
+
[[-25, 25], [25, -25], [-25, -25]].each do |w, h|
|
82
|
+
assert_raises ArgumentError do
|
83
|
+
ImageScience.with_image @path do |img|
|
84
|
+
img.resize(w, h) { |thumb| assert thumb.save(@tmppath) }
|
117
85
|
end
|
118
86
|
end
|
119
|
-
end
|
120
87
|
|
121
|
-
|
122
|
-
|
123
|
-
assert_raises ArgumentError do
|
124
|
-
ImageScience.with_image @path do |img|
|
125
|
-
img.resize(25, -25) do |thumb|
|
126
|
-
assert thumb.save(@tmppath)
|
127
|
-
end
|
128
|
-
end
|
88
|
+
deny File.exist?(@tmppath)
|
129
89
|
end
|
130
|
-
|
131
|
-
deny File.exists?(@tmppath)
|
132
90
|
end
|
133
91
|
|
134
92
|
def test_image_format_retrieval
|
@@ -147,7 +105,7 @@ class TestImageScience < Test::Unit::TestCase
|
|
147
105
|
end
|
148
106
|
|
149
107
|
def test_image_format_retrieval_fail_when_invalid_bytes
|
150
|
-
image = ImageScience.with_bytes(
|
108
|
+
image = ImageScience.with_bytes('some invalid image bytes')
|
151
109
|
assert_equal nil, image.format
|
152
110
|
end
|
153
111
|
|
@@ -166,6 +124,6 @@ class TestImageScience < Test::Unit::TestCase
|
|
166
124
|
assert new_img.save(@tmppath)
|
167
125
|
end
|
168
126
|
|
169
|
-
assert File.
|
127
|
+
assert File.exist?(@tmppath)
|
170
128
|
end
|
171
129
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'test/unit/testcase'
|
2
|
+
require 'test/unit' if $PROGRAM_NAME == __FILE__
|
3
|
+
require 'image_voodoo'
|
4
|
+
|
5
|
+
# Depends on a small portion of awt/shapes working properly
|
6
|
+
class TestImageVoodoo < Test::Unit::TestCase
|
7
|
+
# 04
|
8
|
+
# b8
|
9
|
+
def make_square
|
10
|
+
image = ImageVoodoo.new_image 20, 20, "test.gif"
|
11
|
+
image.square(*upper_left, 10, '000000')
|
12
|
+
image.square(10, 0, 10, '444444')
|
13
|
+
image.square(0, 10, 10, '888888')
|
14
|
+
image.square(*lower_right, 10, 'bb0000')
|
15
|
+
end
|
16
|
+
|
17
|
+
def assert_color(color, red, green, blue, alpha=nil)
|
18
|
+
assert_equal(red, color.red)
|
19
|
+
assert_equal(green, color.green)
|
20
|
+
assert_equal(blue, color.blue)
|
21
|
+
assert_equal(alpha, color.alpha) if alpha
|
22
|
+
end
|
23
|
+
|
24
|
+
def lower_right
|
25
|
+
[10, 10]
|
26
|
+
end
|
27
|
+
|
28
|
+
def upper_left
|
29
|
+
[0, 0]
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: Don't fully know how to predict pixel values for adjust_brightness.
|
33
|
+
|
34
|
+
def test_alpha
|
35
|
+
image = make_square.alpha('000000')
|
36
|
+
assert_equal(0xff, image.color_at(*upper_left).alpha)
|
37
|
+
end
|
38
|
+
|
39
|
+
# 04 -> 40
|
40
|
+
# 8b b8
|
41
|
+
def test_flip_horizontally
|
42
|
+
image = make_square.flip_horizontally
|
43
|
+
assert_color(image.color_at(*upper_left), 0x44, 0x44, 0x44)
|
44
|
+
end
|
45
|
+
|
46
|
+
# 04 -> 8b
|
47
|
+
# 8b 04
|
48
|
+
def test_flip_vertically
|
49
|
+
image = make_square.flip_vertically
|
50
|
+
assert_color(image.color_at(*upper_left), 0x88, 0x88, 0x88)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_greyscale
|
54
|
+
image = make_square.greyscale
|
55
|
+
assert_color(image.color_at(*lower_right), 0x5d, 0x5d, 0x5d)
|
56
|
+
end
|
57
|
+
|
58
|
+
# 04 -0-> 04 -90-> 80 -180-> 4b -270-> b8
|
59
|
+
# 8b 8b b4 08 40
|
60
|
+
def test_rotate
|
61
|
+
image = make_square
|
62
|
+
assert_color(image.color_at(*upper_left), 0x00, 0x00, 0x00)
|
63
|
+
image = image.rotate(90)
|
64
|
+
assert_color(image.color_at(*upper_left), 0x88, 0x88, 0x88)
|
65
|
+
image = image.rotate(180)
|
66
|
+
assert_color(image.color_at(*upper_left), 0x44, 0x44, 0x44)
|
67
|
+
image = image.rotate(270)
|
68
|
+
assert_color(image.color_at(*upper_left), 0xbb, 0x00, 0x00)
|
69
|
+
end
|
70
|
+
|
71
|
+
# 04 -(-90)-> 4b -(-180)-> 80 -(-270)-> b8
|
72
|
+
# 8b 08 b4 40
|
73
|
+
def test_rotate_negative
|
74
|
+
image = make_square
|
75
|
+
image = image.rotate(-90)
|
76
|
+
assert_color(image.color_at(*upper_left), 0x44, 0x44, 0x44)
|
77
|
+
image = image.rotate(-180)
|
78
|
+
assert_color(image.color_at(*upper_left), 0x88, 0x88, 0x88)
|
79
|
+
image = image.rotate(-270)
|
80
|
+
assert_color(image.color_at(*upper_left), 0xbb, 0x00, 0x00)
|
81
|
+
end
|
82
|
+
end
|
data/test/test_metadata.rb
CHANGED
@@ -1,49 +1,56 @@
|
|
1
1
|
require 'test/unit/testcase'
|
2
|
-
require 'test/unit' if $
|
2
|
+
require 'test/unit' if $PROGRAM_NAME == __FILE__
|
3
3
|
require 'image_voodoo'
|
4
4
|
|
5
5
|
IMAGE_DIR = File.join File.dirname(__FILE__), '..', '..', 'metadata-extractor-images'
|
6
6
|
|
7
7
|
# FIXME: If we end up running on travis or other tool this should be ignored
|
8
8
|
# subdir to this project and probably clone repo into that subdir
|
9
|
-
|
10
|
-
puts
|
9
|
+
if !File.exist? IMAGE_DIR
|
10
|
+
puts 'To run this test you must clone:'
|
11
|
+
puts 'https://github.com/drewnoakes/metadata-extractor-images.git'
|
12
|
+
puts 'into a sibling directory to image_voodoo'
|
11
13
|
else
|
12
14
|
class TestImageVoodooMetadata < Test::Unit::TestCase
|
13
15
|
def setup
|
14
|
-
@path = File.join IMAGE_DIR,
|
15
|
-
@path_gps = File.join IMAGE_DIR,
|
16
|
-
@path_no_exif = File.join File.dirname(__FILE__),
|
16
|
+
@path = File.join IMAGE_DIR, 'Apple iPhone 4S.jpg'
|
17
|
+
@path_gps = File.join IMAGE_DIR, 'Apple iPhone 4.jpg'
|
18
|
+
@path_no_exif = File.join File.dirname(__FILE__), 'pix.png'
|
17
19
|
end
|
20
|
+
|
21
|
+
def assert_orientation(expected, metadata)
|
22
|
+
assert_equal expected, metadata[:IFD0][:Orientation]
|
23
|
+
end
|
24
|
+
|
18
25
|
def test_metadata_from_file
|
19
26
|
ImageVoodoo.with_image @path do |img|
|
20
|
-
|
21
|
-
|
22
|
-
assert_equal 6,
|
23
|
-
assert_equal 3264,
|
24
|
-
assert_equal 2448,
|
25
|
-
assert_equal
|
26
|
-
assert_equal
|
27
|
+
metadata = img.metadata
|
28
|
+
assert_orientation 6, metadata
|
29
|
+
assert_equal 6, metadata.orientation
|
30
|
+
assert_equal 3264, metadata.width
|
31
|
+
assert_equal 2448, metadata.height
|
32
|
+
assert_equal 'Apple', metadata.make
|
33
|
+
assert_equal 'iPhone 4S', metadata.model
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
37
|
def test_metadata_from_inputstream
|
31
38
|
ImageVoodoo.with_bytes File.read(@path) do |img|
|
32
|
-
|
39
|
+
assert_orientation 6, img.metadata
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
43
|
def test_metadata_no_ifd0
|
37
44
|
ImageVoodoo.with_image @path_no_exif do |img|
|
38
45
|
assert !img.metadata[:IFD0].exists?
|
39
|
-
|
46
|
+
assert_orientation nil, img.metadata
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
43
50
|
def test_metadata_gps
|
44
51
|
ImageVoodoo.with_image @path_gps do |img|
|
45
52
|
assert img.metadata[:Gps].exists?
|
46
|
-
assert_equal(
|
53
|
+
assert_equal('N', img.metadata[:Gps]['Latitude Ref'])
|
47
54
|
end
|
48
55
|
end
|
49
56
|
end
|
data/test/test_shapes.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test/unit/testcase'
|
2
|
+
require 'test/unit' if $PROGRAM_NAME == __FILE__
|
3
|
+
require 'image_voodoo'
|
4
|
+
|
5
|
+
class TestShapes < Test::Unit::TestCase
|
6
|
+
def test_new_image
|
7
|
+
image = ImageVoodoo.new_image 10, 20, "test.gif"
|
8
|
+
assert_equal 10, image.width
|
9
|
+
assert_equal 20, image.height
|
10
|
+
assert_equal "gif", image.format
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_square
|
14
|
+
image = ImageVoodoo.new_image 10, 10, "test.gif"
|
15
|
+
image.square 0, 0, 10, 'ff9900'
|
16
|
+
color = image.color_at(0, 0)
|
17
|
+
assert_equal(0xff, color.red)
|
18
|
+
assert_equal(0x99, color.green)
|
19
|
+
assert_equal(0x00, color.blue)
|
20
|
+
end
|
21
|
+
end
|