rmagick 7.0.4 → 7.1.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.
@@ -1318,7 +1318,7 @@ Image_background_color(VALUE self)
1318
1318
 
1319
1319
 
1320
1320
  /**
1321
- * Set the the background color to the specified color spec.
1321
+ * Set the background color to the specified color spec.
1322
1322
  *
1323
1323
  * @param color [Magick::Pixel, String] the color
1324
1324
  * @return [Magick::Pixel, String] the given color
@@ -1429,7 +1429,10 @@ Image_bias_eq(VALUE self, VALUE pct)
1429
1429
  char artifact[21];
1430
1430
 
1431
1431
  snprintf(artifact, sizeof(artifact), "%.20g", bias);
1432
- SetImageArtifact(image, "convolve:bias", artifact);
1432
+ if (!SetImageArtifact(image, "convolve:bias", artifact))
1433
+ {
1434
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1435
+ }
1433
1436
  }
1434
1437
  #else
1435
1438
  image->bias = bias;
@@ -1876,11 +1879,17 @@ special_composite(Image *image, Image *overlay, double image_pct, double overlay
1876
1879
 
1877
1880
  blend_geometry(geometry, sizeof(geometry), image_pct, overlay_pct);
1878
1881
  CloneString(&overlay->geometry, geometry);
1879
- SetImageArtifact(overlay, "compose:args", geometry);
1882
+ if (!SetImageArtifact(overlay, "compose:args", geometry))
1883
+ {
1884
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1885
+ }
1880
1886
 
1881
1887
  new_image = rm_clone_image(image);
1882
- SetImageArtifact(new_image, "compose:args", geometry); // 6.9 appears to get this info from canvas (dest) image
1883
-
1888
+ if (!SetImageArtifact(new_image, "compose:args", geometry)) // 6.9 appears to get this info from canvas (dest) image
1889
+ {
1890
+ DestroyImage(new_image);
1891
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
1892
+ }
1884
1893
 
1885
1894
  #if defined(IMAGEMAGICK_7)
1886
1895
  exception = AcquireExceptionInfo();
@@ -1907,12 +1916,12 @@ special_composite(Image *image, Image *overlay, double image_pct, double overlay
1907
1916
  * @overload blend(overlay, src_percent, dst_percent, gravity = Magick::NorthWestGravity, x_offset = 0, y_offset = 0)
1908
1917
  * @param overlay [Magick::Image, Magick::ImageList] The source image for the composite operation.
1909
1918
  * Either an imagelist or an image. If an imagelist, uses the current image.
1910
- * @param src_percent [Numeric, String] Either a non-negative number a string in the form "NN%".
1919
+ * @param src_percent [Numeric, String] Either a non-negative number or a string in the form "NN%".
1911
1920
  * If src_percentage is a number it is interpreted as a percentage.
1912
1921
  * Both 0.25 and "25%" mean 25%. This argument is required.
1913
- * @param dst_percent [Numeric, String] Either a non-negative number a string in the form "NN%".
1922
+ * @param dst_percent [Numeric, String] Either a non-negative number or a string in the form "NN%".
1914
1923
  * If src_percentage is a number it is interpreted as a percentage.
1915
- * Both 0.25 and "25%" mean 25%. This argument may omitted if no other arguments follow it.
1924
+ * Both 0.25 and "25%" mean 25%. This argument may be omitted if no other arguments follow it.
1916
1925
  * In this case the default is 100%-src_percentage.
1917
1926
  * @param gravity [Magick::GravityType] the gravity for offset. the offsets are measured from the NorthWest corner by default.
1918
1927
  * @param x_offset [Numeric] The offset that measured from the left-hand side of the target image.
@@ -2182,7 +2191,7 @@ Image_border_color(VALUE self)
2182
2191
 
2183
2192
 
2184
2193
  /**
2185
- * Set the the border color.
2194
+ * Set the border color.
2186
2195
  *
2187
2196
  * @param [Magick::Pixel, String] color the color
2188
2197
  * @return [Magick::Pixel, String] the given color
@@ -3388,7 +3397,7 @@ Image_columns(VALUE self)
3388
3397
  * - options.highlight_color = color
3389
3398
  * - Emphasize pixel differences with this color. The default is partially transparent red.
3390
3399
  * - options.lowlight_color = color
3391
- * - Demphasize pixel differences with this color. The default is partially transparent white.
3400
+ * - De-emphasize pixel differences with this color. The default is partially transparent white.
3392
3401
  * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
3393
3402
  * imagelist, uses the current image.
3394
3403
  * @param metric [Magick::MetricType] The desired distortion metric.
@@ -3408,7 +3417,7 @@ Image_columns(VALUE self)
3408
3417
  * - options.highlight_color = color
3409
3418
  * - Emphasize pixel differences with this color. The default is partially transparent red.
3410
3419
  * - options.lowlight_color = color
3411
- * - Demphasize pixel differences with this color. The default is partially transparent white.
3420
+ * - De-emphasize pixel differences with this color. The default is partially transparent white.
3412
3421
  * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
3413
3422
  * imagelist, uses the current image.
3414
3423
  * @param metric [Magick::MetricType] The desired distortion metric.
@@ -3416,7 +3425,7 @@ Image_columns(VALUE self)
3416
3425
  * @yield [opt_args]
3417
3426
  * @yieldparam opt_args [Magick::OptionalMethodArguments]
3418
3427
  *
3419
- * @return [Array] The first element is a difference image, the second is a the value of the
3428
+ * @return [Array] The first element is a difference image, the second is the value of the
3420
3429
  * computed distortion represented as a Float.
3421
3430
  */
