image_voodoo 0.8.8 → 0.8.9
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.
- 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
|