chunky_png 1.0.0.beta2 → 1.0.0.rc1

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.
Files changed (44) hide show
  1. data/.infinity_test +1 -1
  2. data/README.rdoc +2 -2
  3. data/chunky_png.gemspec +4 -4
  4. data/lib/chunky_png.rb +14 -8
  5. data/lib/chunky_png/canvas.rb +110 -38
  6. data/lib/chunky_png/canvas/drawing.rb +175 -34
  7. data/lib/chunky_png/canvas/masking.rb +91 -0
  8. data/lib/chunky_png/canvas/operations.rb +141 -112
  9. data/lib/chunky_png/canvas/png_decoding.rb +13 -13
  10. data/lib/chunky_png/canvas/resampling.rb +42 -0
  11. data/lib/chunky_png/color.rb +252 -11
  12. data/lib/chunky_png/compatibility.rb +5 -5
  13. data/lib/chunky_png/dimension.rb +106 -0
  14. data/lib/chunky_png/point.rb +110 -0
  15. data/lib/chunky_png/vector.rb +92 -0
  16. data/spec/chunky_png/canvas/drawing_spec.rb +107 -14
  17. data/spec/chunky_png/canvas/masking_spec.rb +51 -0
  18. data/spec/chunky_png/canvas/operations_spec.rb +142 -75
  19. data/spec/chunky_png/canvas/resampling_spec.rb +31 -0
  20. data/spec/chunky_png/canvas/stream_exporting_spec.rb +20 -0
  21. data/spec/chunky_png/canvas/stream_importing_spec.rb +22 -0
  22. data/spec/chunky_png/canvas_spec.rb +151 -22
  23. data/spec/chunky_png/color_spec.rb +53 -0
  24. data/spec/chunky_png/dimension_spec.rb +43 -0
  25. data/spec/chunky_png/point_spec.rb +71 -0
  26. data/spec/chunky_png/vector_spec.rb +58 -0
  27. data/spec/resources/circles.png +0 -0
  28. data/spec/resources/clock_nn_xdown_ydown.png +0 -0
  29. data/spec/resources/clock_nn_xdown_yup.png +0 -0
  30. data/spec/resources/clock_nn_xup_yup.png +0 -0
  31. data/spec/resources/lines.png +0 -0
  32. data/spec/resources/partial_circles.png +0 -0
  33. data/spec/resources/polygon_filled_horizontal.png +0 -0
  34. data/spec/resources/polygon_filled_vertical.png +0 -0
  35. data/spec/resources/polygon_triangle_filled.png +0 -0
  36. data/spec/resources/polygon_unfilled.png +0 -0
  37. data/spec/resources/rect.png +0 -0
  38. metadata +31 -9
  39. data/spec/resources/clock_flip_horizontally.png +0 -0
  40. data/spec/resources/clock_flip_vertically.png +0 -0
  41. data/spec/resources/clock_rotate_180.png +0 -0
  42. data/spec/resources/clock_rotate_left.png +0 -0
  43. data/spec/resources/clock_rotate_right.png +0 -0
  44. data/spec/resources/clock_stubbed.png +0 -0
