chunky_png 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,4 +3,5 @@ spec/resources/_*.png
3
3
  /pkg
4
4
  /tmp
5
5
  /doc
6
- .yardoc
6
+ /.yardoc
7
+ /.bundle
@@ -0,0 +1,31 @@
1
+ = ChunkyPNG benchmark suite
2
+
3
+ This small benchmark suite is intended to test the speed of PNG decoding
4
+ and encoding against different ruby interpreters. You can set the number
5
+ of runs by passing the N environment variable. You can execute them as
6
+ rake task or as standalone script.
7
+
8
+ rake benchmark:encoding
9
+ rake benchmark:decoding
10
+
11
+ rake benchmark N=10 # Run all of them, using n=10
12
+
13
+ Use rvm to simply run the tests against different interpreters. Of course,
14
+ make sure that the chunky_png is installed for all your interpreters.
15
+
16
+ rvm 1.8.7,1.9.1,rbx rake benchmark N=10
17
+
18
+ == Results
19
+
20
+ Some of my benchmark (N=50) result on my 2007 iMac can be found in this gist:
21
+ http://gist.github.com/495323
22
+
23
+ == Why is this relevant?
24
+
25
+ ChunkyPNG is a pure Ruby library to handle PNG files. Decoding a PNG requires
26
+ a lot of integer math and bitwise operations, and moderate use of the unpack
27
+ method to read binary data. Encoding is a good test for Array#pack, and
28
+ depending on the encoding options, also requires a lot of calculations.
29
+ Therefore, the library is a good benchmark candidate for these methods and
30
+ algorithms. It has been used to improve the Array#pack and String#unpack
31
+ methods in Rubinius.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- chunky_png (0.9.0)
4
+ chunky_png (0.9.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -5,8 +5,8 @@ maximum portability. Let me rephrase: it does NOT require RMagick or any other
5
5
  memory leaking image library.
6
6
 
7
7
  Source code:: http://github.com/wvanbergen/chunky_png/tree
8
- RDoc:: http://rdoc.info/projects/wvanbergen/chunky_png
9
- Wiki:: http://wiki.github.com/wvanbergen/chunky_png
8
+ RDoc:: http://rdoc.info/github/wvanbergen/chunky_png/master/file/README.rdoc
9
+ Wiki:: http://github.com/wvanbergen/chunky_png/wiki
10
10
  Issue tracker:: http://github.com/wvanbergen/chunky_png/issues
11
11
 
12
12
  == Features
@@ -60,6 +60,9 @@ The main classes and modules used within ChunkyPNG are:
60
60
  png_stream = ChunkyPNG::Datastream.from_file('filename.png')
61
61
  png_stream.each_chunk { |chunk| p chunk.type }
62
62
 
63
+ For more information, see the project wiki on http://github.com/wvanbergen/chunky_png/wiki
64
+ or the RDOC documentation on http://rdoc.info/github/wvanbergen/chunky_png/master/file/README.rdoc.
65
+
63
66
  == About
64
67
 
65
68
  The library is written by Willem van Bergen for Floorplanner.com, and released
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
- Dir['tasks/*.rake'].each { |file| load(file) }
2
-
3
1
  require 'rubygems'
4
2
  require 'bundler'
5
3
 
6
4
  Bundler.setup
7
5
 
6
+ Dir['tasks/*.rake'].each { |file| load(file) }
7
+
8
8
  GithubGem::RakeTasks.new(:gem)
9
9
  task :default => [:spec]
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.setup
5
+
6
+ require 'benchmark'
7
+ require 'chunky_png'
8
+
9
+ def image_file(name)
10
+ File.join(File.dirname(__FILE__), '..', 'spec', 'resources', name)
11
+ end
12
+
13
+ def image_data(name)
14
+ data = nil
15
+ File.open(image_file(name), 'rb') { |f| data = f.read }
16
+ data
17
+ end
18
+
19
+ png_stream = image_data('pixelstream_reference.png')
20
+ rgba_pixelstream = image_data('pixelstream.rgba')
21
+ rgb_pixelstream = image_data('pixelstream.rgb')
22
+
23
+ n = (ENV['N'] || '5').to_i
24
+
25
+ puts "---------------------------------------------"
26
+ puts "ChunkyPNG (#{ChunkyPNG::VERSION}) decoding benchmark (n=#{n})"
27
+ puts "---------------------------------------------"
28
+ puts
29
+
30
+ Benchmark.bmbm do |x|
31
+ x.report('From PNG stream') { n.times { ChunkyPNG::Image.from_blob(png_stream) } }
32
+ x.report('From RGBA pixelstream') { n.times { ChunkyPNG::Image.from_rgba_stream(240, 180, rgba_pixelstream) } }
33
+ x.report('From RGB pixelstream') { n.times { ChunkyPNG::Image.from_rgb_stream(240, 180, rgb_pixelstream) } }
34
+ end
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.setup
5
+
6
+ require 'benchmark'
7
+ require 'chunky_png'
8
+
9
+ image = ChunkyPNG::Image.new(240, 180, ChunkyPNG::Color::TRANSPARENT)
10
+
11
+ # set some random pixels
12
+ image[10, 20] = ChunkyPNG::Color.rgba(255, 0, 0, 255)
13
+ image[50, 87] = ChunkyPNG::Color.rgba( 0, 255, 0, 255)
14
+ image[33, 99] = ChunkyPNG::Color.rgba( 0, 0, 255, 255)
15
+
16
+ n = (ENV['N'] || '5').to_i
17
+
18
+ puts "---------------------------------------------"
19
+ puts "ChunkyPNG (#{ChunkyPNG::VERSION}) encoding benchmark (n=#{n})"
20
+ puts "---------------------------------------------"
21
+ puts
22
+
23
+ Benchmark.bmbm do |x|
24
+ x.report('Default (indexed)') { n.times { image.to_blob } }
25
+
26
+ # Presets
27
+ x.report(':fast_rgba') { n.times { image.to_blob(:fast_rgba) } }
28
+ x.report(':fast_rgb') { n.times { image.to_blob(:fast_rgb) } }
29
+ x.report(':best_compression') { n.times { image.to_blob(:best_compression) } }
30
+
31
+ # Some options
32
+ x.report(':rgb') { n.times { image.to_blob(:color_mode => ChunkyPNG::COLOR_TRUECOLOR) } }
33
+ x.report(':rgba') { n.times { image.to_blob(:color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA) } }
34
+ x.report(':indexed') { n.times { image.to_blob(:color_mode => ChunkyPNG::COLOR_INDEXED) } }
35
+ x.report(':interlaced') { n.times { image.to_blob(:interlaced => true) } }
36
+
37
+ # Exports
38
+ x.report('to RGBA pixelstream') { n.times { image.to_rgba_stream } }
39
+ x.report('to RGB pixelstream') { n.times { image.to_rgb_stream } }
40
+ end
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
 
4
4
  # Do not change the version and date fields by hand. This will be done
5
5
  # automatically by the gem release script.
6
- s.version = "0.9.0"
7
- s.date = "2010-08-18"
6
+ s.version = "0.9.1"
7
+ s.date = "2010-09-16"
8
8
 
9
9
  s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
10
10
  s.description = <<-EOT
@@ -31,10 +31,10 @@ Gem::Specification.new do |s|
31
31
  s.add_development_dependency('gemcutter')
32
32
 
33
33
  s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
34
- s.extra_rdoc_files = ['README.rdoc']
34
+ s.extra_rdoc_files = ['README.rdoc', 'BENCHMARKS.rdoc']
35
35
 
36
36
  # Do not change the files and test_files fields by hand. This will be done
37
37
  # automatically by the gem release script.
38
- s.files = %w(.bundle/config .gitignore Gemfile Gemfile.lock LICENSE README.rdoc Rakefile chunky_png.gemspec lib/chunky_png.rb lib/chunky_png/canvas.rb lib/chunky_png/canvas/adam7_interlacing.rb lib/chunky_png/canvas/drawing.rb lib/chunky_png/canvas/operations.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/stream_exporting.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/chunk.rb lib/chunky_png/color.rb lib/chunky_png/datastream.rb lib/chunky_png/image.rb lib/chunky_png/palette.rb lib/chunky_png/rmagick.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/resources/16x16_interlaced.png spec/resources/16x16_non_interlaced.png spec/resources/adam7.png spec/resources/clock.png spec/resources/clock_base.png spec/resources/clock_flip_horizontally.png spec/resources/clock_flip_vertically.png spec/resources/clock_mask.png spec/resources/clock_mask_updated.png spec/resources/clock_rotate_180.png spec/resources/clock_rotate_left.png spec/resources/clock_rotate_right.png spec/resources/clock_stubbed.png spec/resources/clock_updated.png spec/resources/composited.png spec/resources/cropped.png spec/resources/damaged_chunk.png spec/resources/damaged_signature.png spec/resources/gray_10x10.png spec/resources/gray_10x10_grayscale.png spec/resources/gray_10x10_grayscale_alpha.png spec/resources/gray_10x10_indexed.png spec/resources/gray_10x10_truecolor.png spec/resources/gray_10x10_truecolor_alpha.png spec/resources/indexed_4bit.png spec/resources/lines.png spec/resources/operations.png spec/resources/pixelstream.rgb spec/resources/pixelstream.rgba spec/resources/pixelstream_reference.png spec/resources/rect.png spec/resources/replaced.png spec/resources/text_chunk.png spec/resources/transparent_gray_10x10.png spec/resources/ztxt_chunk.png spec/spec_helper.rb tasks/github-gem.rake)
39
- s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb)
38
+ s.files = %w(tasks/github-gem.rake lib/chunky_png/canvas.rb spec/resources/composited.png lib/chunky_png/canvas/drawing.rb spec/resources/gray_10x10_grayscale_alpha.png spec/resources/cropped.png LICENSE spec/resources/clock_mask_updated.png spec/resources/pixelstream.rgba Gemfile spec/resources/clock_rotate_right.png spec/resources/ztxt_chunk.png spec/resources/transparent_gray_10x10.png lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/image.rb spec/resources/lines.png spec/resources/clock_mask.png spec/resources/clock_stubbed.png spec/resources/pixelstream.rgb tasks/benchmarks.rake spec/resources/indexed_4bit.png spec/resources/text_chunk.png chunky_png.gemspec benchmarks/decoding_benchmark.rb spec/resources/gray_10x10_truecolor_alpha.png lib/chunky_png/color.rb spec/resources/damaged_chunk.png spec/resources/rect.png README.rdoc lib/chunky_png/canvas/stream_exporting.rb spec/resources/clock_flip_horizontally.png lib/chunky_png/canvas/stream_importing.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/spec_helper.rb lib/chunky_png/rmagick.rb Gemfile.lock Rakefile spec/chunky_png/canvas/png_decoding_spec.rb lib/chunky_png.rb lib/chunky_png/canvas/png_encoding.rb .gitignore spec/resources/16x16_interlaced.png spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/resources/adam7.png lib/chunky_png/palette.rb spec/resources/gray_10x10_indexed.png spec/chunky_png/canvas_spec.rb spec/resources/clock.png benchmarks/encoding_benchmark.rb spec/chunky_png/image_spec.rb spec/resources/clock_rotate_180.png spec/resources/clock_rotate_left.png BENCHMARKS.rdoc spec/resources/16x16_non_interlaced.png lib/chunky_png/chunk.rb spec/chunky_png/canvas/operations_spec.rb spec/resources/gray_10x10_truecolor.png spec/resources/gray_10x10_grayscale.png spec/resources/pixelstream_reference.png spec/chunky_png_spec.rb spec/resources/operations.png spec/resources/clock_flip_vertically.png spec/chunky_png/rmagick_spec.rb lib/chunky_png/datastream.rb spec/resources/clock_base.png lib/chunky_png/canvas/operations.rb spec/resources/replaced.png spec/resources/clock_updated.png spec/resources/damaged_signature.png spec/chunky_png/datastream_spec.rb lib/chunky_png/canvas/adam7_interlacing.rb spec/chunky_png/color_spec.rb spec/resources/gray_10x10.png)
39
+ s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/color_spec.rb)
40
40
  end
