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 +2 -1
- data/BENCHMARKS.rdoc +31 -0
- data/Gemfile.lock +1 -1
- data/README.rdoc +5 -2
- data/Rakefile +2 -2
- data/benchmarks/decoding_benchmark.rb +34 -0
- data/benchmarks/encoding_benchmark.rb +40 -0
- data/chunky_png.gemspec +5 -5
- data/lib/chunky_png.rb +1 -1
- data/lib/chunky_png/canvas/operations.rb +139 -9
- data/lib/chunky_png/datastream.rb +2 -1
- data/lib/chunky_png/image.rb +40 -5
- data/spec/chunky_png/canvas/operations_spec.rb +69 -16
- data/tasks/benchmarks.rake +26 -0
- metadata +87 -78
- data/.bundle/config +0 -2
data/.gitignore
CHANGED
data/BENCHMARKS.rdoc
ADDED
@@ -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.
|
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -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/
|
9
|
-
Wiki:: http://
|
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
@@ -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
|
data/chunky_png.gemspec
CHANGED
@@ -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.
|
7
|
-
s.date = "2010-
|
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(
|
39
|
-
s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/
|
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
|
data/lib/chunky_png.rb
CHANGED
@@ -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.
|
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
|
-
|
5
|
-
|
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...
|
8
|
-
for x in 0...
|
9
|
-
self[x+
|
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
|
-
|
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::
|
104
|
-
raise ChunkyPNG::
|
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|
|
data/lib/chunky_png/image.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
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
|
-
@
|
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(
|
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 =
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
-
|
9
|
-
version: 0.9.
|
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-
|
18
|
+
date: 2010-09-16 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
- .
|
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
|
-
-
|
91
|
+
- spec/resources/composited.png
|
94
92
|
- lib/chunky_png/canvas/drawing.rb
|
95
|
-
-
|
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/
|
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/
|
108
|
-
-
|
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
|
-
-
|
111
|
-
-
|
112
|
-
-
|
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/
|
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
|
-
-
|
122
|
-
- spec/
|
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
|
-
-
|
129
|
-
- spec/resources/
|
130
|
-
-
|
131
|
-
- spec/
|
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/
|
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/
|
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/
|
150
|
-
- spec/resources/
|
151
|
-
- spec/
|
152
|
-
-
|
153
|
-
-
|
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:
|
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:
|
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/
|
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
|
data/.bundle/config
DELETED