rmagick 7.1.7 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,7 @@ struct ImagesFromImageList_Args
20
20
 
21
21
  static Image *clone_imagelist(Image *);
22
22
  static Image *images_from_imagelist(VALUE, VALUE *);
23
+ static void check_images_writable(VALUE);
23
24
  static VALUE images_from_imagelist_protected(VALUE);
24
25
  static long imagelist_length(VALUE);
25
26
  static long check_imagelist_length(VALUE);
@@ -62,6 +63,23 @@ DEFINE_GVL_VOID_STUB2(RemoveDuplicateLayers, Image **, ExceptionInfo *);
62
63
  DEFINE_GVL_VOID_STUB2(RemoveZeroDelayLayers, Image **, ExceptionInfo *);
63
64
 
64
65
 
66
+ // Destroy the image list that *ptr points to when the cleanup runs, since the
67
+ // call may replace the first image of the list.
68
+ static void
69
+ destroy_list_at(void *ptr, intptr_t arg ATTRIBUTE_UNUSED)
70
+ {
71
+ DestroyImageList(*(Image **)ptr);
72
+ }
73
+
74
+ #if defined(IMAGEMAGICK_6)
75
+ static void
76
+ restore_colorspace(void *ptr, intptr_t colorspace)
77
+ {
78
+ ((Image *)ptr)->colorspace = (ColorspaceType)colorspace;
79
+ }
80
+ #endif
81
+
82
+
65
83
  /**
66
84
  * Repeatedly display the images in the images array to an XWindow screen. The
67
85
  * +delay+ argument is the number of 1/100ths of a second (0 to 65535) to delay
@@ -102,6 +120,10 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
102
120
 
103
121
  // Convert the images array to an images sequence.
104
122
  VALUE clones;
123
+ if (argc == 1)
124
+ {
125
+ check_images_writable(self);
126
+ }
105
127
  images = images_from_imagelist(self, &clones);
106
128
 
107
129
  if (argc == 1)
@@ -117,14 +139,14 @@ ImageList_animate(int argc, VALUE *argv, VALUE self)
117
139
  TypedData_Get_Struct(info_obj, Info, &rm_info_data_type, info);
118
140
  #if defined(IMAGEMAGICK_7)
119
141
  exception = AcquireExceptionInfo();
120
- GVL_STRUCT_TYPE(AnimateImages) args = { info, images, exception };
121
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(AnimateImages), &args);
142
+ DECLARE_GVL_CALL(call, AnimateImages, info, images, exception);
143
+ call.update_each(rb_iv_get(self, "@images")).read(info_obj).split(images).release(exception).run<void>();
122
144
  rm_split(images);
123
145
  CHECK_EXCEPTION();
124
146
  DestroyExceptionInfo(exception);
125
147
  #else
126
- GVL_STRUCT_TYPE(AnimateImages) args = { info, images };
127
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(AnimateImages), &args);
148
+ DECLARE_GVL_CALL(call, AnimateImages, info, images);
149
+ call.update_each(rb_iv_get(self, "@images")).read(info_obj).split(images).run<void>();
128
150
  rm_split(images);
129
151
  rm_check_image_exception(images, RetainOnError);
130
152
  #endif
@@ -158,8 +180,8 @@ ImageList_append(VALUE self, VALUE stack_arg)
158
180
  stack = (MagickBooleanType)RTEST(stack_arg);
159
181
 
160
182
  exception = AcquireExceptionInfo();
161
- GVL_STRUCT_TYPE(AppendImages) args = { images, stack, exception };
162
- new_image = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(AppendImages), &args);
183
+ DECLARE_GVL_CALL(call, AppendImages, images, stack, exception);
184
+ new_image = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
163
185
  rm_split(images);
164
186
  RB_GC_GUARD(clones);
165
187
  rm_check_exception(exception, new_image, DestroyOnError);
@@ -185,8 +207,8 @@ ImageList_average(VALUE self)
185
207
  images = images_from_imagelist(self, &clones);
186
208
 
187
209
  exception = AcquireExceptionInfo();
188
- GVL_STRUCT_TYPE(EvaluateImages) args = { images, MeanEvaluateOperator, exception };
189
- new_image = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(EvaluateImages), &args);
210
+ DECLARE_GVL_CALL(call, EvaluateImages, images, MeanEvaluateOperator, exception);
211
+ new_image = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
190
212
  rm_split(images);
191
213
  RB_GC_GUARD(clones);
192
214
  rm_check_exception(exception, new_image, DestroyOnError);
@@ -215,8 +237,8 @@ ImageList_coalesce(VALUE self)
215
237
  images = images_from_imagelist(self, &clones);
216
238
 
217
239
  exception = AcquireExceptionInfo();
218
- GVL_STRUCT_TYPE(CoalesceImages) args = { images, exception };
219
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CoalesceImages), &args);
240
+ DECLARE_GVL_CALL(call, CoalesceImages, images, exception);
241
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
220
242
  rm_split(images);
221
243
  RB_GC_GUARD(clones);
222
244
  rm_check_exception(exception, new_images, DestroyOnError);
@@ -301,16 +323,20 @@ VALUE ImageList_combine(int argc, VALUE *argv, VALUE self)
301
323
  #endif
302
324
 
303
325
  VALUE clones;
326
+ #if defined(IMAGEMAGICK_6)
327
+ check_images_writable(self);
328
+ #endif
304
329
  images = images_from_imagelist(self, &clones);
305
330
  exception = AcquireExceptionInfo();
306
331
  #if defined(IMAGEMAGICK_6)
307
332
  old_colorspace = images->colorspace;
308
333
  SetImageColorspace(images, colorspace);
309
- GVL_STRUCT_TYPE(CombineImages) args = { images, channel, exception };
334
+ DECLARE_GVL_CALL(call, CombineImages, images, channel, exception);
335
+ call.update(images).restore(restore_colorspace, images, old_colorspace);
310
336
  #else
311
- GVL_STRUCT_TYPE(CombineImages) args = { images, colorspace, exception };
337
+ DECLARE_GVL_CALL(call, CombineImages, images, colorspace, exception);
312
338
  #endif
313
- new_image = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CombineImages), &args);
339
+ new_image = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
314
340
 
315
341
  rm_split(images);
316
342
  RB_GC_GUARD(clones);
@@ -387,8 +413,8 @@ ImageList_composite_layers(int argc, VALUE *argv, VALUE self)
387
413
  new_images->gravity, &geometry);
388
414
 
389
415
  exception = AcquireExceptionInfo();
390
- GVL_STRUCT_TYPE(CompositeLayers) args = { new_images, composite_op, source, geometry.x, geometry.y, exception };
391
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CompositeLayers), &args);
416
+ DECLARE_GVL_CALL(call, CompositeLayers, new_images, composite_op, source, geometry.x, geometry.y, exception);
417
+ call.read_each(rb_iv_get(source_images, "@images")).split(source).destroy(new_images).release(exception).run<void>();
392
418
  rm_split(source);
393
419
  RB_GC_GUARD(source_clones);
394
420
  rm_check_exception(exception, new_images, DestroyOnError);
@@ -416,11 +442,11 @@ ImageList_deconstruct(VALUE self)
416
442
  images = images_from_imagelist(self, &clones);
417
443
  exception = AcquireExceptionInfo();
418
444
  #if defined(IMAGEMAGICK_7)
419
- GVL_STRUCT_TYPE(CompareImagesLayers) args = { images, CompareAnyLayer, exception };
420
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CompareImagesLayers), &args);
445
+ DECLARE_GVL_CALL(call, CompareImagesLayers, images, CompareAnyLayer, exception);
446
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
421
447
  #else
422
- GVL_STRUCT_TYPE(DeconstructImages) args = { images, exception };
423
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(DeconstructImages), &args);
448
+ DECLARE_GVL_CALL(call, DeconstructImages, images, exception);
449
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
424
450
  #endif
425
451
  rm_split(images);
426
452
  RB_GC_GUARD(clones);
@@ -489,8 +515,8 @@ ImageList_flatten_images(VALUE self)
489
515
  images = images_from_imagelist(self, &clones);
490
516
  exception = AcquireExceptionInfo();
491
517
 
492
- GVL_STRUCT_TYPE(MergeImageLayers) args = { images, FlattenLayer, exception };
493
- new_image = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MergeImageLayers), &args);
518
+ DECLARE_GVL_CALL(call, MergeImageLayers, images, FlattenLayer, exception);
519
+ new_image = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
494
520
 
495
521
  rm_split(images);
496
522
  RB_GC_GUARD(clones);
@@ -532,6 +558,7 @@ ImageList_montage(VALUE self)
532
558
  TypedData_Get_Struct(montage_obj, Montage, &rm_montage_data_type, montage);
533
559
 
534
560
  VALUE clones;
561
+ check_images_writable(self);
535
562
  images = images_from_imagelist(self, &clones);
536
563
 
537
564
  for (Image *image = images; image; image = GetNextImageInList(image))
@@ -549,8 +576,8 @@ ImageList_montage(VALUE self)
549
576
  exception = AcquireExceptionInfo();
550
577
 
551
578
  // MontageImage can return more than one image.
552
- GVL_STRUCT_TYPE(MontageImages) args = { images, montage->info, exception };
553
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MontageImages), &args);
579
+ DECLARE_GVL_CALL(call, MontageImages, images, montage->info, exception);
580
+ new_images = call.update_each(rb_iv_get(self, "@images")).read(montage_obj).split(images).release(exception).run<Image *>();
554
581
  rm_split(images);
555
582
  RB_GC_GUARD(clones);
556
583
  rm_check_exception(exception, new_images, DestroyOnError);
@@ -588,8 +615,8 @@ ImageList_morph(VALUE self, VALUE nimages)
588
615
  VALUE clones;
589
616
  images = images_from_imagelist(self, &clones);
590
617
  exception = AcquireExceptionInfo();
591
- GVL_STRUCT_TYPE(MorphImages) args = { images, number_images, exception };
592
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MorphImages), &args);
618
+ DECLARE_GVL_CALL(call, MorphImages, images, number_images, exception);
619
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
593
620
  rm_split(images);
594
621
  RB_GC_GUARD(clones);
595
622
  rm_check_exception(exception, new_images, DestroyOnError);
@@ -614,8 +641,8 @@ ImageList_mosaic(VALUE self)
614
641
  images = images_from_imagelist(self, &clones);
615
642
 
616
643
  exception = AcquireExceptionInfo();
617
- GVL_STRUCT_TYPE(MergeImageLayers) args = { images, MosaicLayer, exception };
618
- new_image = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MergeImageLayers), &args);
644
+ DECLARE_GVL_CALL(call, MergeImageLayers, images, MosaicLayer, exception);
645
+ new_image = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
619
646
 
620
647
  rm_split(images);
621
648
  RB_GC_GUARD(clones);
@@ -652,35 +679,35 @@ ImageList_optimize_layers(VALUE self, VALUE method)
652
679
  {
653
680
  case CoalesceLayer:
654
681
  {
655
- GVL_STRUCT_TYPE(CoalesceImages) args = { images, exception };
656
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CoalesceImages), &args);
682
+ DECLARE_GVL_CALL(call, CoalesceImages, images, exception);
683
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
657
684
  }
658
685
  break;
659
686
  case DisposeLayer:
660
687
  {
661
- GVL_STRUCT_TYPE(DisposeImages) args = { images, exception };
662
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(DisposeImages), &args);
688
+ DECLARE_GVL_CALL(call, DisposeImages, images, exception);
689
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
663
690
  }
664
691
  break;
665
692
  case OptimizeTransLayer:
666
693
  {
667
694
  new_images = clone_imagelist(images);
668
- GVL_STRUCT_TYPE(OptimizeImageTransparency) args = { new_images, exception };
669
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(OptimizeImageTransparency), &args);
695
+ DECLARE_GVL_CALL(call, OptimizeImageTransparency, new_images, exception);
696
+ call.read_each(rb_iv_get(self, "@images")).split(images).destroy(new_images).release(exception).run<void>();
670
697
  }
671
698
  break;
672
699
  case RemoveDupsLayer:
673
700
  {
674
701
  new_images = clone_imagelist(images);
675
- GVL_STRUCT_TYPE(RemoveDuplicateLayers) args = { &new_images, exception };
676
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(RemoveDuplicateLayers), &args);
702
+ DECLARE_GVL_CALL(call, RemoveDuplicateLayers, &new_images, exception);
703
+ call.read_each(rb_iv_get(self, "@images")).split(images).cleanup(destroy_list_at, &new_images).release(exception).run<void>();
677
704
  }
678
705
  break;
679
706
  case RemoveZeroLayer:
680
707
  {
681
708
  new_images = clone_imagelist(images);
682
- GVL_STRUCT_TYPE(RemoveZeroDelayLayers) args = { &new_images, exception };
683
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(RemoveZeroDelayLayers), &args);
709
+ DECLARE_GVL_CALL(call, RemoveZeroDelayLayers, &new_images, exception);
710
+ call.read_each(rb_iv_get(self, "@images")).split(images).cleanup(destroy_list_at, &new_images).release(exception).run<void>();
684
711
  }
685
712
  break;
686
713
  case CompositeLayer:
@@ -691,42 +718,42 @@ ImageList_optimize_layers(VALUE self, VALUE method)
691
718
  // In 6.3.4-ish, OptimizeImageLayer replaced OptimizeLayer
692
719
  case OptimizeImageLayer:
693
720
  {
694
- GVL_STRUCT_TYPE(OptimizeImageLayers) args = { images, exception };
695
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(OptimizeImageLayers), &args);
721
+ DECLARE_GVL_CALL(call, OptimizeImageLayers, images, exception);
722
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
696
723
  }
697
724
  break;
698
725
  // and OptimizeLayer became a "General Purpose, GIF Animation Optimizer" (ref. mogrify.c)
699
726
  case OptimizeLayer:
700
727
  {
701
- GVL_STRUCT_TYPE(CoalesceImages) args_CoalesceImages = { images, exception };
702
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CoalesceImages), &args_CoalesceImages);
728
+ DECLARE_GVL_CALL(coalesce_call, CoalesceImages, images, exception);
729
+ new_images = coalesce_call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
703
730
  rm_split(images);
704
731
  rm_check_exception(exception, new_images, DestroyOnError);
705
732
 
706
- GVL_STRUCT_TYPE(OptimizeImageLayers) args_OptimizeImageLayers = { new_images, exception };
707
- new_images2 = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(OptimizeImageLayers), &args_OptimizeImageLayers);
733
+ DECLARE_GVL_CALL(optimize_call, OptimizeImageLayers, new_images, exception);
734
+ new_images2 = optimize_call.destroy(new_images).release(exception).run<Image *>();
708
735
  DestroyImageList(new_images);
709
736
  rm_check_exception(exception, new_images2, DestroyOnError);
710
737
 
711
738
  new_images = new_images2;
712
- GVL_STRUCT_TYPE(OptimizeImageTransparency) args_OptimizeImageTransparency = { new_images, exception };
713
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(OptimizeImageTransparency), &args_OptimizeImageTransparency);
739
+ DECLARE_GVL_CALL(transparency_call, OptimizeImageTransparency, new_images, exception);
740
+ transparency_call.destroy(new_images).release(exception).run<void>();
714
741
  rm_check_exception(exception, new_images, DestroyOnError);
715
742
  // mogrify supports -dither here. We don't.
716
743
  GetQuantizeInfo(&quantize_info);
717
744
  #if defined(IMAGEMAGICK_7)
718
- GVL_STRUCT_TYPE(RemapImages) args_RemapImages = { &quantize_info, new_images, NULL, exception };
745
+ DECLARE_GVL_CALL(remap_call, RemapImages, &quantize_info, new_images, NULL, exception);
719
746
  #else
720
- GVL_STRUCT_TYPE(RemapImages) args_RemapImages = { &quantize_info, new_images, NULL };
747
+ DECLARE_GVL_CALL(remap_call, RemapImages, &quantize_info, new_images, NULL);
721
748
  #endif
722
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(RemapImages), &args_RemapImages);
749
+ remap_call.destroy(new_images).release(exception).run<void>();
723
750
 
724
751
  }
725
752
  break;
726
753
  case OptimizePlusLayer:
727
754
  {
728
- GVL_STRUCT_TYPE(OptimizePlusImageLayers) args = { images, exception };
729
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(OptimizePlusImageLayers), &args);
755
+ DECLARE_GVL_CALL(call, OptimizePlusImageLayers, images, exception);
756
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
730
757
  }
731
758
  break;
732
759
  case CompareAnyLayer:
@@ -734,36 +761,36 @@ ImageList_optimize_layers(VALUE self, VALUE method)
734
761
  case CompareOverlayLayer:
735
762
  {
736
763
  #if defined(IMAGEMAGICK_7)
737
- GVL_STRUCT_TYPE(CompareImagesLayers) args = { images, mthd, exception };
738
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CompareImagesLayers), &args);
764
+ DECLARE_GVL_CALL(call, CompareImagesLayers, images, mthd, exception);
765
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
739
766
  #else
740
- GVL_STRUCT_TYPE(CompareImageLayers) args = { images, mthd, exception };
741
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CompareImageLayers), &args);
767
+ DECLARE_GVL_CALL(call, CompareImageLayers, images, mthd, exception);
768
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
742
769
  #endif
743
770
  }
744
771
  break;
745
772
  case MosaicLayer:
746
773
  {
747
- GVL_STRUCT_TYPE(MergeImageLayers) args = { images, mthd, exception };
748
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MergeImageLayers), &args);
774
+ DECLARE_GVL_CALL(call, MergeImageLayers, images, mthd, exception);
775
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
749
776
  }
750
777
  break;
751
778
  case FlattenLayer:
752
779
  {
753
- GVL_STRUCT_TYPE(MergeImageLayers) args = { images, mthd, exception };
754
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MergeImageLayers), &args);
780
+ DECLARE_GVL_CALL(call, MergeImageLayers, images, mthd, exception);
781
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
755
782
  }
756
783
  break;
757
784
  case MergeLayer:
758
785
  {
759
- GVL_STRUCT_TYPE(MergeImageLayers) args = { images, mthd, exception };
760
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MergeImageLayers), &args);
786
+ DECLARE_GVL_CALL(call, MergeImageLayers, images, mthd, exception);
787
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
761
788
  }
762
789
  break;
763
790
  case TrimBoundsLayer:
764
791
  {
765
- GVL_STRUCT_TYPE(MergeImageLayers) args = { images, mthd, exception };
766
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(MergeImageLayers), &args);
792
+ DECLARE_GVL_CALL(call, MergeImageLayers, images, mthd, exception);
793
+ new_images = call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
767
794
  }
768
795
  break;
769
796
  default:
@@ -836,6 +863,25 @@ rm_imagelist_from_images(Image *images)
836
863
  }
837
864
 
838
865
 
866
+ /**
867
+ * Raise if an offloaded call is using any image in the imagelist.
868
+ *
869
+ * No Ruby usage (internal function)
870
+ *
871
+ * @param imagelist the imagelist
872
+ */
873
+ static void
874
+ check_images_writable(VALUE imagelist)
875
+ {
876
+ VALUE images = rb_iv_get(imagelist, "@images");
877
+
878
+ for (long i = 0; i < RARRAY_LEN(images); i++)
879
+ {
880
+ rm_check_writable(rb_ary_entry(images, i));
881
+ }
882
+ }
883
+
884
+
839
885
  /**
840
886
  * Convert an array of Image *s to an ImageMagick scene sequence (i.e. a
841
887
  * doubly-linked list of Images).
@@ -863,9 +909,9 @@ images_from_imagelist(VALUE imagelist, VALUE *clones)
863
909
  Image *image;
864
910
 
865
911
  t = rb_ary_entry(images, x);
866
- image = rm_check_destroyed(t);
912
+ image = rm_check_readable(t);
867
913
  // avoid a loop in this linked imagelist, issue #202
868
- if (head == image || GetPreviousImageInList(image) != NULL)
914
+ if (head == image || GetPreviousImageInList(image) != NULL || GetNextImageInList(image) != NULL)
869
915
  {
870
916
  image = rm_clone_image(image);
871
917
 
@@ -987,8 +1033,8 @@ clone_imagelist(Image *images)
987
1033
  {
988
1034
  Image *clone;
989
1035
 
990
- GVL_STRUCT_TYPE(CloneImage) args = { image, 0, 0, MagickTrue, exception };
991
- clone = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CloneImage), &args);
1036
+ DECLARE_GVL_CALL(call, CloneImage, image, 0, 0, MagickTrue, exception);
1037
+ clone = call.keep_thread().run<Image *>();
992
1038
  rm_check_exception(exception, new_imagelist, DestroyOnError);
993
1039
  AppendImageToList(&new_imagelist, clone);
994
1040
  image = GetNextImageInList(image);
@@ -1066,8 +1112,8 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
1066
1112
  VALUE clones;
1067
1113
  images = images_from_imagelist(self, &clones);
1068
1114
  exception = AcquireExceptionInfo();
1069
- GVL_STRUCT_TYPE(CloneImageList) args_CloneImageList = { images, exception };
1070
- new_images = (Image *)CALL_FUNC_WITHOUT_GVL(GVL_FUNC(CloneImageList), &args_CloneImageList);
1115
+ DECLARE_GVL_CALL(clone_call, CloneImageList, images, exception);
1116
+ new_images = clone_call.read_each(rb_iv_get(self, "@images")).split(images).release(exception).run<Image *>();
1071
1117
  rm_split(images);
1072
1118
  RB_GC_GUARD(clones);
1073
1119
  rm_check_exception(exception, new_images, DestroyOnError);
@@ -1075,11 +1121,11 @@ ImageList_quantize(int argc, VALUE *argv, VALUE self)
1075
1121
  rm_ensure_result(new_images);
1076
1122
 
1077
1123
  #if defined(IMAGEMAGICK_7)
1078
- GVL_STRUCT_TYPE(QuantizeImages) args_QuantizeImages = { &quantize_info, new_images, exception };
1124
+ DECLARE_GVL_CALL(quantize_call, QuantizeImages, &quantize_info, new_images, exception);
1079
1125
  #else
1080
- GVL_STRUCT_TYPE(QuantizeImages) args_QuantizeImages = { &quantize_info, new_images };
1126
+ DECLARE_GVL_CALL(quantize_call, QuantizeImages, &quantize_info, new_images);
1081
1127
  #endif
1082
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(QuantizeImages), &args_QuantizeImages);
1128
+ quantize_call.destroy(new_images).release(exception).run<void>();
1083
1129
  rm_check_exception(exception, new_images, DestroyOnError);
1084
1130
  DestroyExceptionInfo(exception);
1085
1131
 
@@ -1116,6 +1162,7 @@ VALUE
1116
1162
  ImageList_remap(int argc, VALUE *argv, VALUE self)
1117
1163
  {
1118
1164
  Image *images, *remap_image = NULL;
1165
+ VALUE remap_obj = Qnil;
1119
1166
  QuantizeInfo quantize_info;
1120
1167
  #if defined(IMAGEMAGICK_7)
1121
1168
  ExceptionInfo *exception;
@@ -1123,9 +1170,8 @@ ImageList_remap(int argc, VALUE *argv, VALUE self)
1123
1170
 
1124
1171
  if (argc > 0 && argv[0] != Qnil)
1125
1172
  {
1126
- VALUE t = rm_cur_image(argv[0]);
1127
- remap_image = rm_check_destroyed(t);
1128
- RB_GC_GUARD(t);
1173
+ remap_obj = rm_cur_image(argv[0]);
1174
+ remap_image = rm_check_readable(remap_obj);
1129
1175
  }
1130
1176
 
1131
1177
  GetQuantizeInfo(&quantize_info);
@@ -1143,23 +1189,25 @@ ImageList_remap(int argc, VALUE *argv, VALUE self)
1143
1189
  }
1144
1190
 
1145
1191
  VALUE clones;
1192
+ check_images_writable(self);
1146
1193
  images = images_from_imagelist(self, &clones);
1147
1194
 
1148
1195
  #if defined(IMAGEMAGICK_7)
1149
1196
  exception = AcquireExceptionInfo();
1150
- GVL_STRUCT_TYPE(RemapImages) args = { &quantize_info, images, remap_image, exception };
1151
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(RemapImages), &args);
1197
+ DECLARE_GVL_CALL(call, RemapImages, &quantize_info, images, remap_image, exception);
1198
+ call.update_each(rb_iv_get(self, "@images")).read(remap_obj).split(images).release(exception).run<void>();
1152
1199
  rm_split(images);
1153
1200
  CHECK_EXCEPTION();
1154
1201
  DestroyExceptionInfo(exception);
1155
1202
  #else
1156
- GVL_STRUCT_TYPE(RemapImages) args = { &quantize_info, images, remap_image };
1157
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(RemapImages), &args);
1203
+ DECLARE_GVL_CALL(call, RemapImages, &quantize_info, images, remap_image);
1204
+ call.update_each(rb_iv_get(self, "@images")).read(remap_obj).split(images).run<void>();
1158
1205
  rm_split(images);
1159
1206
  rm_check_image_exception(images, RetainOnError);
1160
1207
  #endif
1161
1208
 
1162
1209
  RB_GC_GUARD(clones);
1210
+ RB_GC_GUARD(remap_obj);
1163
1211
 
1164
1212
  return self;
1165
1213
  }
@@ -1193,6 +1241,7 @@ ImageList_to_blob(VALUE self)
1193
1241
 
1194
1242
  // Convert the images array to an images sequence.
1195
1243
  VALUE clones;
1244
+ check_images_writable(self);
1196
1245
  images = images_from_imagelist(self, &clones);
1197
1246
 
1198
1247
  exception = AcquireExceptionInfo();
@@ -1217,8 +1266,8 @@ ImageList_to_blob(VALUE self)
1217
1266
  // can happen is that there's only one image or the format
1218
1267
  // doesn't support multi-image files.
1219
1268
  info->adjoin = MagickTrue;
1220
- GVL_STRUCT_TYPE(ImagesToBlob) args = { info, images, &length, exception };
1221
- blob = CALL_FUNC_WITHOUT_GVL(GVL_FUNC(ImagesToBlob), &args);
1269
+ DECLARE_GVL_CALL(call, ImagesToBlob, info, images, &length, exception);
1270
+ blob = call.update_each(rb_iv_get(self, "@images")).read(info_obj).split(images).release(exception).free_result().run<void *>();
1222
1271
  if (blob && exception->severity >= ErrorException)
1223
1272
  {
1224
1273
  magick_free((void*)blob);
@@ -1292,7 +1341,9 @@ ImageList_write(VALUE self, VALUE file)
1292
1341
  }
1293
1342
 
1294
1343
  // Convert the images array to an images sequence.
1295
- VALUE clones;
1344
+ VALUE clones, written;
1345
+ check_images_writable(self);
1346
+ written = rb_ary_dup(rb_iv_get(self, "@images"));
1296
1347
  images = images_from_imagelist(self, &clones);
1297
1348
 
1298
1349
  // Copy the filename into each image. Set a scene number to be used if
@@ -1324,12 +1375,14 @@ ImageList_write(VALUE self, VALUE file)
1324
1375
  {
1325
1376
  rm_sync_image_options(img, info);
1326
1377
  #if defined(IMAGEMAGICK_7)
1327
- GVL_STRUCT_TYPE(WriteImage) args = { info, img, exception };
1328
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(WriteImage), &args);
1378
+ DECLARE_GVL_CALL(call, WriteImage, info, img, exception);
1379
+ call.update_each(written).read(info_obj).split(images).release(exception);
1380
+ call.keep_thread(info->file != NULL).run<void>();
1329
1381
  rm_check_exception(exception, img, RetainOnError);
1330
1382
  #else
1331
- GVL_STRUCT_TYPE(WriteImage) args = { info, img };
1332
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(WriteImage), &args);
1383
+ DECLARE_GVL_CALL(call, WriteImage, info, img);
1384
+ call.update_each(written).read(info_obj).split(images);
1385
+ call.keep_thread(info->file != NULL).run<void>();
1333
1386
  // images will be split before raising an exception
1334
1387
  rm_check_image_exception(images, RetainOnError);
1335
1388
  #endif
@@ -1345,6 +1398,7 @@ ImageList_write(VALUE self, VALUE file)
1345
1398
 
1346
1399
  rm_split(images);
1347
1400
  RB_GC_GUARD(clones);
1401
+ RB_GC_GUARD(written);
1348
1402
 
1349
1403
  RB_GC_GUARD(info_obj);
1350
1404