axon 0.0.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/.gemtest +0 -0
- data/CHANGELOG.rdoc +3 -0
- data/README.rdoc +104 -0
- data/Rakefile +30 -0
- data/TODO.rdoc +12 -0
- data/ext/axon/axon.c +20 -0
- data/ext/axon/bilinear_interpolation.c +115 -0
- data/ext/axon/extconf.rb +21 -0
- data/ext/axon/iccjpeg.c +248 -0
- data/ext/axon/iccjpeg.h +73 -0
- data/ext/axon/interpolation.h +7 -0
- data/ext/axon/jpeg_common.c +118 -0
- data/ext/axon/jpeg_common.h +37 -0
- data/ext/axon/jpeg_native_writer.c +248 -0
- data/ext/axon/jpeg_reader.c +774 -0
- data/ext/axon/nearest_neighbor_interpolation.c +50 -0
- data/ext/axon/png_common.c +21 -0
- data/ext/axon/png_common.h +18 -0
- data/ext/axon/png_native_writer.c +166 -0
- data/ext/axon/png_reader.c +381 -0
- data/lib/axon/axon.so +0 -0
- data/lib/axon/bilinear_scaler.rb +60 -0
- data/lib/axon/cropper.rb +35 -0
- data/lib/axon/fit.rb +67 -0
- data/lib/axon/jpeg_writer.rb +41 -0
- data/lib/axon/nearest_neighbor_scaler.rb +39 -0
- data/lib/axon/png_writer.rb +35 -0
- data/lib/axon/scaler.rb +41 -0
- data/lib/axon/solid.rb +23 -0
- data/lib/axon.rb +45 -0
- data/test/_test_readme.rb +34 -0
- data/test/helper.rb +17 -0
- data/test/reader_tests.rb +115 -0
- data/test/stress_tests.rb +71 -0
- data/test/test_bilinear_scaler.rb +9 -0
- data/test/test_cropper.rb +9 -0
- data/test/test_exif.rb +39 -0
- data/test/test_generator.rb +10 -0
- data/test/test_icc.rb +18 -0
- data/test/test_jpeg.rb +9 -0
- data/test/test_jpeg_reader.rb +109 -0
- data/test/test_jpeg_writer.rb +26 -0
- data/test/test_nearest_neighbor_scaler.rb +13 -0
- data/test/test_png.rb +9 -0
- data/test/test_png_reader.rb +15 -0
- data/test/test_png_writer.rb +13 -0
- data/test/writer_tests.rb +179 -0
- metadata +148 -0
data/lib/axon/cropper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Axon
|
2
|
+
class Cropper
|
3
|
+
include Enumerable
|
4
|
+
include Image
|
5
|
+
|
6
|
+
attr_reader :image, :width, :height, :components, :color_model
|
7
|
+
|
8
|
+
def initialize(image, width, height, x_offset=nil, y_offset=nil)
|
9
|
+
@image = image
|
10
|
+
@width = width
|
11
|
+
@height = height
|
12
|
+
@x_offset = x_offset || 0
|
13
|
+
@y_offset = y_offset || 0
|
14
|
+
@components = image.components
|
15
|
+
@color_model = image.color_model
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
sl_width = @width * @components
|
20
|
+
sl_offset = @x_offset * @components
|
21
|
+
|
22
|
+
@image.each_with_index do |orig_sl, i|
|
23
|
+
next if i < @y_offset
|
24
|
+
yield orig_sl[sl_offset, sl_width]
|
25
|
+
break if i == @height - 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Image
|
31
|
+
def crop(*args)
|
32
|
+
Cropper.new(self, *args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/axon/fit.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Axon
|
2
|
+
class Fit
|
3
|
+
include Image
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(source, width, height)
|
7
|
+
@source, @fit_width, @fit_height = source, width, height
|
8
|
+
end
|
9
|
+
|
10
|
+
def components
|
11
|
+
@source.components
|
12
|
+
end
|
13
|
+
|
14
|
+
def color_model
|
15
|
+
@source.color_model
|
16
|
+
end
|
17
|
+
|
18
|
+
def width
|
19
|
+
@source.width * calc_fit_ratio
|
20
|
+
end
|
21
|
+
|
22
|
+
def height
|
23
|
+
@source.height * calc_fit_ratio
|
24
|
+
end
|
25
|
+
|
26
|
+
def each
|
27
|
+
r = calc_fit_ratio
|
28
|
+
|
29
|
+
if r > 1
|
30
|
+
scaler = NearestNeighborScaler.new(@source, r)
|
31
|
+
scaler.each{ |*a| yield(*a) }
|
32
|
+
elsif r < 1
|
33
|
+
if r <= 0.5 && @source.kind_of?(JPEGReader)
|
34
|
+
@source.scale_denom = calc_jpeg_pre_shrink(r)
|
35
|
+
r = calc_fit_ratio
|
36
|
+
end
|
37
|
+
scaler = BilinearScaler.new(@source, r)
|
38
|
+
scaler.each{ |*a| yield(*a) }
|
39
|
+
else
|
40
|
+
@source.each{ |*a| yield(*a) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def calc_fit_ratio
|
47
|
+
width_ratio = @fit_width.to_f / @source.width
|
48
|
+
height_ratio = @fit_height.to_f / @source.height
|
49
|
+
[width_ratio, height_ratio].min
|
50
|
+
end
|
51
|
+
|
52
|
+
def calc_jpeg_pre_shrink(r)
|
53
|
+
case (1/r)
|
54
|
+
when (0...2) then nil
|
55
|
+
when (2...4) then 2
|
56
|
+
when (4...8) then 4
|
57
|
+
else 8
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Image
|
63
|
+
def fit(*args)
|
64
|
+
Fit.new(self, *args)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Axon
|
4
|
+
class JPEGWriter
|
5
|
+
include JPEGNativeWriter
|
6
|
+
|
7
|
+
attr_accessor :quality, :icc_profile, :exif
|
8
|
+
attr_reader :io, :bufsize, :image
|
9
|
+
|
10
|
+
def initialize(image)
|
11
|
+
@image = image
|
12
|
+
@quality = nil
|
13
|
+
@icc_profile = nil
|
14
|
+
@exif = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(io, bufsize = nil)
|
18
|
+
@bufsize = bufsize || 512
|
19
|
+
@io = io
|
20
|
+
jpeg_native_write
|
21
|
+
end
|
22
|
+
|
23
|
+
def data
|
24
|
+
s = StringIO.new
|
25
|
+
s.set_encoding 'BINARY' if s.respond_to?(:set_encoding)
|
26
|
+
|
27
|
+
write(s)
|
28
|
+
s.string
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module Image
|
33
|
+
def to_jpeg(*args)
|
34
|
+
JPEGWriter.new self, *args
|
35
|
+
end
|
36
|
+
|
37
|
+
def write_jpeg(io)
|
38
|
+
JPEGWriter.new(self).write(io)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Axon
|
2
|
+
class NearestNeighborScaler < Scaler
|
3
|
+
include NearestNeighborScaling
|
4
|
+
include Image
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def each
|
8
|
+
dest_y = 0
|
9
|
+
sample_y = 0
|
10
|
+
|
11
|
+
@image.each_with_index do |scanline, orig_y|
|
12
|
+
while sample_y == orig_y
|
13
|
+
yield interpolate_scanline(scanline)
|
14
|
+
dest_y += 1
|
15
|
+
sample_y = (dest_y / @height_ratio).to_i
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def _interpolate_scanline(scanline)
|
23
|
+
dest_sl = ''
|
24
|
+
|
25
|
+
scanline.size.times do |dest_x|
|
26
|
+
sample_x = (dest_x / @width_ratio).to_i
|
27
|
+
dest_sl << scanline[sample_x * components, components]
|
28
|
+
end
|
29
|
+
|
30
|
+
return dest_sl
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module Image
|
35
|
+
def scale_nearest_neighbor(*args)
|
36
|
+
NearestNeighborScaler.new(self, *args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Axon
|
4
|
+
class PNGWriter
|
5
|
+
include PNGNativeWriter
|
6
|
+
|
7
|
+
attr_reader :image
|
8
|
+
|
9
|
+
def initialize(image)
|
10
|
+
@image = image
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(io)
|
14
|
+
png_native_write(io)
|
15
|
+
end
|
16
|
+
|
17
|
+
def data
|
18
|
+
s = StringIO.new
|
19
|
+
s.set_encoding 'BINARY' if s.respond_to?(:set_encoding)
|
20
|
+
|
21
|
+
write(s)
|
22
|
+
s.string
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Image
|
27
|
+
def to_png
|
28
|
+
PNGWriter.new self
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_png(io)
|
32
|
+
PNGWriter.new(self).write(io)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/axon/scaler.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Axon
|
2
|
+
class Scaler
|
3
|
+
attr_reader :width, :height
|
4
|
+
|
5
|
+
def initialize(image, *args)
|
6
|
+
@image = image
|
7
|
+
|
8
|
+
if args.size == 1
|
9
|
+
init_ratio(args[0])
|
10
|
+
elsif args.size == 2
|
11
|
+
init_dims(args[0], args[1])
|
12
|
+
else
|
13
|
+
raise ArgumentError, "Must give one or two arguments"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def components
|
18
|
+
@image.components
|
19
|
+
end
|
20
|
+
|
21
|
+
def color_model
|
22
|
+
@image.color_model
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def init_ratio(ratio)
|
28
|
+
@width_ratio = @height_ratio = ratio.to_f
|
29
|
+
@width = (@image.width * ratio).floor
|
30
|
+
@height = (@image.height * ratio).floor
|
31
|
+
end
|
32
|
+
|
33
|
+
def init_dims(width, height)
|
34
|
+
@width_ratio = width.to_f / @image.width
|
35
|
+
@width = width
|
36
|
+
|
37
|
+
@height_ratio = height.to_f / @image.height
|
38
|
+
@height = height
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/axon/solid.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Axon
|
2
|
+
class Solid
|
3
|
+
include Image
|
4
|
+
include Enumerable
|
5
|
+
attr_reader :width, :height, :color_model, :components
|
6
|
+
|
7
|
+
def initialize(width, height, color=nil, color_model=nil)
|
8
|
+
@width, @height = width, height
|
9
|
+
@color = color || "\x00\x00\x00"
|
10
|
+
@color_model = color_model || :RGB
|
11
|
+
@components = @color.size
|
12
|
+
end
|
13
|
+
|
14
|
+
def each
|
15
|
+
sl = @color * width
|
16
|
+
height.times { yield sl }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Image
|
21
|
+
# empty
|
22
|
+
end
|
23
|
+
end
|
data/lib/axon.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'axon/axon'
|
2
|
+
|
3
|
+
require 'axon/solid'
|
4
|
+
require 'axon/cropper'
|
5
|
+
require 'axon/scaler'
|
6
|
+
require 'axon/nearest_neighbor_scaler'
|
7
|
+
require 'axon/bilinear_scaler'
|
8
|
+
require 'axon/fit'
|
9
|
+
|
10
|
+
require 'axon/jpeg_writer'
|
11
|
+
require 'axon/png_writer'
|
12
|
+
|
13
|
+
module Axon
|
14
|
+
VERSION = '0.0.1'
|
15
|
+
|
16
|
+
def self.JPEG(thing, markers=nil)
|
17
|
+
if thing.respond_to? :read
|
18
|
+
io = thing
|
19
|
+
rewind_after_scanlines = false
|
20
|
+
elsif thing[0, 1] == "\xFF"
|
21
|
+
io = StringIO.new(thing)
|
22
|
+
rewind_after_scanlines = true
|
23
|
+
else
|
24
|
+
io = File.open(thing)
|
25
|
+
rewind_after_scanlines = true
|
26
|
+
end
|
27
|
+
|
28
|
+
JPEGReader.new(io, markers, rewind_after_scanlines)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.PNG(thing)
|
32
|
+
if thing.respond_to? :read
|
33
|
+
io = thing
|
34
|
+
rewind_after_scanlines = false
|
35
|
+
elsif thing[0, 1] == "\x89"
|
36
|
+
io = StringIO.new(thing)
|
37
|
+
rewind_after_scanlines = true
|
38
|
+
else
|
39
|
+
io = File.open(thing)
|
40
|
+
rewind_after_scanlines = true
|
41
|
+
end
|
42
|
+
|
43
|
+
PNGReader.new(io)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Axon
|
4
|
+
class TestReader < AxonTestCase
|
5
|
+
def setup
|
6
|
+
data = Solid.new(100, 200, "\x0A\x14\x69").to_jpeg.data
|
7
|
+
@io_in = StringIO.new(data)
|
8
|
+
@io_out = StringIO.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_short_chained_example
|
12
|
+
|
13
|
+
# Short, chained example. Reads a JPEG from io_in and writes scaled png to
|
14
|
+
# io_out.
|
15
|
+
Axon.JPEG(@io_in).fit(100, 100).write_png(@io_out)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_longer_example
|
19
|
+
# Even longer example, reads the JPEG header, looks at properties and header
|
20
|
+
# values, sets decompression options, scales the image, sets compression
|
21
|
+
# options, and writes a JPEG.
|
22
|
+
image = Axon.JPEG(@io_in, [:APP2])
|
23
|
+
|
24
|
+
puts image.width
|
25
|
+
puts image.height
|
26
|
+
puts image[:APP2]
|
27
|
+
image.scale_denom = 4
|
28
|
+
|
29
|
+
jpeg = image.fit(100, 100).to_jpeg
|
30
|
+
jpeg.quality = 88
|
31
|
+
jpeg.write(@io_out)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'axon'
|
3
|
+
require 'stringio'
|
4
|
+
require 'reader_tests'
|
5
|
+
require 'writer_tests'
|
6
|
+
|
7
|
+
module Axon
|
8
|
+
class AxonTestCase < MiniTest::Unit::TestCase
|
9
|
+
|
10
|
+
# Generate a solid velvet JPEG
|
11
|
+
def setup
|
12
|
+
@velvet = "\x0A\x14\x69"
|
13
|
+
@image = Solid.new 10, 15, @velvet
|
14
|
+
@io_out = StringIO.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Axon
|
2
|
+
module ReaderTests
|
3
|
+
def test_read_image_from_io
|
4
|
+
assert_equal 10, @reader.width
|
5
|
+
assert_equal 15, @reader.height
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_read_image_from_string
|
9
|
+
assert_equal 10, @reader.width
|
10
|
+
assert_equal 15, @reader.height
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_num_components
|
14
|
+
assert_equal 3, @reader.components
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_color_model
|
18
|
+
assert_equal :RGB, @reader.color_model
|
19
|
+
end
|
20
|
+
|
21
|
+
class DoubleIO < StringIO
|
22
|
+
def read(*args)
|
23
|
+
s = super
|
24
|
+
s[0..20] * 100
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_io_returns_too_much
|
29
|
+
f = DoubleIO.new @data
|
30
|
+
assert_raises(RuntimeError) { @readerclass.new f }
|
31
|
+
end
|
32
|
+
|
33
|
+
class NilIO
|
34
|
+
def read(*args); end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_io_returns_nil
|
38
|
+
assert_raises(RuntimeError) { @readerclass.new NilIO.new }
|
39
|
+
end
|
40
|
+
|
41
|
+
class RaiseIO
|
42
|
+
def read(*args)
|
43
|
+
raise 'heck'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_io_raises_exception
|
48
|
+
assert_raises(RuntimeError) { @readerclass.new RaiseIO.new }
|
49
|
+
end
|
50
|
+
|
51
|
+
class EmptyStringIO
|
52
|
+
def read(*args)
|
53
|
+
""
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_empty_string_io
|
58
|
+
assert_raises(RuntimeError) { @readerclass.new EmptyStringIO.new }
|
59
|
+
end
|
60
|
+
|
61
|
+
class ThatsNotAStringIO
|
62
|
+
def read(*args)
|
63
|
+
:this_should_be_a_string
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_not_a_string_io
|
68
|
+
assert_raises(TypeError) { @readerclass.new ThatsNotAStringIO.new }
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_each
|
72
|
+
size = @reader.width * @reader.components
|
73
|
+
|
74
|
+
@reader.each do |scan_line|
|
75
|
+
assert_equal size, scan_line.size
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_no_shenanigans_during_each
|
80
|
+
@reader.each do |sl|
|
81
|
+
assert_raises(RuntimeError) { @reader.each{} }
|
82
|
+
break
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class OneExceptionIO < StringIO
|
87
|
+
def initialize(*args)
|
88
|
+
@raised_exception = false
|
89
|
+
super
|
90
|
+
end
|
91
|
+
|
92
|
+
def read(*args)
|
93
|
+
unless @raised_exception
|
94
|
+
@raised_exception = true
|
95
|
+
raise 'heck'
|
96
|
+
end
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_recovers_from_initial_io_exception
|
102
|
+
io = OneExceptionIO.new @data
|
103
|
+
r = @readerclass.allocate
|
104
|
+
assert_raises(RuntimeError) { r.send(:initialize, io) }
|
105
|
+
r.send(:initialize, io)
|
106
|
+
r.each{ }
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_multiple_each_calls
|
110
|
+
@reader.each{ }
|
111
|
+
@io_in.rewind
|
112
|
+
@reader.each{ }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Axon
|
4
|
+
class TestStressCases < AxonTestCase
|
5
|
+
def setup
|
6
|
+
@velvet = "\x0A\x14\x69"
|
7
|
+
@image = Generator::Solid.new 1000, 1500, @velvet
|
8
|
+
@jpeg_data = @image.to_jpeg.data
|
9
|
+
@readerclass = JPEGReader
|
10
|
+
end
|
11
|
+
|
12
|
+
class RandomRaiseIO
|
13
|
+
def initialize(source)
|
14
|
+
@io = StringIO.new source
|
15
|
+
@die_at = rand(source.size)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read
|
19
|
+
if @die_at < 2
|
20
|
+
raise 'random death!'
|
21
|
+
end
|
22
|
+
|
23
|
+
read_size = rand @die_at
|
24
|
+
@die_at -= read_size
|
25
|
+
@io.read(read_size)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_io_raises_after_random_sized_reads
|
30
|
+
loop do
|
31
|
+
f = RandomRaiseIO.new(@jpeg_data)
|
32
|
+
r = @readerclass.new(f) rescue puts("new failed")
|
33
|
+
r.each{} rescue puts('each_sl failed')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class CustomIO < StringIO
|
38
|
+
def initialize(str, sequence)
|
39
|
+
super str
|
40
|
+
@sequence = sequence
|
41
|
+
end
|
42
|
+
|
43
|
+
def read
|
44
|
+
if !@sequence || @sequence.empty?
|
45
|
+
raise "random death!"
|
46
|
+
@sequence = nil
|
47
|
+
end
|
48
|
+
super(@sequence.shift)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_custom_io_error
|
53
|
+
loop do
|
54
|
+
f = CustomIO.new(@jpeg_data, [114, 64, 8, 200, 200, 30, 350])
|
55
|
+
|
56
|
+
r = @readerclass.new(f)
|
57
|
+
r.each{ } rescue nil
|
58
|
+
f = CustomIO.new(@jpeg_data, [101, 0])
|
59
|
+
r = @readerclass.new(f) rescue nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_io_returns_nil_after_random_sized_reads
|
64
|
+
loop do
|
65
|
+
f = SometimesNilIO.new(@data)
|
66
|
+
r = @readerclass.new(f)
|
67
|
+
r.each{}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/test/test_exif.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Axon
|
4
|
+
class TestExif < AxonTestCase
|
5
|
+
def test_exif_roundtrip
|
6
|
+
random_data = ""
|
7
|
+
(100).times do
|
8
|
+
random_data << [rand].pack('d') # 800 bytes random data
|
9
|
+
end
|
10
|
+
|
11
|
+
writer = @image.to_jpeg
|
12
|
+
writer.exif = random_data
|
13
|
+
|
14
|
+
image_with_exif = Axon.JPEG(writer.data)
|
15
|
+
assert_equal random_data, image_with_exif.exif
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_exif_with_icc_roundtrip
|
19
|
+
random_icc_data = ""
|
20
|
+
(2**16).times do # a little larger than one jpeg segment
|
21
|
+
random_icc_data << [rand].pack('d') # 8 bytes random data
|
22
|
+
end
|
23
|
+
|
24
|
+
random_exif_data = ""
|
25
|
+
(100).times do
|
26
|
+
random_exif_data << [rand].pack('d') # 800 bytes random data
|
27
|
+
end
|
28
|
+
|
29
|
+
writer = @image.to_jpeg
|
30
|
+
writer.icc_profile = random_icc_data
|
31
|
+
writer.exif = random_exif_data
|
32
|
+
|
33
|
+
image_with_exif_and_icc = Axon.JPEG(writer.data)
|
34
|
+
|
35
|
+
assert_equal random_exif_data, image_with_exif_and_icc.exif
|
36
|
+
assert_equal random_icc_data, image_with_exif_and_icc.icc_profile
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/test/test_icc.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Axon
|
4
|
+
class TestICC < AxonTestCase
|
5
|
+
def test_large_icc_roundtrip
|
6
|
+
random_data = ""
|
7
|
+
(2**16).times do # a little larger than one jpeg segment
|
8
|
+
random_data << [rand].pack('d') # 8 bytes random data
|
9
|
+
end
|
10
|
+
|
11
|
+
writer = @image.to_jpeg
|
12
|
+
writer.icc_profile = random_data
|
13
|
+
|
14
|
+
image_with_icc = Axon.JPEG(writer.data)
|
15
|
+
assert_equal random_data, image_with_icc.icc_profile
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|