@@ -27,7 +27,7 @@ module ChunkyPNG
27
27
 
28
28
  # The current version of ChunkyPNG. This value will be updated automatically
29
29
  # by them gem:release rake task.
30
- VERSION = "0.9.0"
30
+ VERSION = "0.9.1"
31
31
 
32
32
  ###################################################
33
33
  # PNG international standard defined constants
@@ -1,17 +1,49 @@
1
1
  module ChunkyPNG
2
2
  class Canvas
3
+
4
+ # The ChunkyPNG::Canvas::Operations module defines methods to perform operations
5
+ # on a {ChunkyPNG::Canvas}. The module is included into the Canvas class so all
6
+ # these methods are available on every canvas.
7
+ #
8
+ # Note that some of these operations modify the canvas, while some operations return
9
+ # a new canvas and leave the original intact.
10
+ #
11
+ # @see ChunkyPNG::Canvas
3
12
  module Operations
4
- def compose(new_foreground, dx = 0, dy = 0)
5
- check_size_constraints!(new_foreground, dx, dy)
13
+
14
+ # Composes another image onto this image using alpha blending.
15
+ #
16
+ # If you simply want to replace pixels or when the other image does not have
17
+ # transparency, it is faster to use {#replace}.
18
+ #
19
+ # @param [ChunkyPNG::Canvas] other The foreground canvas to compose on the
20
+ # current canvas, using alpha compositing.
21
+ # @param [Integer] offset_x The x-offset to apply the new forgeround on.
22
+ # @param [Integer] offset_y The y-offset to apply the new forgeround on.
23
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas composed onto it.
24
+ # @raise [ChunkyPNG::OutOfBounds] when the other canvas doesn't fit on this one,
25
+ # given the offset and size of the other canavs.
26
+ # @see #replace
27
+ def compose(other, offset_x = 0, offset_y = 0)
28
+ check_size_constraints!(other, offset_x, offset_y)
6
29
 
