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.
@@ -22,6 +22,25 @@ const rb_data_type_t rm_info_data_type = {
22
22
  };
23
23
 
24
24
 
25
+ /**
26
+ * Return the Info struct of an object that is about to be changed.
27
+ *
28
+ * No Ruby usage (internal function)
29
+ *
30
+ * @param self the Info object
31
+ * @return the Info struct
32
+ * @throw RuntimeError if an offloaded call is using the Info
33
+ */
34
+ static Info *
35
+ get_writable_info(VALUE self)
36
+ {
37
+ Info *info;
38
+
39
+ TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
40
+ rm_gvl_check_writable(info);
41
+ return info;
42
+ }
43
+
25
44
  /**
26
45
  * Return the value of the specified option.
27
46
  *
@@ -82,7 +101,7 @@ set_option(VALUE self, const char *key, VALUE string)
82
101
  {
83
102
  Info *info;
84
103
 
85
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
104
+ info = get_writable_info(self);
86
105
 
87
106
  if (NIL_P(string))
88
107
  {
@@ -119,7 +138,7 @@ static VALUE set_color_option(VALUE self, const char *option, VALUE color)
119
138
  PixelColor pp;
120
139
  MagickBooleanType okay;
121
140
 
122
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
141
+ info = get_writable_info(self);
123
142
 
124
143
  if (NIL_P(color))
125
144
  {
@@ -196,7 +215,7 @@ static VALUE set_dbl_option(VALUE self, const char *option, VALUE value)
196
215
  {
197
216
  Info *info;
198
217
 
199
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
218
+ info = get_writable_info(self);
200
219
 
201
220
  if (NIL_P(value))
202
221
  {
@@ -352,7 +371,7 @@ Info_aset(int argc, VALUE *argv, VALUE self)
352
371
  size_t format_l, key_l;
353
372
  char ckey[MaxTextExtent];
354
373
 
355
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
374
+ info = get_writable_info(self);
356
375
 
357
376
  switch (argc)
358
377
  {
@@ -464,7 +483,7 @@ Info_authenticate_eq(VALUE self, VALUE passwd_arg)
464
483
  Info *info;
465
484
  char *passwd = NULL;
466
485
 
467
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
486
+ info = get_writable_info(self);
468
487
 
469
488
  if (!NIL_P(passwd_arg))
470
489
  {
@@ -523,7 +542,7 @@ Info_background_color_eq(VALUE self, VALUE bc_arg)
523
542
  {
524
543
  Info *info;
525
544
 
526
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
545
+ info = get_writable_info(self);
527
546
  Color_to_PixelColor(&info->background_color, bc_arg);
528
547
 
529
548
  return bc_arg;
@@ -555,7 +574,7 @@ Info_border_color_eq(VALUE self, VALUE bc_arg)
555
574
  {
556
575
  Info *info;
557
576
 
558
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
577
+ info = get_writable_info(self);
559
578
  Color_to_PixelColor(&info->border_color, bc_arg);
560
579
 
561
580
  return bc_arg;
@@ -617,7 +636,7 @@ Info_channel(int argc, VALUE *argv, VALUE self)
617
636
  raise_ChannelType_error(argv[argc-1]);
618
637
  }
619
638
 
620
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
639
+ info = get_writable_info(self);
621
640
 
622
641
  info->channel = channels;
623
642
  return self;
@@ -649,7 +668,7 @@ Info_colorspace_eq(VALUE self, VALUE colorspace)
649
668
  {
650
669
  Info *info;
651
670
 
652
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
671
+ info = get_writable_info(self);
653
672
  VALUE_TO_ENUM(colorspace, info->colorspace, ColorspaceType);
654
673
  return colorspace;
655
674
  }
@@ -703,7 +722,7 @@ Info_compression_eq(VALUE self, VALUE type)
703
722
  {
704
723
  Info *info;
705
724
 
706
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
725
+ info = get_writable_info(self);
707
726
  VALUE_TO_ENUM(type, info->compression, CompressionType);
708
727
  return type;
709
728
  }
@@ -729,7 +748,7 @@ Info_define(int argc, VALUE *argv, VALUE self)
729
748
  unsigned int okay;
730
749
  VALUE fmt_arg;
731
750
 
732
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
751
+ info = get_writable_info(self);
733
752
 
734
753
  switch (argc)
735
754
  {
@@ -819,7 +838,7 @@ Info_delay_eq(VALUE self, VALUE string)
819
838
  Info *info;
820
839
  int not_num;
821
840
 
822
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
841
+ info = get_writable_info(self);
823
842
 
824
843
  if (NIL_P(string))
825
844
  {
@@ -868,7 +887,7 @@ Info_density_eq(VALUE self, VALUE density_arg)
868
887
  VALUE density;
869
888
  char *dens;
870
889
 
871
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
890
+ info = get_writable_info(self);
872
891
 
873
892
  if (NIL_P(density_arg))
874
893
  {
@@ -914,7 +933,7 @@ Info_depth_eq(VALUE self, VALUE depth)
914
933
  Info *info;
915
934
  unsigned long d;
916
935
 
917
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
936
+ info = get_writable_info(self);
918
937
  d = NUM2ULONG(depth);
919
938
  switch (d)
920
939
  {
@@ -1033,7 +1052,7 @@ Info_dispose_eq(VALUE self, VALUE disp)
1033
1052
  const char *option;
1034
1053
  int x;
1035
1054
 
1036
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1055
+ info = get_writable_info(self);
1037
1056
 
1038
1057
  if (NIL_P(disp))
1039
1058
  {
@@ -1113,7 +1132,7 @@ Info_endian_eq(VALUE self, VALUE endian)
1113
1132
  VALUE_TO_ENUM(endian, type, EndianType);
1114
1133
  }
1115
1134
 
1116
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1135
+ info = get_writable_info(self);
1117
1136
  info->endian = type;
1118
1137
  return endian;
1119
1138
  }
@@ -1145,7 +1164,7 @@ Info_extract_eq(VALUE self, VALUE extract_arg)
1145
1164
  char *extr;
1146
1165
  VALUE extract;
1147
1166
 
1148
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1167
+ info = get_writable_info(self);
1149
1168
 
1150
1169
  if (NIL_P(extract_arg))
1151
1170
  {
@@ -1198,7 +1217,7 @@ Info_filename_eq(VALUE self, VALUE filename)
1198
1217
  {
1199
1218
  Info *info;
1200
1219
 
1201
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1220
+ info = get_writable_info(self);
1202
1221
 
1203
1222
  // Allow "nil" - remove current filename
1204
1223
  if (NIL_P(filename) || StringValueCStr(filename) == NULL)
@@ -1263,7 +1282,7 @@ Info_font_eq(VALUE self, VALUE font_arg)
1263
1282
  {
1264
1283
  Info *info;
1265
1284
 
1266
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1285
+ info = get_writable_info(self);
1267
1286
  if (NIL_P(font_arg) || StringValueCStr(font_arg) == NULL)
1268
1287
  {
1269
1288
  magick_free(info->font);
@@ -1318,7 +1337,7 @@ Info_format_eq(VALUE self, VALUE magick)
1318
1337
  char *mgk;
1319
1338
  ExceptionInfo *exception;
1320
1339
 
1321
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1340
+ info = get_writable_info(self);
1322
1341
 
1323
1342
  mgk = StringValueCStr(magick);
1324
1343
 
@@ -1361,7 +1380,7 @@ Info_fuzz_eq(VALUE self, VALUE fuzz)
1361
1380
  {
1362
1381
  Info *info;
1363
1382
 
1364
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1383
+ info = get_writable_info(self);
1365
1384
  info->fuzz = rm_fuzz_to_dbl(fuzz);
1366
1385
  return fuzz;
1367
1386
  }
@@ -1464,7 +1483,7 @@ Info_gravity_eq(VALUE self, VALUE grav)
1464
1483
  const char *option;
1465
1484
  int x;
1466
1485
 
1467
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1486
+ info = get_writable_info(self);
1468
1487
 
1469
1488
  if (NIL_P(grav))
1470
1489
  {
@@ -1514,7 +1533,7 @@ Info_image_type_eq(VALUE self, VALUE type)
1514
1533
  {
1515
1534
  Info *info;
1516
1535
 
1517
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1536
+ info = get_writable_info(self);
1518
1537
  VALUE_TO_ENUM(type, info->type, ImageType);
1519
1538
  return type;
1520
1539
  }
@@ -1544,7 +1563,7 @@ Info_interlace_eq(VALUE self, VALUE inter)
1544
1563
  {
1545
1564
  Info *info;
1546
1565
 
1547
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1566
+ info = get_writable_info(self);
1548
1567
  VALUE_TO_ENUM(inter, info->interlace, InterlaceType);
1549
1568
  return inter;
1550
1569
  }
@@ -1599,7 +1618,7 @@ Info_matte_color_eq(VALUE self, VALUE matte_arg)
1599
1618
  {
1600
1619
  Info *info;
1601
1620
 
1602
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1621
+ info = get_writable_info(self);
1603
1622
  Color_to_PixelColor(&info->matte_color, matte_arg);
1604
1623
 
1605
1624
  return matte_arg;
@@ -1677,7 +1696,7 @@ Info_orientation_eq(VALUE self, VALUE inter)
1677
1696
  {
1678
1697
  Info *info;
1679
1698
 
1680
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1699
+ info = get_writable_info(self);
1681
1700
  VALUE_TO_ENUM(inter, info->orientation, OrientationType);
1682
1701
  return inter;
1683
1702
  }
@@ -1720,7 +1739,7 @@ Info_origin_eq(VALUE self, VALUE origin_arg)
1720
1739
  VALUE origin_str;
1721
1740
  char *origin;
1722
1741
 
1723
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1742
+ info = get_writable_info(self);
1724
1743
 
1725
1744
  if (NIL_P(origin_arg))
1726
1745
  {
@@ -1776,7 +1795,7 @@ Info_page_eq(VALUE self, VALUE page_arg)
1776
1795
  VALUE geom_str;
1777
1796
  char *geometry;
1778
1797
 
1779
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1798
+ info = get_writable_info(self);
1780
1799
  if (NIL_P(page_arg))
1781
1800
  {
1782
1801
  magick_free(info->page);
@@ -1880,7 +1899,7 @@ Info_sampling_factor_eq(VALUE self, VALUE sampling_factor)
1880
1899
  char *sampling_factor_p = NULL;
1881
1900
  size_t sampling_factor_len = 0;
1882
1901
 
1883
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1902
+ info = get_writable_info(self);
1884
1903
 
1885
1904
  if (!NIL_P(sampling_factor))
1886
1905
  {
@@ -1928,7 +1947,7 @@ Info_scene_eq(VALUE self, VALUE scene)
1928
1947
  Info *info;
1929
1948
  char buf[25];
1930
1949
 
1931
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1950
+ info = get_writable_info(self);
1932
1951
  info->scene = NUM2ULONG(scene);
1933
1952
 
1934
1953
  snprintf(buf, sizeof(buf), "%" RMIuSIZE "", info->scene);
@@ -1961,7 +1980,7 @@ Info_server_name_eq(VALUE self, VALUE server_arg)
1961
1980
  {
1962
1981
  Info *info;
1963
1982
 
1964
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
1983
+ info = get_writable_info(self);
1965
1984
  if (NIL_P(server_arg) || StringValueCStr(server_arg) == NULL)
1966
1985
  {
1967
1986
  magick_free(info->server_name);
@@ -2003,7 +2022,7 @@ Info_size_eq(VALUE self, VALUE size_arg)
2003
2022
  VALUE size;
2004
2023
  char *sz;
2005
2024
 
2006
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2025
+ info = get_writable_info(self);
2007
2026
 
2008
2027
  if (NIL_P(size_arg))
2009
2028
  {
@@ -2089,7 +2108,7 @@ Info_texture_eq(VALUE self, VALUE texture)
2089
2108
  Image *image;
2090
2109
  char name[MaxTextExtent];
2091
2110
 
2092
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2111
+ info = get_writable_info(self);
2093
2112
 
2094
2113
  // Delete any existing texture file
2095
2114
  if (info->texture)
@@ -2106,7 +2125,7 @@ Info_texture_eq(VALUE self, VALUE texture)
2106
2125
  }
2107
2126
 
2108
2127
  // Create a temp copy of the texture and store its name in the texture field
2109
- image = rm_check_destroyed(texture);
2128
+ image = rm_check_readable(texture);
2110
2129
  rm_write_temp_image(image, name, sizeof(name));
2111
2130
 
2112
2131
  magick_clone_string(&info->texture, name);
@@ -2161,7 +2180,7 @@ Info_tile_offset_eq(VALUE self, VALUE offset)
2161
2180
  rb_raise(rb_eArgError, "invalid tile offset geometry: %s", tile_offset);
2162
2181
  }
2163
2182
 
2164
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2183
+ info = get_writable_info(self);
2165
2184
 
2166
2185
  DeleteImageOption(info, "tile-offset");
2167
2186
  SetImageOption(info, "tile-offset", tile_offset);
@@ -2199,7 +2218,7 @@ Info_transparent_color_eq(VALUE self, VALUE tc_arg)
2199
2218
  {
2200
2219
  Info *info;
2201
2220
 
2202
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2221
+ info = get_writable_info(self);
2203
2222
  Color_to_PixelColor(&info->transparent_color, tc_arg);
2204
2223
 
2205
2224
  return tc_arg;
@@ -2231,7 +2250,7 @@ Info_undefine(VALUE self, VALUE format, VALUE key)
2231
2250
 
2232
2251
  snprintf(fkey, sizeof(fkey), "%.60s:%.*s", format_p, (int)(MaxTextExtent-61), key_p);
2233
2252
 
2234
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2253
+ info = get_writable_info(self);
2235
2254
  DeleteImageOption(info, fkey);
2236
2255
 
2237
2256
  return self;
@@ -2286,7 +2305,7 @@ Info_units_eq(VALUE self, VALUE units)
2286
2305
  {
2287
2306
  Info *info;
2288
2307
 
2289
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2308
+ info = get_writable_info(self);
2290
2309
  VALUE_TO_ENUM(units, info->units, ResolutionType);
2291
2310
  return units;
2292
2311
  }
@@ -2321,7 +2340,7 @@ Info_view_eq(VALUE self, VALUE view_arg)
2321
2340
  Info *info;
2322
2341
  char *view = NULL;
2323
2342
 
2324
- TypedData_Get_Struct(self, Info, &rm_info_data_type, info);
2343
+ info = get_writable_info(self);
2325
2344
 
2326
2345
  if (!NIL_P(view_arg))
2327
2346
  {
@@ -128,6 +128,11 @@ KernelInfo_initialize(VALUE self, VALUE kernel_string)
128
128
  }
129
129
 
130
130
  old_kernel = (KernelInfo *)DATA_PTR(self);
131
+ if (old_kernel && rm_gvl_in_use(old_kernel))
132
+ {
133
+ DestroyKernelInfo(kernel);
134
+ rm_gvl_check_writable(old_kernel);
135
+ }
131
136
  DATA_PTR(self) = kernel;
132
137
  if (old_kernel)
133
138
  {
@@ -173,12 +178,17 @@ get_kernel_info(VALUE self)
173
178
  * @param self the KernelInfo object
174
179
  * @return the KernelInfo struct
175
180
  * @throw FrozenError if the object is frozen
181
+ * @throw RuntimeError if an offloaded call is using the kernel
176
182
  */
