rmagick4j 0.3.4-java → 0.3.9-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/History.txt +84 -0
- data/LICENSE.txt +31 -0
- data/README.txt +25 -0
- data/Rakefile +65 -0
- data/lib/magick4j.jar +0 -0
- data/lib/{RMagick.rb → rmagick.rb} +574 -405
- data/lib/rmagick4j/constants.rb +34 -0
- data/lib/rmagick4j/draw.rb +124 -0
- data/lib/rmagick4j/enum.rb +120 -0
- data/lib/rmagick4j/gradient_fill.rb +14 -0
- data/lib/rmagick4j/image.rb +351 -0
- data/lib/rmagick4j/image_list.rb +25 -0
- data/lib/rmagick4j/pixel.rb +170 -0
- data/lib/rmagick4j/rmagick4j.rb +15 -430
- data/lib/rmagick4j/texture_fill.rb +14 -0
- data/lib/rmagick4j/type_metric.rb +8 -0
- data/lib/rmagick4j/version.rb +5 -0
- data/lib/rvg/clippath.rb +2 -2
- data/lib/rvg/container.rb +2 -2
- data/lib/rvg/describable.rb +2 -2
- data/lib/rvg/embellishable.rb +2 -2
- data/lib/rvg/misc.rb +3 -3
- data/lib/rvg/paint.rb +7 -2
- data/lib/rvg/pathdata.rb +2 -2
- data/lib/rvg/rvg.rb +3 -3
- data/lib/rvg/stretchable.rb +15 -3
- data/lib/rvg/stylable.rb +2 -2
- data/lib/rvg/text.rb +2 -2
- data/lib/rvg/transformable.rb +2 -2
- data/lib/rvg/units.rb +2 -2
- data/test/RMagickTestSuite.rb +129 -0
- data/test/eyetests/bullseye.rb +151 -0
- data/test/eyetests/doc.rb +79 -0
- data/test/eyetests/tests/draw_arc_basic.rb +16 -0
- data/test/eyetests/tests/draw_circle_affine.rb +19 -0
- data/test/eyetests/tests/draw_circle_basic.rb +16 -0
- data/test/eyetests/tests/draw_clip_path.rb +44 -0
- data/test/eyetests/tests/draw_ellipse_affine.rb +19 -0
- data/test/eyetests/tests/draw_ellipse_basic.rb +16 -0
- data/test/eyetests/tests/draw_line_affine.rb +24 -0
- data/test/eyetests/tests/draw_line_basic.rb +21 -0
- data/test/eyetests/tests/draw_multiline_type_metrics.rb +42 -0
- data/test/eyetests/tests/draw_pattern_1.rb +35 -0
- data/test/eyetests/tests/draw_polygon_affine.rb +22 -0
- data/test/eyetests/tests/draw_polygon_basic.rb +19 -0
- data/test/eyetests/tests/draw_polyline_affine.rb +19 -0
- data/test/eyetests/tests/draw_polyline_basic.rb +18 -0
- data/test/eyetests/tests/draw_pop_push.rb +16 -0
- data/test/eyetests/tests/draw_pop_push_translate.rb +22 -0
- data/test/eyetests/tests/draw_rectangle_affine.rb +16 -0
- data/test/eyetests/tests/draw_rectangle_basic.rb +16 -0
- data/test/eyetests/tests/draw_rectangle_narrow.rb +18 -0
- data/test/eyetests/tests/draw_rmagick_test_01.rb +35 -0
- data/test/eyetests/tests/draw_rmagick_test_02.rb +40 -0
- data/test/eyetests/tests/draw_rmagick_test_03.rb +17 -0
- data/test/eyetests/tests/draw_rmagick_test_04.rb +21 -0
- data/test/eyetests/tests/draw_rotate_01.rb +33 -0
- data/test/eyetests/tests/draw_roundrectangle_affine.rb +19 -0
- data/test/eyetests/tests/draw_roundrectangle_basic.rb +16 -0
- data/test/eyetests/tests/draw_scale_01.rb +33 -0
- data/test/eyetests/tests/draw_skewx_01.rb +34 -0
- data/test/eyetests/tests/draw_skewy_01.rb +33 -0
- data/test/eyetests/tests/draw_stroke_miterlimit.rb +21 -0
- data/test/eyetests/tests/effect_blur.rb +9 -0
- data/test/eyetests/tests/effect_charcoal.rb +9 -0
- data/test/eyetests/tests/effect_edge.rb +9 -0
- data/test/eyetests/tests/effect_implode.rb +9 -0
- data/test/eyetests/tests/effect_negate.rb +9 -0
- data/test/eyetests/tests/effect_negate_true.rb +9 -0
- data/test/eyetests/tests/effect_normalize.rb +9 -0
- data/test/eyetests/tests/effect_shade.rb +9 -0
- data/test/eyetests/tests/effect_solarize.rb +10 -0
- data/test/eyetests/tests/effect_wave.rb +9 -0
- data/test/eyetests/tests/gradient_fill_horizontal_diagonal_fill.rb +9 -0
- data/test/eyetests/tests/gradient_fill_horizontal_fill.rb +9 -0
- data/test/eyetests/tests/gradient_fill_point_fill.rb +9 -0
- data/test/eyetests/tests/gradient_fill_vertical_diagonal_fill.rb +9 -0
- data/test/eyetests/tests/gradient_fill_vertical_fill.rb +9 -0
- data/test/eyetests/tests/gruff_accumulator_bar.rb +29 -0
- data/test/eyetests/tests/gruff_area_1.rb +16 -0
- data/test/eyetests/tests/gruff_area_2.rb +27 -0
- data/test/eyetests/tests/gruff_bar_1.rb +29 -0
- data/test/eyetests/tests/gruff_bar_2.rb +19 -0
- data/test/eyetests/tests/gruff_dot_1.rb +19 -0
- data/test/eyetests/tests/gruff_line_1.rb +13 -0
- data/test/eyetests/tests/gruff_line_2.rb +20 -0
- data/test/eyetests/tests/gruff_net_1.rb +16 -0
- data/test/eyetests/tests/gruff_net_2.rb +16 -0
- data/test/eyetests/tests/gruff_pie_1.rb +21 -0
- data/test/eyetests/tests/gruff_pie_2.rb +22 -0
- data/test/eyetests/tests/gruff_scene_1.rb +14 -0
- data/test/eyetests/tests/gruff_scene_2.rb +14 -0
- data/test/eyetests/tests/gruff_sidebar.rb +32 -0
- data/test/eyetests/tests/gruff_sidestacked_bar_1.rb +26 -0
- data/test/eyetests/tests/gruff_sidestacked_bar_2.rb +26 -0
- data/test/eyetests/tests/gruff_spider_1.rb +22 -0
- data/test/eyetests/tests/gruff_spider_2.rb +15 -0
- data/test/eyetests/tests/gruff_stacked_area_1.rb +23 -0
- data/test/eyetests/tests/gruff_stacked_bar_1.rb +23 -0
- data/test/eyetests/tests/gruff_stacked_bar_2.rb +26 -0
- data/test/eyetests/tests/hatch_fill.rb +9 -0
- data/test/eyetests/tests/image_list_flatten_images.rb +15 -0
- data/test/eyetests/tests/new_image.rb +31 -0
- data/test/eyetests/tests/path_a_command_01.rb +16 -0
- data/test/eyetests/tests/path_a_command_02.rb +19 -0
- data/test/eyetests/tests/path_c_command_01.rb +16 -0
- data/test/eyetests/tests/path_c_command_02.rb +16 -0
- data/test/eyetests/tests/path_complex_01.rb +16 -0
- data/test/eyetests/tests/path_espiral_01.rb +29 -0
- data/test/eyetests/tests/path_h_command_01.rb +16 -0
- data/test/eyetests/tests/path_h_command_02.rb +16 -0
- data/test/eyetests/tests/path_l_command_01.rb +16 -0
- data/test/eyetests/tests/path_l_command_02.rb +16 -0
- data/test/eyetests/tests/path_m_command_01.rb +16 -0
- data/test/eyetests/tests/path_m_command_02.rb +16 -0
- data/test/eyetests/tests/path_m_command_03.rb +16 -0
- data/test/eyetests/tests/path_q_command_01.rb +16 -0
- data/test/eyetests/tests/path_q_command_02.rb +16 -0
- data/test/eyetests/tests/path_q_command_03.rb +25 -0
- data/test/eyetests/tests/path_s_command_01.rb +16 -0
- data/test/eyetests/tests/path_s_command_02.rb +16 -0
- data/test/eyetests/tests/path_star_01.rb +19 -0
- data/test/eyetests/tests/path_t_command_01.rb +16 -0
- data/test/eyetests/tests/path_t_command_02.rb +16 -0
- data/test/eyetests/tests/path_v_command_01.rb +16 -0
- data/test/eyetests/tests/path_v_command_02.rb +16 -0
- data/test/eyetests/tests/store_pixel_smiley.rb +123 -0
- data/test/eyetests/tests/texture_fill.rb +11 -0
- data/test/gruff_tests/test/gruff_test_case.rb +123 -0
- data/test/gruff_tests/test/monkey_gruff.rb +7 -0
- data/test/gruff_tests/test/test_accumulator_bar.rb +50 -0
- data/test/gruff_tests/test/test_area.rb +134 -0
- data/test/gruff_tests/test/test_bar.rb +295 -0
- data/test/gruff_tests/test/test_base.rb +8 -0
- data/test/gruff_tests/test/test_bullet.rb +26 -0
- data/test/gruff_tests/test/test_dot.rb +273 -0
- data/test/gruff_tests/test/test_legend.rb +68 -0
- data/test/gruff_tests/test/test_line.rb +554 -0
- data/test/gruff_tests/test/test_mini_bar.rb +33 -0
- data/test/gruff_tests/test/test_mini_pie.rb +20 -0
- data/test/gruff_tests/test/test_mini_side_bar.rb +37 -0
- data/test/gruff_tests/test/test_net.rb +230 -0
- data/test/gruff_tests/test/test_photo.rb +41 -0
- data/test/gruff_tests/test/test_pie.rb +154 -0
- data/test/gruff_tests/test/test_scene.rb +100 -0
- data/test/gruff_tests/test/test_side_bar.rb +12 -0
- data/test/gruff_tests/test/test_sidestacked_bar.rb +89 -0
- data/test/gruff_tests/test/test_spider.rb +216 -0
- data/test/gruff_tests/test/test_stacked_area.rb +52 -0
- data/test/gruff_tests/test/test_stacked_bar.rb +52 -0
- data/test/images/clown.jpg +0 -0
- data/test/images/texture.jpg +0 -0
- data/test/implemented_methods.rb +18 -0
- data/test/spec/draw_spec.rb +43 -0
- data/test/spec/features/step_definitions/geometry_steps.rb +22 -0
- data/test/spec/features/step_definitions/image_filling_steps.rb +49 -0
- data/test/spec/features/support/env.rb +3 -0
- data/test/spec/image_constants.rb +76 -0
- data/test/spec/image_spec.rb +83 -0
- data/test/spec/pixel_spec.rb +89 -0
- metadata +333 -45
- data/lib/RMagick.jar +0 -0
- data/lib/jhlabs-filters.jar +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f9fe85a77a4fd7dbca1d624dc8bcb95da616a9a8
|
4
|
+
data.tar.gz: afe8cb688221536949ff56d56ba3e6431dbc9e61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7181ab773dd7a4faf83bdbe39c9f80339a153aaa15329c765a83ca824fc4658b82fae6c8f00f289ee5a0d42cea27e07af1a9c094b8c9ff8a18f2c7997ffc23f3
|
7
|
+
data.tar.gz: c450e9072b1df82bc954cb6b80a60e60be0751760a075b44f2c566881c3f7ac00fcebad868b9b80938a797ffc38f5d1257f203241c0e1f9acc6357dbca2e842a
|
data/History.txt
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
== 0.3.5
|
2
|
+
|
3
|
+
- Implemented Draw primitives (affice, arc, pattern, path)
|
4
|
+
|
5
|
+
- Improved Image and ImageList:
|
6
|
+
- crop ( http://www.imagemagick.org/RMagick/doc/image1.html#crop )
|
7
|
+
- rotate ( http://www.imagemagick.org/RMagick/doc/image3.html#rotate )
|
8
|
+
- store_pixels (http://www.imagemagick.org/RMagick/doc/image3.html#store_pixels )
|
9
|
+
- flatten_images (http://www.imagemagick.org/RMagick/doc/ilist.html#flatten_images )
|
10
|
+
|
11
|
+
- Implemented more of Pixel (from_HSL, to_HSL, <=>, cmp, intensity)
|
12
|
+
|
13
|
+
- Implemented the fill classes (http://www.imagemagick.org/RMagick/doc/struct.html#fill )
|
14
|
+
|
15
|
+
- Added a side-by-side (MRI vs JRuby) image testing tool named Bullseye
|
16
|
+
|
17
|
+
- Added 680 color names. It can search, but not retrieve the name correctly capitalized.
|
18
|
+
|
19
|
+
== 0.3.4
|
20
|
+
|
21
|
+
- No bugfixes nor new features, just added compatibility with JRuby 1.1.
|
22
|
+
|
23
|
+
== 0.3.3
|
24
|
+
|
25
|
+
- This is a bug fix release to support updates to the string byte array conversion changes in recent versions of JRuby. This release was tested against JRuby 1.0.0RC3.
|
26
|
+
|
27
|
+
== 0.3.2
|
28
|
+
|
29
|
+
Full RMagick required for RMagick4J is included. The gem also includes JH Labs Filters and SVG Salamander, but they aren't much used yet.
|
30
|
+
|
31
|
+
Use it like so for now:
|
32
|
+
|
33
|
+
require 'rubygems'
|
34
|
+
gem PLATFORM == 'java' ? 'rmagick4j' : 'rmagick'
|
35
|
+
require 'RMagick'
|
36
|
+
|
37
|
+
Also see the project home page at http://code.google.com/p/rmagick4j/
|
38
|
+
|
39
|
+
== 0.3.1
|
40
|
+
|
41
|
+
Functionally equivalent to 0.3 release, but it supports JRuby 0.9.8 now. Also, it's a gem. It works along with a standard rmagick gem already installed (for those who keep gems in one place for multiple Ruby installs). For instance, I've tested this as working under both ruby and jruby:
|
42
|
+
|
43
|
+
require 'rubygems'
|
44
|
+
gem 'rmagick4j'
|
45
|
+
gem 'rmagick'
|
46
|
+
require 'gruff'
|
47
|
+
|
48
|
+
I hope to release a full rmagick gem in the near future for those who want to use apps unchanged and have a local GEM_HOME just for jruby.
|
49
|
+
|
50
|
+
== 0.3.0
|
51
|
+
|
52
|
+
More complete Draw features. Supports most Gruff Graphs unit tests.
|
53
|
+
|
54
|
+
== 0.2
|
55
|
+
|
56
|
+
More I/O support including basic handling of write, to_blob, and from_blob. Also upgraded RMagick libs to 1.14.0 and bundled JRuby to 0.9.1. Also reorganized the directory layout better. Moved JRuby files to its own folder. Moved draw support into magickjr package.
|
57
|
+
|
58
|
+
== 0.1
|
59
|
+
|
60
|
+
Hello,
|
61
|
+
|
62
|
+
I've tagged an "m1" release of RMagickJr. Here are the main good things to say about it:
|
63
|
+
|
64
|
+
- At varying degrees of quality and hackishness, it runs all these samples: http://rmagick.rubyforge.org/portfolio.html
|
65
|
+
- The build.xml works and by default shows a sample picture.
|
66
|
+
|
67
|
+
Put together, this means that other people might be able to run it, and they might be able to put it to some simple use. Well, except that it doesn't support real data export yet. It just displays pictures.
|
68
|
+
|
69
|
+
Here are some bad things to say about it:
|
70
|
+
|
71
|
+
- I've tested only on a Mac so far.
|
72
|
+
- Some things are super hacks, and some implementation is super shallow.
|
73
|
+
- Some of the pictures don't look quite right.
|
74
|
+
- Fixing some of what's off (especially the convolution/blurring) will be nontrivial for me.
|
75
|
+
- Some project organization is less than ideal. Still need to understand RubyGems, extensions/ext concepts, and rake better.
|
76
|
+
- Not much attention paid to super performance.
|
77
|
+
- My progress is slow, but that was expected.
|
78
|
+
- Probably a lot more.
|
79
|
+
|
80
|
+
But it's still progress, and I'm actually reading the pick axe (v2 - I'd looked at v1 online a few years ago), so maybe I'll start grokking the Ruby world better soon.
|
81
|
+
|
82
|
+
Maybe by m2 or m3 (or sometime), I could try to find a real app using RMagick and try to make it work with my version. For the next moment, though, I'll probably try tackling page 2 or 3 of the "portfolio" samples at the RMagick web site. And eventually go into class by class and method by method depth. Or something. I'm just trying to work with tracer bullets for now.
|
83
|
+
|
84
|
+
And I might rename the project to "rmagick4j" or "rmagick-jruby" or something at some point. Not sure what's best, so I'm sticking with "jr" for now. And that's an accurate representation for now, anyway.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
The file observer.rb comes from JRuby's distribution of standard Ruby libraries. The file jruby.jar also comes from the JRuby project.
|
2
|
+
|
3
|
+
RMagick.rb, clown.jpg, most of rmagick.gemspec, and the contents of rvg come from the RMagick project. Much of the content of the test demos (currently in "RMagickTestSuite.rb") come from the RMagick web site.
|
4
|
+
|
5
|
+
See these respective projects for the licenses and ownership of these files.
|
6
|
+
|
7
|
+
Other files lies under MIT license.
|
8
|
+
|
9
|
+
Copyright (c) 2010 Tom Palmer, Sergio Arbeo, Patrick Hurley, Karl Palmskog
|
10
|
+
|
11
|
+
Permission is hereby granted, free of charge, to any
|
12
|
+
person obtaining a copy of this software and associated
|
13
|
+
documentation files (the "Software"), to deal in the
|
14
|
+
Software without restriction, including without limitation
|
15
|
+
the rights to use, copy, modify, merge, publish,
|
16
|
+
distribute, sublicense, and/or sell copies of the
|
17
|
+
Software, and to permit persons to whom the Software is
|
18
|
+
furnished to do so, subject to the following conditions:
|
19
|
+
|
20
|
+
The above copyright notice and this permission notice
|
21
|
+
shall be included in all copies or substantial portions of
|
22
|
+
the Software.
|
23
|
+
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
25
|
+
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
26
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
27
|
+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
28
|
+
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
29
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
30
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
31
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.txt
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
RMagick is a Ruby binding to ImageMagick and GraphicsMagick. RMagick4J implements ImageMagick functionality and the C portions of RMagick for use with JRuby.
|
2
|
+
|
3
|
+
== Authors
|
4
|
+
|
5
|
+
This project was written by Thomas Palmer, Sergio Rodríguez Arbeo, and Thomas Enebo with lots of help from the JRuby community.
|
6
|
+
|
7
|
+
== License
|
8
|
+
|
9
|
+
The file observer.rb comes from JRuby's distribution of standard Ruby libraries. The file jruby.jar also comes from the JRuby project.
|
10
|
+
|
11
|
+
RMagick.rb, clown.jpg, most of rmagick.gemspec, and the contents of rvg come from the RMagick project. Much of the content of the test demos (currently in "RMagickTestSuite.rb") come from the RMagick web site.
|
12
|
+
|
13
|
+
See these respective projects for the licenses and ownership of these files.
|
14
|
+
|
15
|
+
Other files in RMagickJr are hereby placed in the public domain.
|
16
|
+
|
17
|
+
== Creating
|
18
|
+
|
19
|
+
To create a gem you should run rake. The useful targets are :clean, :compile, :gem, :release, :test (hoe has more -- see hoe docs). In order to run rake you must have hoe installed.
|
20
|
+
|
21
|
+
To create a new release, you should:
|
22
|
+
|
23
|
+
* Add new version entry to History.txt
|
24
|
+
* Update lib/rmagick4j/version.rb to contain new version
|
25
|
+
* rake release VERSION={{{{YOUR NEW VERSION (e.g. 1.1.1)}}}}
|
data/Rakefile
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
task :default => [:test, :gruff_test, :gem]
|
6
|
+
task :gem => :build
|
7
|
+
|
8
|
+
jar_file = File.join(%w(lib magick4j.jar))
|
9
|
+
|
10
|
+
desc 'Clean up any generated file.'
|
11
|
+
task :clean do
|
12
|
+
rm_rf 'pkg'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Run gruff unit tests.'
|
16
|
+
task :gruff_test do
|
17
|
+
FileList['test/gruff_tests/test/test_*.rb'].each do |file|
|
18
|
+
puts `ruby #{file}`
|
19
|
+
puts ''
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Run a live sample using RMagick4j.'
|
24
|
+
task :sample do
|
25
|
+
load_paths = '-Ijruby -Ilib -Ipkg'
|
26
|
+
sh "java #{classpath(jar_file)} org.jruby.Main #{load_paths} test/RMagickTestSuite.rb addWatermark"
|
27
|
+
end
|
28
|
+
|
29
|
+
task :spec do
|
30
|
+
require 'spec/rake/spectask'
|
31
|
+
desc 'Runs Java Integration Specs'
|
32
|
+
|
33
|
+
Spec::Rake::SpecTask.new do |t|
|
34
|
+
t.spec_opts ||= []
|
35
|
+
t.spec_files = if ENV['class'].nil?
|
36
|
+
FileList['test/spec/**']
|
37
|
+
else
|
38
|
+
File.join('test', 'spec', ENV['class']+'_spec.rb')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
task :stories do
|
45
|
+
if ENV['file'].nil?
|
46
|
+
FileList['test/spec/stories/**/*_runner.rb'].each do |runner|
|
47
|
+
require runner
|
48
|
+
end
|
49
|
+
else
|
50
|
+
require File.join('test', 'spec', 'stories', ENV['file']+'_runner.rb')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
%w(package install_gem debug_gem).each { |t| task t => :compile }
|
55
|
+
|
56
|
+
# helper methods below
|
57
|
+
|
58
|
+
def classpath(extra_jars=nil)
|
59
|
+
jruby_cpath = Java::java.lang.System.getProperty 'java.class.path'
|
60
|
+
path = jruby_cpath ? jruby_cpath.split(File::PATH_SEPARATOR) : []
|
61
|
+
path << FileList['lib/*.jar']
|
62
|
+
path << extra_jars.split(File::PATH_SEPARATOR) if extra_jars
|
63
|
+
"-cp #{path.flatten.join(File::PATH_SEPARATOR)}"
|
64
|
+
end
|
65
|
+
|
data/lib/magick4j.jar
CHANGED
Binary file
|
@@ -1,15 +1,15 @@
|
|
1
|
-
# $Id: RMagick.rb,v 1.
|
1
|
+
# $Id: RMagick.rb,v 1.80 2009/01/02 21:08:14 rmagick Exp $
|
2
2
|
#==============================================================================
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2008 by Timothy P. Hunter
|
4
4
|
# Name: RMagick.rb
|
5
5
|
# Author: Tim Hunter
|
6
6
|
# Purpose: Extend Ruby to interface with ImageMagick.
|
7
|
-
# Notes:
|
7
|
+
# Notes: RMagick2.so defines the classes. The code below adds methods
|
8
8
|
# to the classes.
|
9
9
|
#==============================================================================
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
require File.join(File.dirname(__FILE__), 'rmagick4j', 'rmagick4j.rb')
|
12
|
+
|
13
13
|
module Magick
|
14
14
|
@@formats = nil
|
15
15
|
|
@@ -23,79 +23,106 @@ def Magick.formats(&block)
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
class << self
|
27
|
+
attr_writer :trace_proc
|
28
|
+
end
|
26
29
|
|
27
30
|
# Geometry class and related enum constants
|
28
31
|
class GeometryValue < Enum
|
29
32
|
# no methods
|
30
33
|
end
|
31
34
|
|
32
|
-
PercentGeometry = GeometryValue.new(:PercentGeometry, 1)
|
33
|
-
AspectGeometry = GeometryValue.new(:AspectGeometry, 2)
|
34
|
-
LessGeometry = GeometryValue.new(:LessGeometry, 3)
|
35
|
-
GreaterGeometry = GeometryValue.new(:GreaterGeometry, 4)
|
36
|
-
AreaGeometry = GeometryValue.new(:AreaGeometry, 5)
|
35
|
+
PercentGeometry = GeometryValue.new(:PercentGeometry, 1).freeze
|
36
|
+
AspectGeometry = GeometryValue.new(:AspectGeometry, 2).freeze
|
37
|
+
LessGeometry = GeometryValue.new(:LessGeometry, 3).freeze
|
38
|
+
GreaterGeometry = GeometryValue.new(:GreaterGeometry, 4).freeze
|
39
|
+
AreaGeometry = GeometryValue.new(:AreaGeometry, 5).freeze
|
40
|
+
MinimumGeometry = GeometryValue.new(:MinimumGeometry, 6).freeze
|
37
41
|
|
38
42
|
class Geometry
|
39
|
-
FLAGS = ['', '%', '!', '<', '>', '@']
|
43
|
+
FLAGS = ['', '%', '!', '<', '>', '@', '^']
|
40
44
|
RFLAGS = { '%' => PercentGeometry,
|
41
45
|
'!' => AspectGeometry,
|
42
46
|
'<' => LessGeometry,
|
43
47
|
'>' => GreaterGeometry,
|
44
|
-
'@' => AreaGeometry
|
48
|
+
'@' => AreaGeometry,
|
49
|
+
'^' => MinimumGeometry }
|
45
50
|
|
46
51
|
attr_accessor :width, :height, :x, :y, :flag
|
47
52
|
|
48
53
|
def initialize(width=nil, height=nil, x=nil, y=nil, flag=nil)
|
54
|
+
raise(ArgumentError, "width set to #{width.to_s}") if width.is_a? GeometryValue
|
55
|
+
raise(ArgumentError, "height set to #{height.to_s}") if height.is_a? GeometryValue
|
56
|
+
raise(ArgumentError, "x set to #{x.to_s}") if x.is_a? GeometryValue
|
57
|
+
raise(ArgumentError, "y set to #{y.to_s}") if y.is_a? GeometryValue
|
49
58
|
|
50
59
|
# Support floating-point width and height arguments so Geometry
|
51
60
|
# objects can be used to specify Image#density= arguments.
|
52
|
-
if width
|
53
|
-
|
54
|
-
elsif width
|
55
|
-
|
56
|
-
else
|
57
|
-
Kernel.raise ArgumentError, "width must be >= 0: #{width}"
|
61
|
+
if width && width.to_f >= 0.0
|
62
|
+
@width = width.to_f
|
63
|
+
elsif width
|
64
|
+
Kernel.raise ArgumentError, "width must be >= 0: #{width}"
|
58
65
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
Kernel.raise ArgumentError, "height must be >= 0: #{height}"
|
66
|
+
|
67
|
+
if height && height.to_f >= 0.0
|
68
|
+
@height = height.to_f
|
69
|
+
elsif height
|
70
|
+
Kernel.raise ArgumentError, "height must be >= 0: #{height}"
|
65
71
|
end
|
66
72
|
|
67
73
|
@x = x.to_i
|
68
74
|
@y = y.to_i
|
69
75
|
@flag = flag
|
76
|
+
|
70
77
|
end
|
71
78
|
|
72
79
|
# Construct an object from a geometry string
|
73
|
-
|
80
|
+
W = /(\d+\.\d+%?)|(\d*%?)/
|
81
|
+
H = W
|
82
|
+
X = /(?:([-+]\d+))?/
|
83
|
+
Y = X
|
84
|
+
RE = /\A#{W}x?#{H}#{X}#{Y}([!<>@\^]?)\Z/
|
74
85
|
|
75
86
|
def Geometry.from_s(str)
|
76
|
-
Kernel.raise(ArgumentError, "no geometry string specified") unless str
|
77
|
-
|
78
87
|
m = RE.match(str)
|
79
88
|
if m
|
80
|
-
width = m[1].
|
81
|
-
height = m[
|
82
|
-
x = m[
|
83
|
-
y = m[
|
84
|
-
flag = RFLAGS[m[
|
89
|
+
width = m[1].nil? && m[2].empty? ? nil : (m[1] || m[2]).to_f
|
90
|
+
height = m[3].nil? && m[4].empty? ? nil : (m[3] || m[4]).to_f
|
91
|
+
x = m[5].to_i
|
92
|
+
y = m[6].to_i
|
93
|
+
flag = RFLAGS[m[7]]
|
85
94
|
else
|
86
95
|
Kernel.raise ArgumentError, "invalid geometry format"
|
87
96
|
end
|
97
|
+
if str['%']
|
98
|
+
flag = PercentGeometry
|
99
|
+
end
|
88
100
|
Geometry.new(width, height, x, y, flag)
|
89
101
|
end
|
90
102
|
|
91
103
|
# Convert object to a geometry string
|
92
104
|
def to_s
|
93
105
|
str = ''
|
94
|
-
|
95
|
-
|
96
|
-
|
106
|
+
if @width && @width > 0
|
107
|
+
fmt = @width.truncate == @width ? "%d" : "%.2f"
|
108
|
+
str << sprintf(fmt, @width)
|
109
|
+
str << '%' if @flag == PercentGeometry
|
110
|
+
end
|
111
|
+
|
112
|
+
if (@width && @width > 0 && @flag != PercentGeometry) || (@height && @height > 0)
|
113
|
+
str << 'x'
|
114
|
+
end
|
115
|
+
|
116
|
+
if @height && @height > 0
|
117
|
+
fmt = @height.truncate == @height ? "%d" : "%.2f"
|
118
|
+
str << sprintf(fmt, @height)
|
119
|
+
str << '%' if @flag == PercentGeometry
|
120
|
+
end
|
97
121
|
str << sprintf("%+d%+d", @x, @y) if (@x != 0 || @y != 0)
|
98
|
-
|
122
|
+
if @flag != PercentGeometry
|
123
|
+
str << FLAGS[@flag.to_i]
|
124
|
+
end
|
125
|
+
str
|
99
126
|
end
|
100
127
|
end
|
101
128
|
|
@@ -250,7 +277,7 @@ class Draw
|
|
250
277
|
def define_clip_path(name)
|
251
278
|
begin
|
252
279
|
push('defs')
|
253
|
-
push('clip-path
|
280
|
+
push('clip-path', name)
|
254
281
|
push('graphic-context')
|
255
282
|
yield
|
256
283
|
ensure
|
@@ -333,6 +360,30 @@ class Draw
|
|
333
360
|
primitive "gravity #{GRAVITY_NAMES[grav.to_i]}"
|
334
361
|
end
|
335
362
|
|
363
|
+
# IM 6.4.8-3 and later
|
364
|
+
def interword_spacing(space)
|
365
|
+
begin
|
366
|
+
Float(space)
|
367
|
+
rescue ArgumentError
|
368
|
+
Kernel.raise ArgumentError, "invalid value for interword_spacing"
|
369
|
+
rescue TypeError
|
370
|
+
Kernel.raise TypeError, "can't convert #{space.class} into Float"
|
371
|
+
end
|
372
|
+
primitive "interword-spacing #{space}"
|
373
|
+
end
|
374
|
+
|
375
|
+
# IM 6.4.8-3 and later
|
376
|
+
def kerning(space)
|
377
|
+
begin
|
378
|
+
Float(space)
|
379
|
+
rescue ArgumentError
|
380
|
+
Kernel.raise ArgumentError, "invalid value for kerning"
|
381
|
+
rescue TypeError
|
382
|
+
Kernel.raise TypeError, "can't convert #{space.class} into Float"
|
383
|
+
end
|
384
|
+
primitive "kerning #{space}"
|
385
|
+
end
|
386
|
+
|
336
387
|
# Draw a line
|
337
388
|
def line(startX, startY, endX, endY)
|
338
389
|
primitive "line " + sprintf("%g,%g %g,%g", startX, startY, endX, endY)
|
@@ -424,7 +475,7 @@ class Draw
|
|
424
475
|
primitive "pop graphic-context"
|
425
476
|
else
|
426
477
|
# to_s allows a Symbol to be used instead of a String
|
427
|
-
primitive "pop " + what.to_s
|
478
|
+
primitive "pop " + what.map {|w| w.to_s}.join(' ')
|
428
479
|
end
|
429
480
|
end
|
430
481
|
|
@@ -438,7 +489,7 @@ class Draw
|
|
438
489
|
primitive "push graphic-context"
|
439
490
|
else
|
440
491
|
# to_s allows a Symbol to be used instead of a String
|
441
|
-
primitive "push " + what.to_s
|
492
|
+
primitive "push " + what.map {|w| w.to_s}.join(' ')
|
442
493
|
end
|
443
494
|
end
|
444
495
|
|
@@ -612,7 +663,7 @@ module IPTC
|
|
612
663
|
end
|
613
664
|
|
614
665
|
module Application
|
615
|
-
|
666
|
+
Record_Version = "2:00"
|
616
667
|
Object_Type_Reference = "2:03"
|
617
668
|
Object_Name = "2:05"
|
618
669
|
Title = "2:05"
|
@@ -703,9 +754,12 @@ end # module Magick::IPTC
|
|
703
754
|
class Image
|
704
755
|
include Comparable
|
705
756
|
|
757
|
+
alias_method :affinity, :remap
|
758
|
+
|
706
759
|
# Provide an alternate version of Draw#annotate, for folks who
|
707
760
|
# want to find it in this class.
|
708
761
|
def annotate(draw, width, height, x, y, text, &block)
|
762
|
+
check_destroyed
|
709
763
|
draw.annotate(self, width, height, x, y, text, &block)
|
710
764
|
self
|
711
765
|
end
|
@@ -746,26 +800,19 @@ class Image
|
|
746
800
|
self
|
747
801
|
end
|
748
802
|
|
749
|
-
# Force an image to exact dimensions without changing the aspect ratio.
|
750
|
-
# Resize and crop if necessary. (Thanks to Jerett Taylor!)
|
751
|
-
def crop_resized(ncols, nrows, gravity=CenterGravity)
|
752
|
-
copy.crop_resized!(ncols, nrows, gravity)
|
753
|
-
end
|
754
|
-
|
755
|
-
def crop_resized!(ncols, nrows, gravity=CenterGravity)
|
756
|
-
if ncols != columns || nrows != rows
|
757
|
-
scale = [ncols/columns.to_f, nrows/rows.to_f].max
|
758
|
-
resize!(scale*columns+0.5, scale*rows+0.5)
|
759
|
-
end
|
760
|
-
crop!(gravity, ncols, nrows, true) if ncols != columns || nrows != rows
|
761
|
-
self
|
762
|
-
end
|
763
|
-
|
764
803
|
# Used by ImageList methods - see ImageList#cur_image
|
765
804
|
def cur_image
|
766
805
|
self
|
767
806
|
end
|
768
807
|
|
808
|
+
# Thanks to Russell Norris!
|
809
|
+
def each_pixel
|
810
|
+
get_pixels(0, 0, columns, rows).each_with_index do |p, n|
|
811
|
+
yield(p, n%columns, n/columns)
|
812
|
+
end
|
813
|
+
self
|
814
|
+
end
|
815
|
+
|
769
816
|
# Retrieve EXIF data by entry or all. If one or more entry names specified,
|
770
817
|
# return the values associated with the entries. If no entries specified,
|
771
818
|
# return all entries and values. The return value is an array of [name,value]
|
@@ -778,6 +825,7 @@ class Image
|
|
778
825
|
exif_data.split("\n").each { |exif| ary.push(exif.split('=')) }
|
779
826
|
end
|
780
827
|
else
|
828
|
+
get_exif_by_entry() # ensure properties is populated with exif data
|
781
829
|
entry.each do |name|
|
782
830
|
rval = self["EXIF:#{name}"]
|
783
831
|
ary.push([name, rval])
|
@@ -799,8 +847,9 @@ class Image
|
|
799
847
|
end
|
800
848
|
end
|
801
849
|
else
|
850
|
+
get_exif_by_number() # ensure properties is populated with exif data
|
802
851
|
tag.each do |num|
|
803
|
-
rval = self[
|
852
|
+
rval = self['#%04X' % num.to_i]
|
804
853
|
hash[num] = rval == 'unknown' ? nil : rval
|
805
854
|
end
|
806
855
|
end
|
@@ -841,7 +890,7 @@ class Image
|
|
841
890
|
def level(black_point=0.0, white_point=nil, gamma=nil)
|
842
891
|
black_point = Float(black_point)
|
843
892
|
|
844
|
-
white_point ||= Magick::
|
893
|
+
white_point ||= Magick::QuantumRange - black_point
|
845
894
|
white_point = Float(white_point)
|
846
895
|
|
847
896
|
gamma_arg = gamma
|
@@ -851,7 +900,7 @@ class Image
|
|
851
900
|
if gamma.abs > 10.0 || white_point.abs <= 10.0 || white_point.abs < gamma.abs
|
852
901
|
gamma, white_point = white_point, gamma
|
853
902
|
unless gamma_arg
|
854
|
-
white_point = Magick::
|
903
|
+
white_point = Magick::QuantumRange - black_point
|
855
904
|
end
|
856
905
|
end
|
857
906
|
|
@@ -915,15 +964,37 @@ class Image
|
|
915
964
|
resize(width, height)
|
916
965
|
end
|
917
966
|
|
967
|
+
# Force an image to exact dimensions without changing the aspect ratio.
|
968
|
+
# Resize and crop if necessary. (Thanks to Jerett Taylor!)
|
969
|
+
def resize_to_fill(ncols, nrows=nil, gravity=CenterGravity)
|
970
|
+
copy.resize_to_fill!(ncols, nrows, gravity)
|
971
|
+
end
|
972
|
+
|
973
|
+
def resize_to_fill!(ncols, nrows=nil, gravity=CenterGravity)
|
974
|
+
nrows ||= ncols
|
975
|
+
if ncols != columns || nrows != rows
|
976
|
+
scale = [ncols/columns.to_f, nrows/rows.to_f].max
|
977
|
+
resize!(scale*columns+0.5, scale*rows+0.5)
|
978
|
+
end
|
979
|
+
crop!(gravity, ncols, nrows, true) if ncols != columns || nrows != rows
|
980
|
+
self
|
981
|
+
end
|
982
|
+
|
983
|
+
# Preserve aliases used < RMagick 2.0.1
|
984
|
+
alias_method :crop_resized, :resize_to_fill
|
985
|
+
alias_method :crop_resized!, :resize_to_fill!
|
986
|
+
|
918
987
|
# Convenience method to resize retaining the aspect ratio.
|
919
988
|
# (Thanks to Robert Manni!)
|
920
|
-
def resize_to_fit(cols, rows)
|
989
|
+
def resize_to_fit(cols, rows=nil)
|
990
|
+
rows ||= cols
|
921
991
|
change_geometry(Geometry.new(cols, rows)) do |ncols, nrows|
|
922
992
|
resize(ncols, nrows)
|
923
993
|
end
|
924
994
|
end
|
925
995
|
|
926
|
-
def resize_to_fit!(cols, rows)
|
996
|
+
def resize_to_fit!(cols, rows=nil)
|
997
|
+
rows ||= cols
|
927
998
|
change_geometry(Geometry.new(cols, rows)) do |ncols, nrows|
|
928
999
|
resize!(ncols, nrows)
|
929
1000
|
end
|
@@ -963,6 +1034,7 @@ class Image
|
|
963
1034
|
attr_accessor :dirty
|
964
1035
|
|
965
1036
|
def initialize(img, x, y, width, height)
|
1037
|
+
img.check_destroyed
|
966
1038
|
if width <= 0 || height <= 0
|
967
1039
|
Kernel.raise ArgumentError, "invalid geometry (#{width}x#{height}+#{x}+#{y})"
|
968
1040
|
end
|
@@ -1194,24 +1266,21 @@ class Image
|
|
1194
1266
|
|
1195
1267
|
end # class Magick::Image
|
1196
1268
|
|
1197
|
-
class ImageList
|
1269
|
+
class ImageList
|
1198
1270
|
|
1199
1271
|
include Comparable
|
1272
|
+
include Enumerable
|
1273
|
+
attr_reader :scene
|
1200
1274
|
|
1201
|
-
|
1202
|
-
undef_method :flatten! # These methods are undefined
|
1203
|
-
undef_method :flatten # because they're not useful
|
1204
|
-
undef_method :join # for an ImageList object
|
1205
|
-
undef_method :pack
|
1206
|
-
undef_method :rassoc
|
1207
|
-
undef_method :transpose if Array.instance_methods(false).include? 'transpose'
|
1208
|
-
undef_method :zip if Array.instance_methods(false).include? 'zip'
|
1275
|
+
private
|
1209
1276
|
|
1210
|
-
|
1277
|
+
def get_current()
|
1278
|
+
return @images[@scene].__id__ rescue nil
|
1279
|
+
end
|
1211
1280
|
|
1212
1281
|
protected
|
1213
1282
|
|
1214
|
-
def
|
1283
|
+
def is_an_image(obj)
|
1215
1284
|
unless obj.kind_of? Magick::Image
|
1216
1285
|
Kernel.raise ArgumentError, "Magick::Image required (#{obj.class} given)"
|
1217
1286
|
end
|
@@ -1219,33 +1288,36 @@ protected
|
|
1219
1288
|
end
|
1220
1289
|
|
1221
1290
|
# Ensure array is always an array of Magick::Image objects
|
1222
|
-
def
|
1291
|
+
def is_an_image_array(ary)
|
1223
1292
|
unless ary.respond_to? :each
|
1224
1293
|
Kernel.raise ArgumentError, "Magick::ImageList or array of Magick::Images required (#{ary.class} given)"
|
1225
1294
|
end
|
1226
|
-
ary.each { |obj|
|
1295
|
+
ary.each { |obj| is_an_image obj }
|
1227
1296
|
true
|
1228
1297
|
end
|
1229
1298
|
|
1230
|
-
# Find old current image, update
|
1231
|
-
#
|
1232
|
-
def
|
1233
|
-
if length == 0
|
1234
|
-
|
1299
|
+
# Find old current image, update scene number
|
1300
|
+
# current is the id of the old current image.
|
1301
|
+
def set_current(current)
|
1302
|
+
if length() == 0
|
1303
|
+
self.scene = nil
|
1235
1304
|
return
|
1236
1305
|
# Don't bother looking for current image
|
1237
|
-
elsif
|
1238
|
-
|
1306
|
+
elsif scene() == nil || scene() >= length()
|
1307
|
+
self.scene = length() - 1
|
1239
1308
|
return
|
1240
|
-
elsif
|
1309
|
+
elsif current != nil
|
1310
|
+
# Find last instance of "current" in the list.
|
1311
|
+
# If "current" isn't in the list, set current to last image.
|
1312
|
+
self.scene = length() - 1
|
1241
1313
|
each_with_index do |f,i|
|
1242
|
-
if f.__id__ ==
|
1243
|
-
|
1244
|
-
return
|
1314
|
+
if f.__id__ == current
|
1315
|
+
self.scene = i
|
1245
1316
|
end
|
1246
1317
|
end
|
1318
|
+
return
|
1247
1319
|
end
|
1248
|
-
|
1320
|
+
self.scene = length() - 1
|
1249
1321
|
end
|
1250
1322
|
|
1251
1323
|
public
|
@@ -1253,10 +1325,10 @@ public
|
|
1253
1325
|
# Allow scene to be set to nil
|
1254
1326
|
def scene=(n)
|
1255
1327
|
if n.nil?
|
1256
|
-
Kernel.raise IndexError, "scene number out of bounds" unless length == 0
|
1328
|
+
Kernel.raise IndexError, "scene number out of bounds" unless @images.length == 0
|
1257
1329
|
@scene = nil
|
1258
1330
|
return @scene
|
1259
|
-
elsif length == 0
|
1331
|
+
elsif @images.length == 0
|
1260
1332
|
Kernel.raise IndexError, "scene number out of bounds"
|
1261
1333
|
end
|
1262
1334
|
|
@@ -1268,307 +1340,46 @@ public
|
|
1268
1340
|
return @scene
|
1269
1341
|
end
|
1270
1342
|
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1343
|
+
# All the binary operators work the same way.
|
1344
|
+
# 'other' should be either an ImageList or an Array
|
1345
|
+
%w{& + - |}.each do |op|
|
1346
|
+
module_eval <<-END_BINOPS
|
1347
|
+
def #{op}(other)
|
1348
|
+
ilist = self.class.new
|
1349
|
+
begin
|
1350
|
+
a = other #{op} @images
|
1351
|
+
rescue TypeError
|
1352
|
+
Kernel.raise ArgumentError, "Magick::ImageList expected, got " + other.class.to_s
|
1353
|
+
end
|
1354
|
+
current = get_current()
|
1355
|
+
a.each do |image|
|
1356
|
+
is_an_image image
|
1357
|
+
ilist << image
|
1358
|
+
end
|
1359
|
+
ilist.set_current current
|
1360
|
+
return ilist
|
1289
1361
|
end
|
1290
|
-
|
1291
|
-
args[1].kind_of?(Magick::Image) || is_a_image_array(args[1])
|
1292
|
-
super
|
1293
|
-
@scene = args[0].end
|
1294
|
-
else # f[index] = f1
|
1295
|
-
is_a_image args[1]
|
1296
|
-
super # index can be negative
|
1297
|
-
@scene = args[0] < 0 ? length + args[0] : args[0]
|
1298
|
-
end
|
1299
|
-
args.last # return value is always assigned value
|
1300
|
-
end
|
1301
|
-
|
1302
|
-
def &(other)
|
1303
|
-
is_a_image_array other
|
1304
|
-
cfid = self[@scene].__id__ rescue nil
|
1305
|
-
a = self.class.new.replace super
|
1306
|
-
a.set_cf cfid
|
1307
|
-
return a
|
1362
|
+
END_BINOPS
|
1308
1363
|
end
|
1309
1364
|
|
1310
1365
|
def *(n)
|
1311
1366
|
unless n.kind_of? Integer
|
1312
1367
|
Kernel.raise ArgumentError, "Integer required (#{n.class} given)"
|
1313
1368
|
end
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
def +(other)
|
1321
|
-
cfid = self[@scene].__id__ rescue nil
|
1322
|
-
a = self.class.new.replace super
|
1323
|
-
a.set_cf cfid
|
1324
|
-
return a
|
1325
|
-
end
|
1326
|
-
|
1327
|
-
def -(other)
|
1328
|
-
is_a_image_array other
|
1329
|
-
cfid = self[@scene].__id__ rescue nil
|
1330
|
-
a = self.class.new.replace super
|
1331
|
-
a.set_cf cfid
|
1332
|
-
return a
|
1369
|
+
current = get_current()
|
1370
|
+
ilist = self.class.new
|
1371
|
+
(@images * n).each {|image| ilist << image}
|
1372
|
+
ilist.set_current current
|
1373
|
+
return ilist
|
1333
1374
|
end
|
1334
1375
|
|
1335
1376
|
def <<(obj)
|
1336
|
-
|
1337
|
-
|
1338
|
-
@scene = length-1
|
1339
|
-
return a
|
1340
|
-
end
|
1341
|
-
|
1342
|
-
def |(other)
|
1343
|
-
is_a_image_array other
|
1344
|
-
cfid = self[@scene].__id__ rescue nil
|
1345
|
-
a = self.class.new.replace super
|
1346
|
-
a.set_cf cfid
|
1347
|
-
return a
|
1348
|
-
end
|
1349
|
-
|
1350
|
-
def clear
|
1351
|
-
@scene = nil
|
1352
|
-
super
|
1353
|
-
end
|
1354
|
-
|
1355
|
-
def collect(&block)
|
1356
|
-
cfid = self[@scene].__id__ rescue nil
|
1357
|
-
a = self.class.new.replace super
|
1358
|
-
a.set_cf cfid
|
1359
|
-
return a
|
1360
|
-
end
|
1361
|
-
|
1362
|
-
def collect!(&block)
|
1363
|
-
super
|
1364
|
-
is_a_image_array self
|
1377
|
+
is_an_image obj
|
1378
|
+
@images << obj
|
1379
|
+
@scene = @images.length - 1
|
1365
1380
|
self
|
1366
1381
|
end
|
1367
1382
|
|
1368
|
-
def compact
|
1369
|
-
cfid = self[@scene].__id__ rescue nil
|
1370
|
-
a = self.class.new.replace super
|
1371
|
-
a.set_cf cfid
|
1372
|
-
return a
|
1373
|
-
end
|
1374
|
-
|
1375
|
-
def compact!
|
1376
|
-
cfid = self[@scene].__id__ rescue nil
|
1377
|
-
a = super # returns nil if no changes were made
|
1378
|
-
set_cf cfid
|
1379
|
-
return a
|
1380
|
-
end
|
1381
|
-
|
1382
|
-
def concat(other)
|
1383
|
-
is_a_image_array other
|
1384
|
-
a = super
|
1385
|
-
@scene = length-1
|
1386
|
-
return a
|
1387
|
-
end
|
1388
|
-
|
1389
|
-
def delete(obj, &block)
|
1390
|
-
is_a_image obj
|
1391
|
-
cfid = self[@scene].__id__ rescue nil
|
1392
|
-
a = super
|
1393
|
-
set_cf cfid
|
1394
|
-
return a
|
1395
|
-
end
|
1396
|
-
|
1397
|
-
def delete_at(ndx)
|
1398
|
-
cfid = self[@scene].__id__ rescue nil
|
1399
|
-
a = super
|
1400
|
-
set_cf cfid
|
1401
|
-
return a
|
1402
|
-
end
|
1403
|
-
|
1404
|
-
def delete_if(&block)
|
1405
|
-
cfid = self[@scene].__id__ rescue nil
|
1406
|
-
a = super
|
1407
|
-
set_cf cfid
|
1408
|
-
return a
|
1409
|
-
end
|
1410
|
-
|
1411
|
-
def fill(*args, &block)
|
1412
|
-
is_a_image args[0] unless block_given?
|
1413
|
-
cfid = self[@scene].__id__ rescue nil
|
1414
|
-
super
|
1415
|
-
is_a_image_array self
|
1416
|
-
set_cf cfid
|
1417
|
-
return self
|
1418
|
-
end
|
1419
|
-
|
1420
|
-
def find_all(&block)
|
1421
|
-
cfid = self[@scene].__id__ rescue nil
|
1422
|
-
a = super
|
1423
|
-
a.set_cf cfid
|
1424
|
-
return a
|
1425
|
-
end
|
1426
|
-
|
1427
|
-
if self.superclass.instance_methods(true).include? 'insert' then
|
1428
|
-
def insert(*args)
|
1429
|
-
Kernel.raise(ArgumentError, "can't insert nil") unless args.length > 1
|
1430
|
-
is_a_image_array args[1,args.length-1]
|
1431
|
-
cfid = self[@scene].__id__ rescue nil
|
1432
|
-
super
|
1433
|
-
set_cf cfid
|
1434
|
-
return self
|
1435
|
-
end
|
1436
|
-
end
|
1437
|
-
|
1438
|
-
# Enumerable (or Array) has a #map method that conflicts with our
|
1439
|
-
# own #map method. RMagick.so has defined a synonym for that #map
|
1440
|
-
# called Array#__ary_map__. Here, we define Magick::ImageList#__map__
|
1441
|
-
# to allow the use of the Enumerable/Array#map method on ImageList objects.
|
1442
|
-
def __map__(&block)
|
1443
|
-
cfid = self[@scene].__id__ rescue nil
|
1444
|
-
ensure_image = Proc.new do |img|
|
1445
|
-
rv = block.call(img)
|
1446
|
-
is_a_image rv
|
1447
|
-
return rv
|
1448
|
-
end
|
1449
|
-
a = self.class.new.replace __ary_map__(&ensure_image)
|
1450
|
-
a.set_cf cfid
|
1451
|
-
return a
|
1452
|
-
end
|
1453
|
-
|
1454
|
-
def map!(&block)
|
1455
|
-
ensure_image = Proc.new do |img|
|
1456
|
-
rv = block.call(img)
|
1457
|
-
is_a_image rv
|
1458
|
-
return rv
|
1459
|
-
end
|
1460
|
-
super(&ensure_image)
|
1461
|
-
end
|
1462
|
-
|
1463
|
-
def pop
|
1464
|
-
cfid = self[@scene].__id__ rescue nil
|
1465
|
-
a = super # can return nil
|
1466
|
-
set_cf cfid
|
1467
|
-
return a
|
1468
|
-
end
|
1469
|
-
|
1470
|
-
def push(*objs)
|
1471
|
-
objs.each { |o| is_a_image o }
|
1472
|
-
super
|
1473
|
-
@scene = length - 1
|
1474
|
-
self
|
1475
|
-
end
|
1476
|
-
|
1477
|
-
def reject(&block)
|
1478
|
-
cfid = self[@scene].__id__ rescue nil
|
1479
|
-
a = self.class.new.replace super
|
1480
|
-
a.set_cf cfid
|
1481
|
-
return a
|
1482
|
-
end
|
1483
|
-
|
1484
|
-
def reject!(&block)
|
1485
|
-
cfid = self[@scene].__id__ rescue nil
|
1486
|
-
a = super # can return nil
|
1487
|
-
set_cf cfid
|
1488
|
-
return a
|
1489
|
-
end
|
1490
|
-
|
1491
|
-
def replace(other)
|
1492
|
-
is_a_image_array other
|
1493
|
-
# Since replace gets called so frequently when @scene == nil
|
1494
|
-
# test for it instead of letting rescue catch it.
|
1495
|
-
cfid = nil
|
1496
|
-
if @scene then
|
1497
|
-
cfid = self[@scene].__id__ rescue nil
|
1498
|
-
end
|
1499
|
-
super
|
1500
|
-
# set_cf will fail if the new list has fewer images
|
1501
|
-
# than the scene number indicates.
|
1502
|
-
@scene = self.length == 0 ? nil : 0
|
1503
|
-
set_cf cfid
|
1504
|
-
self
|
1505
|
-
end
|
1506
|
-
|
1507
|
-
def reverse
|
1508
|
-
cfid = self[@scene].__id__ rescue nil
|
1509
|
-
a = self.class.new.replace super
|
1510
|
-
a.set_cf cfid
|
1511
|
-
return a
|
1512
|
-
end
|
1513
|
-
|
1514
|
-
def reverse!
|
1515
|
-
cfid = self[@scene].__id__ rescue nil
|
1516
|
-
a = super
|
1517
|
-
set_cf cfid
|
1518
|
-
return a
|
1519
|
-
end
|
1520
|
-
|
1521
|
-
def select(&block)
|
1522
|
-
cfid = self[@scene].__id__ rescue nil
|
1523
|
-
a = self.class.new.replace super
|
1524
|
-
a.set_cf cfid
|
1525
|
-
return a
|
1526
|
-
end
|
1527
|
-
|
1528
|
-
def shift
|
1529
|
-
cfid = self[@scene].__id__ rescue nil
|
1530
|
-
a = super
|
1531
|
-
set_cf cfid
|
1532
|
-
return a
|
1533
|
-
end
|
1534
|
-
|
1535
|
-
def slice(*args)
|
1536
|
-
self[*args]
|
1537
|
-
end
|
1538
|
-
|
1539
|
-
def slice!(*args)
|
1540
|
-
cfid = self[@scene].__id__ rescue nil
|
1541
|
-
if args.length > 1 || args[0].kind_of?(Range)
|
1542
|
-
a = self.class.new.replace super
|
1543
|
-
else
|
1544
|
-
a = super
|
1545
|
-
end
|
1546
|
-
set_cf cfid
|
1547
|
-
return a
|
1548
|
-
end
|
1549
|
-
|
1550
|
-
def uniq
|
1551
|
-
cfid = self[@scene].__id__ rescue nil
|
1552
|
-
a = self.class.new.replace super
|
1553
|
-
a.set_cf cfid
|
1554
|
-
return a
|
1555
|
-
end
|
1556
|
-
|
1557
|
-
def uniq!(*args)
|
1558
|
-
cfid = self[@scene].__id__ rescue nil
|
1559
|
-
a = super
|
1560
|
-
set_cf cfid
|
1561
|
-
return a
|
1562
|
-
end
|
1563
|
-
|
1564
|
-
# @scene -> new object
|
1565
|
-
def unshift(obj)
|
1566
|
-
is_a_image obj
|
1567
|
-
a = super
|
1568
|
-
@scene = 0
|
1569
|
-
return a
|
1570
|
-
end
|
1571
|
-
|
1572
1383
|
# Compare ImageLists
|
1573
1384
|
# Compare each image in turn until the result of a comparison
|
1574
1385
|
# is not 0. If all comparisons return 0, then
|
@@ -1595,16 +1406,78 @@ public
|
|
1595
1406
|
return self.length <=> other.length
|
1596
1407
|
end
|
1597
1408
|
|
1409
|
+
def [](*args)
|
1410
|
+
a = @images[*args]
|
1411
|
+
if a.respond_to?(:each) then
|
1412
|
+
ilist = self.class.new
|
1413
|
+
a.each {|image| ilist << image}
|
1414
|
+
a = ilist
|
1415
|
+
end
|
1416
|
+
return a
|
1417
|
+
end
|
1418
|
+
|
1419
|
+
def []=(*args)
|
1420
|
+
obj = @images.[]=(*args)
|
1421
|
+
if obj && obj.respond_to?(:each) then
|
1422
|
+
is_an_image_array(obj)
|
1423
|
+
set_current obj.last.__id__
|
1424
|
+
elsif obj
|
1425
|
+
is_an_image(obj)
|
1426
|
+
set_current obj.__id__
|
1427
|
+
else
|
1428
|
+
set_current nil
|
1429
|
+
end
|
1430
|
+
return obj
|
1431
|
+
end
|
1432
|
+
|
1433
|
+
[:at, :each, :each_index, :empty?, :fetch,
|
1434
|
+
:first, :hash, :include?, :index, :length, :rindex, :sort!].each do |mth|
|
1435
|
+
module_eval <<-END_SIMPLE_DELEGATES
|
1436
|
+
def #{mth}(*args, &block)
|
1437
|
+
@images.#{mth}(*args, &block)
|
1438
|
+
end
|
1439
|
+
END_SIMPLE_DELEGATES
|
1440
|
+
end
|
1441
|
+
alias_method :size, :length
|
1442
|
+
|
1443
|
+
# Array#nitems is not available in 1.9
|
1444
|
+
if Array.instance_methods.include?("nitems")
|
1445
|
+
def nitems()
|
1446
|
+
@images.nitems()
|
1447
|
+
end
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
def clear
|
1451
|
+
@scene = nil
|
1452
|
+
@images.clear
|
1453
|
+
end
|
1454
|
+
|
1598
1455
|
def clone
|
1599
1456
|
ditto = dup
|
1600
1457
|
ditto.freeze if frozen?
|
1601
1458
|
return ditto
|
1602
1459
|
end
|
1603
1460
|
|
1461
|
+
# override Enumerable#collect
|
1462
|
+
def collect(&block)
|
1463
|
+
current = get_current()
|
1464
|
+
a = @images.collect(&block)
|
1465
|
+
ilist = self.class.new
|
1466
|
+
a.each {|image| ilist << image}
|
1467
|
+
ilist.set_current current
|
1468
|
+
return ilist
|
1469
|
+
end
|
1470
|
+
|
1471
|
+
def collect!(&block)
|
1472
|
+
@images.collect!(&block)
|
1473
|
+
is_an_image_array @images
|
1474
|
+
self
|
1475
|
+
end
|
1476
|
+
|
1604
1477
|
# Make a deep copy
|
1605
1478
|
def copy
|
1606
1479
|
ditto = self.class.new
|
1607
|
-
each { |f| ditto << f.copy }
|
1480
|
+
@images.each { |f| ditto << f.copy }
|
1608
1481
|
ditto.scene = @scene
|
1609
1482
|
ditto.taint if tainted?
|
1610
1483
|
return ditto
|
@@ -1615,7 +1488,38 @@ public
|
|
1615
1488
|
if ! @scene
|
1616
1489
|
Kernel.raise IndexError, "no images in this list"
|
1617
1490
|
end
|
1618
|
-
|
1491
|
+
@images[@scene]
|
1492
|
+
end
|
1493
|
+
|
1494
|
+
# ImageList#map took over the "map" name. Use alternatives.
|
1495
|
+
alias_method :__map__, :collect
|
1496
|
+
alias_method :map!, :collect!
|
1497
|
+
alias_method :__map__!, :collect!
|
1498
|
+
|
1499
|
+
# ImageMagic used affinity in 6.4.3, switch to remap in 6.4.4.
|
1500
|
+
alias_method :affinity, :remap
|
1501
|
+
|
1502
|
+
def compact
|
1503
|
+
current = get_current()
|
1504
|
+
ilist = self.class.new
|
1505
|
+
a = @images.compact
|
1506
|
+
a.each {|image| ilist << image}
|
1507
|
+
ilist.set_current current
|
1508
|
+
return ilist
|
1509
|
+
end
|
1510
|
+
|
1511
|
+
def compact!
|
1512
|
+
current = get_current()
|
1513
|
+
a = @images.compact! # returns nil if no changes were made
|
1514
|
+
set_current current
|
1515
|
+
return a.nil? ? nil : self
|
1516
|
+
end
|
1517
|
+
|
1518
|
+
def concat(other)
|
1519
|
+
is_an_image_array other
|
1520
|
+
other.each {|image| @images << image}
|
1521
|
+
@scene = length-1
|
1522
|
+
return self
|
1619
1523
|
end
|
1620
1524
|
|
1621
1525
|
# Set same delay for all images
|
@@ -1623,40 +1527,87 @@ public
|
|
1623
1527
|
if Integer(d) < 0
|
1624
1528
|
raise ArgumentError, "delay must be greater than or equal to 0"
|
1625
1529
|
end
|
1626
|
-
each { |f| f.delay = Integer(d) }
|
1530
|
+
@images.each { |f| f.delay = Integer(d) }
|
1627
1531
|
end
|
1628
1532
|
|
1629
|
-
def
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1533
|
+
def delete(obj, &block)
|
1534
|
+
is_an_image obj
|
1535
|
+
current = get_current()
|
1536
|
+
a = @images.delete(obj, &block)
|
1537
|
+
set_current current
|
1538
|
+
return a
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
def delete_at(ndx)
|
1542
|
+
current = get_current()
|
1543
|
+
a = @images.delete_at(ndx)
|
1544
|
+
set_current current
|
1545
|
+
return a
|
1546
|
+
end
|
1547
|
+
|
1548
|
+
def delete_if(&block)
|
1549
|
+
current = get_current()
|
1550
|
+
@images.delete_if(&block)
|
1551
|
+
set_current current
|
1552
|
+
self
|
1634
1553
|
end
|
1635
1554
|
|
1636
1555
|
def dup
|
1637
1556
|
ditto = self.class.new
|
1638
|
-
each {|img| ditto << img}
|
1557
|
+
@images.each {|img| ditto << img}
|
1639
1558
|
ditto.scene = @scene
|
1640
1559
|
ditto.taint if tainted?
|
1641
1560
|
return ditto
|
1642
1561
|
end
|
1643
1562
|
|
1563
|
+
def eql?(other)
|
1564
|
+
is_an_image_array other
|
1565
|
+
eql = other.eql?(@images)
|
1566
|
+
begin # "other" is another ImageList
|
1567
|
+
eql &&= @scene == other.scene
|
1568
|
+
rescue NoMethodError
|
1569
|
+
# "other" is a plain Array
|
1570
|
+
end
|
1571
|
+
return eql
|
1572
|
+
end
|
1573
|
+
|
1574
|
+
def fill(*args, &block)
|
1575
|
+
is_an_image args[0] unless block_given?
|
1576
|
+
current = get_current()
|
1577
|
+
@images.fill(*args, &block)
|
1578
|
+
is_an_image_array self
|
1579
|
+
set_current current
|
1580
|
+
self
|
1581
|
+
end
|
1582
|
+
|
1583
|
+
# Override Enumerable's find_all
|
1584
|
+
def find_all(&block)
|
1585
|
+
current = get_current()
|
1586
|
+
a = @images.find_all(&block)
|
1587
|
+
ilist = self.class.new
|
1588
|
+
a.each {|image| ilist << image}
|
1589
|
+
ilist.set_current current
|
1590
|
+
return ilist
|
1591
|
+
end
|
1592
|
+
alias_method :select, :find_all
|
1593
|
+
|
1644
1594
|
def from_blob(*blobs, &block)
|
1645
1595
|
if (blobs.length == 0)
|
1646
1596
|
Kernel.raise ArgumentError, "no blobs given"
|
1647
1597
|
end
|
1648
1598
|
blobs.each { |b|
|
1649
|
-
Magick::Image.from_blob(b, &block).each { |n|
|
1599
|
+
Magick::Image.from_blob(b, &block).each { |n| @images << n }
|
1650
1600
|
}
|
1651
1601
|
@scene = length - 1
|
1652
1602
|
self
|
1653
1603
|
end
|
1654
1604
|
|
1655
1605
|
# Initialize new instances
|
1656
|
-
def initialize(*filenames)
|
1606
|
+
def initialize(*filenames, &block)
|
1607
|
+
@images = []
|
1657
1608
|
@scene = nil
|
1658
1609
|
filenames.each { |f|
|
1659
|
-
Magick::Image.read(f).each { |n|
|
1610
|
+
Magick::Image.read(f, &block).each { |n| @images << n }
|
1660
1611
|
}
|
1661
1612
|
if length > 0
|
1662
1613
|
@scene = length - 1 # last image in array
|
@@ -1664,11 +1615,19 @@ public
|
|
1664
1615
|
self
|
1665
1616
|
end
|
1666
1617
|
|
1618
|
+
def insert(index, *args)
|
1619
|
+
args.each {|image| is_an_image image}
|
1620
|
+
current = get_current()
|
1621
|
+
@images.insert(index, *args)
|
1622
|
+
set_current current
|
1623
|
+
return self
|
1624
|
+
end
|
1625
|
+
|
1667
1626
|
# Call inspect for all the images
|
1668
1627
|
def inspect
|
1669
|
-
|
1670
|
-
each {|image|
|
1671
|
-
|
1628
|
+
img = []
|
1629
|
+
@images.each {|image| img << image.inspect }
|
1630
|
+
img = "[" + img.join(",\n") + "]\nscene=#{@scene}"
|
1672
1631
|
end
|
1673
1632
|
|
1674
1633
|
# Set the number of iterations of an animated GIF
|
@@ -1677,10 +1636,36 @@ public
|
|
1677
1636
|
if n < 0 || n > 65535
|
1678
1637
|
Kernel.raise ArgumentError, "iterations must be between 0 and 65535"
|
1679
1638
|
end
|
1680
|
-
each {|f| f.iterations=n}
|
1639
|
+
@images.each {|f| f.iterations=n}
|
1681
1640
|
self
|
1682
1641
|
end
|
1683
1642
|
|
1643
|
+
def last(*args)
|
1644
|
+
if args.length == 0
|
1645
|
+
a = @images.last
|
1646
|
+
else
|
1647
|
+
a = @images.last(*args)
|
1648
|
+
ilist = self.class.new
|
1649
|
+
a.each {|img| ilist << img}
|
1650
|
+
@scene = a.length - 1
|
1651
|
+
a = ilist
|
1652
|
+
end
|
1653
|
+
return a
|
1654
|
+
end
|
1655
|
+
|
1656
|
+
# Custom marshal/unmarshal for Ruby 1.8.
|
1657
|
+
def marshal_dump()
|
1658
|
+
ary = [@scene]
|
1659
|
+
@images.each {|i| ary << Marshal.dump(i)}
|
1660
|
+
ary
|
1661
|
+
end
|
1662
|
+
|
1663
|
+
def marshal_load(ary)
|
1664
|
+
@scene = ary.shift
|
1665
|
+
@images = []
|
1666
|
+
ary.each {|a| @images << Marshal.load(a)}
|
1667
|
+
end
|
1668
|
+
|
1684
1669
|
# The ImageList class supports the Magick::Image class methods by simply sending
|
1685
1670
|
# the method to the current image. If the method isn't explicitly supported,
|
1686
1671
|
# send it to the current image in the array. If there are no images, send
|
@@ -1688,7 +1673,7 @@ public
|
|
1688
1673
|
def method_missing(methID, *args, &block)
|
1689
1674
|
begin
|
1690
1675
|
if @scene
|
1691
|
-
|
1676
|
+
@images[@scene].send(methID, *args, &block)
|
1692
1677
|
else
|
1693
1678
|
super
|
1694
1679
|
end
|
@@ -1700,47 +1685,230 @@ public
|
|
1700
1685
|
end
|
1701
1686
|
end
|
1702
1687
|
|
1703
|
-
# Ensure respond_to? answers correctly when we are delegating to Image
|
1704
|
-
alias_method :__respond_to__?, :respond_to?
|
1705
|
-
def respond_to?(methID, priv=false)
|
1706
|
-
return true if __respond_to__?(methID, priv)
|
1707
|
-
if @scene
|
1708
|
-
self[@scene].respond_to?(methID, priv)
|
1709
|
-
else
|
1710
|
-
super
|
1711
|
-
end
|
1712
|
-
end
|
1713
|
-
|
1714
1688
|
# Create a new image and add it to the end
|
1715
1689
|
def new_image(cols, rows, *fill, &info_blk)
|
1716
1690
|
self << Magick::Image.new(cols, rows, *fill, &info_blk)
|
1717
1691
|
end
|
1718
1692
|
|
1693
|
+
def partition(&block)
|
1694
|
+
a = @images.partition(&block)
|
1695
|
+
t = self.class.new
|
1696
|
+
a[0].each { |img| t << img}
|
1697
|
+
t.set_current nil
|
1698
|
+
f = self.class.new
|
1699
|
+
a[1].each { |img| f << img}
|
1700
|
+
f.set_current nil
|
1701
|
+
[t, f]
|
1702
|
+
end
|
1703
|
+
|
1719
1704
|
# Ping files and concatenate the new images
|
1720
1705
|
def ping(*files, &block)
|
1721
1706
|
if (files.length == 0)
|
1722
1707
|
Kernel.raise ArgumentError, "no files given"
|
1723
1708
|
end
|
1724
1709
|
files.each { |f|
|
1725
|
-
Magick::Image.ping(f, &block).each { |n|
|
1710
|
+
Magick::Image.ping(f, &block).each { |n| @images << n }
|
1726
1711
|
}
|
1727
1712
|
@scene = length - 1
|
1728
1713
|
self
|
1729
1714
|
end
|
1730
1715
|
|
1716
|
+
def pop
|
1717
|
+
current = get_current()
|
1718
|
+
a = @images.pop # can return nil
|
1719
|
+
set_current current
|
1720
|
+
return a
|
1721
|
+
end
|
1722
|
+
|
1723
|
+
def push(*objs)
|
1724
|
+
objs.each do |image|
|
1725
|
+
is_an_image image
|
1726
|
+
@images << image
|
1727
|
+
end
|
1728
|
+
@scene = length - 1
|
1729
|
+
self
|
1730
|
+
end
|
1731
|
+
|
1731
1732
|
# Read files and concatenate the new images
|
1732
1733
|
def read(*files, &block)
|
1733
1734
|
if (files.length == 0)
|
1734
1735
|
Kernel.raise ArgumentError, "no files given"
|
1735
1736
|
end
|
1736
1737
|
files.each { |f|
|
1737
|
-
Magick::Image.read(f, &block).each { |n|
|
1738
|
+
Magick::Image.read(f, &block).each { |n| @images << n }
|
1738
1739
|
}
|
1739
1740
|
@scene = length - 1
|
1740
1741
|
self
|
1741
1742
|
end
|
1743
|
+
|
1744
|
+
# override Enumerable's reject
|
1745
|
+
def reject(&block)
|
1746
|
+
current = get_current()
|
1747
|
+
ilist = self.class.new
|
1748
|
+
a = @images.reject(&block)
|
1749
|
+
a.each {|image| ilist << image}
|
1750
|
+
ilist.set_current current
|
1751
|
+
return ilist
|
1752
|
+
end
|
1753
|
+
|
1754
|
+
def reject!(&block)
|
1755
|
+
current = get_current()
|
1756
|
+
a = @images.reject!(&block)
|
1757
|
+
@images = a if !a.nil?
|
1758
|
+
set_current current
|
1759
|
+
return a.nil? ? nil : self
|
1760
|
+
end
|
1761
|
+
|
1762
|
+
def replace(other)
|
1763
|
+
is_an_image_array other
|
1764
|
+
current = get_current()
|
1765
|
+
@images.clear
|
1766
|
+
other.each {|image| @images << image}
|
1767
|
+
@scene = self.length == 0 ? nil : 0
|
1768
|
+
set_current current
|
1769
|
+
self
|
1770
|
+
end
|
1771
|
+
|
1772
|
+
# Ensure respond_to? answers correctly when we are delegating to Image
|
1773
|
+
alias_method :__respond_to__?, :respond_to?
|
1774
|
+
def respond_to?(methID, priv=false)
|
1775
|
+
return true if __respond_to__?(methID, priv)
|
1776
|
+
if @scene
|
1777
|
+
@images[@scene].respond_to?(methID, priv)
|
1778
|
+
else
|
1779
|
+
super
|
1780
|
+
end
|
1781
|
+
end
|
1782
|
+
|
1783
|
+
def reverse
|
1784
|
+
current = get_current()
|
1785
|
+
a = self.class.new
|
1786
|
+
@images.reverse_each {|image| a << image}
|
1787
|
+
a.set_current current
|
1788
|
+
return a
|
1789
|
+
end
|
1790
|
+
|
1791
|
+
def reverse!
|
1792
|
+
current = get_current()
|
1793
|
+
@images.reverse!
|
1794
|
+
set_current current
|
1795
|
+
self
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
def reverse_each
|
1799
|
+
@images.reverse_each {|image| yield(image)}
|
1800
|
+
self
|
1801
|
+
end
|
1802
|
+
|
1803
|
+
def shift
|
1804
|
+
current = get_current()
|
1805
|
+
a = @images.shift
|
1806
|
+
set_current current
|
1807
|
+
return a
|
1808
|
+
end
|
1809
|
+
|
1810
|
+
def slice(*args)
|
1811
|
+
current = get_current()
|
1812
|
+
slice = @images.slice(*args)
|
1813
|
+
if slice
|
1814
|
+
ilist = self.class.new
|
1815
|
+
if slice.respond_to?(:each) then
|
1816
|
+
slice.each {|image| ilist << image}
|
1817
|
+
else
|
1818
|
+
ilist << slice
|
1819
|
+
end
|
1820
|
+
else
|
1821
|
+
ilist = nil
|
1822
|
+
end
|
1823
|
+
return ilist
|
1824
|
+
end
|
1825
|
+
|
1826
|
+
def slice!(*args)
|
1827
|
+
current = get_current()
|
1828
|
+
a = @images.slice!(*args)
|
1829
|
+
set_current current
|
1830
|
+
return a
|
1831
|
+
end
|
1832
|
+
|
1833
|
+
def ticks_per_second=(t)
|
1834
|
+
if Integer(t) < 0
|
1835
|
+
Kernel.raise ArgumentError, "ticks_per_second must be greater than or equal to 0"
|
1836
|
+
end
|
1837
|
+
@images.each { |f| f.ticks_per_second = Integer(t) }
|
1838
|
+
end
|
1839
|
+
|
1840
|
+
def to_a
|
1841
|
+
a = Array.new
|
1842
|
+
@images.each {|image| a << image}
|
1843
|
+
return a
|
1844
|
+
end
|
1845
|
+
|
1846
|
+
def uniq
|
1847
|
+
current = get_current()
|
1848
|
+
a = self.class.new
|
1849
|
+
@images.uniq.each {|image| a << image}
|
1850
|
+
a.set_current current
|
1851
|
+
return a
|
1852
|
+
end
|
1853
|
+
|
1854
|
+
def uniq!(*args)
|
1855
|
+
current = get_current()
|
1856
|
+
a = @images.uniq!
|
1857
|
+
set_current current
|
1858
|
+
return a.nil? ? nil : self
|
1859
|
+
end
|
1860
|
+
|
1861
|
+
# @scene -> new object
|
1862
|
+
def unshift(obj)
|
1863
|
+
is_an_image obj
|
1864
|
+
@images.unshift(obj)
|
1865
|
+
@scene = 0
|
1866
|
+
self
|
1867
|
+
end
|
1868
|
+
|
1869
|
+
def values_at(*args)
|
1870
|
+
a = @images.values_at(*args)
|
1871
|
+
a = self.class.new
|
1872
|
+
@images.values_at(*args).each {|image| a << image}
|
1873
|
+
a.scene = a.length - 1
|
1874
|
+
return a
|
1875
|
+
end
|
1876
|
+
alias_method :indexes, :values_at
|
1877
|
+
alias_method :indices, :values_at
|
1878
|
+
|
1742
1879
|
end # Magick::ImageList
|
1743
1880
|
|
1881
|
+
|
1882
|
+
# Collects non-specific optional method arguments
|
1883
|
+
class OptionalMethodArguments
|
1884
|
+
def initialize(img)
|
1885
|
+
@img = img
|
1886
|
+
end
|
1887
|
+
|
1888
|
+
# miscellaneous options like -verbose
|
1889
|
+
def method_missing(mth, val)
|
1890
|
+
@img.define(mth.to_s.tr('_', '-'), val)
|
1891
|
+
end
|
1892
|
+
|
1893
|
+
# set(key, val) corresponds to -set option:key val
|
1894
|
+
def define(key, val = nil)
|
1895
|
+
@img.define(key, val)
|
1896
|
+
end
|
1897
|
+
|
1898
|
+
# accepts Pixel object or color name
|
1899
|
+
def highlight_color=(color)
|
1900
|
+
color = @img.to_color(color) if color.respond_to?(:to_color)
|
1901
|
+
@img.define("highlight-color", color)
|
1902
|
+
end
|
1903
|
+
|
1904
|
+
# accepts Pixel object or color name
|
1905
|
+
def lowlight_color=(color)
|
1906
|
+
color = @img.to_color(color) if color.respond_to?(:to_color)
|
1907
|
+
@img.define("lowlight-color", color)
|
1908
|
+
end
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
|
1744
1912
|
# Example fill class. Fills the image with the specified background
|
1745
1913
|
# color, then crosshatches with the specified crosshatch color.
|
1746
1914
|
# @dist is the number of pixels between hatch lines.
|
@@ -1766,3 +1934,4 @@ class HatchFill
|
|
1766
1934
|
end
|
1767
1935
|
|
1768
1936
|
end # Magick
|
1937
|
+
|