@@ -0,0 +1,91 @@
1
+ module ChunkyPNG
2
+ class Canvas
3
+
4
+ # The ChunkyPNG::Canvas::Masking module defines methods to perform masking
5
+ # and theming oeprations on a {ChunkyPNG::Canvas}. The module is included into the Canvas class so all
6
+ # these methods are available on every canvas.
7
+ #
8
+ # @see ChunkyPNG::Canvas
9
+ module Masking
10
+
11
+ # Creates a new image, based on the current image but with a new theme color.
12
+ #
13
+ # This method will replace one color in an image with another image. This is done by
14
+ # first extracting the pixels with a color close to the original theme color as a mask
15
+ # image, changing the color of this mask image and then apply it on the original image.
16
+ #
17
+ # Mask extraction works best when the theme colored pixels are clearly distinguishable
18
+ # from a background color (preferably white). You can set a tolerance level to influence
19
+ # the extraction process.
20
+ #
21
+ # @param [Integer] old_theme_color The original theme color in this image.
22
+ # @param [Integer] new_theme_color The color to replace the old theme color with.
23
+ # @param [Integer] The backrgound color opn which the theme colored pixels are placed.
24
+ # @param [Integer] tolerance The tolerance level to use when extracting the mask image. Five is
25
+ # the default; increase this if the masked image does not extract all the required pixels,
26
+ # decrease it if too many pixels get extracted.
27
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the theme colored pixels changed.
28
+ # @see #change_theme_color!
29
+ # @see #change_mask_color!
30
+ def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
31
+ base, mask = extract_mask(old_theme_color, bg_color, tolerance)
32
+ mask.change_mask_color!(new_theme_color)
33
+ self.replace!(base.compose!(mask))
34
+ end
35
+
36
+ # Creates a base image and a mask image from an original image that has a particular theme color.
37
+ # This can be used to easily change a theme color in an image.
38
+ #
39
+ # It will extract all the pixels that look like the theme color (with a tolerance level) and put
40
+ # these in a mask image. All the other pixels will be stored in a base image. Both images will be
41
+ # of the exact same size as the original image. The original image will be left untouched.
42
+ #
43
+ # The color of the mask image can be changed with {#change_mask_color!}. This new mask image can
44
+ # then be composed upon the base image to create an image with a new theme color. A call to
45
+ # {#change_theme_color!} will perform this in one go.
46
+ #
47
+ # @param [Integer] mask_color The current theme color.
48
+ # @param [Integer] bg_color The background color on which the theme colored pxiels are applied.
49
+ # @param [Integer] tolerance The tolerance level to use when extracting the mask image. Five is
50
+ # the default; increase this if the masked image does not extract all the required pixels,
51
+ # decrease it if too many pixels get extracted.
52
+ # @return [Array<ChunkyPNG::Canvas, ChunkyPNG::Canvas>] An array with the base canvas and the mask
53
+ # canvas as elements.
54
+ # @see #change_theme_color!
55
+ # @see #change_mask_color!
56
+ def extract_mask(mask_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
57
+ base_pixels = []
58
+ mask_pixels = []
59
+
60
+ pixels.each do |pixel|
61
+ if ChunkyPNG::Color.alpha_decomposable?(pixel, mask_color, bg_color, tolerance)
62
+ mask_pixels << ChunkyPNG::Color.decompose_color(pixel, mask_color, bg_color, tolerance)
63
+ base_pixels << bg_color
64
+ else
65
+ mask_pixels << (mask_color & 0xffffff00)
66
+ base_pixels << pixel
67
+ end
68
+ end
69
+
70
+ [ self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels) ]
71
+ end
72
+
73
+ # Changes the color of a mask image.
74
+ #
75
+ # This method works on acanavs extracte out of another image using the {#extract_mask} method.
76
+ # It can then be applied on the extracted base image. See {#change_theme_color!} to perform
77
+ # these operations in one go.
78
+ #
79
+ # @param [Integer] new_color The color to replace the original mask color with.
80
+ # @raise [ChunkyPNG::ExpectationFailed] when this canvas is not a mask image, i.e. its palette
81
+ # has more than once color, disregarding transparency.
82
+ # @see #change_theme_color!
83
+ # @see #extract_mask
84
+ def change_mask_color!(new_color)
85
+ raise ChunkyPNG::ExpectationFailed, "This is not a mask image!" if palette.opaque_palette.size != 1
86
+ pixels.map! { |pixel| (new_color & 0xffffff00) | ChunkyPNG::Color.a(pixel) }
87
+ self
88
+ end
89
+ end
90
+ end
91
+ end
@@ -11,10 +11,11 @@ module ChunkyPNG
11
11
  # @see ChunkyPNG::Canvas
12
12
  module Operations
13
13
 
14
- # Composes another image onto this image using alpha blending.
14
+ # Composes another image onto this image using alpha blending. This will modify
15
+ # the current canvas.
15
16
  #
16
17
  # If you simply want to replace pixels or when the other image does not have
17
- # transparency, it is faster to use {#replace}.
18
+ # transparency, it is faster to use {#replace!}.
18
19
  #
19
20
  # @param [ChunkyPNG::Canvas] other The foreground canvas to compose on the
20
21
  # current canvas, using alpha compositing.
@@ -22,9 +23,10 @@ module ChunkyPNG
22
23
  # @param [Integer] offset_y The y-offset to apply the new forgeround on.
23
24
  # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas composed onto it.
24
25
  # @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)
26
+ # given the offset and size of the other canvas.
27
+ # @see #replace!
28
+ # @see #compose
29
+ def compose!(other, offset_x = 0, offset_y = 0)
28
30
  check_size_constraints!(other, offset_x, offset_y)
29
31
 
30
32
  for y in 0...other.height do
@@ -34,17 +36,41 @@ module ChunkyPNG
34
36
  end
35
37
  self
36
38
  end