177
183
  static KernelInfo *
178
- get_unfrozen_kernel_info(VALUE self)
184
+ get_writable_kernel_info(VALUE self)
179
185
  {
186
+ KernelInfo *kernel;
187
+
180
188
  rb_check_frozen(self);
181
- return get_kernel_info(self);
189
+ kernel = get_kernel_info(self);
190
+ rm_gvl_check_writable(kernel);
191
+ return kernel;
182
192
  }
183
193
 
184
194
 
@@ -190,8 +200,8 @@ get_unfrozen_kernel_info(VALUE self)
190
200
  VALUE
191
201
  KernelInfo_unity_add(VALUE self, VALUE scale)
192
202
  {
193
- GVL_STRUCT_TYPE(UnityAddKernelInfo) args = { get_unfrozen_kernel_info(self), NUM2DBL(scale) };
194
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(UnityAddKernelInfo), &args);
203
+ DECLARE_GVL_CALL(call, UnityAddKernelInfo, get_writable_kernel_info(self), NUM2DBL(scale));
204
+ call.update(self).run<void>();
195
205
  return Qnil;
196
206
  }
197
207
 
@@ -213,8 +223,8 @@ KernelInfo_scale(VALUE self, VALUE scale, VALUE flags)
213
223
 
214
224
  VALUE_TO_ENUM(flags, geoflags, GeometryFlags);