7
- for y in 0...new_foreground.height do
8
- for x in 0...new_foreground.width do
9
- self[x+dx, y+dy] = ChunkyPNG::Color.compose(new_foreground[x, y], self[x+dx, y+dy])
30
+ for y in 0...other.height do
31
+ for x in 0...other.width do
32
+ self[x + offset_x, y + offset_y] = ChunkyPNG::Color.compose(other[x, y], self[x + offset_x, y + offset_y])
10
33
  end
11
34
  end
12
35
  self
13
36
  end
14
37
 
38
+ # Replaces pixels on this image by pixels from another pixels, on a given offset.
39
+ #
40
+ # This will completely replace the pixels of the background image. If you want to blend
41
+ # them with semi-transparent pixels from the foreground image, see {#compose}.
42
+ #
43
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas composed onto it.
44
+ # @raise [ChunkyPNG::OutOfBounds] when the other canvas doesn't fit on this one,
45
+ # given the offset and size of the other canavs.
46
+ # @see #compose
15
47
  def replace(other, offset_x = 0, offset_y = 0)
16
48
  check_size_constraints!(other, offset_x, offset_y)
17
49
 
@@ -21,7 +53,22 @@ module ChunkyPNG
21
53
  self
22
54
  end
23
55
 
56
+ # Crops an image, given the coordinates and size of the image that needs to be cut out.
57
+ # This will leave the original image intact and return a new, cropped image with pixels
58
+ # copied from the original image.
59
+ #
60
+ # @param [Integer] x The x-coordinate of the top left corner of the image to be cropped.
61
+ # @param [Integer] y The y-coordinate of the top left corner of the image to be cropped.
62
+ # @param [Integer] crop_width The width of the image to be cropped.
63
+ # @param [Integer] crop_height The height of the image to be cropped.
64
+ # @return [ChunkyPNG::Canvas] Returns the newly created cropped image.
65
+ # @raise [ChunkyPNG::OutOfBounds] when the crop dimensions plus the given coordinates
66
+ # are bigger then the original image.
24
67
  def crop(x, y, crop_width, crop_height)
68
+
69
+ raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_width + x > width
70
+ raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_height + y > height
71
+
25
72
  new_pixels = []
26
73
  for cy in 0...crop_height do
27
74
  new_pixels += pixels.slice((cy + y) * width + x, crop_width)
@@ -29,13 +76,52 @@ module ChunkyPNG
29
76
  ChunkyPNG::Canvas.new(crop_width, crop_height, new_pixels)
30
77
  end
31
78
 
79
+ # Creates a new image, based on the current image but with a new theme color.
80
+ #
81
+ # This method will replace one color in an image with another image. This is done by
82
+ # first extracting the pixels with a color close to the original theme color as a mask
83
+ # image, changing the color of this mask image and then apply it on the original image.
84
+ #
85
+ # Mask extraction works best when the theme colored pixels are clearly distinguishable
86
+ # from a background color (preferably white). You can set a tolerance level to influence
87
+ # the extraction process.
88
+ #
89
+ # @param [Integer] old_theme_color The original theme color in this image.
90
+ # @param [Integer] new_theme_color The color to replace the old theme color with.
91
+ # @param [Integer] The backrgound color opn which the theme colored pixels are placed.
92
+ # @param [Integer] tolerance The tolerance level to use when extracting the mask image. Five is
93
+ # the default; increase this if the masked image does not extract all the required pixels,
94
+ # decrease it if too many pixels get extracted.
95
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the theme colored pixels changed.
96
+ # @see #change_theme_color!
97
+ # @see #change_mask_color!
32
98
  def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
33
99
  base, mask = extract_mask(old_theme_color, bg_color, tolerance)
34
100
  mask.change_mask_color!(new_theme_color)
35
101
  self.replace(base.compose(mask))
36
102
  end
37
103
 
