chunky_png 1.0.0.beta2 → 1.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|