215
225
 
216
- GVL_STRUCT_TYPE(ScaleKernelInfo) args = { get_unfrozen_kernel_info(self), NUM2DBL(scale), geoflags };
217
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(ScaleKernelInfo), &args);
226
+ DECLARE_GVL_CALL(call, ScaleKernelInfo, get_writable_kernel_info(self), NUM2DBL(scale), geoflags);
227
+ call.update(self).run<void>();
218
228
  return Qnil;
219
229
  }
220
230
 
@@ -227,10 +237,14 @@ KernelInfo_scale(VALUE self, VALUE scale, VALUE flags)
227
237
  VALUE
228
238
  KernelInfo_scale_geometry(VALUE self, VALUE geometry)
229
239
  {
230
- char *geom = StringValueCStr(geometry);
240
+ KernelInfo *kernel = get_writable_kernel_info(self);
241
+ char *geom;
242
+
243
+ geometry = rb_str_new_frozen(StringValue(geometry));
244
+ geom = StringValueCStr(geometry);
231
245
 
232
- GVL_STRUCT_TYPE(ScaleGeometryKernelInfo) args = { get_unfrozen_kernel_info(self), geom };
233
- CALL_FUNC_WITHOUT_GVL(GVL_FUNC(ScaleGeometryKernelInfo), &args);
246
+ DECLARE_GVL_CALL(call, ScaleGeometryKernelInfo, kernel, geom);
247
+ call.update(self).run<void>();
234
248
 
235
249
  RB_GC_GUARD(geometry);
236
250
 
@@ -257,6 +271,11 @@ KernelInfo_init_copy(VALUE self, VALUE orig)
257
271
  }