38
- def extract_mask(mask_color, bg_color, tolerance = 5)
104
+ # Creates a base image and a mask image from an original image that has a particular theme color.
105
+ # This can be used to easily change a theme color in an image.
106
+ #
107
+ # It will extract all the pixels that look like the theme color (with a tolerance level) and put
108
+ # these in a mask image. All the other pixels will be stored in a base image. Both images will be
109
+ # of the exact same size as the original image. The original image will be left untouched.
110
+ #
111
+ # The color of the mask image can be changed with {#change_mask_color!}. This new mask image can
112
+ # then be composed upon the base image to create an image with a new theme color. A call to
113
+ # {#change_theme_color!} will perform this in one go.
114
+ #
115
+ # @param [Integer] mask_color The current theme color.
116
+ # @param [Integer] bg_color The background color on which the theme colored pxiels are applied.
117
+ # @param [Integer] tolerance The tolerance level to use when extracting the mask image. Five is
118
+ # the default; increase this if the masked image does not extract all the required pixels,
119
+ # decrease it if too many pixels get extracted.
120
+ # @return [Array<ChunkyPNG::Canvas, ChunkyPNG::Canvas>] An array with the base canvas and the mask
121
+ # canvas as elements.
122
+ # @see #change_theme_color!
123
+ # @see #change_mask_color!
124
+ def extract_mask(mask_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
39
125
  base_pixels = []
40
126
  mask_pixels = []
41
127
 
@@ -52,11 +138,30 @@ module ChunkyPNG
52
138
  [ self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels) ]
53
139
  end
54
140
 
141
+ # Changes the color of a mask image.
142
+ #
143
+ # This method works on acanavs extracte out of another image using the {#extract_mask} method.
144
+ # It can then be applied on the extracted base image. See {#change_theme_color!} to perform
145
+ # these operations in one go.
146
+ #
147
+ # @param [Integer] new_color The color to replace the original mask color with.
148
+ # @raise [ChunkyPNG::ExpectationFailed] when this canvas is not a mask image, i.e. its palette
149
+ # has more than once color, disregarding transparency.
150
+ # @see #change_theme_color!
151
+ # @see #extract_mask
55
152
  def change_mask_color!(new_color)
56
153
  raise ChunkyPNG::ExpectationFailed, "This is not a mask image!" if palette.opaque_palette.size != 1
57
154
  pixels.map! { |pixel| (new_color & 0xffffff00) | ChunkyPNG::Color.a(pixel) }
155
+ self
58
156
  end
59
157
 
158
+ # Flips the image horizontally.
159
+ #
160
+ # This will flip the image on its horizontal axis, e.g. pixels on the top will now
161
+ # be pixels on the bottom. Chaining this method twice will return the original canvas.
162
+ # This method will leave the original object intact and return a new canvas.
163
+ #
164
+ # @return [ChunkyPNG::Canvas] The flipped image
60
165
  def flip_horizontally
61
166
  self.class.new(width, height).tap do |flipped|
62
167
  for y in 0...height do
@@ -65,6 +170,13 @@ module ChunkyPNG
65
170
  end
66
171
  end
67
172
 
173
+ # Flips the image horizontally.
174
+ #
175
+ # This will flip the image on its vertical axis, e.g. pixels on the left will now
176
+ # be pixels on the right. Chaining this method twice will return the original canvas.
177
+ # This method will leave the original object intact and return a new canvas.
178
+ #
179
+ # @return [ChunkyPNG::Canvas] The flipped image
68
180
  def flip_vertically
69
181
  self.class.new(width, height).tap do |flipped|
70
182
  for x in 0...width do
@@ -73,6 +185,10 @@ module ChunkyPNG
73
185
  end
74
186
  end
75
187
 
188
+ # Rotates the image 90 degrees clockwise.
189
+ # This method will leave the original object intact and return a new canvas.
190
+ #
191
+ # @return [ChunkyPNG::Canvas] The rotated image
76
192
  def rotate_right
77
193
  self.class.new(height, width).tap do |rotated|
78
194
  for i in 0...width do
@@ -81,6 +197,10 @@ module ChunkyPNG
81
197
  end
82
198
  end
83
199
 
200
+ # Rotates the image 90 degrees counter-clockwise.
201
+ # This method will leave the original object intact and return a new canvas.
202
+ #
203
+ # @return [ChunkyPNG::Canvas] The rotated image.
84
204
  def rotate_left
85
205
  self.class.new(height, width).tap do |rotated|
86
206
  for i in 0...width do
@@ -89,6 +209,10 @@ module ChunkyPNG
89
209
  end
90
210
  end
91
211
 
212
+ # Rotates the image 180 degrees.
213
+ # This method will leave the original object intact and return a new canvas.
214
+ #
215
+ # @return [ChunkyPNG::Canvas] The rotated image.
92
216
  def rotate_180
93
217
  self.class.new(width, height).tap do |flipped|
94
218
  for y in 0...height do
@@ -98,10 +222,16 @@ module ChunkyPNG
98
222
  end
99
223
 
100
224
  protected
101
-
225
+
226
+ # Checks whether another image has the correct dimension to be used for an operation
227
+ # on the current image, given an offset coordinate to work with.
228
+ # @param [ChunkyPNG::Canvas] other The other canvas
229
+ # @param [Integer] offset_x The x offset on which the other image will be applied.
230
+ # @param [Integer] offset_y The y offset on which the other image will be applied.
231
+ # @raise [ChunkyPNG::OutOfBounds] when the other image doesn't fit.
102
232
  def check_size_constraints!(other, offset_x, offset_y)
103
- raise ChunkyPNG::ExpectationFailed, "Background image width is too small!" if width < other.width + offset_x
104
- raise ChunkyPNG::ExpectationFailed, "Background image height is too small!" if height < other.height + offset_y
233
+ raise ChunkyPNG::OutOfBounds, "Background image width is too small!" if width < other.width + offset_x
234
+ raise ChunkyPNG::OutOfBounds, "Background image height is too small!" if height < other.height + offset_y
105
235
  end
106
236
  end
107
237
  end
@@ -37,7 +37,6 @@ module ChunkyPNG
37
37
  # @return [ChunkyPNG::Chunk::Header]
38
38
  attr_accessor :end_chunk
39
39
 
40
-
41
40
  # Initializes a new Datastream instance.
42
41
  def initialize
