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.

Files changed (108) hide show
  1. data/ChangeLog +78 -25
  2. data/README.html +117 -188
  3. data/README.txt +116 -181
  4. data/build_tarball.rake +205 -0
  5. data/doc/comtasks.html +2 -2
  6. data/doc/constants.html +118 -44
  7. data/doc/draw.html +57 -99
  8. data/doc/ex/adaptive_threshold.rb +1 -10
  9. data/doc/ex/add_noise.rb +4 -5
  10. data/doc/ex/axes.rb +1 -1
  11. data/doc/ex/bilevel_channel.rb +2 -13
  12. data/doc/ex/bounding_box.rb +3 -4
  13. data/doc/ex/channel.rb +6 -7
  14. data/doc/ex/clip_path.rb +11 -5
  15. data/doc/ex/color_histogram.rb +8 -20
  16. data/doc/ex/composite_layers.rb +53 -0
  17. data/doc/ex/fill_pattern.rb +26 -0
  18. data/doc/ex/get_multiline_type_metrics.rb +26 -37
  19. data/doc/ex/get_type_metrics.rb +25 -25
  20. data/doc/ex/images/notimplemented.gif +0 -0
  21. data/doc/ex/level.rb +1 -1
  22. data/doc/ex/matte_floodfill.rb +5 -6
  23. data/doc/ex/matte_replace.rb +5 -6
  24. data/doc/ex/negate_channel.rb +0 -10
  25. data/doc/ex/opacity.rb +3 -5
  26. data/doc/ex/polaroid.rb +4 -1
  27. data/doc/ex/posterize.rb +1 -12
  28. data/doc/ex/preview.rb +1 -8
  29. data/doc/ex/radial_blur.rb +1 -11
  30. data/doc/ex/raise.rb +1 -4
  31. data/doc/ex/random_threshold_channel.rb +4 -9
  32. data/doc/ex/sepiatone.rb +2 -9
  33. data/doc/ex/shadow.rb +12 -18
  34. data/doc/ex/sketch.rb +2 -9
  35. data/doc/ex/smile.rb +7 -7
  36. data/doc/ex/splice.rb +3 -10
  37. data/doc/ex/stegano.rb +5 -0
  38. data/doc/ex/threshold.rb +2 -2
  39. data/doc/ex/transpose.rb +1 -8
  40. data/doc/ex/transverse.rb +1 -8
  41. data/doc/ex/trim.rb +1 -2
  42. data/doc/ex/viewex.rb +4 -5
  43. data/doc/ex/vignette.rb +1 -8
  44. data/doc/ex/watermark.rb +1 -0
  45. data/doc/ex/wet_floor.rb +8 -14
  46. data/doc/ilist.html +301 -110
  47. data/doc/image1.html +362 -258
  48. data/doc/image2.html +429 -286
  49. data/doc/image3.html +418 -192
  50. data/doc/imageattrs.html +100 -39
  51. data/doc/imusage.html +26 -21
  52. data/doc/index.html +52 -93
  53. data/doc/info.html +160 -64
  54. data/doc/magick.html +37 -71
  55. data/doc/optequiv.html +155 -61
  56. data/doc/rvg.html +3 -3
  57. data/doc/rvgclip.html +2 -2
  58. data/doc/rvggroup.html +2 -2
  59. data/doc/rvgimage.html +3 -3
  60. data/doc/rvgpattern.html +3 -3
  61. data/doc/rvgshape.html +2 -2
  62. data/doc/rvgstyle.html +2 -2
  63. data/doc/rvgtext.html +2 -2
  64. data/doc/rvgtspan.html +4 -4
  65. data/doc/rvgtut.html +4 -4
  66. data/doc/rvguse.html +3 -3
  67. data/doc/rvgxform.html +2 -2
  68. data/doc/struct.html +26 -29
  69. data/doc/usage.html +99 -48
  70. data/examples/crop_with_gravity.rb +46 -0
  71. data/examples/demo.rb +2 -2
  72. data/examples/histogram.rb +11 -11
  73. data/examples/identify.rb +45 -45
  74. data/examples/spinner.rb +3 -2
  75. data/ext/RMagick/MANIFEST +7 -8
  76. data/ext/RMagick/extconf.rb +242 -0
  77. data/ext/RMagick/rmagick.h +136 -222
  78. data/ext/RMagick/rmdraw.c +226 -229
  79. data/ext/RMagick/rmfill.c +69 -118
  80. data/ext/RMagick/rmilist.c +234 -94
  81. data/ext/RMagick/rmimage.c +1719 -2564
  82. data/ext/RMagick/rminfo.c +433 -619
  83. data/ext/RMagick/rmmain.c +249 -487
  84. data/ext/RMagick/rmutil.c +344 -563
  85. data/lib/RMagick.rb +414 -358
  86. data/lib/rvg/clippath.rb +2 -2
  87. data/lib/rvg/container.rb +2 -2
  88. data/lib/rvg/describable.rb +2 -2
  89. data/lib/rvg/embellishable.rb +2 -2
  90. data/lib/rvg/misc.rb +3 -3
  91. data/lib/rvg/paint.rb +2 -7
  92. data/lib/rvg/pathdata.rb +2 -2
  93. data/lib/rvg/rvg.rb +2 -2
  94. data/lib/rvg/stretchable.rb +2 -14
  95. data/lib/rvg/stylable.rb +2 -2
  96. data/lib/rvg/text.rb +2 -2
  97. data/lib/rvg/transformable.rb +2 -2
  98. data/lib/rvg/units.rb +2 -2
  99. data/{metaconfig.in → metaconfig} +0 -1
  100. data/post-setup.rb +1 -1
  101. data/rmagick.gemspec +6 -9
  102. metadata +41 -49
  103. data/Makefile.in +0 -42
  104. data/configure +0 -12358
  105. data/configure.ac +0 -791
  106. data/ext/RMagick/extconf.rb.in +0 -25
  107. data/ext/RMagick/rmagick_config.h.in +0 -285
  108. data/gem_extconf.rb +0 -42
