chunky_png 1.0.0.beta2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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.