43
42
  @other_chunks = []
@@ -94,6 +93,7 @@ module ChunkyPNG
94
93
  # This method reads the PNG signature from the stream, setting the current position
95
94
  # of the stream directly after the signature, where the IHDR chunk should begin.
96
95
  #
96
+ # @param [IO] io The stream to read the PNG signature from.
97
97
  # @raise [RuntimeError] An exception is raised if the PNG signature is not found at
98
98
  # the beginning of the stream.
99
99
  def verify_signature!(io)
@@ -133,6 +133,7 @@ module ChunkyPNG
133
133
  end
134
134
 
135
135
  # Returns all the textual metadata key/value pairs as hash.
136
+ # @return [Hash] A hash containing metadata fields and their values.
136
137
  def metadata
137
138
  metadata = {}
138
139
  other_chunks.select do |chunk|
@@ -1,24 +1,45 @@
1
1
  module ChunkyPNG
2
2
 
3
- # Image class
3
+ # ChunkyPNG::Image is an extension of the {ChunkyPNG::Canvas} class, that
4
+ # also includes support for metadata.
4
5
  #
6
+ # @see ChunkyPNG::Canvas
5
7
  class Image < Canvas
6
8
 
9
+ # The minimumsize of bytes the value of a metadata field should be before compression
10
+ # is enabled for the chunk.
7
11
  METADATA_COMPRESSION_TRESHOLD = 300
8
12
 
13
+ # @return [Hash] The hash of metadata fields for this PNG image.
9
14
  attr_accessor :metadata
10
15
 
11
- def initialize(width, height, initial = ChunkyPNG::Color::TRANSPARENT, metadata = {})
12
- super(width, height, initial)
16
+ # Initializes a new ChunkyPNG::Image instance.
17
+ # @param [Integer] width The width of the new image.
18
+ # @param [Integer] height The height of the new image.
19
+ # @param [Integer] bg_color The background color of the new image.
20
+ # @param [Hash] metadata A hash of metadata fields and values for this image.
21
+ # @see ChunkyPNG::Canvas#initialize
22
+ def initialize(width, height, bg_color = ChunkyPNG::Color::TRANSPARENT, metadata = {})
23
+ super(width, height, bg_color)
13
24
  @metadata = metadata
14
- @metadata_compression_treshhold = 300
15
25
  end
16
26
 
27
+ # Initializes a copy of another ChunkyPNG::Image instance.
28
+ #
29
+ # @param [ChunkyPNG::Image] other The other image to copy.
17
30
  def initialize_copy(other)
18
31
  super(other)
19
- @metdata = other.metadata
32
+ @metadata = other.metadata
20
33
  end
21
34
 
35
+ # Returns the metadata for this image as PNG chunks.
36
+ #
37
+ # Chunks will either be of the {ChunkyPNG::Chunk::Text} type for small
38
+ # values (in bytes), or of the {ChunkyPNG::Chunk::CompressedText} type
39
+ # for values that are larger in size.
40
+ #
41
+ # @return [Array<ChunkyPNG::Chunk>] An array of metadata chunks.
42
+ # @see ChunkyPNG::Image::METADATA_COMPRESSION_TRESHOLD
22
43
  def metadata_chunks
23
44
  metadata.map do |key, value|
24
45
  if value.length >= METADATA_COMPRESSION_TRESHOLD
@@ -29,12 +50,26 @@ module ChunkyPNG
29
50
  end
30
51
  end
31
52
 
53
+ # Encodes the image to a PNG datastream for saving to disk or writing to an IO stream.
54
+ #
55
+ # Besides encoding the canvas, it will also encode the metadata fields to text chunks.
56
+ #
57
+ # @param [Hash] constraints The constraints to use when encoding the canvas.
58
+ # @return [ChunkyPNG::Datastream] The datastream that contains this image.
59
+ # @see ChunkyPNG::Canvas::PNGEncoding#to_datastream
60
+ # @see #metadata_chunks
32
61
  def to_datastream(constraints = {})
33
62
  ds = super(constraints)
34
63
  ds.other_chunks += metadata_chunks
35
64
  return ds
36
65
  end
37
66
 
67
+ # Reads a ChunkyPNG::Image intance from a data stream.
68
+ #
69
+ # Besides decoding the canvas, this will also read the metadata fields
70
+ # from the datastream.
71
+ #
72
+ # @param [ChunkyPNG::Datastream] The datastream to read from.
38
73
  def self.from_datastream(ds)
39
74
  image = super(ds)
40
75
  image.metadata = ds.metadata
@@ -2,19 +2,21 @@ require 'spec_helper'
2
2
 
3
3
  describe ChunkyPNG::Canvas::Operations do
4
4
  describe '#crop' do
5
- before(:each) do
6
- @canvas = ChunkyPNG::Canvas.from_file(resource_file('operations.png'))
7
- end
5
+ before { @canvas = reference_canvas('operations') }
8
6
 
9
7
  it "should crop the right pixels from the original canvas" do
10
8
  cropped = @canvas.crop(10, 5, 4, 8)
11
9
  cropped.should == reference_canvas('cropped')
12
10
  end
11
+
12
+ it "should raise an exception when the cropped image falls outside the oiginal image" do
13
+ lambda { @canvas.crop(16, 16, 2, 2) }.should raise_error(ChunkyPNG::OutOfBounds)
14
+ end
13
15
  end
14
16
 
15
17
  describe '#compose' do
16
18
  it "should compose pixels correctly" do
17
- canvas = ChunkyPNG::Canvas.from_file(resource_file('operations.png'))
19
+ canvas = reference_canvas('operations')
18
20
  subcanvas = ChunkyPNG::Canvas.new(4, 8, ChunkyPNG::Color.rgba(0, 0, 0, 75))
19
21
  canvas.compose(subcanvas, 8, 4)
20
22
  canvas.should == reference_canvas('composited')
@@ -25,18 +27,24 @@ describe ChunkyPNG::Canvas::Operations do
25
27
  mask = reference_canvas('clock_mask_updated')
26
28
  base.compose(mask).should == reference_canvas('clock_updated')
27
29
  end