3422
3431
  VALUE
@@ -4072,7 +4081,10 @@ Image_composite_mathematics(int argc, VALUE *argv, VALUE self)
4072
4081
  composite_image = rm_check_destroyed(rm_cur_image(argv[0]));
4073
4082
 
4074
4083
  snprintf(compose_args, sizeof(compose_args), "%-.16g,%-.16g,%-.16g,%-.16g", NUM2DBL(argv[1]), NUM2DBL(argv[2]), NUM2DBL(argv[3]), NUM2DBL(argv[4]));
4075
- SetImageArtifact(composite_image, "compose:args", compose_args);
4084
+ if (!SetImageArtifact(composite_image, "compose:args", compose_args))
4085
+ {
4086
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
4087
+ }
4076
4088
 
4077
4089
  // Call composite(False, gravity, x_off, y_off, MathematicsCompositeOp, DefaultChannels)
4078
4090
  args[0] = argv[0];
@@ -4145,13 +4157,16 @@ composite_tiled(int bang, int argc, VALUE *argv, VALUE self)
4145
4157
 
4146
4158
  comp_image = rm_check_destroyed(rm_cur_image(argv[0]));
4147
4159
 
4160
+ if (!SetImageArtifact(comp_image, "modify-outside-overlay", "false"))
4161
+ {
4162
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
4163
+ }
4164
+
4148
4165
  if (!bang)
4149
4166
  {
4150
4167
  image = rm_clone_image(image);
4151
4168
  }
4152
4169
 
4153
- SetImageArtifact(comp_image, "modify-outside-overlay", "false");
4154
-
4155
4170
  status = MagickTrue;
4156
4171
  columns = comp_image->columns;
4157
4172
 
@@ -4656,7 +4671,7 @@ Image_contrast_stretch_channel(int argc, VALUE *argv, VALUE self)
4656
4671
  }
4657
4672
 
