chunky_png 1.3.5 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +13 -0
- data/LICENSE +1 -1
- data/README.md +88 -0
- data/benchmarks/filesize_benchmark.rb +1 -1
- data/chunky_png.gemspec +1 -1
- data/lib/chunky_png.rb +2 -2
- data/lib/chunky_png/canvas/drawing.rb +4 -4
- data/lib/chunky_png/canvas/operations.rb +0 -1
- data/lib/chunky_png/canvas/png_decoding.rb +36 -36
- data/lib/chunky_png/color.rb +1 -1
- data/lib/chunky_png/datastream.rb +1 -1
- data/lib/chunky_png/version.rb +1 -1
- data/spec/chunky_png/datastream_spec.rb +6 -0
- data/spec/resources/trailing_bytes_after_iend_chunk.png +0 -0
- metadata +7 -5
- data/README.rdoc +0 -84
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fcd13f536104dcb74ae0a6ab6f4c32fe743b62d0
|
|
4
|
+
data.tar.gz: dfbfd7a772203855d816b00650b2c0559392588c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5eaa5acf93abd3766ff83a825552c879396c8a61cc0f9f72ee1b4904cbd38f4e4f33caf98d1968cae748c30140f6d65f0f10453ed34c001b9a2cda37bf76ab66
|
|
7
|
+
data.tar.gz: 184f7559e6cabfe646b6c18cc1cb9d33c5f67b64f204deb30ceb264c0143959fbea27e34630521f3a84fe9d8fff59579fabc2ad96fe15577e6e10eb898f22272
|
data/CHANGELOG.rdoc
CHANGED
|
@@ -9,6 +9,19 @@ The file documents the changes to this library over the different versions.
|
|
|
9
9
|
|
|
10
10
|
- Nothing yet!
|
|
11
11
|
|
|
12
|
+
=== 1.3.6 - 2016-06-19
|
|
13
|
+
|
|
14
|
+
- Allow reading images from streams that have trailing data after the IEND chunk.
|
|
15
|
+
- Add compatibility for Ruby 2.3's frozen string literals.
|
|
16
|
+
- Documentation updates and small cleanups.
|
|
17
|
+
|
|
18
|
+
=== 1.3.5 - 2015-10-28
|
|
19
|
+
|
|
20
|
+
- Performance improvements for <tt>Canvas#crop!</tt> and <tt>ImageData.combine_chunks</tt>
|
|
21
|
+
- Update <tt>chunky_png/rmagick</tt> to work with the latest versions of RMagick.
|
|
22
|
+
- Bugfix in <tt>Color#from_hsl</tt> and <tt>Color#from_hsv</tt> when hue value is 360.
|
|
23
|
+
- Fix encoding issue in <tt>Datastream#to_blob</tt>
|
|
24
|
+
|
|
12
25
|
=== 1.3.4 - 2015-02-16
|
|
13
26
|
|
|
14
27
|
- Assert compatibility with Ruby 2.2
|
data/LICENSE
CHANGED
data/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ChunkyPNG [](https://travis-ci.org/wvanbergen/chunky_png)
|
|
2
|
+
|
|
3
|
+
This library can read and write PNG files. It is written in pure Ruby for
|
|
4
|
+
maximum portability. Let me rephrase: it does NOT require RMagick or any other
|
|
5
|
+
memory leaking image library.
|
|
6
|
+
|
|
7
|
+
- [Source code](http://github.com/wvanbergen/chunky_png/tree)
|
|
8
|
+
- [RDoc](http://rdoc.info/gems/chunky_png/frames)
|
|
9
|
+
- [Wiki](http://github.com/wvanbergen/chunky_png/wiki)
|
|
10
|
+
- [Issue tracker](http://github.com/wvanbergen/chunky_png/issues)
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- Decodes any image that the PNG standard allows. This includes all standard
|
|
15
|
+
color modes, all bit depths, all transparency, and interlacing and filtering
|
|
16
|
+
options.
|
|
17
|
+
- Encodes images supports all color modes (true color, grayscale, and indexed)
|
|
18
|
+
and transparency for all these color modes. The best color mode will be
|
|
19
|
+
chosen automatically, based on the amount of used colors.
|
|
20
|
+
- R/W access to the image's pixels.
|
|
21
|
+
- R/W access to all image metadata that is stored in chunks.
|
|
22
|
+
- Memory efficient (uses a Fixnum, i.e. 4 or 8 bytes of memory per pixel,
|
|
23
|
+
depending on the hardware)
|
|
24
|
+
- Reasonably fast for Ruby standards, by only using integer math and a highly
|
|
25
|
+
optimized saving routine.
|
|
26
|
+
- Interoperability with RMagick if you really have to.
|
|
27
|
+
|
|
28
|
+
Also, have a look at [OilyPNG](http://github.com/wvanbergen/oily_png) which
|
|
29
|
+
is a mixin module that implements some of the ChunkyPNG algorithms in C, which
|
|
30
|
+
provides a massive speed boost to encoding and decoding.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
require 'chunky_png'
|
|
36
|
+
|
|
37
|
+
# Creating an image from scratch, save as an interlaced PNG
|
|
38
|
+
png = ChunkyPNG::Image.new(16, 16, ChunkyPNG::Color::TRANSPARENT)
|
|
39
|
+
png[1,1] = ChunkyPNG::Color.rgba(10, 20, 30, 128)
|
|
40
|
+
png[2,1] = ChunkyPNG::Color('black @ 0.5')
|
|
41
|
+
png.save('filename.png', :interlace => true)
|
|
42
|
+
|
|
43
|
+
# Compose images using alpha blending.
|
|
44
|
+
avatar = ChunkyPNG::Image.from_file('avatar.png')
|
|
45
|
+
badge = ChunkyPNG::Image.from_file('no_ie_badge.png')
|
|
46
|
+
avatar.compose!(badge, 10, 10)
|
|
47
|
+
avatar.save('composited.png', :fast_rgba) # Force the fast saving routine.
|
|
48
|
+
|
|
49
|
+
# Accessing metadata
|
|
50
|
+
image = ChunkyPNG::Image.from_file('with_metadata.png')
|
|
51
|
+
puts image.metadata['Title']
|
|
52
|
+
image.metadata['Author'] = 'Willem van Bergen'
|
|
53
|
+
image.save('with_metadata.png') # Overwrite file
|
|
54
|
+
|
|
55
|
+
# Low level access to PNG chunks
|
|
56
|
+
png_stream = ChunkyPNG::Datastream.from_file('filename.png')
|
|
57
|
+
png_stream.each_chunk { |chunk| p chunk.type }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Also check out the screencast on the ChunkyPNG homepage by John Davison,
|
|
61
|
+
which illustrates basic usage of the library on the [ChunkyPNG
|
|
62
|
+
website](http://chunkypng.com/).
|
|
63
|
+
|
|
64
|
+
For more information, see the [project
|
|
65
|
+
wiki](https://github.com/wvanbergen/chunky_png/wiki) or the [RDOC
|
|
66
|
+
documentation](http://www.rubydoc.info/gems/chunky_png/frames).
|
|
67
|
+
|
|
68
|
+
## Security warning
|
|
69
|
+
|
|
70
|
+
ChunkyPNG is vulnerable to decompression bombs, which means that ChunkyPNG is
|
|
71
|
+
vulnerable to DOS attacks by running out of memory when loading a specifically
|
|
72
|
+
crafted PNG file. Because of the pure-Ruby nature of the library it is very hard
|
|
73
|
+
to fix this problem in the library itself.
|
|
74
|
+
|
|
75
|
+
In order to safely deal with untrusted images, you should make sure to do the
|
|
76
|
+
image processing using ChunkyPNG in a separate process, e.g. by using fork or a
|
|
77
|
+
background processing library.
|
|
78
|
+
|
|
79
|
+
## About
|
|
80
|
+
|
|
81
|
+
The library is written by Willem van Bergen for Floorplanner.com, and released
|
|
82
|
+
under the MIT license (see LICENSE). Please contact me for questions or
|
|
83
|
+
remarks. Patches are greatly appreciated!
|
|
84
|
+
|
|
85
|
+
Please check out CHANGELOG.rdoc to see what changed in all versions.
|
|
86
|
+
|
|
87
|
+
P.S.: The name of this library is intentionally similar to Chunky Bacon and
|
|
88
|
+
Chunky GIF. Use Google if you want to know _why_. :-)
|
|
@@ -4,7 +4,7 @@ require 'bundler/setup'
|
|
|
4
4
|
require 'benchmark'
|
|
5
5
|
require 'chunky_png'
|
|
6
6
|
|
|
7
|
-
files = ['pixelstream_reference.png', 'operations.png', '
|
|
7
|
+
files = ['pixelstream_reference.png', 'operations.png', 'clock.png']
|
|
8
8
|
|
|
9
9
|
def encode_png(image, constraints = {})
|
|
10
10
|
filesize = nil
|
data/chunky_png.gemspec
CHANGED
|
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
|
|
|
40
40
|
s.add_development_dependency('rspec', '~> 3')
|
|
41
41
|
|
|
42
42
|
s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
|
|
43
|
-
s.extra_rdoc_files = ['README.
|
|
43
|
+
s.extra_rdoc_files = ['README.md', 'BENCHMARKING.rdoc', 'CONTRIBUTING.rdoc', 'CHANGELOG.rdoc']
|
|
44
44
|
|
|
45
45
|
s.files = `git ls-files`.split($/)
|
|
46
46
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
data/lib/chunky_png.rb
CHANGED
|
@@ -129,12 +129,12 @@ module ChunkyPNG
|
|
|
129
129
|
# set correctly to ASCII-8BIT (binary) in Ruby 1.9.
|
|
130
130
|
# @return [String] An empty string, with encoding set to binary in Ruby 1.9
|
|
131
131
|
# @private
|
|
132
|
-
EMPTY_BYTEARRAY = force_binary(
|
|
132
|
+
EMPTY_BYTEARRAY = force_binary(String.new).freeze
|
|
133
133
|
|
|
134
134
|
# Null-byte, with the encoding set correctly to ASCII-8BIT (binary) in Ruby 1.9.
|
|
135
135
|
# @return [String] A binary string, consisting of one NULL-byte.
|
|
136
136
|
# @private
|
|
137
|
-
EXTRA_BYTE = force_binary("\0").freeze
|
|
137
|
+
EXTRA_BYTE = force_binary(String.new("\0")).freeze
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
require 'chunky_png/version'
|
|
@@ -299,12 +299,12 @@ module ChunkyPNG
|
|
|
299
299
|
end
|
|
300
300
|
|
|
301
301
|
unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
|
302
|
-
lines.each_with_index do |length,
|
|
302
|
+
lines.each_with_index do |length, y_offset|
|
|
303
303
|
if length > 0
|
|
304
|
-
line(x0 - length, y0 -
|
|
304
|
+
line(x0 - length, y0 - y_offset, x0 + length, y0 - y_offset, fill_color)
|
|
305
305
|
end
|
|
306
|
-
if length > 0 &&
|
|
307
|
-
line(x0 - length, y0 +
|
|
306
|
+
if length > 0 && y_offset > 0
|
|
307
|
+
line(x0 - length, y0 + y_offset, x0 + length, y0 + y_offset, fill_color)
|
|
308
308
|
end
|
|
309
309
|
end
|
|
310
310
|
end
|
|
@@ -273,7 +273,6 @@ module ChunkyPNG
|
|
|
273
273
|
# @return [ChunkyPNG::Canvas] Itself, but rotated clockwise.
|
|
274
274
|
# @see #rotate_right for a version that leaves the current canvas intact
|
|
275
275
|
def rotate_right!
|
|
276
|
-
rotated = self.class.new(height, width)
|
|
277
276
|
new_pixels = []
|
|
278
277
|
0.upto(width - 1) { |i| new_pixels += column(i).reverse }
|
|
279
278
|
replace_canvas!(height, width, new_pixels)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module ChunkyPNG
|
|
2
2
|
class Canvas
|
|
3
3
|
|
|
4
|
-
# The PNGDecoding contains methods for decoding PNG datastreams to create a
|
|
5
|
-
# Canvas object. The datastream can be provided as filename, string or IO
|
|
4
|
+
# The PNGDecoding contains methods for decoding PNG datastreams to create a
|
|
5
|
+
# Canvas object. The datastream can be provided as filename, string or IO
|
|
6
6
|
# stream.
|
|
7
7
|
#
|
|
8
8
|
# Overview of the decoding process:
|
|
@@ -22,7 +22,7 @@ module ChunkyPNG
|
|
|
22
22
|
# * All lines combined to form the original image.
|
|
23
23
|
#
|
|
24
24
|
# For interlaced images, the original image was split into 7 subimages.
|
|
25
|
-
# These images get decoded just like the process above (from step 3), and get
|
|
25
|
+
# These images get decoded just like the process above (from step 3), and get
|
|
26
26
|
# combined to form the original images.
|
|
27
27
|
#
|
|
28
28
|
# @see ChunkyPNG::Canvas::PNGEncoding
|
|
@@ -33,7 +33,7 @@ module ChunkyPNG
|
|
|
33
33
|
# tRNS chunk from the PNG stream. For RGB(A) images, no palette is required.
|
|
34
34
|
# @return [ChunkyPNG::Palette]
|
|
35
35
|
attr_accessor :decoding_palette
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
# The color to be replaced with fully transparent pixels.
|
|
38
38
|
attr_accessor :transparent_color
|
|
39
39
|
|
|
@@ -84,11 +84,11 @@ module ChunkyPNG
|
|
|
84
84
|
when ChunkyPNG::COLOR_GRAYSCALE
|
|
85
85
|
self.transparent_color = ds.transparency_chunk.grayscale_entry(depth) if ds.transparency_chunk
|
|
86
86
|
end
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
decode_png_pixelstream(ds.imagedata, width, height, color_mode, depth, interlace)
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
-
# Decodes a canvas from a PNG encoded pixelstream, using a given width, height,
|
|
91
|
+
# Decodes a canvas from a PNG encoded pixelstream, using a given width, height,
|
|
92
92
|
# color mode and interlacing mode.
|
|
93
93
|
# @param [String] stream The pixelstream to read from.
|
|
94
94
|
# @param [Integer] width The width of the image.
|
|
@@ -105,14 +105,14 @@ module ChunkyPNG
|
|
|
105
105
|
when ChunkyPNG::INTERLACING_ADAM7; decode_png_with_adam7_interlacing(stream, width, height, color_mode, depth)
|
|
106
106
|
else raise ChunkyPNG::NotSupported, "Don't know how the handle interlacing method #{interlace}!"
|
|
107
107
|
end
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
image.pixels.map! { |c| c == transparent_color ? ChunkyPNG::Color::TRANSPARENT : c } if transparent_color
|
|
110
110
|
return image
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
protected
|
|
114
114
|
|
|
115
|
-
# Decodes a canvas from a non-interlaced PNG encoded pixelstream, using a
|
|
115
|
+
# Decodes a canvas from a non-interlaced PNG encoded pixelstream, using a
|
|
116
116
|
# given width, height and color mode.
|
|
117
117
|
# @param stream (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
|
|
118
118
|
# @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
|
|
@@ -124,7 +124,7 @@ module ChunkyPNG
|
|
|
124
124
|
decode_png_image_pass(stream, width, height, color_mode, depth, 0)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
-
# Decodes a canvas from a Adam 7 interlaced PNG encoded pixelstream, using a
|
|
127
|
+
# Decodes a canvas from a Adam 7 interlaced PNG encoded pixelstream, using a
|
|
128
128
|
# given width, height and color mode.
|
|
129
129
|
# @param stream (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
|
|
130
130
|
# @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
|
|
@@ -143,19 +143,19 @@ module ChunkyPNG
|
|
|
143
143
|
end
|
|
144
144
|
canvas
|
|
145
145
|
end
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
# Extract 4 consecutive bits from a byte.
|
|
148
148
|
# @param [Integer] byte The byte (0..255) value to extract a 4 bit value from.
|
|
149
|
-
# @param [Integer] index The index within the byte. This should be either 0 or 2;
|
|
149
|
+
# @param [Integer] index The index within the byte. This should be either 0 or 2;
|
|
150
150
|
# the value will be modded by 2 to enforce this.
|
|
151
151
|
# @return [Integer] The extracted 4bit value (0..15)
|
|
152
152
|
def decode_png_extract_4bit_value(byte, index)
|
|
153
153
|
(index & 0x01 == 0) ? ((byte & 0xf0) >> 4) : (byte & 0x0f)
|
|
154
154
|
end
|
|
155
|
-
|
|
155
|
+
|
|
156
156
|
# Extract 2 consecutive bits from a byte.
|
|
157
157
|
# @param [Integer] byte The byte (0..255) value to extract a 2 bit value from.
|
|
158
|
-
# @param [Integer] index The index within the byte. This should be either 0, 1, 2, or 3;
|
|
158
|
+
# @param [Integer] index The index within the byte. This should be either 0, 1, 2, or 3;
|
|
159
159
|
# the value will be modded by 4 to enforce this.
|
|
160
160
|
# @return [Integer] The extracted 2 bit value (0..3)
|
|
161
161
|
def decode_png_extract_2bit_value(byte, index)
|
|
@@ -165,49 +165,49 @@ module ChunkyPNG
|
|
|
165
165
|
|
|
166
166
|
# Extract a bit from a byte on a given index.
|
|
167
167
|
# @param [Integer] byte The byte (0..255) value to extract a bit from.
|
|
168
|
-
# @param [Integer] index The index within the byte. This should be 0..7;
|
|
168
|
+
# @param [Integer] index The index within the byte. This should be 0..7;
|
|
169
169
|
# the value will be modded by 8 to enforce this.
|
|
170
170
|
# @return [Integer] Either 1 or 0.
|
|
171
171
|
def decode_png_extract_1bit_value(byte, index)
|
|
172
172
|
bitshift = 7 - (index & 0x07)
|
|
173
173
|
(byte & (0x01 << bitshift)) >> bitshift
|
|
174
174
|
end
|
|
175
|
-
|
|
175
|
+
|
|
176
176
|
# Resamples a 16 bit value to an 8 bit value. This will discard some color information.
|
|
177
177
|
# @param [Integer] value The 16 bit value to resample.
|
|
178
178
|
# @return [Integer] The 8 bit resampled value
|
|
179
179
|
def decode_png_resample_16bit_value(value)
|
|
180
180
|
value >> 8
|
|
181
181
|
end
|
|
182
|
-
|
|
182
|
+
|
|
183
183
|
# No-op - available for completeness sake only
|
|
184
184
|
# @param [Integer] value The 8 bit value to resample.
|
|
185
185
|
# @return [Integer] The 8 bit resampled value
|
|
186
186
|
def decode_png_resample_8bit_value(value)
|
|
187
187
|
value
|
|
188
188
|
end
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
# Resamples a 4 bit value to an 8 bit value.
|
|
191
191
|
# @param [Integer] value The 4 bit value to resample.
|
|
192
192
|
# @return [Integer] The 8 bit resampled value.
|
|
193
193
|
def decode_png_resample_4bit_value(value)
|
|
194
194
|
value << 4 | value
|
|
195
195
|
end
|
|
196
|
-
|
|
196
|
+
|
|
197
197
|
# Resamples a 2 bit value to an 8 bit value.
|
|
198
198
|
# @param [Integer] value The 2 bit value to resample.
|
|
199
199
|
# @return [Integer] The 8 bit resampled value.
|
|
200
200
|
def decode_png_resample_2bit_value(value)
|
|
201
201
|
value << 6 | value << 4 | value << 2 | value
|
|
202
202
|
end
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
# Resamples a 1 bit value to an 8 bit value.
|
|
205
205
|
# @param [Integer] value The 1 bit value to resample.
|
|
206
206
|
# @return [Integer] The 8 bit resampled value
|
|
207
207
|
def decode_png_resample_1bit_value(value)
|
|
208
208
|
value == 0x01 ? 0xff : 0x00
|
|
209
209
|
end
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
|
|
212
212
|
# Decodes a scanline of a 1-bit, indexed image into a row of pixels.
|
|
213
213
|
# @param [String] stream The stream to decode from.
|
|
@@ -216,7 +216,7 @@ module ChunkyPNG
|
|
|
216
216
|
# @return [Array<Integer>] An array of decoded pixels.
|
|
217
217
|
def decode_png_pixels_from_scanline_indexed_1bit(stream, pos, width)
|
|
218
218
|
(0...width).map do |index|
|
|
219
|
-
palette_pos = decode_png_extract_1bit_value(stream.getbyte(pos + 1 + (index >> 3)), index)
|
|
219
|
+
palette_pos = decode_png_extract_1bit_value(stream.getbyte(pos + 1 + (index >> 3)), index)
|
|
220
220
|
decoding_palette[palette_pos]
|
|
221
221
|
end
|
|
222
222
|
end
|
|
@@ -266,14 +266,14 @@ module ChunkyPNG
|
|
|
266
266
|
end
|
|
267
267
|
return pixels
|
|
268
268
|
end
|
|
269
|
-
|
|
269
|
+
|
|
270
270
|
# Decodes a scanline of an 8-bit, true color image into a row of pixels.
|
|
271
271
|
# @params (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
272
272
|
# @return (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
273
273
|
def decode_png_pixels_from_scanline_truecolor_8bit(stream, pos, width)
|
|
274
274
|
stream.unpack("@#{pos + 1}" << ('NX' * width)).map { |c| c | 0x000000ff }
|
|
275
275
|
end
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
# Decodes a scanline of a 16-bit, true color image into a row of pixels.
|
|
278
278
|
# @params (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
279
279
|
# @return (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
@@ -291,7 +291,7 @@ module ChunkyPNG
|
|
|
291
291
|
def decode_png_pixels_from_scanline_grayscale_alpha_8bit(stream, pos, width)
|
|
292
292
|
(0...width).map { |i| ChunkyPNG::Color.grayscale_alpha(stream.getbyte(pos + (i * 2) + 1), stream.getbyte(pos + (i * 2) + 2)) }
|
|
293
293
|
end
|
|
294
|
-
|
|
294
|
+
|
|
295
295
|
# Decodes a scanline of a 16-bit, grayscale image with transparency into a row of pixels.
|
|
296
296
|
# @params (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
297
297
|
# @return (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
@@ -332,14 +332,14 @@ module ChunkyPNG
|
|
|
332
332
|
ChunkyPNG::Color.grayscale(decode_png_resample_4bit_value(value))
|
|
333
333
|
end
|
|
334
334
|
end
|
|
335
|
-
|
|
335
|
+
|
|
336
336
|
# Decodes a scanline of an 8-bit, grayscale image into a row of pixels.
|
|
337
337
|
# @params (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
338
338
|
# @return (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
339
339
|
def decode_png_pixels_from_scanline_grayscale_8bit(stream, pos, width)
|
|
340
340
|
(1..width).map { |i| ChunkyPNG::Color.grayscale(stream.getbyte(pos + i)) }
|
|
341
341
|
end
|
|
342
|
-
|
|
342
|
+
|
|
343
343
|
# Decodes a scanline of a 16-bit, grayscale image into a row of pixels.
|
|
344
344
|
# @params (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
345
345
|
# @return (see #decode_png_pixels_from_scanline_indexed_1bit)
|
|
@@ -347,7 +347,7 @@ module ChunkyPNG
|
|
|
347
347
|
values = stream.unpack("@#{pos + 1}n#{width}")
|
|
348
348
|
values.map { |value| ChunkyPNG::Color.grayscale(decode_png_resample_16bit_value(value)) }
|
|
349
349
|
end
|
|
350
|
-
|
|
350
|
+
|
|
351
351
|
# Returns the method name to use to decode scanlines into pixels.
|
|
352
352
|
# @param [Integer] color_mode The color mode of the image.
|
|
353
353
|
# @param [Integer] depth The bit depth of the image.
|
|
@@ -362,12 +362,12 @@ module ChunkyPNG
|
|
|
362
362
|
when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; :"decode_png_pixels_from_scanline_grayscale_alpha_#{depth}bit"
|
|
363
363
|
else nil
|
|
364
364
|
end
|
|
365
|
-
|
|
365
|
+
|
|
366
366
|
raise ChunkyPNG::NotSupported, "No decoder found for color mode #{color_mode} and #{depth}-bit depth!" unless respond_to?(decoder_method, true)
|
|
367
367
|
decoder_method
|
|
368
368
|
end
|
|
369
369
|
|
|
370
|
-
# Decodes a single PNG image pass width a given width, height and color
|
|
370
|
+
# Decodes a single PNG image pass width a given width, height and color
|
|
371
371
|
# mode, to a Canvas, starting at the given position in the stream.
|
|
372
372
|
#
|
|
373
373
|
# A non-interlaced image only consists of one pass, while an Adam7
|
|
@@ -380,21 +380,21 @@ module ChunkyPNG
|
|
|
380
380
|
# @param [Integer] start_pos The position in the pixel stream to start reading.
|
|
381
381
|
# @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
|
|
382
382
|
def decode_png_image_pass(stream, width, height, color_mode, depth, start_pos)
|
|
383
|
-
|
|
383
|
+
|
|
384
384
|
pixels = []
|
|
385
385
|
if width > 0 && height > 0
|
|
386
|
-
|
|
386
|
+
|
|
387
387
|
stream << ChunkyPNG::EXTRA_BYTE if color_mode == ChunkyPNG::COLOR_TRUECOLOR
|
|
388
388
|
pixel_decoder = decode_png_pixels_from_scanline_method(color_mode, depth)
|
|
389
389
|
line_length = ChunkyPNG::Color.scanline_bytesize(color_mode, depth, width)
|
|
390
390
|
pixel_size = ChunkyPNG::Color.pixel_bytesize(color_mode, depth)
|
|
391
|
-
|
|
391
|
+
|
|
392
392
|
raise ChunkyPNG::ExpectationFailed, "Invalid stream length!" unless stream.bytesize - start_pos >= ChunkyPNG::Color.pass_bytesize(color_mode, depth, width, height)
|
|
393
393
|
|
|
394
394
|
pos, prev_pos = start_pos, nil
|
|
395
|
-
for
|
|
395
|
+
for _ in 0...height do
|
|
396
396
|
decode_png_str_scanline(stream, pos, prev_pos, line_length, pixel_size)
|
|
397
|
-
pixels
|
|
397
|
+
pixels.concat(send(pixel_decoder, stream, pos, width))
|
|
398
398
|
|
|
399
399
|
prev_pos = pos
|
|
400
400
|
pos += line_length + 1
|
|
@@ -404,9 +404,9 @@ module ChunkyPNG
|
|
|
404
404
|
new(width, height, pixels)
|
|
405
405
|
end
|
|
406
406
|
|
|
407
|
-
# Decodes a scanline if it was encoded using filtering.
|
|
407
|
+
# Decodes a scanline if it was encoded using filtering.
|
|
408
408
|
#
|
|
409
|
-
# It will extract the filtering method from the first byte of the scanline, and uses the
|
|
409
|
+
# It will extract the filtering method from the first byte of the scanline, and uses the
|
|
410
410
|
# method to change the subsequent bytes to unfiltered values. This will modify the pixelstream.
|
|
411
411
|
#
|
|
412
412
|
# The bytes of the scanline can then be used to construct pixels, based on the color mode..
|
data/lib/chunky_png/color.rb
CHANGED
|
@@ -589,7 +589,7 @@ module ChunkyPNG
|
|
|
589
589
|
# include_alpha=true (0-255)
|
|
590
590
|
# @see http://en.wikipedia.org/wiki/HSL_and_HSV
|
|
591
591
|
def to_hsv(color, include_alpha = false)
|
|
592
|
-
hue, chroma, max,
|
|
592
|
+
hue, chroma, max, _ = hue_and_chroma(color)
|
|
593
593
|
value = max
|
|
594
594
|
saturation = chroma.zero? ? 0.0 : chroma.fdiv(value)
|
|
595
595
|
|
data/lib/chunky_png/version.rb
CHANGED
|
@@ -17,6 +17,12 @@ describe ChunkyPNG::Datastream do
|
|
|
17
17
|
stream = StringIO.new
|
|
18
18
|
expect { ChunkyPNG::Datastream.from_io(stream) }.to raise_error(ChunkyPNG::SignatureMismatch)
|
|
19
19
|
end
|
|
20
|
+
|
|
21
|
+
it "should read a stream with trailing data without failing" do
|
|
22
|
+
filename = resource_file('trailing_bytes_after_iend_chunk.png')
|
|
23
|
+
image = ChunkyPNG::Datastream.from_file(filename)
|
|
24
|
+
expect(image).to be_instance_of(ChunkyPNG::Datastream)
|
|
25
|
+
end
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
describe '#metadata' do
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chunky_png
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Willem van Bergen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2016-06-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -60,7 +60,7 @@ email:
|
|
|
60
60
|
executables: []
|
|
61
61
|
extensions: []
|
|
62
62
|
extra_rdoc_files:
|
|
63
|
-
- README.
|
|
63
|
+
- README.md
|
|
64
64
|
- BENCHMARKING.rdoc
|
|
65
65
|
- CONTRIBUTING.rdoc
|
|
66
66
|
- CHANGELOG.rdoc
|
|
@@ -73,7 +73,7 @@ files:
|
|
|
73
73
|
- CONTRIBUTING.rdoc
|
|
74
74
|
- Gemfile
|
|
75
75
|
- LICENSE
|
|
76
|
-
- README.
|
|
76
|
+
- README.md
|
|
77
77
|
- Rakefile
|
|
78
78
|
- benchmarks/decoding_benchmark.rb
|
|
79
79
|
- benchmarks/encoding_benchmark.rb
|
|
@@ -384,6 +384,7 @@ files:
|
|
|
384
384
|
- spec/resources/rect.png
|
|
385
385
|
- spec/resources/replaced.png
|
|
386
386
|
- spec/resources/text_chunk.png
|
|
387
|
+
- spec/resources/trailing_bytes_after_iend_chunk.png
|
|
387
388
|
- spec/resources/ztxt_chunk.png
|
|
388
389
|
- spec/spec_helper.rb
|
|
389
390
|
- tasks/benchmarks.rake
|
|
@@ -413,7 +414,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
413
414
|
version: '0'
|
|
414
415
|
requirements: []
|
|
415
416
|
rubyforge_project:
|
|
416
|
-
rubygems_version: 2.0.14
|
|
417
|
+
rubygems_version: 2.0.14.1
|
|
417
418
|
signing_key:
|
|
418
419
|
specification_version: 4
|
|
419
420
|
summary: Pure ruby library for read/write, chunk-level access to PNG files
|
|
@@ -699,5 +700,6 @@ test_files:
|
|
|
699
700
|
- spec/resources/rect.png
|
|
700
701
|
- spec/resources/replaced.png
|
|
701
702
|
- spec/resources/text_chunk.png
|
|
703
|
+
- spec/resources/trailing_bytes_after_iend_chunk.png
|
|
702
704
|
- spec/resources/ztxt_chunk.png
|
|
703
705
|
- spec/spec_helper.rb
|
data/README.rdoc
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
= Chunky PNG {<img src="https://travis-ci.org/wvanbergen/chunky_png.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/wvanbergen/chunky_png]
|
|
2
|
-
|
|
3
|
-
This library can read and write PNG files. It is written in pure Ruby for
|
|
4
|
-
maximum portability. Let me rephrase: it does NOT require RMagick or any other
|
|
5
|
-
memory leaking image library.
|
|
6
|
-
|
|
7
|
-
Source code:: http://github.com/wvanbergen/chunky_png/tree
|
|
8
|
-
RDoc:: http://rdoc.info/gems/chunky_png/frames
|
|
9
|
-
Wiki:: http://github.com/wvanbergen/chunky_png/wiki
|
|
10
|
-
Issue tracker:: http://github.com/wvanbergen/chunky_png/issues
|
|
11
|
-
|
|
12
|
-
== Features
|
|
13
|
-
|
|
14
|
-
* Decodes any image that the PNG standard allows. This includes all standard
|
|
15
|
-
color modes, all bit depths and all transparency, interlacing and filtering options.
|
|
16
|
-
* Encodes images supports all color modes (true color, grayscale and indexed)
|
|
17
|
-
and transparency for all these color modes. The best color mode will be
|
|
18
|
-
chosen automatically, based on the amount of used colors.
|
|
19
|
-
* R/W access to the image's pixels.
|
|
20
|
-
* R/W access to all image metadata that is stored in chunks.
|
|
21
|
-
* Memory efficient (uses a Fixnum, i.e. 4 or 8 bytes of memory per pixel, depending
|
|
22
|
-
on the hardware)
|
|
23
|
-
* Reasonably fast for Ruby standards, by only using integer math and a highly
|
|
24
|
-
optimized saving routine.
|
|
25
|
-
* Interoperability with RMagick if you really have to.
|
|
26
|
-
|
|
27
|
-
Also, have a look at OilyPNG at http://github.com/wvanbergen/oily_png. OilyPNG is a
|
|
28
|
-
mixin module that implements some of the ChunkyPNG algorithms in C, which
|
|
29
|
-
provides a massive speed boost to encoding and decoding.
|
|
30
|
-
|
|
31
|
-
== Usage
|
|
32
|
-
|
|
33
|
-
require 'chunky_png'
|
|
34
|
-
|
|
35
|
-
# Creating an image from scratch, save as an interlaced PNG
|
|
36
|
-
png = ChunkyPNG::Image.new(16, 16, ChunkyPNG::Color::TRANSPARENT)
|
|
37
|
-
png[1,1] = ChunkyPNG::Color.rgba(10, 20, 30, 128)
|
|
38
|
-
png[2,1] = ChunkyPNG::Color('black @ 0.5')
|
|
39
|
-
png.save('filename.png', :interlace => true)
|
|
40
|
-
|
|
41
|
-
# Compose images using alpha blending.
|
|
42
|
-
avatar = ChunkyPNG::Image.from_file('avatar.png')
|
|
43
|
-
badge = ChunkyPNG::Image.from_file('no_ie_badge.png')
|
|
44
|
-
avatar.compose!(badge, 10, 10)
|
|
45
|
-
avatar.save('composited.png', :fast_rgba) # Force the fast saving routine.
|
|
46
|
-
|
|
47
|
-
# Accessing metadata
|
|
48
|
-
image = ChunkyPNG::Image.from_file('with_metadata.png')
|
|
49
|
-
puts image.metadata['Title']
|
|
50
|
-
image.metadata['Author'] = 'Willem van Bergen'
|
|
51
|
-
image.save('with_metadata.png') # Overwrite file
|
|
52
|
-
|
|
53
|
-
# Low level access to PNG chunks
|
|
54
|
-
png_stream = ChunkyPNG::Datastream.from_file('filename.png')
|
|
55
|
-
png_stream.each_chunk { |chunk| p chunk.type }
|
|
56
|
-
|
|
57
|
-
Also check out the screencast on the ChunkyPNG homepage by John Davison,
|
|
58
|
-
which illustrates basic usage of the library on the ChunkyPNG website:
|
|
59
|
-
http://chunkypng.com/
|
|
60
|
-
|
|
61
|
-
For more information, see the project wiki on https://github.com/wvanbergen/chunky_png/wiki
|
|
62
|
-
or the RDOC documentation on http://www.rubydoc.info/gems/chunky_png/frames
|
|
63
|
-
|
|
64
|
-
== Security warning
|
|
65
|
-
|
|
66
|
-
ChunkyPNG is vulnerable to decompression bombs, which means that ChunkyPNG is vulnerable to
|
|
67
|
-
DOS attacks by running out of memory when loading a specifically crafted PNG file. Because
|
|
68
|
-
of the pure-Ruby nature of the library it is very hard to fix this problem in the library
|
|
69
|
-
itself.
|
|
70
|
-
|
|
71
|
-
In order to safely deal with untrusted images, you should make sure to do the image
|
|
72
|
-
processing using ChunkyPNG in a separate process, e.g. by using fork or a background
|
|
73
|
-
processing library.
|
|
74
|
-
|
|
75
|
-
== About
|
|
76
|
-
|
|
77
|
-
The library is written by Willem van Bergen for Floorplanner.com, and released
|
|
78
|
-
under the MIT license (see LICENSE). Please contact me for questions or
|
|
79
|
-
remarks. Patches are greatly appreciated!
|
|
80
|
-
|
|
81
|
-
Please check out CHANGELOG.rdoc to see what changed in all versions.
|
|
82
|
-
|
|
83
|
-
P.S.: The name of this library is intentionally similar to Chunky Bacon and
|
|
84
|
-
Chunky GIF. Use Google if you want to know _why. :-)
|