258
272
 
259
273
  old_kernel = (KernelInfo *)DATA_PTR(self);
274
+ if (old_kernel && rm_gvl_in_use(old_kernel))
275
+ {
276
+ DestroyKernelInfo(kernel);
277
+ rm_gvl_check_writable(old_kernel);
278
+ }
260
279
  DATA_PTR(self) = kernel;
261
280
  if (old_kernel)
262
281
  {
@@ -232,6 +232,8 @@ Init_RMagick2(void)
232
232
  rb_ext_ractor_safe(true);
233
233
  #endif
234
234
 
235
+ rm_gvl_init();
236
+
235
237
  Module_Magick = rb_define_module("Magick");
236
238
 
237
239
  set_managed_memory();
@@ -107,6 +107,26 @@ Montage_alloc(VALUE klass)
107
107
  }
108
108
 
109
109
 
110
+ /**
111
+ * Return the Montage struct of an object that is about to be changed.
112
+ *
113
+ * No Ruby usage (internal function)
114
+ *
115
+ * @param self the Montage object
116
+ * @return the Montage struct
117
+ * @throw RuntimeError if an offloaded call is using the Montage
118
+ */
119
+ static Montage *
120
+ get_writable_montage(VALUE self)
121
+ {
122
+ Montage *montage;
123
+
124
+ TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
125
+ rm_gvl_check_writable(montage);
126
+ return montage;
127
+ }
128
+
129
+
110
130
  /**
111
131
  * Set background_color value.
112
132
  *
@@ -118,7 +138,7 @@ Montage_background_color_eq(VALUE self, VALUE color)
118
138
  {
119
139
  Montage *montage;
120
140
 
121
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
141
+ montage = get_writable_montage(self);
122
142
  Color_to_PixelColor(&montage->info->background_color, color);
123
143
  return color;
124
144
  }
@@ -135,7 +155,7 @@ Montage_border_color_eq(VALUE self, VALUE color)
135
155
  {
136
156
  Montage *montage;
137
157
 
138
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
158
+ montage = get_writable_montage(self);
139
159
  Color_to_PixelColor(&montage->info->border_color, color);
140
160
  return color;
141
161
  }
@@ -152,7 +172,7 @@ Montage_border_width_eq(VALUE self, VALUE width)
152
172
  {
153
173
  Montage *montage;
154
174
 
155
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
175
+ montage = get_writable_montage(self);
156
176
  montage->info->border_width = NUM2ULONG(width);
157
177
  return width;
158
178
  }
@@ -169,7 +189,7 @@ Montage_compose_eq(VALUE self, VALUE compose)
169
189
  {
170
190
  Montage *montage;
171
191
 
172
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
192
+ montage = get_writable_montage(self);
173
193
  VALUE_TO_ENUM(compose, montage->compose, CompositeOperator);
174
194
  return compose;
175
195
  }
@@ -186,7 +206,7 @@ Montage_filename_eq(VALUE self, VALUE filename)
186
206
  {
187
207
  Montage *montage;
188
208
 
189
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
209
+ montage = get_writable_montage(self);
190
210
  strlcpy(montage->info->filename, StringValueCStr(filename), sizeof(montage->info->filename));
191
211
  return filename;
192
212
  }
@@ -203,7 +223,7 @@ Montage_fill_eq(VALUE self, VALUE color)
203
223
  {
204
224
  Montage *montage;
205
225
 
206
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
226
+ montage = get_writable_montage(self);
207
227
  Color_to_PixelColor(&montage->info->fill, color);
208
228
  return color;
209
229
  }
@@ -220,7 +240,7 @@ Montage_font_eq(VALUE self, VALUE font)
220
240
  {
221
241
  Montage *montage;
222
242
 
223
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
243
+ montage = get_writable_montage(self);
224
244
  magick_clone_string(&montage->info->font, StringValueCStr(font));
225
245
 
226
246
  return font;
@@ -243,7 +263,7 @@ Montage_frame_eq(VALUE self, VALUE frame_arg)
243
263
  Montage *montage;
244
264
  VALUE frame;
245
265
 
246
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
266
+ montage = get_writable_montage(self);
247
267
  frame = rb_String(frame_arg);
248
268
  magick_clone_string(&montage->info->frame, StringValueCStr(frame));
249
269
 
@@ -270,7 +290,7 @@ Montage_geometry_eq(VALUE self, VALUE geometry_arg)
270
290
  Montage *montage;
271
291
  VALUE geometry;
272
292
 
273
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
293
+ montage = get_writable_montage(self);
274
294
  geometry = rb_String(geometry_arg);
275
295
  magick_clone_string(&montage->info->geometry, StringValueCStr(geometry));
276
296
 
@@ -291,7 +311,7 @@ Montage_gravity_eq(VALUE self, VALUE gravity)
291
311
  {
292
312
  Montage *montage;
293
313
 
294
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
314
+ montage = get_writable_montage(self);
295
315
  VALUE_TO_ENUM(gravity, montage->info->gravity, GravityType);
296
316
  return gravity;
297
317
  }
@@ -321,7 +341,7 @@ Montage_matte_color_eq(VALUE self, VALUE color)
321
341
  {
322
342
  Montage *montage;
323
343
 
324
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
344
+ montage = get_writable_montage(self);
325
345
  Color_to_PixelColor(&montage->info->matte_color, color);
326
346
  return color;
327
347
  }
@@ -338,7 +358,7 @@ Montage_pointsize_eq(VALUE self, VALUE size)
338
358
  {
339
359
  Montage *montage;
340
360
 
341
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
361
+ montage = get_writable_montage(self);
342
362
  montage->info->pointsize = NUM2DBL(size);
343
363
  return size;
344
364
  }
@@ -355,7 +375,7 @@ Montage_shadow_eq(VALUE self, VALUE shadow)
355
375
  {
356
376
  Montage *montage;
357
377
 
358
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
378
+ montage = get_writable_montage(self);
359
379
  montage->info->shadow = (MagickBooleanType) RTEST(shadow);
360
380
  return shadow;
361
381
  }
@@ -372,7 +392,7 @@ Montage_stroke_eq(VALUE self, VALUE color)
372
392
  {
373
393
  Montage *montage;
374
394
 
375
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
395
+ montage = get_writable_montage(self);
376
396
  Color_to_PixelColor(&montage->info->stroke, color);
377
397
  return color;
378
398
  }
@@ -392,7 +412,7 @@ Montage_texture_eq(VALUE self, VALUE texture)
392
412
  Image *texture_image;
393
413
  char temp_name[MaxTextExtent];
394
414
 
395
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
415
+ montage = get_writable_montage(self);
396
416
 
397
417
  // If we had a previously defined temp texture image,
398
418
  // remove it now in preparation for this new one.
@@ -404,7 +424,7 @@ Montage_texture_eq(VALUE self, VALUE texture)
404
424
  }
405
425
 
406
426
  texture = rm_cur_image(texture);
407
- texture_image = rm_check_destroyed(texture);
427
+ texture_image = rm_check_readable(texture);
408
428
 
409
429
  // Write a temp copy of the image & save its name.
410
430
  rm_write_temp_image(texture_image, temp_name, sizeof(temp_name));
@@ -431,7 +451,7 @@ Montage_tile_eq(VALUE self, VALUE tile_arg)
431
451
  Montage *montage;
432
452
  VALUE tile;
433
453
 
434
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
454
+ montage = get_writable_montage(self);
435
455
  tile = rb_String(tile_arg);
436
456
  magick_clone_string(&montage->info->tile, StringValueCStr(tile));
437
457
 
@@ -456,7 +476,7 @@ Montage_title_eq(VALUE self, VALUE title)
456
476
  Montage *montage;
457
477
  const char *title_cstr;
458
478
 
459
- TypedData_Get_Struct(self, Montage, &rm_montage_data_type, montage);
479
+ montage = get_writable_montage(self);
460
480
  title_cstr = StringValueCStr(title);
461
481
 
462
482
  if (rm_has_file_reference(title_cstr))
@@ -890,7 +890,7 @@ Pixel_init_copy(VALUE self, VALUE orig)
890
890
  * @param red [Numeric] The red value
891
891
  * @param green [Numeric] The green value
892
892
  * @param blue [Numeric] The blue value
893
- * @param opacity [Numeric] The opacity value
893
+ * @param opacity [Numeric] The opacity value. The alpha is set to QuantumRange minus this value.
894
894
  * @return [Magick::Pixel] self
895
895
  */