4658
4673
  /**
4659
- * Apply a user supplied kernel to the image according to the given mophology method.
4674
+ * Apply a user supplied kernel to the image according to the given morphology method.
4660
4675
  *
4661
4676
  * @param method_v [Magick::MorphologyMethod] the morphology method
4662
4677
  * @param iterations [Numeric] apply the operation this many times (or no change).
@@ -4681,7 +4696,7 @@ Image_morphology(VALUE self, VALUE method_v, VALUE iterations, VALUE kernel_v)
4681
4696
  }
4682
4697
 
4683
4698
  /**
4684
- * Apply a user supplied kernel to the image channel according to the given mophology method.
4699
+ * Apply a user supplied kernel to the image channel according to the given morphology method.
4685
4700
  *
4686
4701
  * @param channel_v [Magick::ChannelType] a channel type
4687
4702
  * @param method_v [Magick::MorphologyMethod] the morphology method
@@ -5241,6 +5256,28 @@ Image_decipher(VALUE self, VALUE passphrase)
5241
5256
  }
5242
5257
 
5243
5258
 
5259
+ /**
5260
+ * Return the value of an artifact set by {Magick::Image#define} or by
5261
+ * {Magick::Image::Info#define}.
5262
+ *
5263
+ * @param artifact [String] the artifact to look up
5264
+ * @return [String, nil] the value, or nil if the artifact is not set
5265
+ * @see Magick::Image#define
5266
+ */
5267
+ VALUE
5268
+ Image_artifact(VALUE self, VALUE artifact)
5269
+ {
5270
+ Image *image;
5271
+ const char *value;
5272
+
5273
+ image = rm_check_destroyed(self);
5274
+ artifact = rb_String(artifact);
5275
+ value = GetImageArtifact(image, StringValueCStr(artifact));
5276
+
5277
+ return value ? rb_str_new2(value) : Qnil;
5278
+ }
5279
+
5280
+
5244
5281
  /**
5245
5282
  * Associates makes a copy of the given string arguments and
5246
5283
  * inserts it into the artifact tree.
@@ -5427,7 +5464,10 @@ Image_deskew(int argc, VALUE *argv, VALUE self)
5427
5464
  width = NUM2ULONG(argv[1]);
5428
5465
  memset(auto_crop_width, 0, sizeof(auto_crop_width));
5429
5466
  snprintf(auto_crop_width, sizeof(auto_crop_width), "%lu", width);
5430
- SetImageArtifact(image, "deskew:auto-crop", auto_crop_width);
5467
+ if (!SetImageArtifact(image, "deskew:auto-crop", auto_crop_width))
5468
+ {
5469
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
5470
+ }
5431
5471
  case 1:
5432
5472
  threshold = rm_percentage(argv[0], 1.0) * QuantumRange;
5433
5473
  case 0:
@@ -5630,6 +5670,41 @@ Image_displace(int argc, VALUE *argv, VALUE self)
5630
5670
  }
5631
5671
 
5632
5672
 
5673
+ /**
5674
+ * Compute columns * rows * map_length for a pixel buffer, raising RangeError on
5675
+ * overflow.
5676
+ *
5677
+ * The product is used to size the buffer that ImageMagick fills based on the
5678
+ * (caller-supplied) columns and rows. If the multiplication wrapped around, the
5679
+ * buffer would be allocated too small and ImageMagick would write out of bounds.
5680
+ *
5681
+ * No Ruby usage (internal function)
5682
+ *
5683
+ * @param columns the number of columns
5684
+ * @param rows the number of rows
5685
+ * @param map_length the number of channels per pixel (length of the map string)
5686
+ * @return columns * rows * map_length
5687
+ * @throw RangeError if the multiplication overflows
5688
+ */
5689
+ static size_t
5690
+ pixel_buffer_count(size_t columns, size_t rows, size_t map_length)
5691
+ {
5692
+ size_t pixels;
5693
+
5694
+ if (columns != 0 && rows > SIZE_MAX / columns)
5695
+ {
5696
+ rb_raise(rb_eRangeError, "pixel buffer dimensions too large (%" RMIuSIZE "x%" RMIuSIZE ")", columns, rows);
5697
+ }
5698
+ pixels = columns * rows;
5699
+ if (map_length != 0 && pixels > SIZE_MAX / map_length)
5700
+ {
5701
+ rb_raise(rb_eRangeError, "pixel buffer dimensions too large (%" RMIuSIZE "x%" RMIuSIZE " map=%" RMIuSIZE ")",
5702
+ columns, rows, map_length);
5703
+ }
5704
+ return pixels * map_length;
5705
+ }
5706
+
5707
+
5633
5708
  /**
5634
5709
  * Extract pixel data from the image and returns it as an array of pixels. The "x", "y", "width" and
5635
5710
  * "height" parameters specify the rectangle to be extracted. The "map" parameter reflects the
@@ -5685,7 +5760,7 @@ Image_dispatch(int argc, VALUE *argv, VALUE self)
5685
5760
  }
5686
5761
 
5687
5762
  // Compute the size of the pixel array and allocate the memory.
5688
- npixels = columns * rows * mapL;
5763
+ npixels = pixel_buffer_count(columns, rows, mapL);
5689
5764
  pixels.v = stg_type == QuantumPixel ? (void *) ALLOC_N(Quantum, npixels)
5690
5765
  : (void *) ALLOC_N(double, npixels);
5691
5766
 
@@ -5814,12 +5889,12 @@ Image_dispose_eq(VALUE self, VALUE dispose)
5814
5889
  * @overload dissolve(overlay, src_percent, dst_percent = -1.0, gravity = Magick::NorthWestGravity, x_offset = 0, y_offset = 0)
5815
5890
  * @param overlay [Magick::Image, Magick::ImageList] The source image for the composite operation.
5816
5891
  * Either an imagelist or an image. If an imagelist, uses the current image.
5817
- * @param src_percent [Numeric, String] Either a non-negative number a string in the form "NN%".
5892
+ * @param src_percent [Numeric, String] Either a non-negative number or a string in the form "NN%".
5818
5893
  * If src_percentage is a number it is interpreted as a percentage.
5819
5894
  * Both 0.25 and "25%" mean 25%. This argument is required.
5820
- * @param dst_percent [Numeric, String] Either a non-negative number a string in the form "NN%".
5895
+ * @param dst_percent [Numeric, String] Either a non-negative number or a string in the form "NN%".
5821
5896
  * If src_percentage is a number it is interpreted as a percentage.
5822
- * Both 0.25 and "25%" mean 25%. This argument may omitted if no other arguments follow it.
5897
+ * Both 0.25 and "25%" mean 25%. This argument may be omitted if no other arguments follow it.
5823
5898
  * In this case the default is 100%-src_percentage.
5824
5899
  * @param gravity [Magick::GravityType] the gravity for offset. the offsets are measured from the
5825
5900
  * NorthWest corner by default.
@@ -5899,7 +5974,7 @@ Image_dissolve(int argc, VALUE *argv, VALUE self)
5899
5974
  * the image (with appropriate viewport changes, or post-distort cropping and resizing).
5900
5975
  * - options.verbose(true)
5901
5976
  * - Attempt to output the internal coefficients, and the -fx equivalent to the distortion, for
5902
- expert study, and debugging purposes. This many not be available for all distorts.
5977
+ expert study, and debugging purposes. This may not be available for all distorts.
5903
5978
  * @param type [Magick::DistortMethod] a DistortMethod value
5904
5979
  * @param points [Array<Numeric>] an Array of Numeric values. The size of the array depends on the distortion type.
5905
5980
  * @param bestfit [Boolean] If bestfit is enabled, and the distortion allows it, the destination
@@ -6105,7 +6180,7 @@ Image__dump(VALUE self, VALUE depth ATTRIBUTE_UNUSED)
6105
6180
 
6106
6181
 
6107
6182
  /**
6108
- * Duplicates a image.
6183
+ * Duplicates an image.
6109
6184
  *
6110
6185
  * @return [Magick::Image] a new image
6111
6186
  */