30
+
31
+ it "should raise an exception when the pixels to compose fall outside the image" do
32
+ lambda { reference_canvas('operations').compose(ChunkyPNG::Canvas.new(1,1), 16, 16) }.should raise_error(ChunkyPNG::OutOfBounds)
33
+ end
28
34
  end
29
35
 
30
36
  describe '#replace' do
31
- before(:each) do
32
- @canvas = ChunkyPNG::Canvas.from_file(resource_file('operations.png'))
33
- end
37
+ before { @canvas = reference_canvas('operations') }
34
38
 
35
39
  it "should replace the correct pixels" do
36
40
  subcanvas = ChunkyPNG::Canvas.new(3, 2, ChunkyPNG::Color.rgb(200, 255, 0))
37
41
  @canvas.replace(subcanvas, 5, 4)
38
42
  @canvas.should == reference_canvas('replaced')
39
43
  end
44
+
45
+ it "should raise an exception when the pixels to replace fall outside the image" do
46
+ lambda { @canvas.replace(ChunkyPNG::Canvas.new(1,1), 16, 16) }.should raise_error(ChunkyPNG::OutOfBounds)
47
+ end
40
48
  end
41
49
 
42
50
  describe '#change_theme_color!' do
@@ -86,35 +94,80 @@ describe ChunkyPNG::Canvas::Operations do
86
94
  @mask.change_mask_color!(@new_color)
87
95
  @mask.palette.opaque_palette.size.should == 1
88
96
  end
97
+
98
+ it "should raise an exception when the mask image has more than once color" do
99
+ not_a_mask = reference_canvas('operations')
100
+ lambda { not_a_mask.change_mask_color!(@new_color) }.should raise_error(ChunkyPNG::ExpectationFailed)
101
+ end
89
102
  end
90
-
103
+ end
104
+
105
+ describe ChunkyPNG::Canvas::Operations do
106
+ before { @stubbed = reference_canvas('clock_stubbed') }
107
+
91
108
  describe '#flip_horizontally' do
92
109
  it "should flip the pixels horizontally" do
93
- reference_canvas('clock_stubbed').flip_horizontally.should == reference_canvas('clock_flip_horizontally')
110
+ @stubbed.flip_horizontally.should == reference_canvas('clock_flip_horizontally')
111
+ end
112
+
113
+ it "should return itself when applied twice" do
114
+ @stubbed.flip_horizontally.flip_horizontally.should == @stubbed
94
115
  end
95
116
  end
96
-
117
+
97
118
  describe '#flip_vertically' do
98
119
  it "should flip the pixels vertically" do
99
- reference_canvas('clock_stubbed').flip_vertically.should == reference_canvas('clock_flip_vertically')
120
+ @stubbed.flip_vertically.should == reference_canvas('clock_flip_vertically')
121
+ end
122
+
123
+ it "should return itself when applied twice" do
124
+ @stubbed.flip_vertically.flip_vertically.should == @stubbed
100
125
  end
101
126
  end
102
127
 
103
128
  describe '#rotate_left' do
104
129
  it "should rotate the pixels 90 degrees counter-clockwise" do
105
- reference_canvas('clock_stubbed').rotate_left.should == reference_canvas('clock_rotate_left')
130
+ @stubbed.rotate_left.should == reference_canvas('clock_rotate_left')
131
+ end
132
+
133
+ it "it should rotate 180 degrees when applied twice" do
134
+ @stubbed.rotate_left.rotate_left.should == reference_canvas('clock_rotate_180')
135
+ end
136
+
137
+ it "it should rotate right when applied three times" do
138
+ @stubbed.rotate_left.rotate_left.rotate_left.should == reference_canvas('clock_rotate_right')
139
+ end
140
+
141
+ it "should return itself when applied four times" do
142
+ @stubbed.rotate_left.rotate_left.rotate_left.rotate_left.should == @stubbed
106
143
  end
107
144
  end
108
-
145
+
109
146
  describe '#rotate_right' do
110
147
  it "should rotate the pixels 90 degrees clockwise" do
111
- reference_canvas('clock_stubbed').rotate_right.should == reference_canvas('clock_rotate_right')
148
+ @stubbed.rotate_right.should == reference_canvas('clock_rotate_right')
149
+ end
150
+
151
+ it "it should rotate 180 degrees when applied twice" do
152
+ @stubbed.rotate_right.rotate_right.should == reference_canvas('clock_rotate_180')
153
+ end
154
+
155
+ it "it should rotate left when applied three times" do
156
+ @stubbed.rotate_right.rotate_right.rotate_right.should == reference_canvas('clock_rotate_left')
157
+ end
158
+
159
+ it "should return itself when applied four times" do
160
+ @stubbed.rotate_right.rotate_right.rotate_right.rotate_right.should == @stubbed
112
161
  end
113
162
  end
114
-
163
+
115
164
  describe '#rotate_180' do
116
165
  it "should rotate the pixels 180 degrees" do
117
- reference_canvas('clock_stubbed').rotate_180.should == reference_canvas('clock_rotate_180')
166
+ @stubbed.rotate_180.should == reference_canvas('clock_rotate_180')
167
+ end
168
+
169
+ it "should return itself when applied twice" do
170
+ @stubbed.rotate_180.rotate_180.should == @stubbed
118
171
  end
119
172
  end
120
173
  end
@@ -0,0 +1,26 @@
1
+ all_benchamrk_tasks = []
2
+
3
+ namespace(:benchmark) do
4
+
5
+ Dir[File.join(File.dirname(__FILE__), '..', 'benchmarks', '*_benchmark.rb')]. each do |benchmark_file|
6
+ task_name = File.basename(benchmark_file, '_benchmark.rb').to_sym
7
+
8
+ desc "Run the #{task_name} benchmark."
9
+ task(task_name, :n) do |task, args|
10
+ ENV['N'] = args[:n] if args[:n]
11
+ load(File.expand_path(benchmark_file))
12
+ end
13
+
14
+ all_benchamrk_tasks << "benchmark:#{task_name}"
15
+ end
16
+ end
17
+
18
+ unless all_benchamrk_tasks.empty?
19
+ desc 'Run the whole benchmark suite'
20
+ task(:benchmark, :n) do |task, args|
21
+ all_benchamrk_tasks.each do |t|
22
+ task(t).invoke(args[:n])
23
+ puts
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chunky_png
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 57
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 9
8
- - 0
9
- version: 0.9.0
9
+ - 1
10
+ version: 0.9.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Willem van Bergen
@@ -14,62 +15,66 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-08-18 00:00:00 -04:00
18
+ date: 2010-09-16 00:00:00 +02:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- name: rake
22
- requirement: &id001 !ruby/object:Gem::Requirement
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
23
23
  none: false
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
+ hash: 3
27
28
  segments:
