rmagick 1.15.17 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rmagick might be problematic. Click here for more details.
- data/ChangeLog +78 -25
- data/README.html +117 -188
- data/README.txt +116 -181
- data/build_tarball.rake +205 -0
- data/doc/comtasks.html +2 -2
- data/doc/constants.html +118 -44
- data/doc/draw.html +57 -99
- data/doc/ex/adaptive_threshold.rb +1 -10
- data/doc/ex/add_noise.rb +4 -5
- data/doc/ex/axes.rb +1 -1
- data/doc/ex/bilevel_channel.rb +2 -13
- data/doc/ex/bounding_box.rb +3 -4
- data/doc/ex/channel.rb +6 -7
- data/doc/ex/clip_path.rb +11 -5
- data/doc/ex/color_histogram.rb +8 -20
- data/doc/ex/composite_layers.rb +53 -0
- data/doc/ex/fill_pattern.rb +26 -0
- data/doc/ex/get_multiline_type_metrics.rb +26 -37
- data/doc/ex/get_type_metrics.rb +25 -25
- data/doc/ex/images/notimplemented.gif +0 -0
- data/doc/ex/level.rb +1 -1
- data/doc/ex/matte_floodfill.rb +5 -6
- data/doc/ex/matte_replace.rb +5 -6
- data/doc/ex/negate_channel.rb +0 -10
- data/doc/ex/opacity.rb +3 -5
- data/doc/ex/polaroid.rb +4 -1
- data/doc/ex/posterize.rb +1 -12
- data/doc/ex/preview.rb +1 -8
- data/doc/ex/radial_blur.rb +1 -11
- data/doc/ex/raise.rb +1 -4
- data/doc/ex/random_threshold_channel.rb +4 -9
- data/doc/ex/sepiatone.rb +2 -9
- data/doc/ex/shadow.rb +12 -18
- data/doc/ex/sketch.rb +2 -9
- data/doc/ex/smile.rb +7 -7
- data/doc/ex/splice.rb +3 -10
- data/doc/ex/stegano.rb +5 -0
- data/doc/ex/threshold.rb +2 -2
- data/doc/ex/transpose.rb +1 -8
- data/doc/ex/transverse.rb +1 -8
- data/doc/ex/trim.rb +1 -2
- data/doc/ex/viewex.rb +4 -5
- data/doc/ex/vignette.rb +1 -8
- data/doc/ex/watermark.rb +1 -0
- data/doc/ex/wet_floor.rb +8 -14
- data/doc/ilist.html +301 -110
- data/doc/image1.html +362 -258
- data/doc/image2.html +429 -286
- data/doc/image3.html +418 -192
- data/doc/imageattrs.html +100 -39
- data/doc/imusage.html +26 -21
- data/doc/index.html +52 -93
- data/doc/info.html +160 -64
- data/doc/magick.html +37 -71
- data/doc/optequiv.html +155 -61
- data/doc/rvg.html +3 -3
- data/doc/rvgclip.html +2 -2
- data/doc/rvggroup.html +2 -2
- data/doc/rvgimage.html +3 -3
- data/doc/rvgpattern.html +3 -3
- data/doc/rvgshape.html +2 -2
- data/doc/rvgstyle.html +2 -2
- data/doc/rvgtext.html +2 -2
- data/doc/rvgtspan.html +4 -4
- data/doc/rvgtut.html +4 -4
- data/doc/rvguse.html +3 -3
- data/doc/rvgxform.html +2 -2
- data/doc/struct.html +26 -29
- data/doc/usage.html +99 -48
- data/examples/crop_with_gravity.rb +46 -0
- data/examples/demo.rb +2 -2
- data/examples/histogram.rb +11 -11
- data/examples/identify.rb +45 -45
- data/examples/spinner.rb +3 -2
- data/ext/RMagick/MANIFEST +7 -8
- data/ext/RMagick/extconf.rb +242 -0
- data/ext/RMagick/rmagick.h +136 -222
- data/ext/RMagick/rmdraw.c +226 -229
- data/ext/RMagick/rmfill.c +69 -118
- data/ext/RMagick/rmilist.c +234 -94
- data/ext/RMagick/rmimage.c +1719 -2564
- data/ext/RMagick/rminfo.c +433 -619
- data/ext/RMagick/rmmain.c +249 -487
- data/ext/RMagick/rmutil.c +344 -563
- data/lib/RMagick.rb +414 -358
- 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 +2 -7
- data/lib/rvg/pathdata.rb +2 -2
- data/lib/rvg/rvg.rb +2 -2
- data/lib/rvg/stretchable.rb +2 -14
- 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/{metaconfig.in → metaconfig} +0 -1
- data/post-setup.rb +1 -1
- data/rmagick.gemspec +6 -9
- metadata +41 -49
- data/Makefile.in +0 -42
- data/configure +0 -12358
- data/configure.ac +0 -791
- data/ext/RMagick/extconf.rb.in +0 -25
- data/ext/RMagick/rmagick_config.h.in +0 -285
- data/gem_extconf.rb +0 -42
data/lib/RMagick.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
# $Id: RMagick.rb,v 1.
|
1
|
+
# $Id: RMagick.rb,v 1.62 2007/12/21 23:24:20 rmagick Exp $
|
2
2
|
#==============================================================================
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2007 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
|
-
require '
|
11
|
+
require 'RMagick2.so'
|
12
12
|
|
13
13
|
module Magick
|
14
14
|
@@formats = nil
|
@@ -23,6 +23,9 @@ 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
|
@@ -91,10 +94,10 @@ class Geometry
|
|
91
94
|
# Convert object to a geometry string
|
92
95
|
def to_s
|
93
96
|
str = ''
|
94
|
-
str << sprintf("%
|
97
|
+
str << sprintf("%d", @width+0.5) if @width > 0
|
95
98
|
str << 'x' if (@width > 0 || @height > 0)
|
96
|
-
str << sprintf("%
|
97
|
-
str << sprintf("%+d%+d", @x, @y) if (@x != 0 || @y != 0)
|
99
|
+
str << sprintf("%d", @height+0.5) if @height > 0
|
100
|
+
str << sprintf("%+d%+d", @x+0.5, @y+0.5) if (@x != 0 || @y != 0)
|
98
101
|
str << FLAGS[@flag.to_i]
|
99
102
|
end
|
100
103
|
end
|
@@ -250,7 +253,7 @@ class Draw
|
|
250
253
|
def define_clip_path(name)
|
251
254
|
begin
|
252
255
|
push('defs')
|
253
|
-
push('clip-path
|
256
|
+
push('clip-path', name)
|
254
257
|
push('graphic-context')
|
255
258
|
yield
|
256
259
|
ensure
|
@@ -424,7 +427,7 @@ class Draw
|
|
424
427
|
primitive "pop graphic-context"
|
425
428
|
else
|
426
429
|
# to_s allows a Symbol to be used instead of a String
|
427
|
-
primitive "pop " + what.to_s
|
430
|
+
primitive "pop " + what.map {|w| w.to_s}.join(' ')
|
428
431
|
end
|
429
432
|
end
|
430
433
|
|
@@ -438,7 +441,7 @@ class Draw
|
|
438
441
|
primitive "push graphic-context"
|
439
442
|
else
|
440
443
|
# to_s allows a Symbol to be used instead of a String
|
441
|
-
primitive "push " + what.to_s
|
444
|
+
primitive "push " + what.map {|w| w.to_s}.join(' ')
|
442
445
|
end
|
443
446
|
end
|
444
447
|
|
@@ -612,7 +615,7 @@ module IPTC
|
|
612
615
|
end
|
613
616
|
|
614
617
|
module Application
|
615
|
-
|
618
|
+
Record_Version = "2:00"
|
616
619
|
Object_Type_Reference = "2:03"
|
617
620
|
Object_Name = "2:05"
|
618
621
|
Title = "2:05"
|
@@ -706,6 +709,7 @@ class Image
|
|
706
709
|
# Provide an alternate version of Draw#annotate, for folks who
|
707
710
|
# want to find it in this class.
|
708
711
|
def annotate(draw, width, height, x, y, text, &block)
|
712
|
+
check_destroyed
|
709
713
|
draw.annotate(self, width, height, x, y, text, &block)
|
710
714
|
self
|
711
715
|
end
|
@@ -766,6 +770,14 @@ class Image
|
|
766
770
|
self
|
767
771
|
end
|
768
772
|
|
773
|
+
# Thanks to Russell Norris!
|
774
|
+
def each_pixel
|
775
|
+
get_pixels(0, 0, columns, rows).each_with_index do |p, n|
|
776
|
+
yield(p, n%columns, n/columns)
|
777
|
+
end
|
778
|
+
self
|
779
|
+
end
|
780
|
+
|
769
781
|
# Retrieve EXIF data by entry or all. If one or more entry names specified,
|
770
782
|
# return the values associated with the entries. If no entries specified,
|
771
783
|
# return all entries and values. The return value is an array of [name,value]
|
@@ -800,7 +812,7 @@ class Image
|
|
800
812
|
end
|
801
813
|
else
|
802
814
|
tag.each do |num|
|
803
|
-
rval = self['#%04X' % num]
|
815
|
+
rval = self["EXIF:#{'#%04X' % num}"]
|
804
816
|
hash[num] = rval == 'unknown' ? nil : rval
|
805
817
|
end
|
806
818
|
end
|
@@ -841,7 +853,7 @@ class Image
|
|
841
853
|
def level(black_point=0.0, white_point=nil, gamma=nil)
|
842
854
|
black_point = Float(black_point)
|
843
855
|
|
844
|
-
white_point ||= Magick::
|
856
|
+
white_point ||= Magick::QuantumRange - black_point
|
845
857
|
white_point = Float(white_point)
|
846
858
|
|
847
859
|
gamma_arg = gamma
|
@@ -851,7 +863,7 @@ class Image
|
|
851
863
|
if gamma.abs > 10.0 || white_point.abs <= 10.0 || white_point.abs < gamma.abs
|
852
864
|
gamma, white_point = white_point, gamma
|
853
865
|
unless gamma_arg
|
854
|
-
white_point = Magick::
|
866
|
+
white_point = Magick::QuantumRange - black_point
|
855
867
|
end
|
856
868
|
end
|
857
869
|
|
@@ -963,6 +975,7 @@ class Image
|
|
963
975
|
attr_accessor :dirty
|
964
976
|
|
965
977
|
def initialize(img, x, y, width, height)
|
978
|
+
img.check_destroyed
|
966
979
|
if width <= 0 || height <= 0
|
967
980
|
Kernel.raise ArgumentError, "invalid geometry (#{width}x#{height}+#{x}+#{y})"
|
968
981
|
end
|
@@ -1194,24 +1207,21 @@ class Image
|
|
1194
1207
|
|
1195
1208
|
end # class Magick::Image
|
1196
1209
|
|
1197
|
-
class ImageList
|
1210
|
+
class ImageList
|
1198
1211
|
|
1199
1212
|
include Comparable
|
1213
|
+
include Enumerable
|
1214
|
+
attr_reader :scene
|
1200
1215
|
|
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'
|
1216
|
+
private
|
1209
1217
|
|
1210
|
-
|
1218
|
+
def get_current()
|
1219
|
+
return @images[@scene].__id__ rescue nil
|
1220
|
+
end
|
1211
1221
|
|
1212
1222
|
protected
|
1213
1223
|
|
1214
|
-
def
|
1224
|
+
def is_an_image(obj)
|
1215
1225
|
unless obj.kind_of? Magick::Image
|
1216
1226
|
Kernel.raise ArgumentError, "Magick::Image required (#{obj.class} given)"
|
1217
1227
|
end
|
@@ -1219,33 +1229,36 @@ protected
|
|
1219
1229
|
end
|
1220
1230
|
|
1221
1231
|
# Ensure array is always an array of Magick::Image objects
|
1222
|
-
def
|
1232
|
+
def is_an_image_array(ary)
|
1223
1233
|
unless ary.respond_to? :each
|
1224
1234
|
Kernel.raise ArgumentError, "Magick::ImageList or array of Magick::Images required (#{ary.class} given)"
|
1225
1235
|
end
|
1226
|
-
ary.each { |obj|
|
1236
|
+
ary.each { |obj| is_an_image obj }
|
1227
1237
|
true
|
1228
1238
|
end
|
1229
1239
|
|
1230
|
-
# Find old current image, update
|
1231
|
-
#
|
1232
|
-
def
|
1233
|
-
if length == 0
|
1234
|
-
|
1240
|
+
# Find old current image, update scene number
|
1241
|
+
# current is the id of the old current image.
|
1242
|
+
def set_current(current)
|
1243
|
+
if length() == 0
|
1244
|
+
self.scene = nil
|
1235
1245
|
return
|
1236
1246
|
# Don't bother looking for current image
|
1237
|
-
elsif
|
1238
|
-
|
1247
|
+
elsif scene() == nil || scene() >= length()
|
1248
|
+
self.scene = length() - 1
|
1239
1249
|
return
|
1240
|
-
elsif
|
1250
|
+
elsif current != nil
|
1251
|
+
# Find last instance of "current" in the list.
|
1252
|
+
# If "current" isn't in the list, set current to last image.
|
1253
|
+
self.scene = length() - 1
|
1241
1254
|
each_with_index do |f,i|
|
1242
|
-
if f.__id__ ==
|
1243
|
-
|
1244
|
-
return
|
1255
|
+
if f.__id__ == current
|
1256
|
+
self.scene = i
|
1245
1257
|
end
|
1246
1258
|
end
|
1259
|
+
return
|
1247
1260
|
end
|
1248
|
-
|
1261
|
+
self.scene = length() - 1
|
1249
1262
|
end
|
1250
1263
|
|
1251
1264
|
public
|
@@ -1253,10 +1266,10 @@ public
|
|
1253
1266
|
# Allow scene to be set to nil
|
1254
1267
|
def scene=(n)
|
1255
1268
|
if n.nil?
|
1256
|
-
Kernel.raise IndexError, "scene number out of bounds" unless length == 0
|
1269
|
+
Kernel.raise IndexError, "scene number out of bounds" unless @images.length == 0
|
1257
1270
|
@scene = nil
|
1258
1271
|
return @scene
|
1259
|
-
elsif length == 0
|
1272
|
+
elsif @images.length == 0
|
1260
1273
|
Kernel.raise IndexError, "scene number out of bounds"
|
1261
1274
|
end
|
1262
1275
|
|
@@ -1268,307 +1281,46 @@ public
|
|
1268
1281
|
return @scene
|
1269
1282
|
end
|
1270
1283
|
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1284
|
+
# All the binary operators work the same way.
|
1285
|
+
# 'other' should be either an ImageList or an Array
|
1286
|
+
%w{& + - |}.each do |op|
|
1287
|
+
module_eval <<-END_BINOPS
|
1288
|
+
def #{op}(other)
|
1289
|
+
ilist = self.class.new
|
1290
|
+
begin
|
1291
|
+
a = other #{op} @images
|
1292
|
+
rescue TypeError
|
1293
|
+
Kernel.raise ArgumentError, "Magick::ImageList expected, got " + other.class.to_s
|
1294
|
+
end
|
1295
|
+
current = get_current()
|
1296
|
+
a.each do |image|
|
1297
|
+
is_an_image image
|
1298
|
+
ilist << image
|
1299
|
+
end
|
1300
|
+
ilist.set_current current
|
1301
|
+
return ilist
|
1289
1302
|
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
|
1303
|
+
END_BINOPS
|
1308
1304
|
end
|
1309
1305
|
|
1310
1306
|
def *(n)
|
1311
1307
|
unless n.kind_of? Integer
|
1312
1308
|
Kernel.raise ArgumentError, "Integer required (#{n.class} given)"
|
1313
1309
|
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
|
1310
|
+
current = get_current()
|
1311
|
+
ilist = self.class.new
|
1312
|
+
(@images * n).each {|image| ilist << image}
|
1313
|
+
ilist.set_current current
|
1314
|
+
return ilist
|
1333
1315
|
end
|
1334
1316
|
|
1335
1317
|
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
|
1365
|
-
self
|
1366
|
-
end
|
1367
|
-
|
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
|
1318
|
+
is_an_image obj
|
1319
|
+
@images << obj
|
1320
|
+
@scene = @images.length - 1
|
1504
1321
|
self
|
1505
1322
|
end
|
1506
1323
|
|
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
1324
|
# Compare ImageLists
|
1573
1325
|
# Compare each image in turn until the result of a comparison
|
1574
1326
|
# is not 0. If all comparisons return 0, then
|
@@ -1595,16 +1347,71 @@ public
|
|
1595
1347
|
return self.length <=> other.length
|
1596
1348
|
end
|
1597
1349
|
|
1350
|
+
def [](*args)
|
1351
|
+
a = @images[*args]
|
1352
|
+
if a.respond_to?(:each) then
|
1353
|
+
ilist = self.class.new
|
1354
|
+
a.each {|image| ilist << image}
|
1355
|
+
a = ilist
|
1356
|
+
end
|
1357
|
+
return a
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
def []=(*args)
|
1361
|
+
obj = @images.[]=(*args)
|
1362
|
+
if obj && obj.respond_to?(:each) then
|
1363
|
+
is_an_image_array(obj)
|
1364
|
+
set_current obj.last.__id__
|
1365
|
+
elsif obj
|
1366
|
+
is_an_image(obj)
|
1367
|
+
set_current obj.__id__
|
1368
|
+
else
|
1369
|
+
set_current nil
|
1370
|
+
end
|
1371
|
+
return obj
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
[:at, :each, :each_index, :empty?, :fetch,
|
1375
|
+
:first, :include?, :index, :length, :nitems, :rindex, :sort!].each do |mth|
|
1376
|
+
module_eval <<-END_SIMPLE_DELEGATES
|
1377
|
+
def #{mth}(*args, &block)
|
1378
|
+
@images.#{mth}(*args, &block)
|
1379
|
+
end
|
1380
|
+
END_SIMPLE_DELEGATES
|
1381
|
+
end
|
1382
|
+
alias_method :size, :length
|
1383
|
+
|
1384
|
+
def clear
|
1385
|
+
@scene = nil
|
1386
|
+
@images.clear
|
1387
|
+
end
|
1388
|
+
|
1598
1389
|
def clone
|
1599
1390
|
ditto = dup
|
1600
1391
|
ditto.freeze if frozen?
|
1601
1392
|
return ditto
|
1602
1393
|
end
|
1603
1394
|
|
1395
|
+
# override Enumerable#collect
|
1396
|
+
def collect(&block)
|
1397
|
+
current = get_current()
|
1398
|
+
a = @images.collect(&block)
|
1399
|
+
ilist = self.class.new
|
1400
|
+
a.each {|image| ilist << image}
|
1401
|
+
ilist.set_current current
|
1402
|
+
return ilist
|
1403
|
+
end
|
1404
|
+
|
1405
|
+
def collect!(&block)
|
1406
|
+
@images.collect!(&block)
|
1407
|
+
is_an_image_array @images
|
1408
|
+
self
|
1409
|
+
end
|
1410
|
+
|
1604
1411
|
# Make a deep copy
|
1605
1412
|
def copy
|
1606
1413
|
ditto = self.class.new
|
1607
|
-
each { |f| ditto << f.copy }
|
1414
|
+
@images.each { |f| ditto << f.copy }
|
1608
1415
|
ditto.scene = @scene
|
1609
1416
|
ditto.taint if tainted?
|
1610
1417
|
return ditto
|
@@ -1615,7 +1422,35 @@ public
|
|
1615
1422
|
if ! @scene
|
1616
1423
|
Kernel.raise IndexError, "no images in this list"
|
1617
1424
|
end
|
1618
|
-
|
1425
|
+
@images[@scene]
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
# ImageList#map took over the "map" name. Use alternatives.
|
1429
|
+
alias_method :__map__, :collect
|
1430
|
+
alias_method :map!, :collect!
|
1431
|
+
alias_method :__map__!, :collect!
|
1432
|
+
|
1433
|
+
def compact
|
1434
|
+
current = get_current()
|
1435
|
+
ilist = self.class.new
|
1436
|
+
a = @images.compact
|
1437
|
+
a.each {|image| ilist << image}
|
1438
|
+
ilist.set_current current
|
1439
|
+
return ilist
|
1440
|
+
end
|
1441
|
+
|
1442
|
+
def compact!
|
1443
|
+
current = get_current()
|
1444
|
+
a = @images.compact! # returns nil if no changes were made
|
1445
|
+
set_current current
|
1446
|
+
return a.nil? ? nil : self
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
def concat(other)
|
1450
|
+
is_an_image_array other
|
1451
|
+
other.each {|image| @images << image}
|
1452
|
+
@scene = length-1
|
1453
|
+
return self
|
1619
1454
|
end
|
1620
1455
|
|
1621
1456
|
# Set same delay for all images
|
@@ -1623,30 +1458,76 @@ public
|
|
1623
1458
|
if Integer(d) < 0
|
1624
1459
|
raise ArgumentError, "delay must be greater than or equal to 0"
|
1625
1460
|
end
|
1626
|
-
each { |f| f.delay = Integer(d) }
|
1461
|
+
@images.each { |f| f.delay = Integer(d) }
|
1627
1462
|
end
|
1628
1463
|
|
1629
|
-
def
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1464
|
+
def delete(obj, &block)
|
1465
|
+
is_an_image obj
|
1466
|
+
current = get_current()
|
1467
|
+
a = @images.delete(obj, &block)
|
1468
|
+
set_current current
|
1469
|
+
return a
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
def delete_at(ndx)
|
1473
|
+
current = get_current()
|
1474
|
+
a = @images.delete_at(ndx)
|
1475
|
+
set_current current
|
1476
|
+
return a
|
1477
|
+
end
|
1478
|
+
|
1479
|
+
def delete_if(&block)
|
1480
|
+
current = get_current()
|
1481
|
+
@images.delete_if(&block)
|
1482
|
+
set_current current
|
1483
|
+
self
|
1634
1484
|
end
|
1635
1485
|
|
1636
1486
|
def dup
|
1637
1487
|
ditto = self.class.new
|
1638
|
-
each {|img| ditto << img}
|
1488
|
+
@images.each {|img| ditto << img}
|
1639
1489
|
ditto.scene = @scene
|
1640
1490
|
ditto.taint if tainted?
|
1641
1491
|
return ditto
|
1642
1492
|
end
|
1643
1493
|
|
1494
|
+
def eql?(other)
|
1495
|
+
is_an_image_array other
|
1496
|
+
eql = other.eql?(@images)
|
1497
|
+
begin # "other" is another ImageList
|
1498
|
+
eql &&= @scene == other.scene
|
1499
|
+
rescue NoMethodError
|
1500
|
+
# "other" is a plain Array
|
1501
|
+
end
|
1502
|
+
return eql
|
1503
|
+
end
|
1504
|
+
|
1505
|
+
def fill(*args, &block)
|
1506
|
+
is_an_image args[0] unless block_given?
|
1507
|
+
current = get_current()
|
1508
|
+
@images.fill(*args, &block)
|
1509
|
+
is_an_image_array self
|
1510
|
+
set_current current
|
1511
|
+
self
|
1512
|
+
end
|
1513
|
+
|
1514
|
+
# Override Enumerable's find_all
|
1515
|
+
def find_all(&block)
|
1516
|
+
current = get_current()
|
1517
|
+
a = @images.find_all(&block)
|
1518
|
+
ilist = self.class.new
|
1519
|
+
a.each {|image| ilist << image}
|
1520
|
+
ilist.set_current current
|
1521
|
+
return ilist
|
1522
|
+
end
|
1523
|
+
alias_method :select, :find_all
|
1524
|
+
|
1644
1525
|
def from_blob(*blobs, &block)
|
1645
1526
|
if (blobs.length == 0)
|
1646
1527
|
Kernel.raise ArgumentError, "no blobs given"
|
1647
1528
|
end
|
1648
1529
|
blobs.each { |b|
|
1649
|
-
Magick::Image.from_blob(b, &block).each { |n|
|
1530
|
+
Magick::Image.from_blob(b, &block).each { |n| @images << n }
|
1650
1531
|
}
|
1651
1532
|
@scene = length - 1
|
1652
1533
|
self
|
@@ -1654,9 +1535,10 @@ public
|
|
1654
1535
|
|
1655
1536
|
# Initialize new instances
|
1656
1537
|
def initialize(*filenames)
|
1538
|
+
@images = []
|
1657
1539
|
@scene = nil
|
1658
1540
|
filenames.each { |f|
|
1659
|
-
Magick::Image.read(f).each { |n|
|
1541
|
+
Magick::Image.read(f).each { |n| @images << n }
|
1660
1542
|
}
|
1661
1543
|
if length > 0
|
1662
1544
|
@scene = length - 1 # last image in array
|
@@ -1664,11 +1546,19 @@ public
|
|
1664
1546
|
self
|
1665
1547
|
end
|
1666
1548
|
|
1549
|
+
def insert(index, *args)
|
1550
|
+
args.each {|image| is_an_image image}
|
1551
|
+
current = get_current()
|
1552
|
+
@images.insert(index, *args)
|
1553
|
+
set_current current
|
1554
|
+
return self
|
1555
|
+
end
|
1556
|
+
|
1667
1557
|
# Call inspect for all the images
|
1668
1558
|
def inspect
|
1669
|
-
|
1670
|
-
each {|image|
|
1671
|
-
|
1559
|
+
img = []
|
1560
|
+
@images.each {|image| img << image.inspect }
|
1561
|
+
img = "[" + img.join(",\n") + "]\nscene=#{@scene}"
|
1672
1562
|
end
|
1673
1563
|
|
1674
1564
|
# Set the number of iterations of an animated GIF
|
@@ -1677,10 +1567,23 @@ public
|
|
1677
1567
|
if n < 0 || n > 65535
|
1678
1568
|
Kernel.raise ArgumentError, "iterations must be between 0 and 65535"
|
1679
1569
|
end
|
1680
|
-
each {|f| f.iterations=n}
|
1570
|
+
@images.each {|f| f.iterations=n}
|
1681
1571
|
self
|
1682
1572
|
end
|
1683
1573
|
|
1574
|
+
def last(*args)
|
1575
|
+
if args.length == 0
|
1576
|
+
a = @images.last
|
1577
|
+
else
|
1578
|
+
a = @images.last(*args)
|
1579
|
+
ilist = self.class.new
|
1580
|
+
a.each {|img| ilist << img}
|
1581
|
+
@scene = a.length - 1
|
1582
|
+
a = ilist
|
1583
|
+
end
|
1584
|
+
return a
|
1585
|
+
end
|
1586
|
+
|
1684
1587
|
# The ImageList class supports the Magick::Image class methods by simply sending
|
1685
1588
|
# the method to the current image. If the method isn't explicitly supported,
|
1686
1589
|
# send it to the current image in the array. If there are no images, send
|
@@ -1688,7 +1591,7 @@ public
|
|
1688
1591
|
def method_missing(methID, *args, &block)
|
1689
1592
|
begin
|
1690
1593
|
if @scene
|
1691
|
-
|
1594
|
+
@images[@scene].send(methID, *args, &block)
|
1692
1595
|
else
|
1693
1596
|
super
|
1694
1597
|
end
|
@@ -1700,45 +1603,197 @@ public
|
|
1700
1603
|
end
|
1701
1604
|
end
|
1702
1605
|
|
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
1606
|
# Create a new image and add it to the end
|
1715
1607
|
def new_image(cols, rows, *fill, &info_blk)
|
1716
1608
|
self << Magick::Image.new(cols, rows, *fill, &info_blk)
|
1717
1609
|
end
|
1718
1610
|
|
1611
|
+
def partition(&block)
|
1612
|
+
a = @images.partition(&block)
|
1613
|
+
t = self.class.new
|
1614
|
+
a[0].each { |img| t << img}
|
1615
|
+
t.set_current nil
|
1616
|
+
f = self.class.new
|
1617
|
+
a[1].each { |img| f << img}
|
1618
|
+
f.set_current nil
|
1619
|
+
[t, f]
|
1620
|
+
end
|
1621
|
+
|
1719
1622
|
# Ping files and concatenate the new images
|
1720
1623
|
def ping(*files, &block)
|
1721
1624
|
if (files.length == 0)
|
1722
1625
|
Kernel.raise ArgumentError, "no files given"
|
1723
1626
|
end
|
1724
1627
|
files.each { |f|
|
1725
|
-
Magick::Image.ping(f, &block).each { |n|
|
1628
|
+
Magick::Image.ping(f, &block).each { |n| @images << n }
|
1726
1629
|
}
|
1727
1630
|
@scene = length - 1
|
1728
1631
|
self
|
1729
1632
|
end
|
1730
1633
|
|
1634
|
+
def pop
|
1635
|
+
current = get_current()
|
1636
|
+
a = @images.pop # can return nil
|
1637
|
+
set_current current
|
1638
|
+
return a
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
def push(*objs)
|
1642
|
+
objs.each do |image|
|
1643
|
+
is_an_image image
|
1644
|
+
@images << image
|
1645
|
+
end
|
1646
|
+
@scene = length - 1
|
1647
|
+
self
|
1648
|
+
end
|
1649
|
+
|
1731
1650
|
# Read files and concatenate the new images
|
1732
1651
|
def read(*files, &block)
|
1733
1652
|
if (files.length == 0)
|
1734
1653
|
Kernel.raise ArgumentError, "no files given"
|
1735
1654
|
end
|
1736
1655
|
files.each { |f|
|
1737
|
-
Magick::Image.read(f, &block).each { |n|
|
1656
|
+
Magick::Image.read(f, &block).each { |n| @images << n }
|
1738
1657
|
}
|
1739
1658
|
@scene = length - 1
|
1740
1659
|
self
|
1741
1660
|
end
|
1661
|
+
|
1662
|
+
# override Enumerable's reject
|
1663
|
+
def reject(&block)
|
1664
|
+
current = get_current()
|
1665
|
+
ilist = self.class.new
|
1666
|
+
a = @images.reject(&block)
|
1667
|
+
a.each {|image| ilist << image}
|
1668
|
+
ilist.set_current current
|
1669
|
+
return ilist
|
1670
|
+
end
|
1671
|
+
|
1672
|
+
def reject!(&block)
|
1673
|
+
current = get_current()
|
1674
|
+
a = @images.reject!(&block)
|
1675
|
+
@images = a if !a.nil?
|
1676
|
+
set_current current
|
1677
|
+
return a.nil? ? nil : self
|
1678
|
+
end
|
1679
|
+
|
1680
|
+
def replace(other)
|
1681
|
+
is_an_image_array other
|
1682
|
+
current = get_current()
|
1683
|
+
@images.clear
|
1684
|
+
other.each {|image| @images << image}
|
1685
|
+
@scene = self.length == 0 ? nil : 0
|
1686
|
+
set_current current
|
1687
|
+
self
|
1688
|
+
end
|
1689
|
+
|
1690
|
+
# Ensure respond_to? answers correctly when we are delegating to Image
|
1691
|
+
alias_method :__respond_to__?, :respond_to?
|
1692
|
+
def respond_to?(methID, priv=false)
|
1693
|
+
return true if __respond_to__?(methID, priv)
|
1694
|
+
if @scene
|
1695
|
+
@images[@scene].respond_to?(methID, priv)
|
1696
|
+
else
|
1697
|
+
super
|
1698
|
+
end
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
def reverse
|
1702
|
+
current = get_current()
|
1703
|
+
a = self.class.new
|
1704
|
+
@images.reverse_each {|image| a << image}
|
1705
|
+
a.set_current current
|
1706
|
+
return a
|
1707
|
+
end
|
1708
|
+
|
1709
|
+
def reverse!
|
1710
|
+
current = get_current()
|
1711
|
+
@images.reverse!
|
1712
|
+
set_current current
|
1713
|
+
self
|
1714
|
+
end
|
1715
|
+
|
1716
|
+
def reverse_each
|
1717
|
+
@images.reverse_each {|image| yield(image)}
|
1718
|
+
self
|
1719
|
+
end
|
1720
|
+
|
1721
|
+
def shift
|
1722
|
+
current = get_current()
|
1723
|
+
a = @images.shift
|
1724
|
+
set_current current
|
1725
|
+
return a
|
1726
|
+
end
|
1727
|
+
|
1728
|
+
def slice(*args)
|
1729
|
+
current = get_current()
|
1730
|
+
slice = @images.slice(*args)
|
1731
|
+
if slice
|
1732
|
+
ilist = self.class.new
|
1733
|
+
if slice.respond_to?(:each) then
|
1734
|
+
slice.each {|image| ilist << image}
|
1735
|
+
else
|
1736
|
+
ilist << slice
|
1737
|
+
end
|
1738
|
+
else
|
1739
|
+
ilist = nil
|
1740
|
+
end
|
1741
|
+
return ilist
|
1742
|
+
end
|
1743
|
+
|
1744
|
+
def slice!(*args)
|
1745
|
+
current = get_current()
|
1746
|
+
a = @images.slice!(*args)
|
1747
|
+
set_current current
|
1748
|
+
return a
|
1749
|
+
end
|
1750
|
+
|
1751
|
+
def ticks_per_second=(t)
|
1752
|
+
if Integer(t) < 0
|
1753
|
+
Kernel.raise ArgumentError, "ticks_per_second must be greater than or equal to 0"
|
1754
|
+
end
|
1755
|
+
@images.each { |f| f.ticks_per_second = Integer(t) }
|
1756
|
+
end
|
1757
|
+
|
1758
|
+
def to_a
|
1759
|
+
a = Array.new
|
1760
|
+
@images.each {|image| a << image}
|
1761
|
+
return a
|
1762
|
+
end
|
1763
|
+
|
1764
|
+
def uniq
|
1765
|
+
current = get_current()
|
1766
|
+
a = self.class.new
|
1767
|
+
@images.uniq.each {|image| a << image}
|
1768
|
+
a.set_current current
|
1769
|
+
return a
|
1770
|
+
end
|
1771
|
+
|
1772
|
+
def uniq!(*args)
|
1773
|
+
current = get_current()
|
1774
|
+
a = @images.uniq!
|
1775
|
+
set_current current
|
1776
|
+
return a.nil? ? nil : self
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
# @scene -> new object
|
1780
|
+
def unshift(obj)
|
1781
|
+
is_an_image obj
|
1782
|
+
@images.unshift(obj)
|
1783
|
+
@scene = 0
|
1784
|
+
self
|
1785
|
+
end
|
1786
|
+
|
1787
|
+
def values_at(*args)
|
1788
|
+
a = @images.values_at(*args)
|
1789
|
+
a = self.class.new
|
1790
|
+
@images.values_at(*args).each {|image| a << image}
|
1791
|
+
a.scene = a.length - 1
|
1792
|
+
return a
|
1793
|
+
end
|
1794
|
+
alias_method :indexes, :values_at
|
1795
|
+
alias_method :indices, :values_at
|
1796
|
+
|
1742
1797
|
end # Magick::ImageList
|
1743
1798
|
|
1744
1799
|
# Example fill class. Fills the image with the specified background
|
@@ -1766,3 +1821,4 @@ class HatchFill
|
|
1766
1821
|
end
|
1767
1822
|
|
1768
1823
|
end # Magick
|
1824
|
+
|