@@ -6636,7 +6711,7 @@ Image_export_pixels(int argc, VALUE *argv, VALUE self)
6636
6711
  }
6637
6712
 
6638
6713
 
6639
- npixels = (long)(cols * rows * strlen(map));
6714
+ npixels = (long)pixel_buffer_count(cols, rows, strlen(map));
6640
6715
  pixels = ALLOC_N(Quantum, npixels);
6641
6716
  if (!pixels) // app recovered from exception
6642
6717
  {
@@ -6804,7 +6879,7 @@ Image_export_pixels_to_str(int argc, VALUE *argv, VALUE self)
6804
6879
  }
6805
6880
 
6806
6881
 
6807
- npixels = cols * rows * strlen(map);
6882
+ npixels = pixel_buffer_count(cols, rows, strlen(map));
6808
6883
  switch (type)
6809
6884
  {
6810
6885
  case CharPixel:
@@ -6833,6 +6908,10 @@ Image_export_pixels_to_str(int argc, VALUE *argv, VALUE self)
6833
6908
 
6834
6909
  // Allocate a string long enough to hold the exported pixel data.
6835
6910
  // Get a pointer to the buffer.
6911
+ if (npixels != 0 && sz > (size_t)LONG_MAX / npixels)
6912
+ {
6913
+ rb_raise(rb_eRangeError, "pixel buffer dimensions too large");
6914
+ }
6836
6915
  string = rb_str_new2("");
6837
6916
  rb_str_resize(string, (long)(sz * npixels));
6838
6917
 
@@ -7086,7 +7165,7 @@ Image_flip_bang(VALUE self)
7086
7165
 
7087
7166
 
7088
7167
  /**
7089
- * Create a horizonal mirror image by reflecting the pixels around the central y-axis.
7168
+ * Create a horizontal mirror image by reflecting the pixels around the central y-axis.
7090
7169
  *
7091
7170
  * @return [Magick::Image] a new image
7092
7171
  * @see Image#flop!
@@ -7102,7 +7181,7 @@ Image_flop(VALUE self)
7102
7181
 
7103
7182
 
7104
7183
  /**
7105
- * Create a horizonal mirror image by reflecting the pixels around the central y-axis.
7184
+ * Create a horizontal mirror image by reflecting the pixels around the central y-axis.
7106
7185
  * In-place form of {Image#flop}.
7107
7186
  *
7108
7187
  * @return [Magick::Image] self
@@ -8012,7 +8091,7 @@ Image_implode(int argc, VALUE *argv, VALUE self)
8012
8091
  * @param y [Numeric] The y-offset of the rectangle to be replaced.
8013
8092
  * @param columns [Numeric] The number of columns in the rectangle.
8014
8093
  * @param rows [Numeric] The number of rows in the rectangle.
8015
- * @param map [String] his string reflects the expected ordering of the pixel array.
8094
+ * @param map [String] This string reflects the expected ordering of the pixel array.
8016
8095
  * @param pixels [Array] An array of pixels.
8017
8096
  * The number of pixels in the array must be the same as the number
8018
8097
  * of pixels in the rectangle, that is, rows*columns.
@@ -8026,8 +8105,8 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
8026
8105
  {
8027
8106
  Image *image;
8028
8107
  long x_off, y_off;
8029
- unsigned long cols, rows;
8030
- unsigned long n, npixels;
8108
+ long cols, rows;
8109
+ size_t n, npixels;
8031
8110
  size_t buffer_l;
8032
8111
  char *map;
8033
8112
  VALUE pixel_arg, pixel_ary;
@@ -8050,8 +8129,8 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
8050
8129
  case 6:
8051
8130
  x_off = NUM2LONG(argv[0]);
8052
8131
  y_off = NUM2LONG(argv[1]);
8053
- cols = NUM2ULONG(argv[2]);
8054
- rows = NUM2ULONG(argv[3]);
8132
+ cols = NUM2LONG(argv[2]);
8133
+ rows = NUM2LONG(argv[3]);
8055
8134
  map = StringValueCStr(argv[4]);
8056
8135
  pixel_arg = argv[5];
8057
8136
  break;
@@ -8065,8 +8144,12 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
8065
8144
  rb_raise(rb_eArgError, "invalid import geometry");
8066
8145
  }
8067
8146
 
8068
- map_l = rm_strnlen_s(map, MaxTextExtent);
8069
- npixels = cols * rows * map_l;
8147
+ map_l = strlen(map);
8148
+ if (map_l == 0)
8149
+ {
8150
+ rb_raise(rb_eArgError, "map must not be empty");
8151
+ }
8152
+ npixels = pixel_buffer_count((size_t)cols, (size_t)rows, map_l);
8070
8153
 
8071
8154
  // Assume that any object that responds to :to_str is a string buffer containing
8072
8155
  // binary pixel data.
@@ -8106,9 +8189,9 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
8106
8189
  {
8107
8190
  rb_raise(rb_eArgError, "pixel buffer must contain an exact multiple of the map length");
8108
8191
  }
8109
- if ((unsigned long)(buffer_l / type_sz) < npixels)
8192
+ if (buffer_l / type_sz < npixels)
8110
8193
  {
8111
- rb_raise(rb_eArgError, "pixel buffer too small (need %lu channel values, got %" RMIuSIZE ")",
8194
+ rb_raise(rb_eArgError, "pixel buffer too small (need %" RMIuSIZE " channel values, got %" RMIuSIZE ")",
8112
8195
  npixels, buffer_l/type_sz);
8113
8196
  }
8114
8197
  }
@@ -8124,9 +8207,9 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
8124
8207
  {
8125
8208
  rb_raise(rb_eArgError, "pixel array must contain an exact multiple of the map length");
8126
8209
  }
8127
- if ((unsigned long)RARRAY_LEN(pixel_ary) < npixels)
8210
+ if ((size_t)RARRAY_LEN(pixel_ary) < npixels)
8128
8211
  {
8129
- rb_raise(rb_eArgError, "pixel array too small (need %lu elements, got %ld)",
8212
+ rb_raise(rb_eArgError, "pixel array too small (need %" RMIuSIZE " elements, got %ld)",
8130
8213
  npixels, RARRAY_LEN(pixel_ary));
8131
8214
  }
8132
8215
 
@@ -8173,9 +8256,9 @@ Image_import_pixels(int argc, VALUE *argv, VALUE self)
8173
8256
 
8174
8257
  #if defined(IMAGEMAGICK_7)
8175
8258
  exception = AcquireExceptionInfo();
8176
- GVL_STRUCT_TYPE(ImportImagePixels) args = { image, x_off, y_off, cols, rows, map, stg_type, buffer, exception };
8259
+ GVL_STRUCT_TYPE(ImportImagePixels) args = { image, x_off, y_off, (size_t)cols, (size_t)rows, map, stg_type, buffer, exception };
8177
8260
  #else
8178
- GVL_STRUCT_TYPE(ImportImagePixels) args = { image, x_off, y_off, cols, rows, map, stg_type, buffer };
8261
+ GVL_STRUCT_TYPE(ImportImagePixels) args = { image, x_off, y_off, (size_t)cols, (size_t)rows, map, stg_type, buffer };
8179
8262
  #endif
8180
8263
  void *ret = CALL_FUNC_WITHOUT_GVL(GVL_FUNC(ImportImagePixels), &args);
8181
8264
  okay = static_cast<MagickBooleanType>(reinterpret_cast<intptr_t &>(ret));
@@ -8875,7 +8958,7 @@ Image__load(VALUE klass ATTRIBUTE_UNUSED, VALUE str)
8875
8958
 
8876
8959
  blob = rm_str2cstr(str, &length);
8877
8960
 
8878
- // Must be as least as big as the 1st 4 fields in DumpedImage
8961
+ // Must be at least as big as the 1st 4 fields in DumpedImage
8879
8962
  if (length <= (long)(sizeof(DumpedImage)-MaxTextExtent))
8880
8963
  {
8881
8964
  rb_raise(rb_eTypeError, "image is invalid or corrupted (too short)");
@@ -9056,6 +9139,8 @@ Image_marshal_load(VALUE self, VALUE ary)
9056
9139
 
9057
9140
  TypedData_Get_Struct(self, Image, &rm_image_data_type, image);
9058
9141
 
9142
+ Check_Type(ary, T_ARRAY);
9143
+
9059
9144
  filename = rb_ary_shift(ary);
9060
9145
  blob = rb_ary_shift(ary);
9061
9146
 
@@ -11539,7 +11624,7 @@ rd_image(VALUE klass ATTRIBUTE_UNUSED, VALUE file, gvl_function_t fp)
11539
11624
  // Convert arg to string. If an exception occurs raise an error condition.
11540
11625
  file = rb_rescue(RESCUE_FUNC(rb_String), file, RESCUE_EXCEPTION_HANDLER_FUNC(file_arg_rescue), file);
11541
11626
 
11542
- filename = rm_str2cstr(file, &filename_l);
11627
+ filename = rm_path2cstr(file, &filename_l);
11543
11628
  filename_l = min(filename_l, MaxTextExtent-1);
11544
11629
  if (filename_l == 0)
11545
11630
  {
@@ -11626,7 +11711,7 @@ Image_recolor(VALUE self, VALUE color_matrix)
11626
11711
  }
11627
11712
  }
11628
11713
 
11629
- order = (unsigned long)sqrt((double)(len + 1.0));
11714
+ order = (unsigned long)sqrt((double)len);
11630
11715
 
11631
11716
  exception = AcquireExceptionInfo();
11632
11717
  #if defined(IMAGEMAGICK_7)
@@ -12750,7 +12835,7 @@ Image_sepiatone(int argc, VALUE *argv, VALUE self)
12750
12835
  * @param colorspace [Magick::ColorspaceType] A ColorspaceType value. Empirical evidence suggests
12751
12836
  * that distances in YUV or YIQ correspond to perceptual color differences more closely than do
12752
12837
  * distances in RGB space. The image is then returned to RGB colorspace after color reduction.
12753
- * @param cluster_threshold [Numeric] The number of pixels in each cluster must exceed the the
12838
+ * @param cluster_threshold [Numeric] The number of pixels in each cluster must exceed the
12754
12839
  * cluster threshold to be considered valid.
12755
12840
  * @param smoothing_threshold [Numeric] The smoothing threshold eliminates noise in the second
12756
12841
  * derivative of the histogram. As the value is increased, you can expect a smoother second
@@ -13092,7 +13177,7 @@ Image_sharpen_channel(int argc, VALUE *argv, VALUE self)
13092
13177
  * center.
13093
13178
  *
13094
13179
  * @param width [Numeric] the width to leave
13095
- * @param height [Numeric] the hight to leave
13180
+ * @param height [Numeric] the height to leave
13096
13181
  * @return [Magick::Image] a new image
13097
13182
  * @see Image#shave!
13098
13183
  */
@@ -13110,7 +13195,7 @@ Image_shave(VALUE self, VALUE width, VALUE height)
13110
13195
  * In-place form of {Image#shave}.
13111
13196
  *
13112
13197
  * @param width [Numeric] the width to leave
13113
- * @param height [Numeric] the hight to leave
13198
+ * @param height [Numeric] the height to leave
13114
13199
  * @return [Magick::Image] a new image
13115
13200
  * @see Image#shave
13116
13201
  */
@@ -14488,7 +14573,7 @@ Image_tint(int argc, VALUE *argv, VALUE self)
14488
14573
  * Return a "blob" (a String) from the image.
14489
14574
  *
14490
14575
  * - The magick member of the Image structure determines the format of the
14491
- * returned blob (GIG, JPEG, PNG, etc.)
14576
+ * returned blob (GIF, JPEG, PNG, etc.)
14492
14577
  *
14493
14578
  * @yield [info]
14494
14579
  * @yieldparam info [Magick::Image::Info]
@@ -14808,7 +14893,7 @@ Image_transparent_color(VALUE self)
14808
14893
 
14809
14894
 
14810
14895
  /**
14811
- * Set the the transparent color to the specified color spec.
14896
+ * Set the transparent color to the specified color spec.
14812
14897
  *
14813
14898
  * @param color [Magick::Pixel, String] the transparent color
14814
14899
  * @return [Magick::Pixel, String] the given color
@@ -15190,13 +15275,13 @@ Image_units_eq(VALUE self, VALUE restype)
15190
15275
  /**
15191
15276
  * Sharpen an image. "amount" is the percentage of the difference between the original and the blur
15192
15277
  * image that is added back into the original. "threshold" is the threshold in pixels needed to
15193
- * apply the diffence amount.
15278
+ * apply the difference amount.
15194
15279
  *
15195
15280
  * No Ruby usage (internal function)
15196
15281
  *
15197
15282
  * @param argc number of input arguments
15198
15283
  * @param argv array of input arguments
15199
- * @param radious the radious
15284
+ * @param radius the radius
15200
15285
  * @param sigma the sigma
15201
15286
  * @param amount the amount
15202
15287
  * @param threshold the threshold
@@ -15236,7 +15321,7 @@ unsharp_mask_args(int argc, VALUE *argv, double *radius, double *sigma,
15236
15321
  break;
15237
15322
 
15238
15323
  // This case can't occur if we're called from Image_unsharp_mask_channel
15239
- // because it has already raised an exception for the the argc > 4 case.
15324
+ // because it has already raised an exception for the argc > 4 case.
15240
15325
  default:
15241
15326
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 4)", argc);
15242
15327
  }
@@ -15246,7 +15331,7 @@ unsharp_mask_args(int argc, VALUE *argv, double *radius, double *sigma,
15246
15331
  /**
15247
15332
  * Sharpen an image. "amount" is the percentage of the difference between the original and the blur
15248
15333
  * image that is added back into the original. "threshold" is the threshold in pixels needed to
15249
- * apply the diffence amount.
15334
+ * apply the difference amount.
15250
15335
  *
15251
15336
  * @overload unsharp_mask(radius = 0.0, sigma = 1.0, amount = 1.0, threshold = 0.05)
15252
15337
  * @param radius [Numeric] The radius of the Gaussian operator.
@@ -15281,7 +15366,7 @@ Image_unsharp_mask(int argc, VALUE *argv, VALUE self)
15281
15366
  /**
15282
15367
  * Sharpen an image. "amount" is the percentage of the difference between the original and the blur
15283
15368
  * image that is added back into the original. "threshold" is the threshold in pixels needed to
15284
- * apply the diffence amount.
15369
+ * apply the difference amount.
15285
15370
  *
15286
15371
  * Only the specified channels are sharpened.
15287
15372
  *
@@ -15459,7 +15544,7 @@ Image_virtual_pixel_method_eq(VALUE self, VALUE method)
15459
15544
  * 25%. The default is 100%.
15460
15545
  * @param x_off [Numeric] The offset of the watermark, measured from the left-hand side of the
15461
15546
  * target image.
15462
- * @param y_off [Numeri] The offset of the watermark, measured from the top of the target image.
15547
+ * @param y_off [Numeric] The offset of the watermark, measured from the top of the target image.
15463
15548
  *
15464
15549
  * @overload watermark(mark, brightness, saturation, gravity, x_off = 0, y_off = 0)
15465
15550
  * @param mark [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an
@@ -15476,7 +15561,7 @@ Image_virtual_pixel_method_eq(VALUE self, VALUE method)
15476
15561
  * NorthWest corner by default.
15477
15562
  * @param x_off [Numeric] The offset of the watermark, measured from the left-hand side of the
15478
15563
  * target image.
15479
- * @param y_off [Numeri] The offset of the watermark, measured from the top of the target image.
15564
+ * @param y_off [Numeric] The offset of the watermark, measured from the top of the target image.
15480
15565
  *
15481
15566
  * @return [Magick::Image] a new image
15482
15567
  */
@@ -15524,7 +15609,10 @@ Image_watermark(int argc, VALUE *argv, VALUE self)
15524
15609
 
15525
15610
  blend_geometry(geometry, sizeof(geometry), src_percent, dst_percent);
15526
15611
  CloneString(&overlay->geometry, geometry);
15527
- SetImageArtifact(overlay, "compose:args", geometry);
15612
+ if (!SetImageArtifact(overlay, "compose:args", geometry))
15613
+ {
15614
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
15615
+ }
15528
15616
 
15529
15617
  new_image = rm_clone_image(image);
15530
15618
  #if defined(IMAGEMAGICK_7)
@@ -15825,7 +15913,7 @@ void add_format_prefix(Info *info, VALUE file)
15825
15913
  }
15826
15914
  file = rb_rescue(RESCUE_FUNC(rb_String), file, RESCUE_EXCEPTION_HANDLER_FUNC(file_arg_rescue), file);
15827
15915
 
15828
- filename = rm_str2cstr(file, &filename_l);
15916
+ filename = rm_path2cstr(file, &filename_l);
15829
15917
 
15830
15918
  if (*info->magick == '\0')
15831
15919
  {
@@ -199,7 +199,15 @@ static VALUE set_dbl_option(VALUE self, const char *option, VALUE value)
199
199
  {
200
200
  len = snprintf(buff, sizeof(buff), "%-10.2f", d);
201
201
  }
202
- memset(buff+len, '\0', sizeof(buff)-len);
202
+ if (len < 0)
203
+ {
204
+ len = 0;
205
+ }
206
+ else if ((size_t)len > sizeof(buff) - 1)
207
+ {
208
+ len = (int)(sizeof(buff) - 1);
209
+ }
210
+ memset(buff+len, '\0', sizeof(buff)-(size_t)len);
203
211
  SetImageOption(info, option, buff);
204
212
  }
205
213
 
@@ -1936,7 +1944,7 @@ Info_server_name_eq(VALUE self, VALUE server_arg)
1936
1944
  }