37
-
39
+
40
+ # Composes another image onto this image using alpha blending. This will return
41
+ # a new canvas and leave the original intact.
42
+ #
43
+ # If you simply want to replace pixels or when the other image does not have
44
+ # transparency, it is faster to use {#replace}.
45
+ #
46
+ # @param (see #compose!)
47
+ # @return [ChunkyPNG::Canvas] Returns the new canvas, composed of the other 2.
48
+ # @raise [ChunkyPNG::OutOfBounds] when the other canvas doesn't fit on this one,
49
+ # given the offset and size of the other canvas.
50
+ #
51
+ # @note API changed since 1.0 - This method now no longer is in place, but returns
52
+ # a new canvas and leaves the original intact. Use {#compose!} if you want to
53
+ # compose on the canvas in place.
54
+ # @see #replace
55
+ def compose(other, offset_x = 0, offset_y = 0)
56
+ dup.compose!(other, offset_x, offset_y)
57
+ end
58
+
38
59
  # Replaces pixels on this image by pixels from another pixels, on a given offset.
60
+ # This method will modify the current canvas.
39
61
  #
40
62
  # 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}.
63
+ # them with semi-transparent pixels from the foreground image, see {#compose!}.
42
64
  #
43
- # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas composed onto it.
65
+ # @param [ChunkyPNG::Canvas] other The foreground canvas to get the pixels from.
66
+ # @param [Integer] offset_x The x-offset to apply the new forgeround on.
67
+ # @param [Integer] offset_y The y-offset to apply the new forgeround on.
68
+ # @return [ChunkyPNG::Canvas] Returns itself, but with the other canvas placed onto it.
44
69
  # @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
47
- def replace(other, offset_x = 0, offset_y = 0)
70
+ # given the offset and size of the other canvas.
71
+ # @see #compose!
72
+ # @see #replace
73
+ def replace!(other, offset_x = 0, offset_y = 0)
48
74
  check_size_constraints!(other, offset_x, offset_y)
49
75
 
50
76
  for y in 0...other.height do
@@ -53,6 +79,25 @@ module ChunkyPNG
53
79
  self
54
80
  end
55
81
 
82
+ # Replaces pixels on this image by pixels from another pixels, on a given offset.
83
+ # This method will modify the current canvas.
84
+ #
85
+ # This will completely replace the pixels of the background image. If you want to blend
86
+ # them with semi-transparent pixels from the foreground image, see {#compose!}.
87
+ #
88
+ # @param (see #replace!)
89
+ # @return [ChunkyPNG::Canvas] Returns a new, combined canvas.
90
+ # @raise [ChunkyPNG::OutOfBounds] when the other canvas doesn't fit on this one,
91
+ # given the offset and size of the other canvas.
92
+ #
93
+ # @note API changed since 1.0 - This method now no longer is in place, but returns
94
+ # a new canvas and leaves the original intact. Use {#replace!} if you want to
95
+ # replace pixels on the canvas in place.
96
+ # @see #compose
97
+ def replace(other, offset_x = 0, offset_y = 0)
98
+ dup.replace!(other, offset_x, offset_y)
99
+ end
100
+
56
101
  # Crops an image, given the coordinates and size of the image that needs to be cut out.
57
102
  # This will leave the original image intact and return a new, cropped image with pixels
58
103
  # copied from the original image.
@@ -76,125 +121,103 @@ module ChunkyPNG
76
121
  ChunkyPNG::Canvas.new(crop_width, crop_height, new_pixels)
77
122
  end
78
123
 
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!
98
- def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
99
- base, mask = extract_mask(old_theme_color, bg_color, tolerance)
100
- mask.change_mask_color!(new_theme_color)
101
- self.replace(base.compose(mask))
102
- end
103
-
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)
125
- base_pixels = []
126
- mask_pixels = []
127
-
128
- pixels.each do |pixel|
129
- if ChunkyPNG::Color.alpha_decomposable?(pixel, mask_color, bg_color, tolerance)
130
- mask_pixels << ChunkyPNG::Color.decompose_color(pixel, mask_color, bg_color, tolerance)
131
- base_pixels << bg_color
132
- else
133
- mask_pixels << (mask_color & 0xffffff00)
134
- base_pixels << pixel
135
- end
136
- end
124
+ # Crops an image, given the coordinates and size of the image that needs to be cut out.
125
+ #
126
+ # This will change the size and content of the current canvas. Use {#crop} if you want to
127
+ # have a new canvas returned instead, leaving the current canvas intact.
128
+ #
129
+ # @param [Integer] x The x-coordinate of the top left corner of the image to be cropped.
130
+ # @param [Integer] y The y-coordinate of the top left corner of the image to be cropped.
131
+ # @param [Integer] crop_width The width of the image to be cropped.
132
+ # @param [Integer] crop_height The height of the image to be cropped.
133
+ # @return [ChunkyPNG::Canvas] Returns itself, but cropped.
134
+ # @raise [ChunkyPNG::OutOfBounds] when the crop dimensions plus the given coordinates
135
+ # are bigger then the original image.
136
+ def crop!(x, y, crop_width, crop_height)
137
137
 