@@ -1,14 +1,14 @@
1
- # $Id: RMagick.rb,v 1.51.4.2 2008/02/24 23:24:17 rmagick Exp $
1
+ # $Id: RMagick.rb,v 1.62 2007/12/21 23:24:20 rmagick Exp $
2
2
  #==============================================================================
3
- # Copyright (C) 2008 by Timothy P. Hunter
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: RMagick.so defines the classes. The code below adds methods
7
+ # Notes: RMagick2.so defines the classes. The code below adds methods
8
8
  # to the classes.
9
9
  #==============================================================================
10
10
 
11
- require 'RMagick.so'
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("%g", @width) if @width > 0
97
+ str << sprintf("%d", @width+0.5) if @width > 0
95
98
  str << 'x' if (@width > 0 || @height > 0)
96
- str << sprintf("%g", @height) if @height > 0
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 ', name)
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
- #Record_Version = "2:00" abends with IM 6.2.9
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::MaxRGB - black_point
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::MaxRGB - black_point
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 < Array
1210
+ class ImageList
1198
1211
 
1199
1212
  include Comparable
1213
+ include Enumerable
1214
+ attr_reader :scene
1200
1215
 
1201
- undef_method :assoc
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
- attr_reader :scene
1218
+ def get_current()
1219
+ return @images[@scene].__id__ rescue nil
1220
+ end
1211
1221
 
1212
1222
  protected
1213
1223
 
1214
- def is_a_image(obj)
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 is_a_image_array(ary)
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| is_a_image obj }
1236
+ ary.each { |obj| is_an_image obj }
1227
1237
  true
1228
1238
  end
1229
1239
 
1230
- # Find old current image, update @scene
1231
- # cfid is the id of the old current image.
1232
- def set_cf(cfid)
1233
- if length == 0
1234
- @scene = nil
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 @scene == nil || @scene >= length
1238
- @scene = length - 1
1247
+ elsif scene() == nil || scene() >= length()
1248
+ self.scene = length() - 1
1239
1249
  return
1240
- elsif cfid != nil
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__ == cfid
1243
- @scene = i
1244
- return
1255
+ if f.__id__ == current
1256
+ self.scene = i
1245
1257
  end
1246
1258
  end
1259
+ return
1247
1260
  end
1248
- @scene = length - 1
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
- def [](*args)
1272
- if (args.length > 1) || args[0].kind_of?(Range)
1273
- self.class.new.replace super
1274
- else
1275
- super
1276
- end
1277
- end
1278
-
1279
- def []=(*args)
1280
- if args.length == 3 # f[start,length] = [f1,f2...]
1281
- args[2].kind_of?(Magick::Image) || is_a_image_array(args[2])
1282
- super
1283
- args[0] = args[0] + length if (args[0] < 0)
1284
- args[1] = length - args[0] if (args[0] + args[1] > length)
1285
- if args[2].kind_of?(Magick::Image)
1286
- @scene = args[0]
1287
- else
1288
- @scene = args[0] + args[2].length - 1
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
- elsif args[0].kind_of? Range # f[first..last] = [f1,f2...]
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
- cfid = self[@scene].__id__ rescue nil
1315
- a = self.class.new.replace super
1316
- a.set_cf cfid
1317
- return a
1318
- end
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
- is_a_image obj
1337
- a = super
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
- self[@scene]
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 ticks_per_second=(t)
1630
- if Integer(t) < 0
1631
- Kernel.raise ArgumentError, "ticks_per_second must be greater than or equal to 0"
1632
- end
1633
- each { |f| f.ticks_per_second = Integer(t) }
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| self << 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| self << 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
- ins = '['
1670
- each {|image| ins << image.inspect << "\n"}
1671
- ins.chomp("\n") + "]\nscene=#{@scene}"
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
- self[@scene].send(methID, *args, &block)
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| self << 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| self << 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
+