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.
- data/.infinity_test +1 -1
- data/README.rdoc +2 -2
- data/chunky_png.gemspec +4 -4
- data/lib/chunky_png.rb +14 -8
- data/lib/chunky_png/canvas.rb +110 -38
- data/lib/chunky_png/canvas/drawing.rb +175 -34
- data/lib/chunky_png/canvas/masking.rb +91 -0
- data/lib/chunky_png/canvas/operations.rb +141 -112
- data/lib/chunky_png/canvas/png_decoding.rb +13 -13
- data/lib/chunky_png/canvas/resampling.rb +42 -0
- data/lib/chunky_png/color.rb +252 -11
- data/lib/chunky_png/compatibility.rb +5 -5
- data/lib/chunky_png/dimension.rb +106 -0
- data/lib/chunky_png/point.rb +110 -0
- data/lib/chunky_png/vector.rb +92 -0
- data/spec/chunky_png/canvas/drawing_spec.rb +107 -14
- data/spec/chunky_png/canvas/masking_spec.rb +51 -0
- data/spec/chunky_png/canvas/operations_spec.rb +142 -75
- data/spec/chunky_png/canvas/resampling_spec.rb +31 -0
- data/spec/chunky_png/canvas/stream_exporting_spec.rb +20 -0
- data/spec/chunky_png/canvas/stream_importing_spec.rb +22 -0
- data/spec/chunky_png/canvas_spec.rb +151 -22
- data/spec/chunky_png/color_spec.rb +53 -0
- data/spec/chunky_png/dimension_spec.rb +43 -0
- data/spec/chunky_png/point_spec.rb +71 -0
- data/spec/chunky_png/vector_spec.rb +58 -0
- data/spec/resources/circles.png +0 -0
- data/spec/resources/clock_nn_xdown_ydown.png +0 -0
- data/spec/resources/clock_nn_xdown_yup.png +0 -0
- data/spec/resources/clock_nn_xup_yup.png +0 -0
- data/spec/resources/lines.png +0 -0
- data/spec/resources/partial_circles.png +0 -0
- data/spec/resources/polygon_filled_horizontal.png +0 -0
- data/spec/resources/polygon_filled_vertical.png +0 -0
- data/spec/resources/polygon_triangle_filled.png +0 -0
- data/spec/resources/polygon_unfilled.png +0 -0
- data/spec/resources/rect.png +0 -0
- metadata +31 -9
- data/spec/resources/clock_flip_horizontally.png +0 -0
- data/spec/resources/clock_flip_vertically.png +0 -0
- data/spec/resources/clock_rotate_180.png +0 -0
- data/spec/resources/clock_rotate_left.png +0 -0
- data/spec/resources/clock_rotate_right.png +0 -0
- data/spec/resources/clock_stubbed.png +0 -0
data/.infinity_test
CHANGED
data/README.rdoc
CHANGED
@@ -35,13 +35,13 @@ provides a massive speed boost to encoding and decoding.
|
|
35
35
|
# Creating an image from scratch, save as an interlaced PNG
|
36
36
|
png = ChunkyPNG::Image.new(16, 16, ChunkyPNG::Color::TRANSPARENT)
|
37
37
|
png[1,1] = ChunkyPNG::Color.rgba(10, 20, 30, 128)
|
38
|
-
png[2,1] = ChunkyPNG::Color
|
38
|
+
png[2,1] = ChunkyPNG::Color('black @ 0.5')
|
39
39
|
png.save('filename.png', :interlace => true)
|
40
40
|
|
41
41
|
# Compose images using alpha blending.
|
42
42
|
avatar = ChunkyPNG::Image.from_file('avatar.png')
|
43
43
|
badge = ChunkyPNG::Image.from_file('no_ie_badge.png')
|
44
|
-
avatar.compose(badge, 10, 10)
|
44
|
+
avatar.compose!(badge, 10, 10)
|
45
45
|
avatar.save('composited.png', :fast_rgba) # Force the fast saving routine.
|
46
46
|
|
47
47
|
# Accessing metadata
|
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 = "1.0.0.
|
7
|
-
s.date = "2011-
|
6
|
+
s.version = "1.0.0.rc1"
|
7
|
+
s.date = "2011-02-24"
|
8
8
|
|
9
9
|
s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
|
10
10
|
s.description = <<-EOT
|
@@ -38,6 +38,6 @@ Gem::Specification.new do |s|
|
|
38
38
|
|
39
39
|
# Do not change the files and test_files fields by hand. This will be done
|
40
40
|
# automatically by the gem release script.
|
41
|
-
s.files = %w(.gitignore .infinity_test .yardopts BENCHMARKS.rdoc Gemfile LICENSE README.rdoc Rakefile benchmarks/decoding_benchmark.rb benchmarks/encoding_benchmark.rb benchmarks/filesize_benchmark.rb chunky_png.gemspec lib/chunky_png.rb lib/chunky_png/canvas.rb lib/chunky_png/canvas/adam7_interlacing.rb lib/chunky_png/canvas/drawing.rb lib/chunky_png/canvas/operations.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/stream_exporting.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/chunk.rb lib/chunky_png/color.rb lib/chunky_png/compatibility.rb lib/chunky_png/datastream.rb lib/chunky_png/image.rb lib/chunky_png/palette.rb lib/chunky_png/rmagick.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/png_suite/background_chunks/bgai4a08.png spec/png_suite/background_chunks/bgai4a16.png spec/png_suite/background_chunks/bgan6a08.png spec/png_suite/background_chunks/bgan6a16.png spec/png_suite/background_chunks/bgbn4a08.png spec/png_suite/background_chunks/bggn4a16.png spec/png_suite/background_chunks/bgwn6a08.png spec/png_suite/background_chunks/bgyn6a16.png spec/png_suite/basic/basi0g01.png spec/png_suite/basic/basi0g01.rgba spec/png_suite/basic/basi0g02.png spec/png_suite/basic/basi0g02.rgba spec/png_suite/basic/basi0g04.png spec/png_suite/basic/basi0g04.rgba spec/png_suite/basic/basi0g08.png spec/png_suite/basic/basi0g08.rgba spec/png_suite/basic/basi0g16.png spec/png_suite/basic/basi0g16.rgba spec/png_suite/basic/basi2c08.png spec/png_suite/basic/basi2c08.rgba spec/png_suite/basic/basi2c16.png spec/png_suite/basic/basi2c16.rgba spec/png_suite/basic/basi3p01.png spec/png_suite/basic/basi3p01.rgba spec/png_suite/basic/basi3p02.png spec/png_suite/basic/basi3p02.rgba spec/png_suite/basic/basi3p04.png spec/png_suite/basic/basi3p04.rgba spec/png_suite/basic/basi3p08.png spec/png_suite/basic/basi3p08.rgba spec/png_suite/basic/basi4a08.png spec/png_suite/basic/basi4a08.rgba spec/png_suite/basic/basi4a16.png spec/png_suite/basic/basi4a16.rgba spec/png_suite/basic/basi6a08.png spec/png_suite/basic/basi6a08.rgba spec/png_suite/basic/basi6a16.png spec/png_suite/basic/basi6a16.rgba spec/png_suite/basic/basn0g01.png spec/png_suite/basic/basn0g01.rgba spec/png_suite/basic/basn0g02.png spec/png_suite/basic/basn0g02.rgba spec/png_suite/basic/basn0g04.png spec/png_suite/basic/basn0g04.rgba spec/png_suite/basic/basn0g08.png spec/png_suite/basic/basn0g08.rgba spec/png_suite/basic/basn0g16.png spec/png_suite/basic/basn0g16.rgba spec/png_suite/basic/basn2c08.png spec/png_suite/basic/basn2c08.rgba spec/png_suite/basic/basn2c16.png spec/png_suite/basic/basn2c16.rgba spec/png_suite/basic/basn3p01.png spec/png_suite/basic/basn3p01.rgba spec/png_suite/basic/basn3p02.png spec/png_suite/basic/basn3p02.rgba spec/png_suite/basic/basn3p04.png spec/png_suite/basic/basn3p04.rgba spec/png_suite/basic/basn3p08.png spec/png_suite/basic/basn3p08.rgba spec/png_suite/basic/basn4a08.png spec/png_suite/basic/basn4a08.rgba spec/png_suite/basic/basn4a16.png spec/png_suite/basic/basn4a16.rgba spec/png_suite/basic/basn6a08.png spec/png_suite/basic/basn6a08.rgba spec/png_suite/basic/basn6a16.png spec/png_suite/basic/basn6a16.rgba spec/png_suite/broken/x00n0g01.png spec/png_suite/broken/xcrn0g04.png spec/png_suite/broken/xlfn0g04.png spec/png_suite/chunk_ordering/oi1n0g16.png spec/png_suite/chunk_ordering/oi1n2c16.png spec/png_suite/chunk_ordering/oi2n0g16.png spec/png_suite/chunk_ordering/oi2n2c16.png spec/png_suite/chunk_ordering/oi4n0g16.png spec/png_suite/chunk_ordering/oi4n2c16.png spec/png_suite/chunk_ordering/oi9n0g16.png spec/png_suite/chunk_ordering/oi9n2c16.png spec/png_suite/compression_levels/z00n2c08.png spec/png_suite/compression_levels/z03n2c08.png spec/png_suite/compression_levels/z06n2c08.png spec/png_suite/compression_levels/z09n2c08.png spec/png_suite/filtering/f00n0g08.png spec/png_suite/filtering/f00n0g08.rgba spec/png_suite/filtering/f00n0g08_reference.png spec/png_suite/filtering/f00n0g08_reference.rgba spec/png_suite/filtering/f00n2c08.png spec/png_suite/filtering/f00n2c08.rgba spec/png_suite/filtering/f00n2c08_reference.png spec/png_suite/filtering/f00n2c08_reference.rgba spec/png_suite/filtering/f01n0g08.png spec/png_suite/filtering/f01n0g08.rgba spec/png_suite/filtering/f01n0g08_reference.png spec/png_suite/filtering/f01n0g08_reference.rgba spec/png_suite/filtering/f01n2c08.png spec/png_suite/filtering/f01n2c08.rgba spec/png_suite/filtering/f01n2c08_reference.png spec/png_suite/filtering/f01n2c08_reference.rgba spec/png_suite/filtering/f02n0g08.png spec/png_suite/filtering/f02n0g08.rgba spec/png_suite/filtering/f02n0g08_reference.png spec/png_suite/filtering/f02n0g08_reference.rgba spec/png_suite/filtering/f02n2c08.png spec/png_suite/filtering/f02n2c08.rgba spec/png_suite/filtering/f02n2c08_reference.png spec/png_suite/filtering/f02n2c08_reference.rgba spec/png_suite/filtering/f03n0g08.png spec/png_suite/filtering/f03n0g08.rgba spec/png_suite/filtering/f03n0g08_reference.png spec/png_suite/filtering/f03n0g08_reference.rgba spec/png_suite/filtering/f03n2c08.png spec/png_suite/filtering/f03n2c08.rgba spec/png_suite/filtering/f03n2c08_reference.png spec/png_suite/filtering/f03n2c08_reference.rgba spec/png_suite/filtering/f04n0g08.png spec/png_suite/filtering/f04n0g08.rgba spec/png_suite/filtering/f04n0g08_reference.png spec/png_suite/filtering/f04n0g08_reference.rgba spec/png_suite/filtering/f04n2c08.png spec/png_suite/filtering/f04n2c08.rgba spec/png_suite/filtering/f04n2c08_reference.png spec/png_suite/filtering/f04n2c08_reference.rgba spec/png_suite/gamma/g03n0g16.png spec/png_suite/gamma/g03n2c08.png spec/png_suite/gamma/g03n3p04.png spec/png_suite/gamma/g04n0g16.png spec/png_suite/gamma/g04n2c08.png spec/png_suite/gamma/g04n3p04.png spec/png_suite/gamma/g05n0g16.png spec/png_suite/gamma/g05n2c08.png spec/png_suite/gamma/g05n3p04.png spec/png_suite/gamma/g07n0g16.png spec/png_suite/gamma/g07n2c08.png spec/png_suite/gamma/g07n3p04.png spec/png_suite/gamma/g10n0g16.png spec/png_suite/gamma/g10n2c08.png spec/png_suite/gamma/g10n3p04.png spec/png_suite/gamma/g25n0g16.png spec/png_suite/gamma/g25n2c08.png spec/png_suite/gamma/g25n3p04.png spec/png_suite/metadata/cm0n0g04.png spec/png_suite/metadata/cm7n0g04.png spec/png_suite/metadata/cm9n0g04.png spec/png_suite/other/ccwn2c08.png spec/png_suite/other/ccwn3p08.png spec/png_suite/other/cdfn2c08.png spec/png_suite/other/cdhn2c08.png spec/png_suite/other/cdsn2c08.png spec/png_suite/other/cdun2c08.png spec/png_suite/other/ch1n3p04.png spec/png_suite/other/ch2n3p08.png spec/png_suite/other/cs3n2c16.png spec/png_suite/other/cs3n3p08.png spec/png_suite/other/cs5n2c08.png spec/png_suite/other/cs5n3p08.png spec/png_suite/other/cs8n2c08.png spec/png_suite/other/cs8n3p08.png spec/png_suite/other/ct0n0g04.png spec/png_suite/other/ct1n0g04.png spec/png_suite/other/ctzn0g04.png spec/png_suite/other/pp0n2c16.png spec/png_suite/other/pp0n6a08.png spec/png_suite/other/ps1n0g08.png spec/png_suite/other/ps1n2c16.png spec/png_suite/other/ps2n0g08.png spec/png_suite/other/ps2n2c16.png spec/png_suite/sizes/s01i3p01.png spec/png_suite/sizes/s01n3p01.png spec/png_suite/sizes/s02i3p01.png spec/png_suite/sizes/s02n3p01.png spec/png_suite/sizes/s03i3p01.png spec/png_suite/sizes/s03n3p01.png spec/png_suite/sizes/s04i3p01.png spec/png_suite/sizes/s04n3p01.png spec/png_suite/sizes/s05i3p02.png spec/png_suite/sizes/s05n3p02.png spec/png_suite/sizes/s06i3p02.png spec/png_suite/sizes/s06n3p02.png spec/png_suite/sizes/s07i3p02.png spec/png_suite/sizes/s07n3p02.png spec/png_suite/sizes/s08i3p02.png spec/png_suite/sizes/s08n3p02.png spec/png_suite/sizes/s09i3p02.png spec/png_suite/sizes/s09n3p02.png spec/png_suite/sizes/s32i3p04.png spec/png_suite/sizes/s32n3p04.png spec/png_suite/sizes/s33i3p04.png spec/png_suite/sizes/s33n3p04.png spec/png_suite/sizes/s34i3p04.png spec/png_suite/sizes/s34n3p04.png spec/png_suite/sizes/s35i3p04.png spec/png_suite/sizes/s35n3p04.png spec/png_suite/sizes/s36i3p04.png spec/png_suite/sizes/s36n3p04.png spec/png_suite/sizes/s37i3p04.png spec/png_suite/sizes/s37n3p04.png spec/png_suite/sizes/s38i3p04.png spec/png_suite/sizes/s38n3p04.png spec/png_suite/sizes/s39i3p04.png spec/png_suite/sizes/s39n3p04.png spec/png_suite/sizes/s40i3p04.png spec/png_suite/sizes/s40n3p04.png spec/png_suite/transparency/tbbn1g04.png spec/png_suite/transparency/tbbn2c16.png spec/png_suite/transparency/tbbn3p08.png spec/png_suite/transparency/tbgn2c16.png spec/png_suite/transparency/tbgn3p08.png spec/png_suite/transparency/tbrn2c08.png spec/png_suite/transparency/tbwn1g16.png spec/png_suite/transparency/tbwn3p08.png spec/png_suite/transparency/tbyn3p08.png spec/png_suite/transparency/tp0n1g08.png spec/png_suite/transparency/tp0n2c08.png spec/png_suite/transparency/tp0n3p08.png spec/png_suite/transparency/tp1n3p08.png spec/png_suite_spec.rb spec/resources/adam7.png spec/resources/clock.png spec/resources/clock_base.png spec/resources/clock_flip_horizontally.png spec/resources/clock_flip_vertically.png spec/resources/clock_mask.png spec/resources/clock_mask_updated.png spec/resources/clock_rotate_180.png spec/resources/clock_rotate_left.png spec/resources/clock_rotate_right.png spec/resources/clock_stubbed.png spec/resources/clock_updated.png spec/resources/composited.png spec/resources/cropped.png spec/resources/damaged_chunk.png spec/resources/damaged_signature.png spec/resources/lines.png spec/resources/operations.png spec/resources/pixelstream.rgb spec/resources/pixelstream.rgba spec/resources/pixelstream_best_compression.png spec/resources/pixelstream_fast_rgba.png spec/resources/pixelstream_reference.png spec/resources/rect.png spec/resources/replaced.png spec/resources/text_chunk.png spec/resources/ztxt_chunk.png spec/spec_helper.rb tasks/benchmarks.rake tasks/github-gem.rake)
|
42
|
-
s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/png_suite_spec.rb)
|
41
|
+
s.files = %w(.gitignore .infinity_test .yardopts BENCHMARKS.rdoc Gemfile LICENSE README.rdoc Rakefile benchmarks/decoding_benchmark.rb benchmarks/encoding_benchmark.rb benchmarks/filesize_benchmark.rb chunky_png.gemspec lib/chunky_png.rb lib/chunky_png/canvas.rb lib/chunky_png/canvas/adam7_interlacing.rb lib/chunky_png/canvas/drawing.rb lib/chunky_png/canvas/masking.rb lib/chunky_png/canvas/operations.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/resampling.rb lib/chunky_png/canvas/stream_exporting.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/chunk.rb lib/chunky_png/color.rb lib/chunky_png/compatibility.rb lib/chunky_png/datastream.rb lib/chunky_png/dimension.rb lib/chunky_png/image.rb lib/chunky_png/palette.rb lib/chunky_png/point.rb lib/chunky_png/rmagick.rb lib/chunky_png/vector.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/masking_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas/resampling_spec.rb spec/chunky_png/canvas/stream_exporting_spec.rb spec/chunky_png/canvas/stream_importing_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/dimension_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/point_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/vector_spec.rb spec/chunky_png_spec.rb spec/png_suite/background_chunks/bgai4a08.png spec/png_suite/background_chunks/bgai4a16.png spec/png_suite/background_chunks/bgan6a08.png spec/png_suite/background_chunks/bgan6a16.png spec/png_suite/background_chunks/bgbn4a08.png spec/png_suite/background_chunks/bggn4a16.png spec/png_suite/background_chunks/bgwn6a08.png spec/png_suite/background_chunks/bgyn6a16.png spec/png_suite/basic/basi0g01.png spec/png_suite/basic/basi0g01.rgba spec/png_suite/basic/basi0g02.png spec/png_suite/basic/basi0g02.rgba spec/png_suite/basic/basi0g04.png spec/png_suite/basic/basi0g04.rgba spec/png_suite/basic/basi0g08.png spec/png_suite/basic/basi0g08.rgba spec/png_suite/basic/basi0g16.png spec/png_suite/basic/basi0g16.rgba spec/png_suite/basic/basi2c08.png spec/png_suite/basic/basi2c08.rgba spec/png_suite/basic/basi2c16.png spec/png_suite/basic/basi2c16.rgba spec/png_suite/basic/basi3p01.png spec/png_suite/basic/basi3p01.rgba spec/png_suite/basic/basi3p02.png spec/png_suite/basic/basi3p02.rgba spec/png_suite/basic/basi3p04.png spec/png_suite/basic/basi3p04.rgba spec/png_suite/basic/basi3p08.png spec/png_suite/basic/basi3p08.rgba spec/png_suite/basic/basi4a08.png spec/png_suite/basic/basi4a08.rgba spec/png_suite/basic/basi4a16.png spec/png_suite/basic/basi4a16.rgba spec/png_suite/basic/basi6a08.png spec/png_suite/basic/basi6a08.rgba spec/png_suite/basic/basi6a16.png spec/png_suite/basic/basi6a16.rgba spec/png_suite/basic/basn0g01.png spec/png_suite/basic/basn0g01.rgba spec/png_suite/basic/basn0g02.png spec/png_suite/basic/basn0g02.rgba spec/png_suite/basic/basn0g04.png spec/png_suite/basic/basn0g04.rgba spec/png_suite/basic/basn0g08.png spec/png_suite/basic/basn0g08.rgba spec/png_suite/basic/basn0g16.png spec/png_suite/basic/basn0g16.rgba spec/png_suite/basic/basn2c08.png spec/png_suite/basic/basn2c08.rgba spec/png_suite/basic/basn2c16.png spec/png_suite/basic/basn2c16.rgba spec/png_suite/basic/basn3p01.png spec/png_suite/basic/basn3p01.rgba spec/png_suite/basic/basn3p02.png spec/png_suite/basic/basn3p02.rgba spec/png_suite/basic/basn3p04.png spec/png_suite/basic/basn3p04.rgba spec/png_suite/basic/basn3p08.png spec/png_suite/basic/basn3p08.rgba spec/png_suite/basic/basn4a08.png spec/png_suite/basic/basn4a08.rgba spec/png_suite/basic/basn4a16.png spec/png_suite/basic/basn4a16.rgba spec/png_suite/basic/basn6a08.png spec/png_suite/basic/basn6a08.rgba spec/png_suite/basic/basn6a16.png spec/png_suite/basic/basn6a16.rgba spec/png_suite/broken/x00n0g01.png spec/png_suite/broken/xcrn0g04.png spec/png_suite/broken/xlfn0g04.png spec/png_suite/chunk_ordering/oi1n0g16.png spec/png_suite/chunk_ordering/oi1n2c16.png spec/png_suite/chunk_ordering/oi2n0g16.png spec/png_suite/chunk_ordering/oi2n2c16.png spec/png_suite/chunk_ordering/oi4n0g16.png spec/png_suite/chunk_ordering/oi4n2c16.png spec/png_suite/chunk_ordering/oi9n0g16.png spec/png_suite/chunk_ordering/oi9n2c16.png spec/png_suite/compression_levels/z00n2c08.png spec/png_suite/compression_levels/z03n2c08.png spec/png_suite/compression_levels/z06n2c08.png spec/png_suite/compression_levels/z09n2c08.png spec/png_suite/filtering/f00n0g08.png spec/png_suite/filtering/f00n0g08.rgba spec/png_suite/filtering/f00n0g08_reference.png spec/png_suite/filtering/f00n0g08_reference.rgba spec/png_suite/filtering/f00n2c08.png spec/png_suite/filtering/f00n2c08.rgba spec/png_suite/filtering/f00n2c08_reference.png spec/png_suite/filtering/f00n2c08_reference.rgba spec/png_suite/filtering/f01n0g08.png spec/png_suite/filtering/f01n0g08.rgba spec/png_suite/filtering/f01n0g08_reference.png spec/png_suite/filtering/f01n0g08_reference.rgba spec/png_suite/filtering/f01n2c08.png spec/png_suite/filtering/f01n2c08.rgba spec/png_suite/filtering/f01n2c08_reference.png spec/png_suite/filtering/f01n2c08_reference.rgba spec/png_suite/filtering/f02n0g08.png spec/png_suite/filtering/f02n0g08.rgba spec/png_suite/filtering/f02n0g08_reference.png spec/png_suite/filtering/f02n0g08_reference.rgba spec/png_suite/filtering/f02n2c08.png spec/png_suite/filtering/f02n2c08.rgba spec/png_suite/filtering/f02n2c08_reference.png spec/png_suite/filtering/f02n2c08_reference.rgba spec/png_suite/filtering/f03n0g08.png spec/png_suite/filtering/f03n0g08.rgba spec/png_suite/filtering/f03n0g08_reference.png spec/png_suite/filtering/f03n0g08_reference.rgba spec/png_suite/filtering/f03n2c08.png spec/png_suite/filtering/f03n2c08.rgba spec/png_suite/filtering/f03n2c08_reference.png spec/png_suite/filtering/f03n2c08_reference.rgba spec/png_suite/filtering/f04n0g08.png spec/png_suite/filtering/f04n0g08.rgba spec/png_suite/filtering/f04n0g08_reference.png spec/png_suite/filtering/f04n0g08_reference.rgba spec/png_suite/filtering/f04n2c08.png spec/png_suite/filtering/f04n2c08.rgba spec/png_suite/filtering/f04n2c08_reference.png spec/png_suite/filtering/f04n2c08_reference.rgba spec/png_suite/gamma/g03n0g16.png spec/png_suite/gamma/g03n2c08.png spec/png_suite/gamma/g03n3p04.png spec/png_suite/gamma/g04n0g16.png spec/png_suite/gamma/g04n2c08.png spec/png_suite/gamma/g04n3p04.png spec/png_suite/gamma/g05n0g16.png spec/png_suite/gamma/g05n2c08.png spec/png_suite/gamma/g05n3p04.png spec/png_suite/gamma/g07n0g16.png spec/png_suite/gamma/g07n2c08.png spec/png_suite/gamma/g07n3p04.png spec/png_suite/gamma/g10n0g16.png spec/png_suite/gamma/g10n2c08.png spec/png_suite/gamma/g10n3p04.png spec/png_suite/gamma/g25n0g16.png spec/png_suite/gamma/g25n2c08.png spec/png_suite/gamma/g25n3p04.png spec/png_suite/metadata/cm0n0g04.png spec/png_suite/metadata/cm7n0g04.png spec/png_suite/metadata/cm9n0g04.png spec/png_suite/other/ccwn2c08.png spec/png_suite/other/ccwn3p08.png spec/png_suite/other/cdfn2c08.png spec/png_suite/other/cdhn2c08.png spec/png_suite/other/cdsn2c08.png spec/png_suite/other/cdun2c08.png spec/png_suite/other/ch1n3p04.png spec/png_suite/other/ch2n3p08.png spec/png_suite/other/cs3n2c16.png spec/png_suite/other/cs3n3p08.png spec/png_suite/other/cs5n2c08.png spec/png_suite/other/cs5n3p08.png spec/png_suite/other/cs8n2c08.png spec/png_suite/other/cs8n3p08.png spec/png_suite/other/ct0n0g04.png spec/png_suite/other/ct1n0g04.png spec/png_suite/other/ctzn0g04.png spec/png_suite/other/pp0n2c16.png spec/png_suite/other/pp0n6a08.png spec/png_suite/other/ps1n0g08.png spec/png_suite/other/ps1n2c16.png spec/png_suite/other/ps2n0g08.png spec/png_suite/other/ps2n2c16.png spec/png_suite/sizes/s01i3p01.png spec/png_suite/sizes/s01n3p01.png spec/png_suite/sizes/s02i3p01.png spec/png_suite/sizes/s02n3p01.png spec/png_suite/sizes/s03i3p01.png spec/png_suite/sizes/s03n3p01.png spec/png_suite/sizes/s04i3p01.png spec/png_suite/sizes/s04n3p01.png spec/png_suite/sizes/s05i3p02.png spec/png_suite/sizes/s05n3p02.png spec/png_suite/sizes/s06i3p02.png spec/png_suite/sizes/s06n3p02.png spec/png_suite/sizes/s07i3p02.png spec/png_suite/sizes/s07n3p02.png spec/png_suite/sizes/s08i3p02.png spec/png_suite/sizes/s08n3p02.png spec/png_suite/sizes/s09i3p02.png spec/png_suite/sizes/s09n3p02.png spec/png_suite/sizes/s32i3p04.png spec/png_suite/sizes/s32n3p04.png spec/png_suite/sizes/s33i3p04.png spec/png_suite/sizes/s33n3p04.png spec/png_suite/sizes/s34i3p04.png spec/png_suite/sizes/s34n3p04.png spec/png_suite/sizes/s35i3p04.png spec/png_suite/sizes/s35n3p04.png spec/png_suite/sizes/s36i3p04.png spec/png_suite/sizes/s36n3p04.png spec/png_suite/sizes/s37i3p04.png spec/png_suite/sizes/s37n3p04.png spec/png_suite/sizes/s38i3p04.png spec/png_suite/sizes/s38n3p04.png spec/png_suite/sizes/s39i3p04.png spec/png_suite/sizes/s39n3p04.png spec/png_suite/sizes/s40i3p04.png spec/png_suite/sizes/s40n3p04.png spec/png_suite/transparency/tbbn1g04.png spec/png_suite/transparency/tbbn2c16.png spec/png_suite/transparency/tbbn3p08.png spec/png_suite/transparency/tbgn2c16.png spec/png_suite/transparency/tbgn3p08.png spec/png_suite/transparency/tbrn2c08.png spec/png_suite/transparency/tbwn1g16.png spec/png_suite/transparency/tbwn3p08.png spec/png_suite/transparency/tbyn3p08.png spec/png_suite/transparency/tp0n1g08.png spec/png_suite/transparency/tp0n2c08.png spec/png_suite/transparency/tp0n3p08.png spec/png_suite/transparency/tp1n3p08.png spec/png_suite_spec.rb spec/resources/adam7.png spec/resources/circles.png spec/resources/clock.png spec/resources/clock_base.png spec/resources/clock_mask.png spec/resources/clock_mask_updated.png spec/resources/clock_nn_xdown_ydown.png spec/resources/clock_nn_xdown_yup.png spec/resources/clock_nn_xup_yup.png spec/resources/clock_updated.png spec/resources/composited.png spec/resources/cropped.png spec/resources/damaged_chunk.png spec/resources/damaged_signature.png spec/resources/lines.png spec/resources/operations.png spec/resources/partial_circles.png spec/resources/pixelstream.rgb spec/resources/pixelstream.rgba spec/resources/pixelstream_best_compression.png spec/resources/pixelstream_fast_rgba.png spec/resources/pixelstream_reference.png spec/resources/polygon_filled_horizontal.png spec/resources/polygon_filled_vertical.png spec/resources/polygon_triangle_filled.png spec/resources/polygon_unfilled.png spec/resources/rect.png spec/resources/replaced.png spec/resources/text_chunk.png spec/resources/ztxt_chunk.png spec/spec_helper.rb tasks/benchmarks.rake tasks/github-gem.rake)
|
42
|
+
s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/masking_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas/resampling_spec.rb spec/chunky_png/canvas/stream_exporting_spec.rb spec/chunky_png/canvas/stream_importing_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/dimension_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/point_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png/vector_spec.rb spec/chunky_png_spec.rb spec/png_suite_spec.rb)
|
43
43
|
end
|
data/lib/chunky_png.rb
CHANGED
@@ -1,20 +1,26 @@
|
|
1
|
+
# Basic requirements from standard library
|
1
2
|
require 'set'
|
2
3
|
require 'zlib'
|
3
4
|
require 'stringio'
|
4
5
|
require 'enumerator'
|
5
6
|
|
7
|
+
# Ruby 1.8 / 1.9 compatibility
|
6
8
|
require 'chunky_png/compatibility'
|
9
|
+
|
10
|
+
# PNG file structure
|
7
11
|
require 'chunky_png/datastream'
|
8
12
|
require 'chunky_png/chunk'
|
13
|
+
|
14
|
+
# Colors
|
9
15
|
require 'chunky_png/palette'
|
10
16
|
require 'chunky_png/color'
|
11
|
-
|
12
|
-
|
13
|
-
require 'chunky_png/
|
14
|
-
require 'chunky_png/
|
15
|
-
require 'chunky_png/
|
16
|
-
|
17
|
-
|
17
|
+
|
18
|
+
# Geometry
|
19
|
+
require 'chunky_png/point'
|
20
|
+
require 'chunky_png/vector'
|
21
|
+
require 'chunky_png/dimension'
|
22
|
+
|
23
|
+
# Canvas / Image classes
|
18
24
|
require 'chunky_png/canvas'
|
19
25
|
require 'chunky_png/image'
|
20
26
|
|
@@ -28,7 +34,7 @@ module ChunkyPNG
|
|
28
34
|
|
29
35
|
# The current version of ChunkyPNG. This value will be updated automatically
|
30
36
|
# by them gem:release rake task.
|
31
|
-
VERSION = "1.0.0.
|
37
|
+
VERSION = "1.0.0.rc1"
|
32
38
|
|
33
39
|
###################################################
|
34
40
|
# PNG international standard defined constants
|
data/lib/chunky_png/canvas.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
require 'chunky_png/canvas/png_encoding'
|
2
|
+
require 'chunky_png/canvas/png_decoding'
|
3
|
+
require 'chunky_png/canvas/adam7_interlacing'
|
4
|
+
require 'chunky_png/canvas/stream_exporting'
|
5
|
+
require 'chunky_png/canvas/stream_importing'
|
6
|
+
require 'chunky_png/canvas/operations'
|
7
|
+
require 'chunky_png/canvas/drawing'
|
8
|
+
require 'chunky_png/canvas/resampling'
|
9
|
+
require 'chunky_png/canvas/masking'
|
10
|
+
|
1
11
|
module ChunkyPNG
|
2
12
|
|
3
13
|
# The ChunkPNG::Canvas class represents a raster image as a matrix of
|
@@ -30,6 +40,8 @@ module ChunkyPNG
|
|
30
40
|
|
31
41
|
include Operations
|
32
42
|
include Drawing
|
43
|
+
include Resampling
|
44
|
+
include Masking
|
33
45
|
|
34
46
|
# @return [Integer] The number of columns in this canvas
|
35
47
|
attr_reader :width
|
@@ -61,10 +73,10 @@ module ChunkyPNG
|
|
61
73
|
|
62
74
|
if initial.kind_of?(Integer)
|
63
75
|
@pixels = Array.new(width * height, initial)
|
64
|
-
elsif initial.kind_of?(Array) && initial.
|
76
|
+
elsif initial.kind_of?(Array) && initial.length == width * height
|
65
77
|
@pixels = initial
|
66
78
|
else
|
67
|
-
raise ChunkyPNG::ExpectationFailed, "Cannot use this value as initial canvas: #{initial.inspect}!"
|
79
|
+
raise ChunkyPNG::ExpectationFailed, "Cannot use this value as initial #{width}x#{height} canvas: #{initial.inspect}!"
|
68
80
|
end
|
69
81
|
end
|
70
82
|
|
@@ -87,41 +99,90 @@ module ChunkyPNG
|
|
87
99
|
# PROPERTIES
|
88
100
|
#################################################################
|
89
101
|
|
90
|
-
# Returns the
|
91
|
-
# @return
|
92
|
-
def
|
93
|
-
|
102
|
+
# Returns the dimension (width x height) for this canvas.
|
103
|
+
# @return [ChunkyPNG::Dimension] A dimension instante with the width and height set for this canvas.
|
104
|
+
def dimension
|
105
|
+
ChunkyPNG::Dimension.new(width, height)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns the area of this canvas in number of pixels.
|
109
|
+
# @return [Integer] The number of pixels in this canvas
|
110
|
+
def area
|
111
|
+
pixels.length
|
94
112
|
end
|
95
113
|
|
96
114
|
# Replaces a single pixel in this canvas.
|
97
|
-
#
|
98
|
-
# @
|
99
|
-
#
|
100
|
-
#
|
115
|
+
#
|
116
|
+
# @overload []=(x, y, color)
|
117
|
+
# Sets the color value of a pixel given a x- and y-coordinate
|
118
|
+
# @param [Integer] x The x-coordinate of the pixel (column)
|
119
|
+
# @param [Integer] y The y-coordinate of the pixel (row)
|
120
|
+
# @param [Integer] color The new color for the provided coordinates.
|
121
|
+
# @return [Integer] The new color value for this pixel, i.e. <tt>color</tt>.
|
122
|
+
#
|
123
|
+
# @overload []=(point, color)
|
124
|
+
# Sets the color value of a pixel given point-like value.
|
125
|
+
# @param [ChunkyPNG::Point, ...] point The point on the canvas to replace.
|
126
|
+
# @param [Integer] color The new color for the provided coordinates.
|
127
|
+
# @return [Integer] The new color value for this pixel, i.e. <tt>color</tt>.
|
128
|
+
#
|
101
129
|
# @raise [ChunkyPNG::OutOfBounds] when the coordinates are outside of the image's dimensions.
|
102
|
-
|
103
|
-
|
104
|
-
|
130
|
+
# @see #set_pixel
|
131
|
+
def []=(*args)
|
132
|
+
point = args.length == 2 ? ChunkyPNG::Point(args.first) : ChunkyPNG::Point(args[0], args[1])
|
133
|
+
assert_xy!(point.x, point.y)
|
134
|
+
@pixels[point.y * width + point.x] = args.last
|
105
135
|
end
|
106
136
|
|
107
137
|
# Replaces a single pixel in this canvas, without bounds checking.
|
108
|
-
#
|
109
|
-
#
|
138
|
+
#
|
139
|
+
# This method return value and effects are undefined for coordinates
|
140
|
+
# out of bounds of the canvas.
|
141
|
+
#
|
142
|
+
# @param [Integer] x The x-coordinate of the pixel (column)
|
143
|
+
# @param [Integer] y The y-coordinate of the pixel (row)
|
144
|
+
# @param [Inteer] pixel The new color for the provided coordinates.
|
145
|
+
# @return [Integer] The new color value for this pixel, i.e. <tt>color</tt>.
|
110
146
|
def set_pixel(x, y, color)
|
111
147
|
@pixels[y * width + x] = color
|
112
148
|
end
|
113
|
-
|
114
|
-
#
|
149
|
+
|
150
|
+
# Replaces a single pixel in this canvas, with bounds checking. It will do
|
151
|
+
# noting if the provided coordinates are out of bounds.
|
152
|
+
#
|
115
153
|
# @param [Integer] x The x-coordinate of the pixel (column)
|
116
154
|
# @param [Integer] y The y-coordinate of the pixel (row)
|
117
|
-
# @
|
155
|
+
# @param [CInteger] pixel The new color value for the provided coordinates.
|
156
|
+
# @return [Integer] The new color value for this pixel, i.e. <tt>color</tt>, or
|
157
|
+
# <tt>nil</tt> if the coordinates are out of bounds.
|
158
|
+
def set_pixel_if_within_bounds(x, y, color)
|
159
|
+
return unless include_xy?(x, y)
|
160
|
+
@pixels[y * width + x] = color
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns a single pixel's color value from this canvas.
|
164
|
+
#
|
165
|
+
# @overload [](point)
|
166
|
+
# Returns the color value given a point-like value.
|
167
|
+
# @param [ChunkyPNG::Point, ...] point The coordinates of the pixel as point.
|
168
|
+
# @return [Integer] The current color value at the provided coordinates.
|
169
|
+
#
|
170
|
+
# @overload [](x, y)
|
171
|
+
# Returns the color value given a x- and y-coordinate.
|
172
|
+
# @param [Integer] x The x-coordinate of the pixel (column)
|
173
|
+
# @param [Integer] y The y-coordinate of the pixel (row)
|
174
|
+
# @return [Integer] The current color value at the provided coordinates.
|
175
|
+
#
|
118
176
|
# @raise [ChunkyPNG::OutOfBounds] when the coordinates are outside of the image's dimensions.
|
119
|
-
|
120
|
-
|
121
|
-
|
177
|
+
# @see #get_pixel
|
178
|
+
def [](*args)
|
179
|
+
point = ChunkyPNG::Point(*args)
|
180
|
+
assert_xy!(point.x, point.y)
|
181
|
+
@pixels[point.y * width + point.x]
|
122
182
|
end
|
123
183
|
|
124
|
-
# Returns a single pixel from this canvas, without checking bounds.
|
184
|
+
# Returns a single pixel from this canvas, without checking bounds. The return value for
|
185
|
+
# this method is undefined if the coordinates are out of bounds.
|
125
186
|
# @param (see #[])
|
126
187
|
# @return [ChunkyPNG::Color] The current pixel at the provided coordinates.
|
127
188
|
def get_pixel(x, y)
|
@@ -163,16 +224,17 @@ module ChunkyPNG
|
|
163
224
|
end
|
164
225
|
|
165
226
|
# Checks whether the given coordinates are in the range of the canvas
|
166
|
-
# @param [
|
167
|
-
# @
|
168
|
-
#
|
169
|
-
#
|
170
|
-
def
|
171
|
-
|
227
|
+
# @param [ChunkyPNG::Point, Array, Hash, String] point_like The point to check.
|
228
|
+
# @return [true, false] True if the x and y coordinates of the point are
|
229
|
+
# within the limits of this canvas.
|
230
|
+
# @see ChunkyPNG::Point.single
|
231
|
+
def include_point?(*point_like)
|
232
|
+
dimension.include?(ChunkyPNG::Point(*point_like))
|
172
233
|
end
|
173
234
|
|
174
|
-
alias_method :include?,
|
175
|
-
|
235
|
+
alias_method :include?, :include_point?
|
236
|
+
alias_method :include_xy?, :include_point?
|
237
|
+
|
176
238
|
# Checks whether the given y-coordinate is in the range of the canvas
|
177
239
|
# @param [Integer] y The y-coordinate of the pixel (row)
|
178
240
|
# @return [true, false] True if the y-coordinate is in the range of this canvas.
|
@@ -227,34 +289,44 @@ module ChunkyPNG
|
|
227
289
|
|
228
290
|
protected
|
229
291
|
|
292
|
+
# Replaces the image, given a new width, new height, and a new pixel array.
|
293
|
+
def replace_canvas!(new_width, new_height, new_pixels)
|
294
|
+
raise ChunkyPNG::ExpectationFailed, "The provided pixel array should have #{new_width * new_height} items" unless new_pixels.length == new_width * new_height
|
295
|
+
@width, @height, @pixels = new_width, new_height, new_pixels
|
296
|
+
return self
|
297
|
+
end
|
298
|
+
|
230
299
|
# Throws an exception if the x-coordinate is out of bounds.
|
231
300
|
def assert_x!(x)
|
232
|
-
raise ChunkyPNG::OutOfBounds, "Column index out of bounds!" unless include_x?(x)
|
301
|
+
raise ChunkyPNG::OutOfBounds, "Column index #{x} out of bounds!" unless include_x?(x)
|
233
302
|
return true
|
234
303
|
end
|
235
304
|
|
236
305
|
# Throws an exception if the y-coordinate is out of bounds.
|
237
306
|
def assert_y!(y)
|
238
|
-
raise ChunkyPNG::OutOfBounds, "Row index out of bounds!" unless include_y?(y)
|
307
|
+
raise ChunkyPNG::OutOfBounds, "Row index #{y} out of bounds!" unless include_y?(y)
|
239
308
|
return true
|
240
309
|
end
|
241
310
|
|
242
311
|
# Throws an exception if the x- or y-coordinate is out of bounds.
|
243
312
|
def assert_xy!(x, y)
|
244
|
-
raise ChunkyPNG::OutOfBounds, "Coordinates out of bounds!" unless include_xy?(x, y)
|
313
|
+
raise ChunkyPNG::OutOfBounds, "Coordinates (#{x},#{y}) out of bounds!" unless include_xy?(x, y)
|
245
314
|
return true
|
246
315
|
end
|
247
|
-
|
316
|
+
|
317
|
+
# Throws an exception if the vector_length does not match this canvas' height.
|
248
318
|
def assert_height!(vector_length)
|
249
|
-
raise ChunkyPNG::ExpectationFailed, "The length of the vector does not match the canvas height!" if height != vector_length
|
319
|
+
raise ChunkyPNG::ExpectationFailed, "The length of the vector (#{vector_length}) does not match the canvas height (#{height})!" if height != vector_length
|
250
320
|
return true
|
251
321
|
end
|
252
|
-
|
322
|
+
|
323
|
+
# Throws an exception if the vector_length does not match this canvas' width.
|
253
324
|
def assert_width!(vector_length)
|
254
|
-
raise ChunkyPNG::ExpectationFailed, "The length of the vector does not match the canvas width!" if width != vector_length
|
325
|
+
raise ChunkyPNG::ExpectationFailed, "The length of the vector (#{vector_length}) does not match the canvas width (#{width})!" if width != vector_length
|
255
326
|
return true
|
256
327
|
end
|
257
|
-
|
328
|
+
|
329
|
+
# Throws an exception if the matrix width and height does not match this canvas' dimensions.
|
258
330
|
def assert_size!(matrix_width, matrix_height)
|
259
331
|
raise ChunkyPNG::ExpectationFailed, "The width of the matrix does not match the canvas width!" if width != matrix_width
|
260
332
|
raise ChunkyPNG::ExpectationFailed, "The height of the matrix does not match the canvas height!" if height != matrix_height
|
@@ -1,63 +1,91 @@
|
|
1
1
|
module ChunkyPNG
|
2
2
|
class Canvas
|
3
3
|
|
4
|
+
# Module that adds some primitive drawing methods to {ChunkyPNG::Canvas}.
|
5
|
+
#
|
6
|
+
# All of these methods change the current canvas instance and do not create a new one,
|
7
|
+
# even though the method names do not end with a bang.
|
8
|
+
#
|
9
|
+
# @note Drawing operations will not fail when something is drawn outside of the bounds
|
10
|
+
# of the canvas; these pixels will simply be ignored.
|
11
|
+
# @see ChunkyPNG::Canvas
|
4
12
|
module Drawing
|
5
13
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
14
|
+
# Composes a pixel on the canvas by alpha blending a color with its background color.
|
15
|
+
# @overload compose_pixel(x, y, color)
|
16
|
+
# @param [Integer] x The x-coordinate of the pixel to blend.
|
17
|
+
# @param [Integer] y The y-coordinate of the pixel to blend.
|
18
|
+
# @param [Integer] color The foreground color to blend with
|
19
|
+
# @overload compose_pixel(point, color)
|
20
|
+
# @param [ChunkyPNG::Point, ...] point The point on the canvas to blend.
|
21
|
+
# @param [Integer] color The foreground color to blend with
|
22
|
+
def compose_pixel(*args)
|
23
|
+
point = args.length == 2 ? ChunkyPNG::Point(args.first) : ChunkyPNG::Point(args[0], args[1])
|
24
|
+
return unless include?(point)
|
25
|
+
set_pixel(point.x, point.y, ChunkyPNG::Color.compose(args.last, get_pixel(point.x, point.y)))
|
9
26
|
end
|
10
27
|
|
11
28
|
# Draws an anti-aliased line using Xiaolin Wu's algorithm.
|
12
29
|
#
|
13
|
-
|
14
|
-
|
30
|
+
# @param [Integer] x0 The x-coordinate of the first control point.
|
31
|
+
# @param [Integer] y0 The y-coordinate of the first control point.
|
32
|
+
# @param [Integer] x1 The x-coordinate of the second control point.
|
33
|
+
# @param [Integer] y1 The y-coordinate of the second control point.
|
34
|
+
# @param [Integer] stroke_color The color to use for this line.
|
35
|
+
# @param [true, false] inclusive Whether to draw the last pixel.
|
36
|
+
# Set to false when drawing multiplelines in a path.
|
37
|
+
# @return [ChunkyPNG::Canvas] Itself, with the line drawn.
|
38
|
+
def line_xiaolin_wu(x0, y0, x1, y1, stroke_color, inclusive = true)
|
15
39
|
dx = x1 - x0
|
16
40
|
sx = dx < 0 ? -1 : 1
|
17
41
|
dx *= sx
|
18
42
|
dy = y1 - y0
|
43
|
+
sy = dy < 0 ? -1 : 1
|
44
|
+
dy *= sy
|
19
45
|
|
20
46
|
if dy == 0 # vertical line
|
21
|
-
|
22
|
-
|
47
|
+
x0.step(inclusive ? x1 : x1 - sx, sx) do |x|
|
48
|
+
compose_pixel(x, y0, stroke_color)
|
23
49
|
end
|
50
|
+
|
24
51
|
elsif dx == 0 # horizontal line
|
25
|
-
(
|
26
|
-
|
52
|
+
y0.step(inclusive ? y1 : y1 - sy, sy) do |y|
|
53
|
+
compose_pixel(x0, y, stroke_color)
|
27
54
|
end
|
55
|
+
|
28
56
|
elsif dx == dy # diagonal
|
29
|
-
x0.step(x1, sx) do |x|
|
30
|
-
|
31
|
-
y0 +=
|
57
|
+
x0.step(inclusive ? x1 : x1 - sx, sx) do |x|
|
58
|
+
compose_pixel(x, y0, stroke_color)
|
59
|
+
y0 += sy
|
32
60
|
end
|
33
61
|
|
34
62
|
elsif dy > dx # vertical displacement
|
35
|
-
|
36
|
-
e_acc = 0
|
63
|
+
compose_pixel(x0, y0, stroke_color)
|
64
|
+
e_acc = 0
|
37
65
|
e = ((dx << 16) / dy.to_f).round
|
38
|
-
(
|
66
|
+
(dy - 1).downto(0) do |i|
|
39
67
|
e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xffff
|
40
|
-
x0
|
68
|
+
x0 += sx if (e_acc <= e_acc_temp)
|
41
69
|
w = 0xff - (e_acc >> 8)
|
42
|
-
|
43
|
-
|
44
|
-
|
70
|
+
compose_pixel(x0, y0, ChunkyPNG::Color.fade(stroke_color, w))
|
71
|
+
compose_pixel(x0 + sx, y0 + sy, ChunkyPNG::Color.fade(stroke_color, 0xff - w)) if inclusive || i > 0
|
72
|
+
y0 += sy
|
45
73
|
end
|
46
|
-
|
74
|
+
compose_pixel(x1, y1, stroke_color) if inclusive
|
47
75
|
|
48
76
|
else # horizontal displacement
|
49
|
-
|
77
|
+
compose_pixel(x0, y0, stroke_color)
|
50
78
|
e_acc = 0
|
51
|
-
e = (dy << 16) / dx
|
79
|
+
e = ((dy << 16) / dx.to_f).round
|
52
80
|
(dx - 1).downto(0) do |i|
|
53
81
|
e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xffff
|
54
|
-
y0 +=
|
82
|
+
y0 += sy if (e_acc <= e_acc_temp)
|
55
83
|
w = 0xff - (e_acc >> 8)
|
56
|
-
|
84
|
+
compose_pixel(x0, y0, ChunkyPNG::Color.fade(stroke_color, w))
|
85
|
+
compose_pixel(x0 + sx, y0 + sy, ChunkyPNG::Color.fade(stroke_color, 0xff - w)) if inclusive || i > 0
|
57
86
|
x0 += sx
|
58
|
-
point(x0, y0 + 1, ChunkyPNG::Color.fade(color, 0xff - w)) if include_xy?(x0, y0 + 1)
|
59
87
|
end
|
60
|
-
|
88
|
+
compose_pixel(x1, y1, stroke_color) if inclusive
|
61
89
|
end
|
62
90
|
|
63
91
|
return self
|
@@ -65,23 +93,136 @@ module ChunkyPNG
|
|
65
93
|
|
66
94
|
alias_method :line, :line_xiaolin_wu
|
67
95
|
|
68
|
-
|
96
|
+
|
97
|
+
# Draws a polygon on the canvas using the stroke_color, filled using the fill_color if any.
|
98
|
+
#
|
99
|
+
# @param [Array, String] The control point vector. Accepts everything {ChunkyPNG.Vector} accepts.
|
100
|
+
# @param [Integer] stroke_color The stroke color to use for this polygon.
|
101
|
+
# @param [Integer] fill_color The fill color to use for this polygon.
|
102
|
+
# @return [ChunkyPNG::Canvas] Itself, with the polygon drawn.
|
103
|
+
def polygon(path, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT)
|
104
|
+
|
105
|
+
vector = ChunkyPNG::Vector(*path)
|
106
|
+
raise ChunkyPNG::ExpectationFailed, "A polygon requires at least 3 points" if path.length < 3
|
107
|
+
|
108
|
+
# Fill
|
109
|
+
unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
110
|
+
vector.y_range.each do |y|
|
111
|
+
intersections = []
|
112
|
+
vector.edges.each do |p1, p2|
|
113
|
+
if (p1.y < y && p2.y >= y) || (p2.y < y && p1.y >= y)
|
114
|
+
intersections << (p1.x + (y - p1.y).to_f / (p2.y - p1.y) * (p2.x - p1.x)).round
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
intersections.sort!
|
119
|
+
0.step(intersections.length - 1, 2) do |i|
|
120
|
+
intersections[i].upto(intersections[i + 1]) do |x|
|
121
|
+
compose_pixel(x, y, fill_color)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Stroke
|
128
|
+
vector.each_edge do |(from_x, from_y), (to_x, to_y)|
|
129
|
+
line(from_x, from_y, to_x, to_y, stroke_color, false)
|
130
|
+
end
|
131
|
+
|
132
|
+
return self
|
133
|
+
end
|
134
|
+
|
135
|
+
# Draws a rectangle on the canvas, using two control points.
|
136
|
+
#
|
137
|
+
# @param [Integer] x0 The x-coordinate of the first control point.
|
138
|
+
# @param [Integer] y0 The y-coordinate of the first control point.
|
139
|
+
# @param [Integer] x1 The x-coordinate of the second control point.
|
140
|
+
# @param [Integer] y1 The y-coordinate of the second control point.
|
141
|
+
# @param [Integer] stroke_color The line color to use for this rectangle.
|
142
|
+
# @param [Integer] fill_color The fill color to use for this rectangle.
|
143
|
+
# @return [ChunkyPNG::Canvas] Itself, with the rectangle drawn.
|
144
|
+
def rect(x0, y0, x1, y1, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT)
|
69
145
|
|
70
146
|
# Fill
|
71
|
-
|
72
|
-
[
|
73
|
-
|
147
|
+
unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
148
|
+
[x0, x1].min.upto([x0, x1].max) do |x|
|
149
|
+
[y0, y1].min.upto([y0, y1].max) do |y|
|
150
|
+
compose_pixel(x, y, fill_color)
|
151
|
+
end
|
74
152
|
end
|
75
153
|
end
|
76
154
|
|
77
155
|
# Stroke
|
78
|
-
line(x0, y0, x0, y1,
|
79
|
-
line(x0, y1, x1, y1,
|
80
|
-
line(x1, y1, x1, y0,
|
81
|
-
line(x1, y0, x0, y0,
|
156
|
+
line(x0, y0, x0, y1, stroke_color, false)
|
157
|
+
line(x0, y1, x1, y1, stroke_color, false)
|
158
|
+
line(x1, y1, x1, y0, stroke_color, false)
|
159
|
+
line(x1, y0, x0, y0, stroke_color, false)
|
82
160
|
|
83
161
|
return self
|
84
162
|
end
|
163
|
+
|
164
|
+
# Draws a circle on the canvas.
|
165
|
+
#
|
166
|
+
# @param [Integer] x0 The x-coordinate of the center of the circle.
|
167
|
+
# @param [Integer] y0 The y-coordinate of the center of the circle.
|
168
|
+
# @param [Integer] radius The radius of the circle from the center point.
|
169
|
+
# @param [Integer] stroke_color The color to use for the line.
|
170
|
+
# @param [Integer] fill_color The color to use that fills the circle.
|
171
|
+
# @return [ChunkyPNG::Canvas] Itself, with the circle drawn.
|
172
|
+
def circle(x0, y0, radius, stroke_color = ChunkyPNG::Color::BLACK, fill_color = ChunkyPNG::Color::TRANSPARENT)
|
173
|
+
|
174
|
+
f = 1 - radius
|
175
|
+
ddF_x = 1
|
176
|
+
ddF_y = -2 * radius
|
177
|
+
x = 0
|
178
|
+
y = radius
|
179
|
+
|
180
|
+
compose_pixel(x0, y0 + radius, stroke_color)
|
181
|
+
compose_pixel(x0, y0 - radius, stroke_color)
|
182
|
+
compose_pixel(x0 + radius, y0, stroke_color)
|
183
|
+
compose_pixel(x0 - radius, y0, stroke_color)
|
184
|
+
|
185
|
+
lines = [radius - 1] unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
186
|
+
|
187
|
+
while x < y
|
188
|
+
|
189
|
+
if f >= 0
|
190
|
+
y -= 1
|
191
|
+
ddF_y += 2
|
192
|
+
f += ddF_y
|
193
|
+
end
|
194
|
+
|
195
|
+
x += 1
|
196
|
+
ddF_x += 2
|
197
|
+
f += ddF_x
|
198
|
+
|
199
|
+
unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
200
|
+
lines[y] = lines[y] ? [lines[y], x - 1].min : x - 1
|
201
|
+
lines[x] = lines[x] ? [lines[x], y - 1].min : y - 1
|
202
|
+
end
|
203
|
+
|
204
|
+
compose_pixel(x0 + x, y0 + y, stroke_color)
|
205
|
+
compose_pixel(x0 - x, y0 + y, stroke_color)
|
206
|
+
compose_pixel(x0 + x, y0 - y, stroke_color)
|
207
|
+
compose_pixel(x0 - x, y0 - y, stroke_color)
|
208
|
+
|
209
|
+
unless x == y
|
210
|
+
compose_pixel(x0 + y, y0 + x, stroke_color)
|
211
|
+
compose_pixel(x0 - y, y0 + x, stroke_color)
|
212
|
+
compose_pixel(x0 + y, y0 - x, stroke_color)
|
213
|
+
compose_pixel(x0 - y, y0 - x, stroke_color)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
unless fill_color == ChunkyPNG::Color::TRANSPARENT
|
218
|
+
lines.each_with_index do |length, y|
|
219
|
+
line(x0 - length, y0 - y, x0 + length, y0 - y, fill_color) if length > 0
|
220
|
+
line(x0 - length, y0 + y, x0 + length, y0 + y, fill_color) if length > 0 && y > 0
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
return self
|
225
|
+
end
|
85
226
|
end
|
86
227
|
end
|
87
228
|
end
|