138
- [ self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels) ]
139
- end
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
152
- def change_mask_color!(new_color)
153
- raise ChunkyPNG::ExpectationFailed, "This is not a mask image!" if palette.opaque_palette.size != 1
154
- pixels.map! { |pixel| (new_color & 0xffffff00) | ChunkyPNG::Color.a(pixel) }
155
- self
138
+ raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_width + x > width
139
+ raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_height + y > height
140
+
141
+ new_pixels = []
142
+ for cy in 0...crop_height do
143
+ new_pixels += pixels.slice((cy + y) * width + x, crop_width)
144
+ end
145
+ replace_canvas!(crop_width, crop_height, new_pixels)
156
146
  end
157
147
 
158
- # Flips the image horizontally.
148
+ # Flips the image horizontally, leaving the original intact.
159
149
  #
160
150
  # This will flip the image on its horizontal axis, e.g. pixels on the top will now
161
151
  # be pixels on the bottom. Chaining this method twice will return the original canvas.
162
152
  # This method will leave the original object intact and return a new canvas.
163
153
  #
164
154
  # @return [ChunkyPNG::Canvas] The flipped image
155
+ # @see #flip_horizontally!
165
156
  def flip_horizontally
166
- self.class.new(width, height).tap do |flipped|
167
- for y in 0...height do
168
- flipped.replace_row!(height - (y + 1), row(y))
169
- end
157
+ dup.flip_horizontally!
158
+ end
159
+
160
+ # Flips the image horizontally in place.
161
+ #
162
+ # This will flip the image on its horizontal axis, e.g. pixels on the top will now
163
+ # be pixels on the bottom. Chaining this method twice will return the original canvas.
164
+ # This method will leave the original object intact and return a new canvas.
165
+ #
166
+ # @return [ChunkyPNG::Canvas] Itself, but flipped
167
+ # @see #flip_horizontally
168
+ def flip_horizontally!
169
+ for y in 0..((height - 1) >> 1) do
170
+ other_y = height - (y + 1)
171
+ other_row = row(other_y)
172
+ replace_row!(other_y, row(y))
173
+ replace_row!(y, other_row)
170
174
  end
175
+ return self
171
176
  end
172
177
 
173
- # Flips the image horizontally.
178
+ alias_method :flip!, :flip_horizontally!
179
+ alias_method :flip, :flip_horizontally
180
+
181
+ # Flips the image vertically, leaving the orginial intact.
174
182
  #
175
183
  # This will flip the image on its vertical axis, e.g. pixels on the left will now
176
184
  # be pixels on the right. Chaining this method twice will return the original canvas.
177
185
  # This method will leave the original object intact and return a new canvas.
178
186
  #
179
187
  # @return [ChunkyPNG::Canvas] The flipped image
188
+ # @see #flip_vertically!
180
189
  def flip_vertically
181
- self.class.new(width, height).tap do |flipped|
182
- for x in 0...width do
183
- flipped.replace_column!(width - (x + 1), column(x))
184
- end
190
+ dup.flip_vertically!
191
+ end
192
+
193
+ # Flips the image vertically in place.
194
+ #
195
+ # This will flip the image on its vertical axis, e.g. pixels on the left will now
196
+ # be pixels on the right. Chaining this method twice will return the original canvas.
197
+ # This method will leave the original object intact and return a new canvas.
198
+ #
199
+ # @return [ChunkyPNG::Canvas] Itself, but flipped
200
+ # @see #flip_vertically
201
+ def flip_vertically!
202
+ for y in 0...height do
203
+ replace_row!(y, row(y).reverse)
185
204
  end
205
+ return self
186
206
  end
207
+
208
+ alias_method :mirror!, :flip_vertically!
209
+ alias_method :mirror, :flip_vertically
187
210
 
188
211
  # Rotates the image 90 degrees clockwise.
189
212
  # This method will leave the original object intact and return a new canvas.
190
213
  #
191
214
  # @return [ChunkyPNG::Canvas] The rotated image
192
215
  def rotate_right