28
29
  - 0
29
30
  version: "0"
31
+ requirement: *id001
30
32
  type: :development
33
+ name: rake
31
34
  prerelease: false
32
- version_requirements: *id001
33
35
  - !ruby/object:Gem::Dependency
34
- name: rspec
35
- requirement: &id002 !ruby/object:Gem::Requirement
36
+ version_requirements: &id002 !ruby/object:Gem::Requirement
36
37
  none: false
37
38
  requirements:
38
39
  - - ">="
39
40
  - !ruby/object:Gem::Version
41
+ hash: 9
40
42
  segments:
41
43
  - 1
42
44
  - 3
43
45
  version: "1.3"
46
+ requirement: *id002
44
47
  type: :development
48
+ name: rspec
45
49
  prerelease: false
46
- version_requirements: *id002
47
50
  - !ruby/object:Gem::Dependency
48
- name: git
49
- requirement: &id003 !ruby/object:Gem::Requirement
51
+ version_requirements: &id003 !ruby/object:Gem::Requirement
50
52
  none: false
51
53
  requirements:
52
54
  - - ">="
53
55
  - !ruby/object:Gem::Version
56
+ hash: 3
54
57
  segments:
55
58
  - 0
56
59
  version: "0"
60
+ requirement: *id003
57
61
  type: :development
62
+ name: git
58
63
  prerelease: false
59
- version_requirements: *id003
60
64
  - !ruby/object:Gem::Dependency
61
- name: gemcutter
62
- requirement: &id004 !ruby/object:Gem::Requirement
65
+ version_requirements: &id004 !ruby/object:Gem::Requirement
63
66
  none: false
64
67
  requirements:
65
68
  - - ">="
66
69
  - !ruby/object:Gem::Version
70
+ hash: 3
67
71
  segments:
68
72
  - 0
69
73
  version: "0"
74
+ requirement: *id004
70
75
  type: :development
76
+ name: gemcutter
71
77
  prerelease: false
72
- version_requirements: *id004
73
78
  description: " This pure Ruby library can read and write PNG images without depending on an external \n image library, like RMagick. It tries to be memory efficient and reasonably fast.\n \n It supports reading and writing all PNG variants that are defined in the specification, \n with one limitation: only 8-bit color depth is supported. It supports all transparency, \n interlacing and filtering options the PNG specifications allows. It can also read and \n write textual metadata from PNG files. Low-level read/write access to PNG chunks is\n also possible.\n \n This library supports simple drawing on the image canvas and simple operations like alpha composition\n and cropping. Finally, it can import from and export to RMagick for interoperability. \n"
74
79
  email:
75
80
  - willem@railsdoctors.com
@@ -79,78 +84,82 @@ extensions: []
79
84
 
80
85
  extra_rdoc_files:
81
86
  - README.rdoc
87
+ - BENCHMARKS.rdoc
82
88
  files:
83
- - .bundle/config
84
- - .gitignore
85
- - Gemfile
86
- - Gemfile.lock
87
- - LICENSE
88
- - README.rdoc
89
- - Rakefile
90
- - chunky_png.gemspec
91
- - lib/chunky_png.rb
89
+ - tasks/github-gem.rake
92
90
  - lib/chunky_png/canvas.rb
93
- - lib/chunky_png/canvas/adam7_interlacing.rb
91
+ - spec/resources/composited.png
94
92
  - lib/chunky_png/canvas/drawing.rb
95
- - lib/chunky_png/canvas/operations.rb
93
+ - spec/resources/gray_10x10_grayscale_alpha.png
94
+ - spec/resources/cropped.png
95
+ - LICENSE
96
+ - spec/resources/clock_mask_updated.png
97
+ - spec/resources/pixelstream.rgba
98
+ - Gemfile
99
+ - spec/resources/clock_rotate_right.png
100
+ - spec/resources/ztxt_chunk.png
101
+ - spec/resources/transparent_gray_10x10.png
96
102
  - lib/chunky_png/canvas/png_decoding.rb
97
- - lib/chunky_png/canvas/png_encoding.rb
103
+ - lib/chunky_png/image.rb
104
+ - spec/resources/lines.png
105
+ - spec/resources/clock_mask.png
106
+ - spec/resources/clock_stubbed.png
107
+ - spec/resources/pixelstream.rgb
108
+ - tasks/benchmarks.rake
109
+ - spec/resources/indexed_4bit.png
110
+ - spec/resources/text_chunk.png
111
+ - chunky_png.gemspec
112
+ - benchmarks/decoding_benchmark.rb
113
+ - spec/resources/gray_10x10_truecolor_alpha.png
114
+ - lib/chunky_png/color.rb
115
+ - spec/resources/damaged_chunk.png
116
+ - spec/resources/rect.png
117
+ - README.rdoc
98
118
  - lib/chunky_png/canvas/stream_exporting.rb
119
+ - spec/resources/clock_flip_horizontally.png
99
120
  - lib/chunky_png/canvas/stream_importing.rb
100
- - lib/chunky_png/chunk.rb
101
- - lib/chunky_png/color.rb
102
- - lib/chunky_png/datastream.rb
103
- - lib/chunky_png/image.rb
104
- - lib/chunky_png/palette.rb
105
- - lib/chunky_png/rmagick.rb
106
121
  - spec/chunky_png/canvas/adam7_interlacing_spec.rb