1937
1945
 
1938
1946
  /**
1939
- * Get ths size
1947
+ * Get the size
1940
1948
  *
1941
1949
  * @return [String] the size as a Geometry object
1942
1950
  * @see https://www.imagemagick.org/Magick++/Geometry.html
@@ -2374,7 +2382,7 @@ Info_alloc(VALUE klass)
2374
2382
 
2375
2383
 
2376
2384
  /**
2377
- * Provide a Info.new method for internal use.
2385
+ * Provide an Info.new method for internal use.
2378
2386
  *
2379
2387
  * No Ruby usage (internal function)
2380
2388
  *
@@ -194,7 +194,7 @@ KernelInfo_scale_geometry(VALUE self, VALUE geometry)
194
194
  }
195
195
 
196
196
  /**
197
- * Creates a new clone of the object so that its can be modified without effecting the original.
197
+ * Creates a new clone of the object so that it can be modified without affecting the original.
198
198
  *
199
199
  * @return [Magick::KernelInfo] new KernelInfo object
200
200
  */
@@ -120,7 +120,7 @@ rm_aligned_malloc_size(void *ptr)
120
120
  #elif defined(HAVE_MALLOC_SIZE)
121
121
  return malloc_size(ptr);
122
122
  #elif defined(HAVE__ALIGNED_MSIZE)