193
- self.class.new(height, width).tap do |rotated|
194
- for i in 0...width do
195
- rotated.replace_row!(i, column(i).reverse)
196
- end
216
+ rotated = self.class.new(height, width)
217
+ for i in 0...width do
218
+ rotated.replace_row!(i, column(i).reverse)
197
219
  end
220
+ return rotated
198
221
  end
199
222
 
200
223
  # Rotates the image 90 degrees counter-clockwise.
@@ -202,25 +225,31 @@ module ChunkyPNG
202
225
  #
203
226
  # @return [ChunkyPNG::Canvas] The rotated image.
204
227
  def rotate_left
205
- self.class.new(height, width).tap do |rotated|
206
- for i in 0...width do
207
- rotated.replace_row!(width - (i + 1), column(i))
208
- end
228
+ rotated = self.class.new(height, width)
229
+ for i in 0...width do
230
+ rotated.replace_row!(width - (i + 1), column(i))
209
231
  end
232
+ return rotated
210
233
  end
211
-
234
+
212
235
  # Rotates the image 180 degrees.
213
236
  # This method will leave the original object intact and return a new canvas.
214
237
  #
215
238
  # @return [ChunkyPNG::Canvas] The rotated image.
239
+ # @see #rotate_180!
216
240
  def rotate_180
217
- self.class.new(width, height).tap do |flipped|
218
- for y in 0...height do
219
- flipped.replace_row!(height - (y + 1), row(y).reverse)
220
- end
221
- end
241
+ dup.rotate_180!
222
242
  end
223
-
243
+
244
+ # Rotates the image 180 degrees in place.
245
+ #
246
+ # @return [ChunkyPNG::Canvas] Itself, but rotated 180 degrees.
247
+ # @see #rotate_180
248
+ def rotate_180!
249
+ pixels.reverse!
250
+ return self
251
+ end
252
+
224
253
  protected
225
254
 
226
255
  # Checks whether another image has the correct dimension to be used for an operation
@@ -251,12 +251,12 @@ module ChunkyPNG
251
251
  # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
252
252
  # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
253
253
  def decode_png_pixels_from_scanline_truecolor_alpha_16bit(stream, pos, width)
254
- [].tap do |pixels|
255
- stream.unpack("@#{pos + 1}n#{width * 4}").each_slice(4) do |r, g, b, a|
256
- pixels << ChunkyPNG::Color.rgba(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g),
257
- decode_png_resample_16bit_value(b), decode_png_resample_16bit_value(a))
258
- end
254
+ pixels = []
255
+ stream.unpack("@#{pos + 1}n#{width * 4}").each_slice(4) do |r, g, b, a|
256
+ pixels << ChunkyPNG::Color.rgba(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g),
257
+ decode_png_resample_16bit_value(b), decode_png_resample_16bit_value(a))
259
258
  end
259
+ return pixels
260
260
  end
261
261
 
262
262
  # Decodes a scanline of an 8-bit, true color image into a row of pixels.
@@ -270,11 +270,11 @@ module ChunkyPNG
270
270
  # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
271
271
  # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
272
272
  def decode_png_pixels_from_scanline_truecolor_16bit(stream, pos, width)
273
- [].tap do |pixels|
274
- stream.unpack("@#{pos + 1}n#{width * 3}").each_slice(3) do |r, g, b|
275
- pixels << ChunkyPNG::Color.rgb(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(b))
276
- end
273
+ pixels = []
274
+ stream.unpack("@#{pos + 1}n#{width * 3}").each_slice(3) do |r, g, b|
275
+ pixels << ChunkyPNG::Color.rgb(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(b))
277
276
  end
277
+ return pixels
278
278
  end
279
279
 
280
280
  # Decodes a scanline of an 8-bit, grayscale image with transparency into a row of pixels.
@@ -288,11 +288,11 @@ module ChunkyPNG
288
288
  # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
289
289
  # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
290
290
  def decode_png_pixels_from_scanline_grayscale_alpha_16bit(stream, pos, width)
291
- [].tap do |pixels|
292
- stream.unpack("@#{pos + 1}n#{width * 2}").each_slice(2) do |g, a|
293
- pixels << ChunkyPNG::Color.grayscale_alpha(decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(a))
294
- end
291
+ pixels = []
292
+ stream.unpack("@#{pos + 1}n#{width * 2}").each_slice(2) do |g, a|
293
+ pixels << ChunkyPNG::Color.grayscale_alpha(decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(a))
295
294
  end
295
+ return pixels
296
296
  end
297
297
 
298
298
  # Decodes a scanline of a 1-bit, grayscale image into a row of pixels.