107
- - spec/chunky_png/canvas/drawing_spec.rb
108
- - spec/chunky_png/canvas/operations_spec.rb
122
+ - spec/spec_helper.rb
123
+ - lib/chunky_png/rmagick.rb
124
+ - Gemfile.lock
125
+ - Rakefile
109
126
  - spec/chunky_png/canvas/png_decoding_spec.rb
110
- - spec/chunky_png/canvas/png_encoding_spec.rb
111
- - spec/chunky_png/canvas_spec.rb
112
- - spec/chunky_png/color_spec.rb
113
- - spec/chunky_png/datastream_spec.rb
114
- - spec/chunky_png/image_spec.rb
115
- - spec/chunky_png/rmagick_spec.rb
116
- - spec/chunky_png_spec.rb
127
+ - lib/chunky_png.rb
128
+ - lib/chunky_png/canvas/png_encoding.rb
129
+ - .gitignore
117
130
  - spec/resources/16x16_interlaced.png
118
- - spec/resources/16x16_non_interlaced.png
131
+ - spec/chunky_png/canvas/drawing_spec.rb
132
+ - spec/chunky_png/canvas/png_encoding_spec.rb
119
133
  - spec/resources/adam7.png
134
+ - lib/chunky_png/palette.rb
135
+ - spec/resources/gray_10x10_indexed.png
136
+ - spec/chunky_png/canvas_spec.rb
120
137
  - spec/resources/clock.png
121
- - spec/resources/clock_base.png
122
- - spec/resources/clock_flip_horizontally.png
123
- - spec/resources/clock_flip_vertically.png
124
- - spec/resources/clock_mask.png
125
- - spec/resources/clock_mask_updated.png
138
+ - benchmarks/encoding_benchmark.rb
139
+ - spec/chunky_png/image_spec.rb
126
140
  - spec/resources/clock_rotate_180.png
127
141
  - spec/resources/clock_rotate_left.png
128
- - spec/resources/clock_rotate_right.png
129
- - spec/resources/clock_stubbed.png
130
- - spec/resources/clock_updated.png
131
- - spec/resources/composited.png
132
- - spec/resources/cropped.png
133
- - spec/resources/damaged_chunk.png
134
- - spec/resources/damaged_signature.png
135
- - spec/resources/gray_10x10.png
136
- - spec/resources/gray_10x10_grayscale.png
137
- - spec/resources/gray_10x10_grayscale_alpha.png
138
- - spec/resources/gray_10x10_indexed.png
142
+ - BENCHMARKS.rdoc
143
+ - spec/resources/16x16_non_interlaced.png
144
+ - lib/chunky_png/chunk.rb
145
+ - spec/chunky_png/canvas/operations_spec.rb
139
146
  - spec/resources/gray_10x10_truecolor.png
140
- - spec/resources/gray_10x10_truecolor_alpha.png
141
- - spec/resources/indexed_4bit.png
142
- - spec/resources/lines.png
143
- - spec/resources/operations.png
144
- - spec/resources/pixelstream.rgb
145
- - spec/resources/pixelstream.rgba
147
+ - spec/resources/gray_10x10_grayscale.png
146
148
  - spec/resources/pixelstream_reference.png
147
- - spec/resources/rect.png
149
+ - spec/chunky_png_spec.rb
150
+ - spec/resources/operations.png
151
+ - spec/resources/clock_flip_vertically.png
152
+ - spec/chunky_png/rmagick_spec.rb
153
+ - lib/chunky_png/datastream.rb
154
+ - spec/resources/clock_base.png
155
+ - lib/chunky_png/canvas/operations.rb
148
156
  - spec/resources/replaced.png
149
- - spec/resources/text_chunk.png
150
- - spec/resources/transparent_gray_10x10.png
151
- - spec/resources/ztxt_chunk.png
152
- - spec/spec_helper.rb
153
- - tasks/github-gem.rake
157
+ - spec/resources/clock_updated.png
158
+ - spec/resources/damaged_signature.png
159
+ - spec/chunky_png/datastream_spec.rb
160
+ - lib/chunky_png/canvas/adam7_interlacing.rb
161
+ - spec/chunky_png/color_spec.rb
162
+ - spec/resources/gray_10x10.png
154
163
  has_rdoc: true
155
164
  homepage: http://wiki.github.com/wvanbergen/chunky_png
156
165
  licenses: []
@@ -170,7 +179,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
170
179
  requirements:
171
180
  - - ">="
172
181
  - !ruby/object:Gem::Version
173
- hash: 2219291082232343403
182
+ hash: 3
174
183
  segments:
175
184
  - 0
176
185
  version: "0"
@@ -179,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
188
  requirements:
180
189
  - - ">="
181
190
  - !ruby/object:Gem::Version
182
- hash: 2219291082232343403
191
+ hash: 3
183
192
  segments:
184
193
  - 0
185
194
  version: "0"
@@ -192,13 +201,13 @@ specification_version: 3
192
201
  summary: Pure ruby library for read/write, chunk-level access to PNG files
193
202
  test_files:
194
203
  - spec/chunky_png/canvas/adam7_interlacing_spec.rb
195
- - spec/chunky_png/canvas/drawing_spec.rb
196
- - spec/chunky_png/canvas/operations_spec.rb
197
204
  - spec/chunky_png/canvas/png_decoding_spec.rb
205
+ - spec/chunky_png/canvas/drawing_spec.rb
198
206
  - spec/chunky_png/canvas/png_encoding_spec.rb
199
207
  - spec/chunky_png/canvas_spec.rb
200
- - spec/chunky_png/color_spec.rb
201
- - spec/chunky_png/datastream_spec.rb
202
208
  - spec/chunky_png/image_spec.rb
203
- - spec/chunky_png/rmagick_spec.rb
209
+ - spec/chunky_png/canvas/operations_spec.rb
204
210
  - spec/chunky_png_spec.rb
211
+ - spec/chunky_png/rmagick_spec.rb
212
+ - spec/chunky_png/datastream_spec.rb
213
+ - spec/chunky_png/color_spec.rb
@@ -1,2 +0,0 @@
1
- ---
2
- BUNDLE_DISABLE_SHARED_GEMS: "1"