896
896
  VALUE
@@ -910,7 +910,7 @@ Pixel_initialize(int argc, VALUE *argv, VALUE self)
910
910
  #if defined(IMAGEMAGICK_7)
911
911
  if (argv[3] != Qnil)
912
912
  {
913
- pixel->alpha = APP2QUANTUM(argv[3]);
913
+ pixel->alpha = QuantumRange - APP2QUANTUM(argv[3]);
914
914
  }
915
915
  #else
916
916
  if (argv[3] != Qnil)
@@ -1184,11 +1184,14 @@ Pixel_to_color(int argc, VALUE *argv, VALUE self)
1184
1184
  switch (depth)
1185
1185
  {
1186
1186
  case 8:
1187
- #if MAGICKCORE_QUANTUM_DEPTH == 16 || MAGICKCORE_QUANTUM_DEPTH == 32
1187
+ #if MAGICKCORE_QUANTUM_DEPTH == 16 || MAGICKCORE_QUANTUM_DEPTH == 32 || MAGICKCORE_QUANTUM_DEPTH == 64
1188
1188
  case 16:
1189
1189
  #endif
1190
- #if MAGICKCORE_QUANTUM_DEPTH == 32
1190
+ #if MAGICKCORE_QUANTUM_DEPTH == 32 || MAGICKCORE_QUANTUM_DEPTH == 64
1191
1191
  case 32:
1192
+ #endif
1193
+ #if MAGICKCORE_QUANTUM_DEPTH == 64
1194
+ case 64:
1192
1195
  #endif
1193
1196
  break;
1194
1197
  default: