chunky_png 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/chunky_png.gemspec
CHANGED
@@ -3,7 +3,7 @@ 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.
|
6
|
+
s.version = "0.5.1"
|
7
7
|
s.date = "2010-01-16"
|
8
8
|
|
9
9
|
s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
|
data/lib/chunky_png.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'zlib'
|
3
|
+
require 'stringio'
|
3
4
|
|
4
5
|
require 'chunky_png/datastream'
|
5
6
|
require 'chunky_png/chunk'
|
@@ -21,7 +22,7 @@ module ChunkyPNG
|
|
21
22
|
|
22
23
|
# The current version of ChunkyPNG. This value will be updated automatically
|
23
24
|
# by them gem:release rake task.
|
24
|
-
VERSION = "0.5.
|
25
|
+
VERSION = "0.5.1"
|
25
26
|
|
26
27
|
###################################################
|
27
28
|
# PNG international standard defined constants
|
data/lib/chunky_png/canvas.rb
CHANGED
@@ -54,7 +54,7 @@ module ChunkyPNG
|
|
54
54
|
if initial.kind_of?(Fixnum)
|
55
55
|
@pixels = Array.new(width * height, initial)
|
56
56
|
elsif initial.kind_of?(Array) && initial.size == width * height
|
57
|
-
@pixels = initial
|
57
|
+
@pixels = initial
|
58
58
|
else
|
59
59
|
raise "Cannot use this value as initial canvas: #{initial.inspect}!"
|
60
60
|
end
|
@@ -4,8 +4,8 @@ module ChunkyPNG
|
|
4
4
|
def compose(new_foreground, dx = 0, dy = 0)
|
5
5
|
check_size_constraints!(new_foreground, dx, dy)
|
6
6
|
|
7
|
-
new_foreground.height
|
8
|
-
new_foreground.width
|
7
|
+
for y in 0...new_foreground.height do
|
8
|
+
for x in 0...new_foreground.width do
|
9
9
|
self[x+dx, y+dy] = ChunkyPNG::Color.compose(new_foreground[x, y], self[x+dx, y+dy])
|
10
10
|
end
|
11
11
|
end
|
@@ -15,7 +15,7 @@ module ChunkyPNG
|
|
15
15
|
def replace(other, offset_x = 0, offset_y = 0)
|
16
16
|
check_size_constraints!(other, offset_x, offset_y)
|
17
17
|
|
18
|
-
other.height
|
18
|
+
for y in 0...other.height do
|
19
19
|
pixels[(y + offset_y) * width + offset_x, other.width] = other.pixels[y * other.width, other.width]
|
20
20
|
end
|
21
21
|
self
|
@@ -23,7 +23,7 @@ module ChunkyPNG
|
|
23
23
|
|
24
24
|
def crop(x, y, crop_width, crop_height)
|
25
25
|
new_pixels = []
|
26
|
-
crop_height
|
26
|
+
for cy in 0...crop_height do
|
27
27
|
new_pixels += pixels.slice((cy + y) * width + x, crop_width)
|
28
28
|
end
|
29
29
|
ChunkyPNG::Canvas.new(crop_width, crop_height, new_pixels)
|
@@ -5,6 +5,11 @@ module ChunkyPNG
|
|
5
5
|
#
|
6
6
|
module PNGEncoding
|
7
7
|
|
8
|
+
TRUECOLOR_ENCODER = lambda { |color| Color.to_truecolor_bytes(color) }
|
9
|
+
TRUECOLOR_ALPHA_ENCODER = lambda { |color| Color.to_truecolor_alpha_bytes(color) }
|
10
|
+
GRAYSCALE_ENCODER = lambda { |color| Color.to_grayscale_bytes(color) }
|
11
|
+
GRAYSCALE_ALPHA_ENCODER = lambda { |color| Color.to_grayscale_alpha_bytes(color) }
|
12
|
+
|
8
13
|
def write(io, constraints = {})
|
9
14
|
to_datastream(constraints).write(io)
|
10
15
|
end
|
@@ -50,9 +55,22 @@ module ChunkyPNG
|
|
50
55
|
end
|
51
56
|
|
52
57
|
def determine_png_encoding(constraints = {})
|
53
|
-
|
54
|
-
|
55
|
-
|
58
|
+
|
59
|
+
if constraints == :fast_rgb
|
60
|
+
encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR }
|
61
|
+
elsif constraints == :fast_rgba
|
62
|
+
encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA }
|
63
|
+
else
|
64
|
+
encoding = constraints
|
65
|
+
end
|
66
|
+
|
67
|
+
# Do not create a pallete when the encoding is given and does not require a palette.
|
68
|
+
if encoding[:color_mode]
|
69
|
+
encoding[:palette] ||= palette if encoding[:color_mode] == ChunkyPNG::COLOR_INDEXED
|
70
|
+
else
|
71
|
+
encoding[:palette] ||= palette
|
72
|
+
encoding[:color_mode] ||= encoding[:palette].best_colormode
|
73
|
+
end
|
56
74
|
|
57
75
|
encoding[:interlace] = case encoding[:interlace]
|
58
76
|
when nil, false, ChunkyPNG::INTERLACING_NONE then ChunkyPNG::INTERLACING_NONE
|
@@ -71,11 +89,11 @@ module ChunkyPNG
|
|
71
89
|
|
72
90
|
pixel_size = Color.bytesize(color_mode)
|
73
91
|
pixel_encoder = case color_mode
|
74
|
-
when ChunkyPNG::COLOR_TRUECOLOR then
|
75
|
-
when ChunkyPNG::COLOR_TRUECOLOR_ALPHA then
|
92
|
+
when ChunkyPNG::COLOR_TRUECOLOR then TRUECOLOR_ENCODER
|
93
|
+
when ChunkyPNG::COLOR_TRUECOLOR_ALPHA then TRUECOLOR_ALPHA_ENCODER
|
94
|
+
when ChunkyPNG::COLOR_GRAYSCALE then GRAYSCALE_ENCODER
|
95
|
+
when ChunkyPNG::COLOR_GRAYSCALE_ALPHA then GRAYSCALE_ALPHA_ENCODER
|
76
96
|
when ChunkyPNG::COLOR_INDEXED then lambda { |color| [palette.index(color)] }
|
77
|
-
when ChunkyPNG::COLOR_GRAYSCALE then lambda { |color| Color.to_grayscale_bytes(color) }
|
78
|
-
when ChunkyPNG::COLOR_GRAYSCALE_ALPHA then lambda { |color| Color.to_grayscale_alpha_bytes(color) }
|
79
97
|
else raise "Cannot encode pixels for this mode: #{color_mode}!"
|
80
98
|
end
|
81
99
|
|
@@ -102,19 +120,27 @@ module ChunkyPNG
|
|
102
120
|
end
|
103
121
|
|
104
122
|
def encode_png_image_pass_to_stream(stream, pixel_size, pixel_encoder)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
123
|
+
case pixel_encoder
|
124
|
+
when TRUECOLOR_ALPHA_ENCODER
|
125
|
+
stream << pixels.pack("xN#{width}" * height)
|
126
|
+
when TRUECOLOR_ENCODER
|
127
|
+
line_packer = 'x' + ('NX' * width)
|
128
|
+
stream << pixels.pack(line_packer * height)
|
129
|
+
else
|
130
|
+
previous_bytes = Array.new(pixel_size * width, 0)
|
131
|
+
each_scanline do |line|
|
132
|
+
unencoded_bytes = line.map(&pixel_encoder).flatten
|
133
|
+
stream << encode_png_scanline_up(unencoded_bytes, previous_bytes, pixel_size).pack('C*')
|
134
|
+
previous_bytes = unencoded_bytes
|
135
|
+
end
|
136
|
+
end
|
111
137
|
end
|
112
138
|
|
113
139
|
# Passes to this canvas of pixel values line by line.
|
114
140
|
# @yield [Array<Fixnum>] An line of fixnums reprsenting pixels
|
115
141
|
def each_scanline(&block)
|
116
|
-
height
|
117
|
-
scanline = pixels[width *
|
142
|
+
for line_no in 0...height do
|
143
|
+
scanline = pixels[width * line_no, width]
|
118
144
|
yield(scanline)
|
119
145
|
end
|
120
146
|
end
|
@@ -136,7 +162,7 @@ module ChunkyPNG
|
|
136
162
|
|
137
163
|
def encode_png_scanline_sub(original_bytes, previous_bytes = nil, pixelsize = 3)
|
138
164
|
encoded_bytes = []
|
139
|
-
original_bytes.length
|
165
|
+
for index in 0...original_bytes.length do
|
140
166
|
a = (index >= pixelsize) ? original_bytes[index - pixelsize] : 0
|
141
167
|
encoded_bytes[index] = (original_bytes[index] - a) % 256
|
142
168
|
end
|
@@ -145,7 +171,7 @@ module ChunkyPNG
|
|
145
171
|
|
146
172
|
def encode_png_scanline_up(original_bytes, previous_bytes, pixelsize = 3)
|
147
173
|
encoded_bytes = []
|
148
|
-
original_bytes.length
|
174
|
+
for index in 0...original_bytes.length do
|
149
175
|
b = previous_bytes[index]
|
150
176
|
encoded_bytes[index] = (original_bytes[index] - b) % 256
|
151
177
|
end
|
@@ -154,7 +180,7 @@ module ChunkyPNG
|
|
154
180
|
|
155
181
|
def encode_png_scanline_average(original_bytes, previous_bytes, pixelsize = 3)
|
156
182
|
encoded_bytes = []
|
157
|
-
original_bytes.length
|
183
|
+
for index in 0...original_bytes.length do
|
158
184
|
a = (index >= pixelsize) ? original_bytes[index - pixelsize] : 0
|
159
185
|
b = previous_bytes[index]
|
160
186
|
encoded_bytes[index] = (original_bytes[index] - (a + b / 2).floor) % 256
|
@@ -164,7 +190,7 @@ module ChunkyPNG
|
|
164
190
|
|
165
191
|
def encode_png_scanline_paeth(original_bytes, previous_bytes, pixelsize = 3)
|
166
192
|
encoded_bytes = []
|
167
|
-
original_bytes.length
|
193
|
+
for i in 0...original_bytes.length do
|
168
194
|
a = (i >= pixelsize) ? original_bytes[i - pixelsize] : 0
|
169
195
|
b = previous_bytes[i]
|
170
196
|
c = (i >= pixelsize) ? previous_bytes[i - pixelsize] : 0
|