chunky_png 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +6 -8
- data/chunky_png.gemspec +4 -4
- data/lib/chunky_png.rb +4 -2
- data/lib/chunky_png/canvas.rb +11 -1
- data/lib/chunky_png/canvas/drawing.rb +60 -0
- data/lib/chunky_png/canvas/png_encoding.rb +2 -1
- data/lib/chunky_png/chunk.rb +114 -4
- data/lib/chunky_png/color.rb +10 -1
- data/lib/chunky_png/datastream.rb +8 -7
- data/lib/chunky_png/rmagick.rb +1 -1
- data/spec/chunky_png/canvas/drawing_spec.rb +29 -0
- data/spec/resources/lines.png +0 -0
- metadata +5 -2
data/README.rdoc
CHANGED
@@ -16,7 +16,7 @@ Issue tracker:: http://github.com/wvanbergen/chunky_png/issues
|
|
16
16
|
color modes and all transparency, interlacing and filtering options.
|
17
17
|
* Encodes images supports all color modes (true color, grayscale and indexed)
|
18
18
|
and transparency for all these color modes. The best color mode will be
|
19
|
-
chosen automatically, based on the
|
19
|
+
chosen automatically, based on the amount of used colors.
|
20
20
|
* R/W access to the image's pixels.
|
21
21
|
* R/W access to all image metadata that is stored in chunks.
|
22
22
|
* Memory efficient (uses a Fixnum, i.e. 4 bytes of memory, per pixel)
|
@@ -26,12 +26,12 @@ Issue tracker:: http://github.com/wvanbergen/chunky_png/issues
|
|
26
26
|
|
27
27
|
== Classes
|
28
28
|
|
29
|
-
The main classes used within ChunkyPNG are:
|
29
|
+
The main classes and modules used within ChunkyPNG are:
|
30
30
|
|
31
31
|
<tt>ChunkyPNG::Image</tt> :: create PNG images from scratch or based on another PNG image.
|
32
32
|
<tt>ChunkyPNG::Datastream</tt> :: low-level read and write access to PNG images from or to a file or stream.
|
33
33
|
<tt>ChunkyPNG::Canvas</tt> :: represents an image canvas as a matrix of pixels.
|
34
|
-
<tt>ChunkyPNG::Color</tt> ::
|
34
|
+
<tt>ChunkyPNG::Color</tt> :: to handle Fixnums as color values.
|
35
35
|
|
36
36
|
== Usage
|
37
37
|
|
@@ -53,19 +53,17 @@ The main classes used within ChunkyPNG are:
|
|
53
53
|
image = ChunkyPNG::Image.from_file('with_metadata.png')
|
54
54
|
puts image.metadata['Title']
|
55
55
|
image.metadata['Author'] = 'Willem van Bergen'
|
56
|
-
image.save('with_metadata.png') # Overwrite
|
56
|
+
image.save('with_metadata.png') # Overwrite file
|
57
57
|
|
58
58
|
# Low level access to PNG chunks
|
59
59
|
png_stream = ChunkyPNG::Datastream.from_file('filename.png')
|
60
60
|
png_stream.each_chunk { |chunk| p chunk.type }
|
61
61
|
|
62
|
-
(Note: this is subject to change while work is in progress)
|
63
|
-
|
64
62
|
== About
|
65
63
|
|
66
64
|
The library is written by Willem van Bergen for Floorplanner.com, and released
|
67
65
|
under the MIT license (see LICENSE). Please contact me for questions or
|
68
|
-
remarks. Patches are greatly appreciated!
|
66
|
+
remarks. Patches are greatly appreciated!
|
69
67
|
|
70
68
|
P.S.: The name of this library is intentionally similar to Chunky Bacon and
|
71
|
-
Chunky GIF. Use Google if you want to know _why.
|
69
|
+
Chunky GIF. Use Google if you want to know _why. :-)
|
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.5.
|
7
|
-
s.date = "2010-01-
|
6
|
+
s.version = "0.5.4"
|
7
|
+
s.date = "2010-01-18"
|
8
8
|
|
9
9
|
s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
|
10
10
|
s.description = <<-EOT
|
@@ -32,6 +32,6 @@ Gem::Specification.new do |s|
|
|
32
32
|
|
33
33
|
# Do not change the files and test_files fields by hand. This will be done
|
34
34
|
# automatically by the gem release script.
|
35
|
-
s.files = %w(spec/spec_helper.rb spec/resources/ztxt_chunk.png spec/resources/text_chunk.png spec/resources/replaced.png spec/resources/pixelstream.rgb spec/resources/indexed_4bit.png spec/resources/gray_10x10_grayscale.png spec/resources/damaged_signature.png spec/resources/damaged_chunk.png spec/chunky_png/canvas/png_encoding_spec.rb lib/chunky_png/canvas/stream_exporting.rb spec/resources/gray_10x10.png lib/chunky_png/color.rb lib/chunky_png/canvas/operations.rb .gitignore spec/resources/gray_10x10_truecolor_alpha.png spec/chunky_png/canvas_spec.rb LICENSE spec/resources/gray_10x10_truecolor.png spec/resources/composited.png spec/chunky_png/color_spec.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb lib/chunky_png/chunk.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/adam7_interlacing.rb spec/resources/operations.png spec/chunky_png/canvas/png_decoding_spec.rb lib/chunky_png/canvas.rb Rakefile spec/resources/transparent_gray_10x10.png spec/resources/pixelstream.rgba spec/resources/cropped.png README.rdoc spec/resources/gray_10x10_indexed.png spec/resources/16x16_non_interlaced.png spec/chunky_png_spec.rb lib/chunky_png/palette.rb lib/chunky_png/datastream.rb chunky_png.gemspec tasks/github-gem.rake spec/resources/pixelstream_reference.png spec/resources/gray_10x10_grayscale_alpha.png spec/resources/16x16_interlaced.png spec/chunky_png/image_spec.rb lib/chunky_png/canvas/drawing.rb spec/resources/adam7.png lib/chunky_png/rmagick.rb lib/chunky_png/image.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/datastream_spec.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png.rb)
|
36
|
-
s.test_files = %w(spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/datastream_spec.rb)
|
35
|
+
s.files = %w(spec/spec_helper.rb spec/resources/ztxt_chunk.png spec/resources/text_chunk.png spec/resources/replaced.png spec/resources/pixelstream.rgb spec/resources/indexed_4bit.png spec/resources/gray_10x10_grayscale.png spec/resources/damaged_signature.png spec/resources/damaged_chunk.png spec/chunky_png/canvas/png_encoding_spec.rb lib/chunky_png/canvas/stream_exporting.rb spec/resources/gray_10x10.png lib/chunky_png/color.rb lib/chunky_png/canvas/operations.rb .gitignore spec/resources/gray_10x10_truecolor_alpha.png spec/chunky_png/canvas_spec.rb LICENSE spec/resources/gray_10x10_truecolor.png spec/resources/composited.png spec/chunky_png/color_spec.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb lib/chunky_png/chunk.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/adam7_interlacing.rb spec/resources/operations.png spec/chunky_png/canvas/png_decoding_spec.rb lib/chunky_png/canvas.rb Rakefile spec/resources/transparent_gray_10x10.png spec/resources/pixelstream.rgba spec/resources/cropped.png README.rdoc spec/resources/gray_10x10_indexed.png spec/resources/16x16_non_interlaced.png spec/chunky_png_spec.rb spec/chunky_png/canvas/drawing_spec.rb lib/chunky_png/palette.rb lib/chunky_png/datastream.rb chunky_png.gemspec tasks/github-gem.rake spec/resources/pixelstream_reference.png spec/resources/lines.png spec/resources/gray_10x10_grayscale_alpha.png spec/resources/16x16_interlaced.png spec/chunky_png/image_spec.rb lib/chunky_png/canvas/drawing.rb spec/resources/adam7.png lib/chunky_png/rmagick.rb lib/chunky_png/image.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/datastream_spec.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png.rb)
|
36
|
+
s.test_files = %w(spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/datastream_spec.rb)
|
37
37
|
end
|
data/lib/chunky_png.rb
CHANGED
@@ -16,15 +16,17 @@ require 'chunky_png/canvas/drawing'
|
|
16
16
|
require 'chunky_png/canvas'
|
17
17
|
require 'chunky_png/image'
|
18
18
|
|
19
|
-
# ChunkyPNG
|
19
|
+
# ChunkyPNG - the pury ruby library to access PNG files.
|
20
20
|
#
|
21
21
|
# The ChunkyPNG module defines some constants that are used in the
|
22
22
|
# PNG specification.
|
23
|
+
#
|
24
|
+
# @author Willem van Bergen
|
23
25
|
module ChunkyPNG
|
24
26
|
|
25
27
|
# The current version of ChunkyPNG. This value will be updated automatically
|
26
28
|
# by them gem:release rake task.
|
27
|
-
VERSION = "0.5.
|
29
|
+
VERSION = "0.5.4"
|
28
30
|
|
29
31
|
###################################################
|
30
32
|
# PNG international standard defined constants
|
data/lib/chunky_png/canvas.rb
CHANGED
@@ -108,6 +108,15 @@ module ChunkyPNG
|
|
108
108
|
def [](x, y)
|
109
109
|
@pixels[y * width + x]
|
110
110
|
end
|
111
|
+
|
112
|
+
# Checks whether the given coordinates are in the range of the canvas
|
113
|
+
# @param [Integer] x The x-coordinate of the pixel (column)
|
114
|
+
# @param [Integer] y The y-coordinate of the pixel (row)
|
115
|
+
# @return [true, false] True if the x and y coordinate are in the range
|
116
|
+
# of this canvas.
|
117
|
+
def include?(x, y)
|
118
|
+
(0...width).include?(x) && (0...height).include?(y)
|
119
|
+
end
|
111
120
|
|
112
121
|
# Returns the palette used for this canvas.
|
113
122
|
# @return [ChunkyPNG::Palette] A pallete which contains all the colors that are
|
@@ -131,7 +140,8 @@ module ChunkyPNG
|
|
131
140
|
# EXPORTING
|
132
141
|
#################################################################
|
133
142
|
|
134
|
-
# Creates an ChunkyPNG::Image object from this canvas
|
143
|
+
# Creates an ChunkyPNG::Image object from this canvas.
|
144
|
+
# @return [ChunkyPNG::Image] This canvas wrapped in an Image instance.
|
135
145
|
def to_image
|
136
146
|
ChunkyPNG::Image.from_canvas(self)
|
137
147
|
end
|
@@ -3,6 +3,66 @@ module ChunkyPNG
|
|
3
3
|
|
4
4
|
module Drawing
|
5
5
|
|
6
|
+
# Sets a point on the canvas by composing a pixel with its background color.
|
7
|
+
def point(x, y, color)
|
8
|
+
self[x, y] = ChunkyPNG::Color.compose(color, self[x, y])
|
9
|
+
end
|
10
|
+
|
11
|
+
# Draws an anti-aliased line using Xiaolin Wu's algorithm.
|
12
|
+
#
|
13
|
+
def line_xiaolin_wu(x0, y0, x1, y1, color)
|
14
|
+
y0, y1, x0, x1 = y1, y0, x1, x0 if y0 > y1
|
15
|
+
dx = x1 - x0
|
16
|
+
sx = dx < 0 ? -1 : 1
|
17
|
+
dx *= sx
|
18
|
+
dy = y1 - y0
|
19
|
+
|
20
|
+
if dy == 0 # vertical line
|
21
|
+
Range.new(*[x0,x1].sort).each do |x|
|
22
|
+
point(x, y0, color)
|
23
|
+
end
|
24
|
+
elsif dx == 0 # horizontal line
|
25
|
+
(y0..y1).each do |y|
|
26
|
+
point(x0, y, color)
|
27
|
+
end
|
28
|
+
elsif dx == dy # diagonal
|
29
|
+
x0.step(x1, sx) do |x|
|
30
|
+
point(x, y0, color)
|
31
|
+
y0 += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
elsif dy > dx # vertical displacement
|
35
|
+
point(x0, y0, color)
|
36
|
+
e_acc = 0
|
37
|
+
e = ((dx << 16) / dy.to_f).round
|
38
|
+
(y0...y1-1).each do |i|
|
39
|
+
e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xffff
|
40
|
+
x0 = x0 + sx if (e_acc <= e_acc_temp)
|
41
|
+
w = 0xff - (e_acc >> 8)
|
42
|
+
point(x0, y0, ChunkyPNG::Color.fade(color, w)) if include?(x0, y0)
|
43
|
+
y0 = y0 + 1
|
44
|
+
point(x0 + sx, y0, ChunkyPNG::Color.fade(color, 0xff - w)) if include?(x0 + sx, y0)
|
45
|
+
end
|
46
|
+
point(x1, y1, color)
|
47
|
+
|
48
|
+
else # horizontal displacement
|
49
|
+
point(x0, y0, color)
|
50
|
+
e_acc = 0
|
51
|
+
e = (dy << 16) / dx
|
52
|
+
(dx - 1).downto(0) do |i|
|
53
|
+
e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xffff
|
54
|
+
y0 += 1 if (e_acc <= e_acc_temp)
|
55
|
+
w = 0xff - (e_acc >> 8)
|
56
|
+
point(x0, y0, ChunkyPNG::Color.fade(color, w)) if include?(x0, y0)
|
57
|
+
x0 += sx
|
58
|
+
point(x0, y0 + 1, ChunkyPNG::Color.fade(color, 0xff - w)) if include?(x0, y0 + 1)
|
59
|
+
end
|
60
|
+
point(x1, y1, color)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
alias :line :line_xiaolin_wu
|
65
|
+
|
6
66
|
end
|
7
67
|
end
|
8
68
|
end
|
@@ -141,7 +141,8 @@ module ChunkyPNG
|
|
141
141
|
end
|
142
142
|
|
143
143
|
# Passes to this canvas of pixel values line by line.
|
144
|
-
# @yield [
|
144
|
+
# @yield [line] Yields the scanlines of this image one by one.
|
145
|
+
# @yieldparam [Array<Fixnum>] line An line of fixnums representing pixels
|
145
146
|
def each_scanline(&block)
|
146
147
|
for line_no in 0...height do
|
147
148
|
scanline = pixels[width * line_no, width]
|
data/lib/chunky_png/chunk.rb
CHANGED
@@ -9,6 +9,8 @@ module ChunkyPNG
|
|
9
9
|
# represented by the {ChunkyPNG::Chunk::Header} class. These specialized
|
10
10
|
# classes help accessing the content of the chunk. All other chunks are
|
11
11
|
# represented by the {ChunkyPNG::Chunk::Generic} class.
|
12
|
+
#
|
13
|
+
# @see ChunkyPNG::Datastream
|
12
14
|
module Chunk
|
13
15
|
|
14
16
|
# Reads a chunk from an IO stream.
|
@@ -37,37 +39,79 @@ module ChunkyPNG
|
|
37
39
|
raise "Chuck CRC mismatch!" if found_crc != expected_crc
|
38
40
|
end
|
39
41
|
|
42
|
+
# The base chunk class is the superclass for every chunk type. It contains
|
43
|
+
# methods to write the chunk to an output stream.
|
44
|
+
#
|
45
|
+
# A subclass should implement the +content+ method, which gets called when
|
46
|
+
# the chunk gets written to a PNG datastream
|
47
|
+
#
|
48
|
+
# @abstract
|
40
49
|
class Base
|
50
|
+
|
51
|
+
# The four-character type indicator for the chunk. This field is used to
|
52
|
+
# find the correct class for a chunk when it is loaded from a PNG stream.
|
53
|
+
# @return [String]
|
41
54
|
attr_accessor :type
|
42
55
|
|
56
|
+
# Initializes the chunk instance.
|
57
|
+
# @param [String] type The four character chunk type indicator.
|
58
|
+
# @param [Hash] attributes A hash of attributes to set on this chunk.
|
43
59
|
def initialize(type, attributes = {})
|
44
60
|
self.type = type
|
45
61
|
attributes.each { |k, v| send("#{k}=", v) }
|
46
62
|
end
|
47
63
|
|
64
|
+
# Writes the chunk to the IO stream, using the provided content.
|
65
|
+
# The checksum will be calculated and appended to the stream.
|
66
|
+
# @param [IO] io The IO stream to write to.
|
67
|
+
# @param [String] content The content for this chunk.
|
48
68
|
def write_with_crc(io, content)
|
49
69
|
io << [content.length].pack('N') << type << content
|
50
70
|
io << [Zlib.crc32(content, Zlib.crc32(type))].pack('N')
|
51
71
|
end
|
52
72
|
|
73
|
+
# Writes the chunk to the IO stream.
|
74
|
+
#
|
75
|
+
# It will call te +content+ method to get the content for this chunk,
|
76
|
+
# and will calculate and append the checksum automatically.
|
77
|
+
# @param [IO] io The IO stream to write to.
|
53
78
|
def write(io)
|
54
79
|
write_with_crc(io, content || '')
|
55
80
|
end
|
56
81
|
end
|
57
82
|
|
83
|
+
# The Generic chunk type will read the content from the chunk as it,
|
84
|
+
# and will write it back as it was read.
|
58
85
|
class Generic < Base
|
59
86
|
|
87
|
+
# The attribute to store the content from the chunk, which gets
|
88
|
+
# written by the +write+ method.
|
60
89
|
attr_accessor :content
|
61
90
|
|
91
|
+
|
62
92
|
def initialize(type, content = '')
|
63
93
|
super(type, :content => content)
|
64
94
|
end
|
65
95
|
|
96
|
+
# Creates an instance, given the chunk's type and content.
|
97
|
+
# @param [String] type The four character chunk type indicator.
|
98
|
+
# @param [String] content The content read from the chunk.
|
99
|
+
# @return [ChunkyPNG::Chunk::Generic] The new chunk instance.
|
66
100
|
def self.read(type, content)
|
67
101
|
self.new(type, content)
|
68
102
|
end
|
69
103
|
end
|
70
104
|
|
105
|
+
# The header (IHDR) chunk is the first chunk of every PNG image, and
|
106
|
+
# contains information about the image: i.e. its width, height, color
|
107
|
+
# depth, color mode, compression method, filtering method and interlace
|
108
|
+
# method.
|
109
|
+
#
|
110
|
+
# ChunkyPNG supports all values for these variables that are defined in
|
111
|
+
# the PNG spec, except for color depth: Only 8-bit depth images are
|
112
|
+
# supported. Note that it is still possible to access the chunk for such
|
113
|
+
# an image, but ChunkyPNG will raise an exception if you try to access
|
114
|
+
# the pixel data.
|
71
115
|
class Header < Base
|
72
116
|
|
73
117
|
attr_accessor :width, :height, :depth, :color, :compression, :filtering, :interlace
|
@@ -81,35 +125,63 @@ module ChunkyPNG
|
|
81
125
|
@interlace ||= ChunkyPNG::INTERLACING_NONE
|
82
126
|
end
|
83
127
|
|
128
|
+
# Reads the 13 bytes of content from the header chunk to set the image attributes.
|
129
|
+
# @param [String] type The four character chunk type indicator (= "IHDR").
|
130
|
+
# @param [String] content The 13 bytes of content read from the chunk.
|
131
|
+
# @return [ChunkyPNG::Chunk::End] The new Header chunk instance with the
|
132
|
+
# variables set to the values according to the content.
|
84
133
|
def self.read(type, content)
|
85
134
|
fields = content.unpack('NNC5')
|
86
135
|
self.new(:width => fields[0], :height => fields[1], :depth => fields[2], :color => fields[3],
|
87
136
|
:compression => fields[4], :filtering => fields[5], :interlace => fields[6])
|
88
137
|
end
|
89
138
|
|
139
|
+
# Returns the content for this chunk when it gets written to a file, by packing the
|
140
|
+
# image information variables into the correct format.
|
141
|
+
# @return [String] The 13-byte content for the header chunk.
|
90
142
|
def content
|
91
143
|
[width, height, depth, color, compression, filtering, interlace].pack('NNC5')
|
92
144
|
end
|
93
145
|
end
|
94
146
|
|
147
|
+
# The End (IEND) chunk indicates the last chunk of a PNG stream. It does not
|
148
|
+
# contain any data.
|
95
149
|
class End < Base
|
150
|
+
|
96
151
|
def initialize
|
97
152
|
super('IEND')
|
98
153
|
end
|
99
|
-
|
154
|
+
|
155
|
+
# Reads the END chunk. It will check if the content is empty.
|
156
|
+
# @param [String] type The four character chunk type indicator (= "IEND").
|
157
|
+
# @param [String] content The content read from the chunk. Should be empty.
|
158
|
+
# @return [ChunkyPNG::Chunk::End] The new End chunk instance.
|
159
|
+
# @raise [RuntimeError] Raises an exception if the content was not empty.
|
100
160
|
def self.read(type, content)
|
101
161
|
raise 'The IEND chunk should be empty!' if content != ''
|
102
162
|
self.new
|
103
163
|
end
|
104
164
|
|
165
|
+
# Returns an empty string, because this chunk should always be empty.
|
166
|
+
# @return [""] An empty string.
|
105
167
|
def content
|
106
168
|
''
|
107
169
|
end
|
108
170
|
end
|
109
171
|
|
172
|
+
# The Palette (PLTE) chunk contains the image's palette, i.e. the
|
173
|
+
# 8-bit RGB colors this image is using.
|
174
|
+
#
|
175
|
+
# @see ChunkyPNG::Chunk::Transparency
|
176
|
+
# @see ChunkyPNG::Palette
|
110
177
|
class Palette < Generic
|
111
178
|
end
|
112
179
|
|
180
|
+
# A transparency (tRNS) chunk contains the alpha channel for the colors
|
181
|
+
# defined in the Palette (PLTE) chunk
|
182
|
+
#
|
183
|
+
# @see ChunkyPNG::Chunk::Palette
|
184
|
+
# @see ChunkyPNG::Palette
|
113
185
|
class Transparency < Generic
|
114
186
|
end
|
115
187
|
|
@@ -126,6 +198,14 @@ module ChunkyPNG
|
|
126
198
|
end
|
127
199
|
end
|
128
200
|
|
201
|
+
# The Text (tEXt) chunk contains keyword/value metadata about the PNG stream.
|
202
|
+
# In this chunk, the value is stored uncompressed.
|
203
|
+
#
|
204
|
+
# The tEXt chunk only supports Latin-1 encoded textual data. If you need UTF-8
|
205
|
+
# support, check out the InternationalText chunk type.
|
206
|
+
#
|
207
|
+
# @see ChunkyPNG::Chunk::CompressedText
|
208
|
+
# @see ChunkyPNG::Chunk::InternationalText
|
129
209
|
class Text < Base
|
130
210
|
|
131
211
|
attr_accessor :keyword, :value
|
@@ -140,17 +220,27 @@ module ChunkyPNG
|
|
140
220
|
new(keyword, value)
|
141
221
|
end
|
142
222
|
|
223
|
+
# Creates the content to write to the stream, by concatenating the keyword
|
224
|
+
# with the value, joined by a null character.
|
225
|
+
#
|
226
|
+
# @return The content that should be written to the datastream.
|
143
227
|
def content
|
144
228
|
[keyword, value].pack('Z*a*')
|
145
229
|
end
|
146
230
|
end
|
147
231
|
|
232
|
+
# The CompressedText (zTXt) chunk contains keyword/value metadata about
|
233
|
+
# the PNG stream. In this chunk, the value is compressed using Deflate
|
234
|
+
# compression.
|
235
|
+
#
|
236
|
+
# @see ChunkyPNG::Chunk::CompressedText
|
237
|
+
# @see ChunkyPNG::Chunk::InternationalText
|
148
238
|
class CompressedText < Base
|
149
239
|
|
150
240
|
attr_accessor :keyword, :value
|
151
241
|
|
152
242
|
def initialize(keyword, value)
|
153
|
-
super('
|
243
|
+
super('zTXt')
|
154
244
|
@keyword, @value = keyword, value
|
155
245
|
end
|
156
246
|
|
@@ -160,17 +250,37 @@ module ChunkyPNG
|
|
160
250
|
new(keyword, Zlib::Inflate.inflate(value))
|
161
251
|
end
|
162
252
|
|
253
|
+
# Creates the content to write to the stream, by concatenating the keyword
|
254
|
+
# with the deflated value, joined by a null character.
|
255
|
+
#
|
256
|
+
# @return The content that should be written to the datastream.
|
163
257
|
def content
|
164
258
|
[keyword, ChunkyPNG::COMPRESSION_DEFAULT, Zlib::Deflate.deflate(value)].pack('Z*Ca*')
|
165
259
|
end
|
166
260
|
end
|
167
261
|
|
262
|
+
# The Text (iTXt) chunk contains keyword/value metadata about the PNG stream.
|
263
|
+
# The metadata in this chunk can be encoded using UTF-8 characters. Moreover,
|
264
|
+
# it is possible to define the language of the metadata, and give a translation
|
265
|
+
# of the keyword name. Finally, it supports bot compressed and uncompressed
|
266
|
+
# values.
|
267
|
+
#
|
268
|
+
# @todo This chunk is currently not implemented, but merely read and written
|
269
|
+
# back intact.
|
270
|
+
#
|
271
|
+
# @see ChunkyPNG::Chunk::Text
|
272
|
+
# @see ChunkyPNG::Chunk::CompressedText
|
168
273
|
class InternationalText < Generic
|
274
|
+
|
169
275
|
# TODO
|
170
276
|
end
|
171
277
|
|
172
|
-
# Maps chunk types to classes
|
173
|
-
#
|
278
|
+
# Maps chunk types to classes, based on the four byte chunk type indicator at the
|
279
|
+
# beginning of a chunk.
|
280
|
+
#
|
281
|
+
# If a chunk type is not specified in this hash, the Generic chunk type will be used.
|
282
|
+
#
|
283
|
+
# @see ChunkyPNG::Chunk.read
|
174
284
|
CHUNK_TYPES = {
|
175
285
|
'IHDR' => Header, 'IEND' => End, 'IDAT' => ImageData, 'PLTE' => Palette, 'tRNS' => Transparency,
|
176
286
|
'tEXt' => Text, 'zTXt' => CompressedText, 'iTXt' => InternationalText
|
data/lib/chunky_png/color.rb
CHANGED
@@ -46,7 +46,7 @@ module ChunkyPNG
|
|
46
46
|
def grayscale_alpha(teint, a)
|
47
47
|
teint << 24 | teint << 16 | teint << 8 | a
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
####################################################################
|
51
51
|
# COLOR IMPORTING
|
52
52
|
####################################################################
|
@@ -222,6 +222,15 @@ module ChunkyPNG
|
|
222
222
|
(fg + bg) >> 1
|
223
223
|
end
|
224
224
|
|
225
|
+
# Lowers the intensity of a color, by lowering its alpha by a given factor.
|
226
|
+
# @param [Fixnum] color The color to adjust.
|
227
|
+
# @param [Fixnum] factor Fade factor as an integer between 0 and 255.
|
228
|
+
# @return [Fixnum] The faded color.
|
229
|
+
def fade(color, factor)
|
230
|
+
new_alpha = int8_mult(a(color), factor)
|
231
|
+
(color & 0xffffff00) | new_alpha
|
232
|
+
end
|
233
|
+
|
225
234
|
####################################################################
|
226
235
|
# CONVERSIONS
|
227
236
|
####################################################################
|
@@ -44,9 +44,9 @@ module ChunkyPNG
|
|
44
44
|
@data_chunks = []
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
##############################################################################
|
48
48
|
# LOADING DATASTREAMS
|
49
|
-
|
49
|
+
##############################################################################
|
50
50
|
|
51
51
|
class << self
|
52
52
|
|
@@ -102,16 +102,17 @@ module ChunkyPNG
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
-
|
105
|
+
##################################################################################
|
106
106
|
# CHUNKS
|
107
|
-
|
107
|
+
##################################################################################
|
108
108
|
|
109
109
|
# Enumerates the chunks in this datastream.
|
110
110
|
#
|
111
111
|
# This will iterate over the chunks using the order in which the chunks
|
112
112
|
# should appear in the PNG file.
|
113
113
|
#
|
114
|
-
# @yield [
|
114
|
+
# @yield [chunk] Yields the chunks in this datastrean, one by one in the correct order.
|
115
|
+
# @yieldparam [ChunkyPNG::Chunk::Base] chunk A chunk in this datastream.
|
115
116
|
# @see ChunkyPNG::Datastream#chunks
|
116
117
|
def each_chunk
|
117
118
|
yield(header_chunk)
|
@@ -138,9 +139,9 @@ module ChunkyPNG
|
|
138
139
|
metadata
|
139
140
|
end
|
140
141
|
|
141
|
-
|
142
|
+
##################################################################################
|
142
143
|
# WRITING DATASTREAMS
|
143
|
-
|
144
|
+
##################################################################################
|
144
145
|
|
145
146
|
# Writes the datastream to the given output stream.
|
146
147
|
# @param [IO] io The output stream to write to.
|
data/lib/chunky_png/rmagick.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ChunkyPNG::Canvas::Drawing do
|
4
|
+
|
5
|
+
describe '#point' do
|
6
|
+
it "should compose colors correctly" do
|
7
|
+
canvas = ChunkyPNG::Canvas.new(1, 1, ChunkyPNG::Color.rgb(200, 150, 100))
|
8
|
+
canvas.point(0,0, ChunkyPNG::Color.rgba(100, 150, 200, 128))
|
9
|
+
canvas[0,0].should == ChunkyPNG::Color.rgb(150, 150, 150)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#line' do
|
14
|
+
it "should draw lines correctly with anti-aliasing" do
|
15
|
+
canvas = ChunkyPNG::Canvas.new(32, 32, ChunkyPNG::Color::WHITE)
|
16
|
+
|
17
|
+
canvas.line( 0, 0, 31, 31, ChunkyPNG::Color::BLACK)
|
18
|
+
canvas.line( 0, 31, 31, 0, ChunkyPNG::Color::BLACK)
|
19
|
+
canvas.line(15, 31, 15, 0, ChunkyPNG::Color.rgba(200, 0, 0, 128))
|
20
|
+
canvas.line( 0, 15, 31, 15, ChunkyPNG::Color.rgba(200, 0, 0, 128))
|
21
|
+
canvas.line( 0, 15, 31, 31, ChunkyPNG::Color.rgba( 0, 200, 0, 128))
|
22
|
+
canvas.line( 0, 15, 31, 0, ChunkyPNG::Color.rgba( 0, 200, 0, 128))
|
23
|
+
canvas.line(15, 0, 31, 31, ChunkyPNG::Color.rgba( 0, 0, 200, 128))
|
24
|
+
canvas.line(15, 0, 0, 31, ChunkyPNG::Color.rgba( 0, 0, 200, 128))
|
25
|
+
|
26
|
+
canvas.should == reference_canvas('lines')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chunky_png
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Willem van Bergen
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-18 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -69,11 +69,13 @@ files:
|
|
69
69
|
- spec/resources/gray_10x10_indexed.png
|
70
70
|
- spec/resources/16x16_non_interlaced.png
|
71
71
|
- spec/chunky_png_spec.rb
|
72
|
+
- spec/chunky_png/canvas/drawing_spec.rb
|
72
73
|
- lib/chunky_png/palette.rb
|
73
74
|
- lib/chunky_png/datastream.rb
|
74
75
|
- chunky_png.gemspec
|
75
76
|
- tasks/github-gem.rake
|
76
77
|
- spec/resources/pixelstream_reference.png
|
78
|
+
- spec/resources/lines.png
|
77
79
|
- spec/resources/gray_10x10_grayscale_alpha.png
|
78
80
|
- spec/resources/16x16_interlaced.png
|
79
81
|
- spec/chunky_png/image_spec.rb
|
@@ -125,6 +127,7 @@ test_files:
|
|
125
127
|
- spec/chunky_png/canvas/adam7_interlacing_spec.rb
|
126
128
|
- spec/chunky_png/canvas/png_decoding_spec.rb
|
127
129
|
- spec/chunky_png_spec.rb
|
130
|
+
- spec/chunky_png/canvas/drawing_spec.rb
|
128
131
|
- spec/chunky_png/image_spec.rb
|
129
132
|
- spec/chunky_png/rmagick_spec.rb
|
130
133
|
- spec/chunky_png/datastream_spec.rb
|