chunky_png 1.3.11 → 1.3.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +35 -0
- data/.standard.yml +16 -0
- data/.yardopts +1 -1
- data/CHANGELOG.rdoc +8 -4
- data/CONTRIBUTING.rdoc +17 -8
- data/Gemfile +15 -3
- data/LICENSE +1 -1
- data/README.md +15 -9
- data/Rakefile +5 -3
- data/benchmarks/decoding_benchmark.rb +17 -17
- data/benchmarks/encoding_benchmark.rb +22 -19
- data/benchmarks/filesize_benchmark.rb +6 -6
- data/bin/rake +29 -0
- data/bin/standardrb +29 -0
- data/chunky_png.gemspec +17 -15
- data/docs/.gitignore +3 -0
- data/docs/CNAME +1 -0
- data/docs/_config.yml +9 -0
- data/docs/_posts/2010-01-14-memory-efficiency-when-using-ruby.md +136 -0
- data/docs/_posts/2010-01-17-ode-to-array-pack-and-string-unpack.md +82 -0
- data/docs/_posts/2014-11-07-the-value-of-a-pure-ruby-library.md +61 -0
- data/docs/index.md +88 -0
- data/lib/chunky_png.rb +17 -30
- data/lib/chunky_png/canvas.rb +31 -28
- data/lib/chunky_png/canvas/adam7_interlacing.rb +16 -10
- data/lib/chunky_png/canvas/data_url_exporting.rb +3 -3
- data/lib/chunky_png/canvas/data_url_importing.rb +3 -3
- data/lib/chunky_png/canvas/drawing.rb +30 -43
- data/lib/chunky_png/canvas/masking.rb +14 -14
- data/lib/chunky_png/canvas/operations.rb +28 -24
- data/lib/chunky_png/canvas/png_decoding.rb +39 -33
- data/lib/chunky_png/canvas/png_encoding.rb +111 -103
- data/lib/chunky_png/canvas/resampling.rb +27 -32
- data/lib/chunky_png/canvas/stream_exporting.rb +8 -8
- data/lib/chunky_png/canvas/stream_importing.rb +8 -8
- data/lib/chunky_png/chunk.rb +101 -66
- data/lib/chunky_png/color.rb +218 -212
- data/lib/chunky_png/datastream.rb +22 -28
- data/lib/chunky_png/dimension.rb +18 -11
- data/lib/chunky_png/image.rb +11 -11
- data/lib/chunky_png/palette.rb +6 -9
- data/lib/chunky_png/point.rb +27 -26
- data/lib/chunky_png/rmagick.rb +10 -10
- data/lib/chunky_png/vector.rb +28 -29
- data/lib/chunky_png/version.rb +3 -1
- data/spec/chunky_png/canvas/adam7_interlacing_spec.rb +20 -21
- data/spec/chunky_png/canvas/data_url_exporting_spec.rb +8 -5
- data/spec/chunky_png/canvas/data_url_importing_spec.rb +5 -6
- data/spec/chunky_png/canvas/drawing_spec.rb +46 -38
- data/spec/chunky_png/canvas/masking_spec.rb +15 -16
- data/spec/chunky_png/canvas/operations_spec.rb +68 -67
- data/spec/chunky_png/canvas/png_decoding_spec.rb +37 -38
- data/spec/chunky_png/canvas/png_encoding_spec.rb +59 -50
- data/spec/chunky_png/canvas/resampling_spec.rb +19 -21
- data/spec/chunky_png/canvas/stream_exporting_spec.rb +47 -27
- data/spec/chunky_png/canvas/stream_importing_spec.rb +10 -11
- data/spec/chunky_png/canvas_spec.rb +63 -52
- data/spec/chunky_png/color_spec.rb +115 -114
- data/spec/chunky_png/datastream_spec.rb +49 -51
- data/spec/chunky_png/dimension_spec.rb +10 -10
- data/spec/chunky_png/image_spec.rb +11 -14
- data/spec/chunky_png/point_spec.rb +21 -23
- data/spec/chunky_png/rmagick_spec.rb +7 -8
- data/spec/chunky_png/vector_spec.rb +21 -17
- data/spec/chunky_png_spec.rb +2 -2
- data/spec/png_suite_spec.rb +35 -40
- data/spec/spec_helper.rb +6 -10
- data/tasks/benchmarks.rake +7 -8
- metadata +46 -10
- data/.travis.yml +0 -18
- data/lib/chunky_png/compatibility.rb +0 -15
data/lib/chunky_png/canvas.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require "chunky_png/canvas/png_encoding"
|
4
|
+
require "chunky_png/canvas/png_decoding"
|
5
|
+
require "chunky_png/canvas/adam7_interlacing"
|
6
|
+
require "chunky_png/canvas/stream_exporting"
|
7
|
+
require "chunky_png/canvas/stream_importing"
|
8
|
+
require "chunky_png/canvas/data_url_exporting"
|
9
|
+
require "chunky_png/canvas/data_url_importing"
|
10
|
+
require "chunky_png/canvas/operations"
|
11
|
+
require "chunky_png/canvas/drawing"
|
12
|
+
require "chunky_png/canvas/resampling"
|
13
|
+
require "chunky_png/canvas/masking"
|
12
14
|
|
13
15
|
module ChunkyPNG
|
14
16
|
# The ChunkyPNG::Canvas class represents a raster image as a matrix of
|
@@ -56,7 +58,6 @@ module ChunkyPNG
|
|
56
58
|
# This array always should have +width * height+ elements.
|
57
59
|
attr_reader :pixels
|
58
60
|
|
59
|
-
|
60
61
|
#################################################################
|
61
62
|
# CONSTRUCTORS
|
62
63
|
#################################################################
|
@@ -68,7 +69,7 @@ module ChunkyPNG
|
|
68
69
|
# @param [Integer] height The height in pixels of this canvas
|
69
70
|
# @param [Integer, ...] background_color The initial background color of
|
70
71
|
# this canvas. This can be a color value or any value that
|
71
|
-
# {ChunkyPNG::Color
|
72
|
+
# {ChunkyPNG::Color#parse} can handle.
|
72
73
|
#
|
73
74
|
# @overload initialize(width, height, initial)
|
74
75
|
# @param [Integer] width The width in pixels of this canvas
|
@@ -78,9 +79,10 @@ module ChunkyPNG
|
|
78
79
|
def initialize(width, height, initial = ChunkyPNG::Color::TRANSPARENT)
|
79
80
|
@width, @height = width, height
|
80
81
|
|
81
|
-
if initial.
|
82
|
-
|
83
|
-
|
82
|
+
if initial.is_a?(Array)
|
83
|
+
pixel_count = width * height
|
84
|
+
unless initial.length == pixel_count
|
85
|
+
raise ArgumentError, "The initial array should have #{width}x#{height} = #{pixel_count} elements!"
|
84
86
|
end
|
85
87
|
@pixels = initial
|
86
88
|
else
|
@@ -104,7 +106,6 @@ module ChunkyPNG
|
|
104
106
|
new(canvas.width, canvas.height, canvas.pixels.dup)
|
105
107
|
end
|
106
108
|
|
107
|
-
|
108
109
|
#################################################################
|
109
110
|
# PROPERTIES
|
110
111
|
#################################################################
|
@@ -143,7 +144,7 @@ module ChunkyPNG
|
|
143
144
|
#
|
144
145
|
# @param [Integer] x The x-coordinate of the pixel (column)
|
145
146
|
# @param [Integer] y The y-coordinate of the pixel (row)
|
146
|
-
# @param [Integer]
|
147
|
+
# @param [Integer] color The new color for the provided coordinates.
|
147
148
|
# @return [Integer] The new color value for this pixel, i.e.
|
148
149
|
# <tt>color</tt>.
|
149
150
|
def set_pixel(x, y, color)
|
@@ -155,7 +156,7 @@ module ChunkyPNG
|
|
155
156
|
#
|
156
157
|
# @param [Integer] x The x-coordinate of the pixel (column)
|
157
158
|
# @param [Integer] y The y-coordinate of the pixel (row)
|
158
|
-
# @param [Integer]
|
159
|
+
# @param [Integer] color The new color value for the provided coordinates.
|
159
160
|
# @return [Integer] The new color value for this pixel, i.e.
|
160
161
|
# <tt>color</tt>, or <tt>nil</tt> if the coordinates are out of bounds.
|
161
162
|
def set_pixel_if_within_bounds(x, y, color)
|
@@ -233,7 +234,7 @@ module ChunkyPNG
|
|
233
234
|
dimension.include?(ChunkyPNG::Point(*point_like))
|
234
235
|
end
|
235
236
|
|
236
|
-
|
237
|
+
alias include? include_point?
|
237
238
|
|
238
239
|
# Checks whether the given x- and y-coordinate are in the range of the
|
239
240
|
# canvas
|
@@ -274,11 +275,13 @@ module ChunkyPNG
|
|
274
275
|
# @return [true, false] True if the size and pixel values of the other
|
275
276
|
# canvas are exactly the same as this canvas's size and pixel values.
|
276
277
|
def eql?(other)
|
277
|
-
other.
|
278
|
-
|
278
|
+
other.is_a?(self.class) &&
|
279
|
+
other.pixels == pixels &&
|
280
|
+
other.width == width &&
|
281
|
+
other.height == height
|
279
282
|
end
|
280
283
|
|
281
|
-
alias
|
284
|
+
alias == eql?
|
282
285
|
|
283
286
|
#################################################################
|
284
287
|
# EXPORTING
|
@@ -294,9 +297,9 @@ module ChunkyPNG
|
|
294
297
|
# @return [String] A nicely formatted string representation of this canvas.
|
295
298
|
# @private
|
296
299
|
def inspect
|
297
|
-
inspected = "<#{self.class.name} #{width}x#{height} ["
|
300
|
+
inspected = +"<#{self.class.name} #{width}x#{height} ["
|
298
301
|
for y in 0...height
|
299
|
-
inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(
|
302
|
+
inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(" ") << "]"
|
300
303
|
end
|
301
304
|
inspected << "\n]>"
|
302
305
|
end
|
@@ -358,13 +361,13 @@ module ChunkyPNG
|
|
358
361
|
|
359
362
|
# Throws an exception if the matrix width and height does not match this canvas' dimensions.
|
360
363
|
def assert_size!(matrix_width, matrix_height)
|
361
|
-
if width
|
364
|
+
if width != matrix_width
|
362
365
|
raise ChunkyPNG::ExpectationFailed,
|
363
|
-
|
366
|
+
"The width of the matrix does not match the canvas width!"
|
364
367
|
end
|
365
368
|
if height != matrix_height
|
366
369
|
raise ChunkyPNG::ExpectationFailed,
|
367
|
-
|
370
|
+
"The height of the matrix does not match the canvas height!"
|
368
371
|
end
|
369
372
|
true
|
370
373
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
1
3
|
module ChunkyPNG
|
2
4
|
class Canvas
|
3
|
-
|
4
5
|
# Methods for decoding and encoding Adam7 interlacing.
|
5
6
|
#
|
6
7
|
# Adam7 interlacing extracts 7 pass images out of a single image, that can be encoded to a
|
@@ -8,12 +9,15 @@ module ChunkyPNG
|
|
8
9
|
# ChunkyPNG canvas and is used to extract the pass images from the original image, or to
|
9
10
|
# reconstruct an original image from separate pass images.
|
10
11
|
module Adam7Interlacing
|
11
|
-
|
12
12
|
# Returns an array with the x-shift, x-offset, y-shift and y-offset for the requested pass.
|
13
13
|
# @param [Integer] pass The pass number, should be in 0..6.
|
14
14
|
def adam7_multiplier_offset(pass)
|
15
|
-
[
|
16
|
-
|
15
|
+
[
|
16
|
+
3 - (pass >> 1),
|
17
|
+
pass & 1 == 0 ? 0 : 8 >> ((pass + 1) >> 1),
|
18
|
+
pass == 0 ? 3 : 3 - ((pass - 1) >> 1),
|
19
|
+
pass == 0 || pass & 1 == 1 ? 0 : 8 >> (pass >> 1),
|
20
|
+
]
|
17
21
|
end
|
18
22
|
|
19
23
|
# Returns the pixel dimensions of the requested pass.
|
@@ -22,10 +26,12 @@ module ChunkyPNG
|
|
22
26
|
# @param [Integer] original_height The height of the original image.
|
23
27
|
def adam7_pass_size(pass, original_width, original_height)
|
24
28
|
x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
|
25
|
-
[
|
26
|
-
(
|
29
|
+
[
|
30
|
+
(original_width - x_offset + (1 << x_shift) - 1) >> x_shift,
|
31
|
+
(original_height - y_offset + (1 << y_shift) - 1) >> y_shift,
|
32
|
+
]
|
27
33
|
end
|
28
|
-
|
34
|
+
|
29
35
|
# Returns an array of the dimension of all the pass images.
|
30
36
|
# @param [Integer] original_width The width of the original image.
|
31
37
|
# @param [Integer] original_height The height of the original image.
|
@@ -49,7 +55,7 @@ module ChunkyPNG
|
|
49
55
|
end
|
50
56
|
end
|
51
57
|
end
|
52
|
-
|
58
|
+
|
53
59
|
# Extracts a pass from a complete image
|
54
60
|
# @param [Integer] pass The pass number, should be in 0..6.
|
55
61
|
# @param [ChunkyPNG::Canvas] canvas The image that is being deconstructed.
|
@@ -57,13 +63,13 @@ module ChunkyPNG
|
|
57
63
|
def adam7_extract_pass(pass, canvas)
|
58
64
|
x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
|
59
65
|
sm_pixels = []
|
60
|
-
|
66
|
+
|
61
67
|
y_offset.step(canvas.height - 1, 1 << y_shift) do |y|
|
62
68
|
x_offset.step(canvas.width - 1, 1 << x_shift) do |x|
|
63
69
|
sm_pixels << canvas[x, y]
|
64
70
|
end
|
65
71
|
end
|
66
|
-
|
72
|
+
|
67
73
|
new_canvas_args = adam7_pass_size(pass, canvas.width, canvas.height) + [sm_pixels]
|
68
74
|
ChunkyPNG::Canvas.new(*new_canvas_args)
|
69
75
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
1
3
|
module ChunkyPNG
|
2
4
|
class Canvas
|
3
|
-
|
4
5
|
# Methods to export a canvas to a PNG data URL.
|
5
6
|
module DataUrlExporting
|
6
|
-
|
7
7
|
# Exports the canvas as a data url (e.g. data:image/png;base64,<data>) that can
|
8
8
|
# easily be used inline in CSS or HTML.
|
9
9
|
# @return [String] The canvas formatted as a data URL string.
|
10
10
|
def to_data_url
|
11
|
-
[
|
11
|
+
["data:image/png;base64,", to_blob].pack("A*m").delete("\n")
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
1
3
|
module ChunkyPNG
|
2
4
|
class Canvas
|
3
|
-
|
4
5
|
# Methods to import a canvas from a PNG data URL.
|
5
6
|
module DataUrlImporting
|
6
|
-
|
7
7
|
# Imports a canvas from a PNG data URL.
|
8
8
|
# @param [String] string The data URL string to load from.
|
9
9
|
# @return [Canvas] The imported canvas.
|
@@ -11,7 +11,7 @@ module ChunkyPNG
|
|
11
11
|
# formatted PNG data URL (i.e. it should start with "data:image/png;base64,")
|
12
12
|
def from_data_url(string)
|
13
13
|
if string =~ %r[^data:image/png;base64,((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)$]
|
14
|
-
from_blob($1.unpack(
|
14
|
+
from_blob($1.unpack("m").first)
|
15
15
|
else
|
16
16
|
raise SignatureMismatch, "The string was not a properly formatted data URL for a PNG image."
|
17
17
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
1
3
|
module ChunkyPNG
|
2
4
|
class Canvas
|
3
|
-
|
4
5
|
# Module that adds some primitive drawing methods to {ChunkyPNG::Canvas}.
|
5
6
|
#
|
6
7
|
# All of these methods change the current canvas instance and do not create
|
@@ -10,7 +11,6 @@ module ChunkyPNG
|
|
10
11
|
# the bounds of the canvas; these pixels will simply be ignored.
|
11
12
|
# @see ChunkyPNG::Canvas
|
12
13
|
module Drawing
|
13
|
-
|
14
14
|
# Composes a pixel on the canvas by alpha blending a color with its
|
15
15
|
# background color.
|
16
16
|
#
|
@@ -33,44 +33,44 @@ module ChunkyPNG
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# Draws a Bezier curve
|
36
|
-
# @param [Array, Point] A collection of control points
|
36
|
+
# @param [Array, Point] points A collection of control points
|
37
|
+
# @param [Integer] stroke_color
|
37
38
|
# @return [Chunky:PNG::Canvas] Itself, with the curve drawn
|
38
39
|
def bezier_curve(points, stroke_color = ChunkyPNG::Color::BLACK)
|
39
40
|
points = ChunkyPNG::Vector(*points)
|
40
41
|
case points.length
|
41
|
-
when 0, 1
|
42
|
-
when 2
|
42
|
+
when 0, 1 then return self
|
43
|
+
when 2 then return line(points[0].x, points[0].y, points[1].x, points[1].y, stroke_color)
|
43
44
|
end
|
44
45
|
|
45
|
-
curve_points =
|
46
|
+
curve_points = []
|
46
47
|
|
47
48
|
t = 0
|
48
49
|
n = points.length - 1
|
49
|
-
bicof = 0
|
50
50
|
|
51
51
|
while t <= 100
|
52
|
-
|
52
|
+
bicof = 0
|
53
|
+
cur_p = ChunkyPNG::Point.new(0, 0)
|
53
54
|
|
54
55
|
# Generate a float of t.
|
55
56
|
t_f = t / 100.00
|
56
57
|
|
57
|
-
cur_p.x += ((1 - t_f)
|
58
|
-
cur_p.y += ((1 - t_f)
|
58
|
+
cur_p.x += ((1 - t_f)**n) * points[0].x
|
59
|
+
cur_p.y += ((1 - t_f)**n) * points[0].y
|
59
60
|
|
60
61
|
for i in 1...points.length - 1
|
61
|
-
bicof = binomial_coefficient(n
|
62
|
+
bicof = binomial_coefficient(n, i)
|
62
63
|
|
63
|
-
cur_p.x += (bicof * (1 - t_f)
|
64
|
-
cur_p.y += (bicof * (1 - t_f)
|
64
|
+
cur_p.x += (bicof * (1 - t_f)**(n - i)) * (t_f**i) * points[i].x
|
65
|
+
cur_p.y += (bicof * (1 - t_f)**(n - i)) * (t_f**i) * points[i].y
|
65
66
|
i += 1
|
66
67
|
end
|
67
68
|
|
68
|
-
cur_p.x += (t_f
|
69
|
-
cur_p.y += (t_f
|
69
|
+
cur_p.x += (t_f**n) * points[n].x
|
70
|
+
cur_p.y += (t_f**n) * points[n].y
|
70
71
|
|
71
72
|
curve_points << cur_p
|
72
73
|
|
73
|
-
bicof = 0
|
74
74
|
t += 1
|
75
75
|
end
|
76
76
|
|
@@ -127,9 +127,7 @@ module ChunkyPNG
|
|
127
127
|
w = 0xff - (e_acc >> 8)
|
128
128
|
compose_pixel(x0, y0, ChunkyPNG::Color.fade(stroke_color, w))
|
129
129
|
if inclusive || i > 0
|
130
|
-
compose_pixel(x0 + sx,
|
131
|
-
y0 + sy,
|
132
|
-
ChunkyPNG::Color.fade(stroke_color, 0xff - w))
|
130
|
+
compose_pixel(x0 + sx, y0 + sy, ChunkyPNG::Color.fade(stroke_color, 0xff - w))
|
133
131
|
end
|
134
132
|
y0 += sy
|
135
133
|
end
|
@@ -145,9 +143,7 @@ module ChunkyPNG
|
|
145
143
|
w = 0xff - (e_acc >> 8)
|
146
144
|
compose_pixel(x0, y0, ChunkyPNG::Color.fade(stroke_color, w))
|
147
145
|
if inclusive || i > 0
|
148
|
-
compose_pixel(x0 + sx,
|
149
|
-
y0 + sy,
|
150
|
-
ChunkyPNG::Color.fade(stroke_color, 0xff - w))
|
146
|
+
compose_pixel(x0 + sx, y0 + sy, ChunkyPNG::Color.fade(stroke_color, 0xff - w))
|
151
147
|
end
|
152
148
|
x0 += sx
|
153
149
|
end
|
@@ -157,23 +153,20 @@ module ChunkyPNG
|
|
157
153
|
self
|
158
154
|
end
|
159
155
|
|
160
|
-
|
156
|
+
alias line line_xiaolin_wu
|
161
157
|
|
162
158
|
# Draws a polygon on the canvas using the stroke_color, filled using the
|
163
159
|
# fill_color if any.
|
164
160
|
#
|
165
|
-
# @param [Array, String] The control point vector. Accepts everything
|
161
|
+
# @param [Array, String] path The control point vector. Accepts everything
|
166
162
|
# {ChunkyPNG.Vector} accepts.
|
167
163
|
# @param [Integer] stroke_color The stroke color to use for this polygon.
|
168
164
|
# @param [Integer] fill_color The fill color to use for this polygon.
|
169
165
|
# @return [ChunkyPNG::Canvas] Itself, with the polygon drawn.
|
170
|
-
def polygon(path,
|
171
|
-
stroke_color = ChunkyPNG::Color::BLACK,
|
172
|
-
fill_color = ChunkyPNG::Color::TRANSPARENT)
|
173
|
-
|
166
|
+
def polygon(path, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT)
|
174
167
|
vector = ChunkyPNG::Vector(*path)
|
175
168
|
if path.length < 3
|
176
|
-
raise ArgumentError,
|
169
|
+
raise ArgumentError, "A polygon requires at least 3 points"
|
177
170
|
end
|
178
171
|
|
179
172
|
stroke_color = ChunkyPNG::Color.parse(stroke_color)
|
@@ -215,10 +208,7 @@ module ChunkyPNG
|
|
215
208
|
# @param [Integer] stroke_color The line color to use for this rectangle.
|
216
209
|
# @param [Integer] fill_color The fill color to use for this rectangle.
|
217
210
|
# @return [ChunkyPNG::Canvas] Itself, with the rectangle drawn.
|
218
|
-
def rect(x0, y0, x1, y1,
|
219
|
-
stroke_color = ChunkyPNG::Color::BLACK,
|
220
|
-
fill_color = ChunkyPNG::Color::TRANSPARENT)
|
221
|
-
|
211
|
+
def rect(x0, y0, x1, y1, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT)
|
222
212
|
stroke_color = ChunkyPNG::Color.parse(stroke_color)
|
223
213
|
fill_color = ChunkyPNG::Color.parse(fill_color)
|
224
214
|
|
@@ -248,16 +238,13 @@ module ChunkyPNG
|
|
248
238
|
# @param [Integer] stroke_color The color to use for the line.
|
249
239
|
# @param [Integer] fill_color The color to use that fills the circle.
|
250
240
|
# @return [ChunkyPNG::Canvas] Itself, with the circle drawn.
|
251
|
-
def circle(x0, y0, radius,
|
252
|
-
stroke_color = ChunkyPNG::Color::BLACK,
|
253
|
-
fill_color = ChunkyPNG::Color::TRANSPARENT)
|
254
|
-
|
241
|
+
def circle(x0, y0, radius, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT)
|
255
242
|
stroke_color = ChunkyPNG::Color.parse(stroke_color)
|
256
243
|
fill_color = ChunkyPNG::Color.parse(fill_color)
|
257
244
|
|
258
245
|
f = 1 - radius
|
259
|
-
|
260
|
-
|
246
|
+
dd_f_x = 1
|
247
|
+
dd_f_y = -2 * radius
|
261
248
|
x = 0
|
262
249
|
y = radius
|
263
250
|
|
@@ -272,13 +259,13 @@ module ChunkyPNG
|
|
272
259
|
|
273
260
|
if f >= 0
|
274
261
|
y -= 1
|
275
|
-
|
276
|
-
f +=
|
262
|
+
dd_f_y += 2
|
263
|
+
f += dd_f_y
|
277
264
|
end
|
278
265
|
|
279
266
|
x += 1
|
280
|
-
|
281
|
-
f +=
|
267
|
+
dd_f_x += 2
|
268
|
+
f += dd_f_x
|
282
269
|
|
283
270
|
unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
284
271
|
lines[y] = lines[y] ? [lines[y], x - 1].min : x - 1
|
@@ -1,13 +1,13 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
1
3
|
module ChunkyPNG
|
2
4
|
class Canvas
|
3
|
-
|
4
5
|
# The ChunkyPNG::Canvas::Masking module defines methods to perform masking
|
5
6
|
# and theming operations on a {ChunkyPNG::Canvas}. The module is included into the Canvas class so all
|
6
7
|
# these methods are available on every canvas.
|
7
8
|
#
|
8
9
|
# @see ChunkyPNG::Canvas
|
9
10
|
module Masking
|
10
|
-
|
11
11
|
# Creates a new image, based on the current image but with a new theme color.
|
12
12
|
#
|
13
13
|
# This method will replace one color in an image with another image. This is done by
|
@@ -21,8 +21,8 @@ module ChunkyPNG
|
|
21
21
|
# @param [Integer] old_theme_color The original theme color in this image.
|
22
22
|
# @param [Integer] new_theme_color The color to replace the old theme color with.
|
23
23
|
# @param [Integer] bg_color The background color on 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,
|
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
26
|
# decrease it if too many pixels get extracted.
|
27
27
|
# @return [ChunkyPNG::Canvas] Returns itself, but with the theme colored pixels changed.
|
28
28
|
# @see #change_theme_color!
|
@@ -30,9 +30,9 @@ module ChunkyPNG
|
|
30
30
|
def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
|
31
31
|
base, mask = extract_mask(old_theme_color, bg_color, tolerance)
|
32
32
|
mask.change_mask_color!(new_theme_color)
|
33
|
-
|
33
|
+
replace!(base.compose!(mask))
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Creates a base image and a mask image from an original image that has a particular theme color.
|
37
37
|
# This can be used to easily change a theme color in an image.
|
38
38
|
#
|
@@ -40,16 +40,16 @@ module ChunkyPNG
|
|
40
40
|
# these in a mask image. All the other pixels will be stored in a base image. Both images will be
|
41
41
|
# of the exact same size as the original image. The original image will be left untouched.
|
42
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
|
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
45
|
# {#change_theme_color!} will perform this in one go.
|
46
46
|
#
|
47
47
|
# @param [Integer] mask_color The current theme color.
|
48
48
|
# @param [Integer] bg_color The background color on which the theme colored pixels 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,
|
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
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
|
52
|
+
# @return [Array<ChunkyPNG::Canvas, ChunkyPNG::Canvas>] An array with the base canvas and the mask
|
53
53
|
# canvas as elements.
|
54
54
|
# @see #change_theme_color!
|
55
55
|
# @see #change_mask_color!
|
@@ -66,10 +66,10 @@ module ChunkyPNG
|
|
66
66
|
base_pixels << pixel
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
70
|
-
[
|
69
|
+
|
70
|
+
[self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels)]
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
# Changes the color of a mask image.
|
74
74
|
#
|
75
75
|
# This method works on a canvas extracted out of another image using the {#extract_mask} method.
|