123
- // Refered to https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/memory-private.h
123
+ // Referred to https://github.com/ImageMagick/ImageMagick/blob/master/MagickCore/memory-private.h
124
124
  #define MAGICKCORE_SIZEOF_VOID_P 8
125
125
  #define CACHE_LINE_SIZE (8 * MAGICKCORE_SIZEOF_VOID_P)
126
126
  size_t _aligned_msize(void *memblock, size_t alignment, size_t offset);
@@ -407,6 +407,7 @@ Init_RMagick2(void)
407
407
  rb_define_method(Class_Image, "alpha?", RUBY_METHOD_FUNC(Image_alpha_q), 0);
408
408
  rb_define_method(Class_Image, "[]", RUBY_METHOD_FUNC(Image_aref), 1);
409
409
  rb_define_method(Class_Image, "[]=", RUBY_METHOD_FUNC(Image_aset), 2);
410
+ rb_define_method(Class_Image, "artifact", RUBY_METHOD_FUNC(Image_artifact), 1);
410
411
  rb_define_method(Class_Image, "auto_gamma_channel", RUBY_METHOD_FUNC(Image_auto_gamma_channel), -1);
411
412
  rb_define_method(Class_Image, "auto_level_channel", RUBY_METHOD_FUNC(Image_auto_level_channel), -1);
412
413
  rb_define_method(Class_Image, "auto_orient", RUBY_METHOD_FUNC(Image_auto_orient), 0);
@@ -1812,7 +1813,7 @@ test_Magick_version(void)
1812
1813
 
1813
1814
  /* ImageMagick versions are defined as major, minor and patch, each of which are defined as a value in 1 byte. */
1814
1815
  /* ImageMagick 6.9.12 has `#define MagickLibVersion 0x69C` */
1815
- /* It use only major and minor versions. */
1816
+ /* It uses only major and minor versions. */
1816
1817
  size_t mask_major_minor_version = 0xFFFFFFF0;
1817
1818
 
1818
1819
  version_str = GetMagickVersion(&version_number);
@@ -23,7 +23,7 @@ const rb_data_type_t rm_montage_data_type = {
23
23
 
24
24
 
25
25
  /**
26
- * Destory the MontageInfo struct and free the Montage struct.
26
+ * Destroy the MontageInfo struct and free the Montage struct.
27
27
  *
28
28
  * No Ruby usage (internal function)
29
29
  *
@@ -463,7 +463,7 @@ Color_to_Pixel(Pixel *pp, VALUE color)
463
463
  * No Ruby usage (internal function)
464
464
  *
465
465
  * @param color the PixelColor to modify
466
- * @param name_arg the coor name
466
+ * @param name_arg the color name
467
467
  * @throw ArgumentError
468
468
  */
469
469
  static void
@@ -666,14 +666,14 @@ Pixel_fcmp(int argc, VALUE *argv, VALUE self)
666
666
 
667
667
 
668
668
  /**
669
- * Construct an {Magick::Pixel} corresponding to the given color name.
669
+ * Construct a {Magick::Pixel} corresponding to the given color name.
670
670
  *
671
671
  * - The "inverse" is {Image#to_color}, b/c the conversion of a pixel to a
672
672
  * color name requires both a color depth and if the opacity value has
673
673
  * meaning.
674
674
  *
675
675
  * @param name [String] the color name
676
- * @return [Magick::Pixel] a new Magic::Pixel object
676
+ * @return [Magick::Pixel] a new Magick::Pixel object
677
677
  * @see Magick::Image#to_color
678
678
  * @see Magick::Pixel#to_color
679
679
  */
@@ -1009,7 +1009,7 @@ Pixel_intensity(VALUE self)
1009
1009
  /**
1010
1010
  * Support Marshal.dump.
1011
1011
  *
1012
- * @return [Hash] a representing the dumped pixel
1012
+ * @return [Hash] a Hash representing the dumped pixel
1013
1013
  */
1014
1014
  VALUE
1015
1015
  Pixel_marshal_dump(VALUE self)
@@ -1046,6 +1046,9 @@ Pixel_marshal_load(VALUE self, VALUE dpixel)
1046
1046
  Pixel *pixel;
1047
1047
 
1048
1048
  TypedData_Get_Struct(self, Pixel, &rm_pixel_data_type, pixel);
1049
+
1050
+ Check_Type(dpixel, T_HASH);
1051
+
1049
1052
  pixel->red = NUM2QUANTUM(rb_hash_aref(dpixel, CSTR2SYM("red")));
1050
1053
  pixel->green = NUM2QUANTUM(rb_hash_aref(dpixel, CSTR2SYM("green")));
1051
1054
  pixel->blue = NUM2QUANTUM(rb_hash_aref(dpixel, CSTR2SYM("blue")));