ext/RMagick/rmimage.c in rmagick-4.1.0.rc2 vs ext/RMagick/rmimage.c in rmagick-4.1.0

- old
+ new

@@ -9,14 +9,15 @@ * @version $Id: rmimage.c,v 1.361 2010/05/03 03:34:48 baror Exp $ * @author Tim Hunter ******************************************************************************/ #include "rmagick.h" +#include <signal.h> #define BEGIN_CHANNEL_MASK(image, channels) \ { \ - ChannelType channel_mask=SetPixelChannelMask(image, (ChannelType)channels); + ChannelType channel_mask = SetPixelChannelMask(image, (ChannelType)channels); #define END_CHANNEL_MASK(image) \ SetPixelChannelMask(image, channel_mask); \ } @@ -61,10 +62,12 @@ static VALUE scale(int, int, VALUE *, VALUE, scaler_t); static VALUE threshold_image(int, VALUE *, VALUE, thresholder_t); static VALUE xform_image(int, VALUE, VALUE, VALUE, VALUE, VALUE, xformer_t); static VALUE array_from_images(Image *); static void call_trace_proc(Image *, const char *); +static VALUE file_arg_rescue(VALUE, VALUE ATTRIBUTE_UNUSED) ATTRIBUTE_NORETURN; +static VALUE rm_trace_creation_handle_exception(VALUE, VALUE) ATTRIBUTE_NORETURN; static const char *BlackPointCompensationKey = "PROFILE:black-point-compensation"; /** @@ -79,11 +82,11 @@ { if (TYPE(hash) != T_HASH) { rb_raise(rb_eArgError, "missing keyword: alpha"); } - + if (FIX2ULONG(rb_hash_size(hash)) != 1) { rb_raise(rb_eArgError, "wrong number of arguments"); } @@ -107,12 +110,12 @@ * @param self this object * @param fp pointer to the function to call * @return a new image */ static VALUE -adaptive_method(int argc, VALUE *argv, VALUE self - , Image *fp(const Image *, const double, const double, ExceptionInfo *)) +adaptive_method(int argc, VALUE *argv, VALUE self, + Image *fp(const Image *, const double, const double, ExceptionInfo *)) { Image *image, *new_image; double radius = 0.0; double sigma = 1.0; ExceptionInfo *exception; @@ -134,15 +137,12 @@ exception = AcquireExceptionInfo(); new_image = (fp)(image, radius, sigma, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } @@ -192,63 +192,49 @@ #else new_image = (fp)(image, channels, radius, sigma, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call AdaptiveBlurImage. + * Adaptively blurs the image by blurring more intensely near image edges and less intensely far + * from edges. The {Magick::Image#adaptive_blur} method blurs the image with a Gaussian operator of + * the given radius and standard deviation (sigma). For reasonable results, radius should be larger + * than sigma. Use a radius of 0 and adaptive_blur selects a suitable radius for you. * - * Ruby usage: - * - @verbatim Image#adaptive_blur @endverbatim - * - @verbatim Image#adaptive_blur(radius) @endverbatim - * - @verbatim Image#adaptive_blur(radius, sigma) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload adaptive_blur(radius = 0.0, sigma = 1.0) + * @param radius [Float] The radius of the Gaussian in pixels, not counting the center pixel. + * @param sigma [Float] The standard deviation of the Laplacian, in pixels. + * @return [Magick::Image] a new image */ VALUE Image_adaptive_blur(int argc, VALUE *argv, VALUE self) { return adaptive_method(argc, argv, self, AdaptiveBlurImage); } /** - * Call AdaptiveBlurImageChannel. + * The same as {Magick::Image#adaptive_blur} except only the specified channels are blurred. * - * Ruby usage: - * - @verbatim Image#adaptive_blur_channel @endverbatim - * - @verbatim Image#adaptive_blur_channel(radius) @endverbatim - * - @verbatim Image#adaptive_blur_channel(radius, sigma) @endverbatim - * - @verbatim Image#adaptive_blur_channel(radius, sigma, channel) @endverbatim - * - @verbatim Image#adaptive_blur_channel(radius, sigma, channel, ...) @endverbatim + * @overload adaptive_blur_channel(radius = 0.0, sigma = 1.0, channel = Magick::AllChannels) + * @param radius [Float] The radius of the Gaussian in pixels, not counting the center pixel. + * @param sigma [Float] The standard deviation of the Laplacian, in pixels. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default channel is AllChannels + * @overload adaptive_blur_channel(radius = 0.0, sigma = 1.0, *channels) + * @param radius [Float] The radius of the Gaussian in pixels, not counting the center pixel. + * @param sigma [Float] The standard deviation of the Laplacian, in pixels. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_adaptive_blur_channel(int argc, VALUE *argv, VALUE self) { #if defined(IMAGEMAGICK_7) @@ -258,20 +244,22 @@ #endif } /** - * Call AdaptiveResizeImage. + * Resizes the image with data dependent triangulation. * - * Ruby usage: - * - @verbatim Image#adaptive_resize(scale_val) @endverbatim - * - @verbatim Image#adaptive_resize(cols, rows) @endverbatim + * @overload adaptive_resize(scale_val) + * @param scale_val [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload adaptive_resize(cols, rows) + * @param cols [Numeric] The desired column size + * @param rows [Numeric] The desired row size. + * + * @return [Magick::Image] a new image */ VALUE Image_adaptive_resize(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -308,54 +296,54 @@ } exception = AcquireExceptionInfo(); new_image = AdaptiveResizeImage(image, columns, rows, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call AdaptiveSharpenImage. + * Adaptively sharpens the image by sharpening more intensely near image edges and less intensely + * far from edges. * - * Ruby usage: - * - @verbatim Image#adaptive_sharpen @endverbatim - * - @verbatim Image#adaptive_sharpen(radius) @endverbatim - * - @verbatim Image#adaptive_sharpen(radius, sigma) @endverbatim + * The {Magick::Image#adaptive_sharpen} method sharpens the image with a Gaussian operator of the + * given radius and standard deviation (sigma). * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 + * For reasonable results, radius should be larger than sigma. + * Use a radius of 0 and adaptive_sharpen selects a suitable radius for you. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload adaptive_sharpen(radius = 0.0, sigma = 1.0) + * @param radius [Float] The radius of the Gaussian in pixels, not counting the center pixel. + * @param sigma [Float] The standard deviation of the Laplacian, in pixels. + * @return [Magick::Image] a new image */ VALUE Image_adaptive_sharpen(int argc, VALUE *argv, VALUE self) { return adaptive_method(argc, argv, self, AdaptiveSharpenImage); } /** - * Call AdaptiveSharpenImageChannel. + * The same as {Magick::Image#adaptive_sharpen} except only the specified channels are sharpened. * - * Ruby usage: - * - @verbatim Image#adaptive_sharpen_channel(radius=0.0, sigma=1.0[, channel...]) @endverbatim + * @overload adaptive_sharpen_channel(radius = 0.0, sigma = 1.0, channel = Magick::AllChannels) + * @param radius [Float] The radius of the Gaussian in pixels, not counting the center pixel. + * @param sigma [Float] The standard deviation of the Laplacian, in pixels. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload adaptive_sharpen_channel(radius = 0.0, sigma = 1.0, *channels) + * @param radius [Float] The radius of the Gaussian in pixels, not counting the center pixel. + * @param sigma [Float] The standard deviation of the Laplacian, in pixels. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image */ VALUE Image_adaptive_sharpen_channel(int argc, VALUE *argv, VALUE self) { #if defined(IMAGEMAGICK_7) @@ -366,29 +354,19 @@ } /** - * Selects an individual threshold for each pixel based on the range of - * intensity values in its local neighborhood. This allows for thresholding of - * an image whose global intensity histogram doesn't contain distinctive peaks. + * Selects an individual threshold for each pixel based on the range of intensity values in its + * local neighborhood. This allows for thresholding of an image whose global intensity histogram + * doesn't contain distinctive peaks. * - * Ruby usage: - * - @verbatim Image#adaptive_threshold @endverbatim - * - @verbatim Image#adaptive_threshold(width) @endverbatim - * - @verbatim Image#adaptive_threshold(width, height) @endverbatim - * - @verbatim Image#adaptive_threshold(width, height, offset) @endverbatim - * - * Notes: - * - Default width is 3 - * - Default height is 3 - * - Default offset is 0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload adaptive_threshold(width = 3, height = 3, offset = 0) + * @param width [Numeric] the width of the local neighborhood. + * @param height [Numeric] the height of the local neighborhood. + * @param offset [Numeric] the mean offset + * @return [Magick::Image] a new image */ VALUE Image_adaptive_threshold(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -413,31 +391,26 @@ } exception = AcquireExceptionInfo(); new_image = AdaptiveThresholdImage(image, width, height, offset, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Set the image composite mask. + * Associates a mask with an image that will be used as the destination image in a + * {Magick::Image#composite} operation. * - * Ruby usage: - * - @verbatim Image#add_compose_mask(mask) @endverbatim + * The areas of the destination image that are masked by white pixels will be modified by the + * {Magick::Image#composite} method, while areas masked by black pixels are unchanged. * - * @param self this object - * @param mask the composite mask - * @return self - * @see Image_mask - * @see Image_delete_compose_mask - * @see SetImageMask in ImageMagick + * @param mask [Magick::Image] the composite mask + * @see Image#mask + * @see Image#delete_compose_mask */ VALUE Image_add_compose_mask(VALUE self, VALUE mask) { Image *image, *mask_image = NULL; @@ -455,39 +428,35 @@ #if defined(IMAGEMAGICK_7) clip_mask = rm_clone_image(mask_image); exception = AcquireExceptionInfo(); - (void) NegateImage(clip_mask, MagickFalse, exception); + NegateImage(clip_mask, MagickFalse, exception); rm_check_exception(exception, clip_mask, DestroyOnError); - (void) SetImageMask(image, CompositePixelMask, clip_mask, exception); - (void) DestroyImage(clip_mask); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageMask(image, CompositePixelMask, clip_mask, exception); + DestroyImage(clip_mask); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else // Delete any previously-existing mask image. // Store a clone of the new mask image. - (void) SetImageMask(image, mask_image); - (void) NegateImage(image->mask, MagickFalse); + SetImageMask(image, mask_image); + NegateImage(image->mask, MagickFalse); // Since both Set and GetImageMask clone the mask image I don't see any // way to negate the mask without referencing it directly. Sigh. #endif return self; } /** - * Add random noise to a copy of the image. + * Adds random noise to the image. * - * Ruby usage: - * - @verbatim Image#add_noise(noise_type) @endverbatim - * - * @param self this object - * @param noise the noise - * @return a new image + * @param noise [Magick::NoiseType] the noise + * @return [Magick::Image] a new image */ VALUE Image_add_noise(VALUE self, VALUE noise) { Image *image, *new_image; @@ -503,33 +472,27 @@ new_image = AddNoiseImage(image, noise_type, 1.0, exception); #else new_image = AddNoiseImage(image, noise_type, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Add random noise to a copy of the image. + * Adds random noise to the specified channel or channels in the image. * - * Ruby usage: - * - @verbatim Image#add_noise_channel(noise_type) @endverbatim - * - @verbatim Image#add_noise_channel(noise_type,channel) @endverbatim - * - @verbatim Image#add_noise_channel(noise_type,channel,channel,...) @endverbatim + * @overload add_noise_channel(noise_type, channel = Magick::AllChannels) + * @param noise [Magick::NoiseType] the noise + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload add_noise_channel(noise_type, *channels) + * @param noise [Magick::NoiseType] the noise + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_add_noise_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -560,45 +523,38 @@ END_CHANNEL_MASK(new_image); #else new_image = AddNoiseImageChannel(image, channels, noise_type, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Add all the profiles in the specified file. + * Adds an ICC (a.k.a. ICM), IPTC, or generic profile. If the file contains more than one profile + * all the profiles are added. * - * Ruby usage: - * - @verbatim Image#add_profile(name) @endverbatim - * - * @param self this object - * @param name the profile filename - * @return self + * @param name [String] The filename of a file containing the profile. + * @return [Magick::Image] self */ VALUE Image_add_profile(VALUE self, VALUE name) { // ImageMagick code based on the code for the "-profile" option in mogrify.c Image *image, *profile_image; ImageInfo *info; ExceptionInfo *exception; char *profile_name; char *profile_filename = NULL; - long profile_filename_l = 0; const StringInfo *profile; image = rm_check_frozen(self); // ProfileImage issues a warning if something goes wrong. - profile_filename = rm_str2cstr(name, &profile_filename_l); + profile_filename = StringValueCStr(name); info = CloneImageInfo(NULL); if (!info) { rb_raise(rb_eNoMemError, "not enough memory to continue"); @@ -606,16 +562,15 @@ profile = GetImageProfile(image, "iptc"); if (profile) { info->profile = (void *)CloneStringInfo(profile); } - strncpy(info->filename, profile_filename, min((size_t)profile_filename_l, sizeof(info->filename))); - info->filename[MaxTextExtent-1] = '\0'; + strlcpy(info->filename, profile_filename, sizeof(info->filename)); exception = AcquireExceptionInfo(); profile_image = ReadImage(info, exception); - (void) DestroyImageInfo(info); + DestroyImageInfo(info); rm_check_exception(exception, profile_image, DestroyOnError); rm_ensure_result(profile_image); ResetImageProfileIterator(profile_image); profile_name = GetNextImageProfile(profile_image); @@ -623,55 +578,57 @@ { profile = GetImageProfile(profile_image, profile_name); if (profile) { #if defined(IMAGEMAGICK_7) - (void) ProfileImage(image, profile_name, GetStringInfoDatum(profile), GetStringInfoLength(profile), exception); + ProfileImage(image, profile_name, GetStringInfoDatum(profile), GetStringInfoLength(profile), exception); if (rm_should_raise_exception(exception, RetainExceptionRetention)) #else - (void) ProfileImage(image, profile_name, GetStringInfoDatum(profile), GetStringInfoLength(profile), MagickFalse); + ProfileImage(image, profile_name, GetStringInfoDatum(profile), GetStringInfoLength(profile), MagickFalse); if (rm_should_raise_exception(&image->exception, RetainExceptionRetention)) #endif { break; } } profile_name = GetNextImageProfile(profile_image); } - (void) DestroyImage(profile_image); + DestroyImage(profile_image); #if defined(IMAGEMAGICK_7) - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_check_image_exception(image, RetainOnError); #endif return self; } /** - * Calls SetImageAlphaChannel. + * Get/Set alpha channel. * - * Ruby usage: - * - @verbatim Image#alpha(type) @endverbatim + * @overload alpha() + * Returns true if the alpha channel will be used, false otherwise. + * This calling is same as {Magick::Image#alpha?}. + * @return [Boolean] true or false + * @see Image#alpha? * - * Notes: - * - Replaces matte=, alpha= - * - Originally there was an alpha attribute getter and setter. These are - * replaced with alpha? and alpha(type). We still define (but don't - * document) alpha=. For backward compatibility, if this method is called - * without an argument, make it act like the old alpha getter and return - * true if the matte channel is active, false otherwise. + * @overload alpha(value) + * Activates, deactivates, resets, or sets the alpha channel. + * @param value [Magick::AlphaChannelOption] An AlphaChannelOption value + * @return [Magick::AlphaChannelOption] the given value * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return the type (or true/false if called without an argument, see above) + * - Replaces {Magick::Image#matte=}, {Magick::Image#alpha=} + * - Originally there was an alpha attribute getter and setter. These are replaced with alpha? and + * alpha(type). We still define (but don't document) alpha=. For backward compatibility, if this + * method is called without an argument, make it act like the old alpha getter and return true if + * the matte channel is active, false otherwise. + * */ VALUE Image_alpha(int argc, VALUE *argv, VALUE self) { Image *image; @@ -695,15 +652,15 @@ image = rm_check_frozen(self); VALUE_TO_ENUM(argv[0], alpha, AlphaChannelOption); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SetImageAlphaChannel(image, alpha, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageAlphaChannel(image, alpha, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageAlphaChannel(image, alpha); + SetImageAlphaChannel(image, alpha); rm_check_image_exception(image, RetainOnError); #endif return argv[0]; } @@ -711,18 +668,11 @@ /** * Determine whether the image's alpha channel is activated. * - * Ruby usage: - * - @verbatim Image#alpha? @endverbatim - * - * Notes: - * - Replaces Image#matte - * - * @param self this object - * @return true if the image's alpha channel is activated + * @return [Boolean] true if the image's alpha channel is activated */ VALUE Image_alpha_q(VALUE self) { Image *image = rm_check_destroyed(self); @@ -735,16 +685,12 @@ /** * Transform an image as dictated by the affine matrix argument. * - * Ruby usage: - * - @verbatim Image#affine_transform(affine_matrix) @endverbatim - * - * @param self this object - * @param affine the affine matrix - * @return a new image + * @param affine [Magick::AffineMatrix] the affine matrix + * @return [Magick::Image] a new image */ VALUE Image_affine_transform(VALUE self, VALUE affine) { Image *image, *new_image; @@ -757,32 +703,27 @@ Export_AffineMatrix(&matrix, affine); exception = AcquireExceptionInfo(); new_image = AffineTransformImage(image, &matrix, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Return the image property associated with "key". + * Returns the value of the image property identified by key. An image may have any number of + * properties. * - * Ruby usage: - * - @verbatim Image#["key"] @endverbatim - * - @verbatim Image#[:key] @endverbatim + * Each property is identified by a string (or symbol) key. + * The property value is a string. ImageMagick predefines some properties, including "Label", + * "Comment", "Signature", and in some cases "EXIF". * - * Notes: - * - Use Image#[]= (aset) to establish more properties or change the value of - * an existing property. - * - * @param self this object - * @param key_arg the key to get - * @return property value or nil if key doesn't exist + * @param key_arg [String, Symbol] the key to get + * @return [String] property value or nil if key doesn't exist + * @see Image#[]= + * @see Image#properties */ VALUE Image_aref(VALUE self, VALUE key_arg) { Image *image; @@ -799,11 +740,11 @@ case T_SYMBOL: key = rb_id2name((ID)SYM2ID(key_arg)); break; default: - key = StringValuePtr(key_arg); + key = StringValueCStr(key_arg); if (*key == '\0') { return Qnil; } break; @@ -822,28 +763,22 @@ attr = rm_get_property(image, key); return attr ? rb_str_new2(attr) : Qnil; } /** - * Update or add image attribute "key". + * Sets the value of an image property. An image may have any number of properties. * - * Ruby usage: - * - @verbatim Image#["key"] = attr @endverbatim - * - @verbatim Image#[:key] = attr @endverbatim + * - Specify attr=nil to remove the key from the list. + * - SetImageProperty normally APPENDS the new value to any existing value. Since this usage is + * tremendously counter-intuitive, this function always deletes the existing value before setting + * the new value. + * - There's no use checking the return value since SetImageProperty returns "False" for many + * reasons, some legitimate. * - * Notes: - * - Specify attr=nil to remove the key from the list. - * - SetImageProperty normally APPENDS the new value to any existing value. - * Since this usage is tremendously counter-intuitive, this function always - * deletes the existing value before setting the new value. - * - There's no use checking the return value since SetImageProperty returns - * "False" for many reasons, some legitimate. - * - * @param self this object - * @param key_arg the key to set - * @param attr_arg the value to which to set it - * @return self + * @param key_arg [String, Symbol] the key to set + * @param attr_arg [String] the value to which to set it + * @return [Magick::Image] self */ VALUE Image_aset(VALUE self, VALUE key_arg, VALUE attr_arg) { Image *image; @@ -851,11 +786,11 @@ char *attr; unsigned int okay; image = rm_check_frozen(self); - attr = attr_arg == Qnil ? NULL : StringValuePtr(attr_arg); + attr = attr_arg == Qnil ? NULL : StringValueCStr(attr_arg); switch (TYPE(key_arg)) { case T_NIL: return self; @@ -863,22 +798,22 @@ case T_SYMBOL: key = rb_id2name((ID)SYM2ID(key_arg)); break; default: - key = StringValuePtr(key_arg); + key = StringValueCStr(key_arg); if (*key == '\0') { return self; } break; } // Delete existing value. SetImageProperty returns False if // the attribute doesn't exist - we don't care. - (void) rm_set_property(image, key, NULL); + rm_set_property(image, key, NULL); // Set new value if (attr) { okay = rm_set_property(image, key, attr); if (!okay) @@ -909,19 +844,17 @@ Data_Get_Struct(self, Image, image); exception = AcquireExceptionInfo(); new_image = (fp)(image, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); @@ -960,36 +893,33 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) (fp)(new_image, exception); + (fp)(new_image, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) (fp)(new_image, channels); + (fp)(new_image, channels); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Get/set the auto Gamma channel + * "Automagically" adjust the gamma level of an image. * - * Ruby usage: - * - @verbatim Image#auto_gamma_channel @endverbatim - * - @verbatim Image#auto_gamma_channel channel @endverbatim - * - @verbatim Image#auto_gamma_channel channel, ... @endverbatim + * @overload auto_gamma_channel(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * + * @overload auto_gamma_channel(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_auto_gamma_channel(int argc, VALUE *argv, VALUE self) { #if defined(IMAGEMAGICK_7) @@ -999,22 +929,19 @@ #endif } /** - * Get/set the auto level channel + * "Automagically" adjust the color levels of an image. * - * Ruby usage: - * - @verbatim Image#auto_level_channel @endverbatim - * - @verbatim Image#auto_level_channel channel @endverbatim - * - @verbatim Image#auto_level_channel channel, ... @endverbatim + * @overload auto_level_channel(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * + * @overload auto_level_channel(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_auto_level_channel(int argc, VALUE *argv, VALUE self) { #if defined(IMAGEMAGICK_7) @@ -1092,54 +1019,48 @@ return new_image; } /** - * Implement mogrify's -auto_orient option automatically orient image based on - * EXIF orientation value. + * Rotates or flips the image based on the image's EXIF orientation tag. * - * Ruby usage: - * - @verbatim Image#auto_orient @endverbatim + * Note that only some models of modern digital cameras can tag an image with the orientation. + * If the image does not have an orientation tag, or the image is already properly oriented, then + * {Magick::Image#auto_orient} returns an exact copy of the image. * - * @param self this object - * @return a new image - * @see mogrify.c (in ImageMagick 6.2.8) + * @return [Magick::Image] a new image + * @see Image#auto_orient! */ VALUE Image_auto_orient(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return auto_orient(False, self); } /** - * Implement mogrify's -auto_orient option automatically orient image based on - * EXIF orientation value. + * Rotates or flips the image based on the image's EXIF orientation tag. + * Note that only some models of modern digital cameras can tag an image with the orientation. + * If the image does not have an orientation tag, or the image is already properly oriented, then + * {Magick::Image#auto_orient!} returns nil. * - * Ruby usage: - * - @verbatim Image#auto_orient! @endverbatim - * - * @param self this object - * @return nil if the image is already properly oriented, otherwise self + * @return [Magick::Image, nil] nil if the image is already properly oriented, otherwise self + * @see Image#auto_orient */ VALUE Image_auto_orient_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return auto_orient(True, self); } /** * Return the name of the background color as a String. * - * Ruby usage: - * - @verbatim Image#background_color @endverbatim - * - * @param self this object - * @return the background color + * @return [String] the background color */ VALUE Image_background_color(VALUE self) { Image *image = rm_check_destroyed(self); @@ -1148,16 +1069,12 @@ /** * Set the the background color to the specified color spec. * - * Ruby usage: - * - @verbatim Image#background_color= @endverbatim - * - * @param self this object - * @param color the color - * @return color + * @param color [Magick::Pixel, String] the color + * @return [Magick::Pixel, String] the given color */ VALUE Image_background_color_eq(VALUE self, VALUE color) { Image *image = rm_check_frozen(self); @@ -1167,15 +1084,11 @@ /** * Return the number of rows (before transformations). * - * Ruby usage: - * - @verbatim Image#base_columns @endverbatim - * - * @param self this object - * @return the number of rows + * @return [Numeric] the number of rows */ VALUE Image_base_columns(VALUE self) { Image *image = rm_check_destroyed(self); @@ -1183,15 +1096,11 @@ } /** * Return the image filename (before transformations). * - * Ruby usage: - * - @verbatim Image#base_filename @endverbatim - * - * @param self this object - * @return the base image filename (or the current filename if there is no base) + * @return [String] the base image filename (or the current filename if there is no base) */ VALUE Image_base_filename(VALUE self) { Image *image = rm_check_destroyed(self); @@ -1206,15 +1115,11 @@ } /** * Return the number of rows (before transformations). * - * Ruby usage: - * - @verbatim Image#base_rows @endverbatim - * - * @param self this object - * @return the number of rows + * @return [Numeric] the number of rows */ VALUE Image_base_rows(VALUE self) { Image *image = rm_check_destroyed(self); @@ -1223,15 +1128,11 @@ /** * Get image bias (used when convolving an image). * - * Ruby usage: - * - @verbatim Image#bias @endverbatim - * - * @param self this object - * @return the image bias + * @return [Float] the image bias */ VALUE Image_bias(VALUE self) { Image *image; @@ -1243,11 +1144,11 @@ const char *artifact = GetImageArtifact(image, "convolve:bias"); if (artifact != (const char *) NULL) { char *q; - bias = InterpretLocaleValue(artifact,&q); + bias = InterpretLocaleValue(artifact, &q); if (*q == '%') { bias *= ((double) QuantumRange + 1.0) / 100.0; } } @@ -1260,16 +1161,12 @@ /** * Set image bias (used when convolving an image). * - * Ruby usage: - * - @verbatim Image#bias = a number between 0.0 and 1.0 or "NN%" @endverbatim - * - * @param self this object - * @param pct the bias - * @return pct + * @param pct [Float, String] Either a number between 0.0 and 1.0 or a string in the form "NN%" + * @return [Float, String] the given value */ VALUE Image_bias_eq(VALUE self, VALUE pct) { Image *image; @@ -1291,23 +1188,21 @@ return pct; } /** - * Create a bilevel image. + * Changes the value of individual pixels based on the intensity of each pixel channel. The result + * is a high-contrast image. * - * Ruby usage: - * - @verbatim Image#bilevel_channel(threshold) @endverbatim - * - @verbatim Image#bilevel_channel(threshold, channel) @endverbatim + * @overload bilevel_channel(threshold, channel = Magick::AllChannels) + * @param threshold [Float] The threshold value, a number between 0 and QuantumRange. * - * Notes: - * - If no channel is specified AllChannels is used + * @overload bilevel_channel(threshold, *channels) + * @param threshold [Float] The threshold value, a number between 0 and QuantumRange. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_bilevel_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -1333,31 +1228,27 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) BilevelImage(new_image, threshold, exception); + BilevelImage(new_image, threshold, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void)BilevelImageChannel(new_image, channels, threshold); + BilevelImageChannel(new_image, channels, threshold); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** * Return current black point compensation attribute. * - * Ruby usage: - * - @verbatim Image#black_point_compensation @endverbatim - * - * @param self this object - * @return the black point compensation + * @return [Boolean] true or false */ VALUE Image_black_point_compensation(VALUE self) { Image *image; @@ -1383,47 +1274,52 @@ /** * Set black point compensation attribute. * - * Ruby usage: - * - @verbatim Image#black_point_compensation=true or false @endverbatim - * - * @param self this object - * @param arg the compensation - * @return arg + * @param arg [Boolean] true or false + * @return [Boolean] the given value */ VALUE Image_black_point_compensation_eq(VALUE self, VALUE arg) { Image *image; const char *value; image = rm_check_frozen(self); - (void) rm_set_property(image, BlackPointCompensationKey, NULL); + rm_set_property(image, BlackPointCompensationKey, NULL); value = RTEST(arg) ? "true" : "false"; - (void) rm_set_property(image, BlackPointCompensationKey, value); + rm_set_property(image, BlackPointCompensationKey, value); return arg; } /** - * Call BlackThresholdImage. + * Forces all pixels below the threshold into black while leaving all pixels above the threshold + * unchanged. * - * Ruby usage: - * - @verbatim Image#black_threshold(red) @endverbatim - * - @verbatim Image#black_threshold(red, green) @endverbatim - * - @verbatim Image#black_threshold(red, green, blue) @endverbatim - * - @verbatim Image#black_threshold(red, green, blue, alpha: alpha) @endverbatim + * @overload black_threshold(red) + * @param red [Numeric] the number for red channel * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see threshold_image - * @see Image_white_threshold + * @overload black_threshold(red, green) + * @param red [Numeric] the number for red channel + * @param green [Numeric] the number for green channel + * + * @overload black_threshold(red, green, blue) + * @param red [Numeric] the number for red channel + * @param green [Numeric] the number for green channel + * @param blue [Numeric] the number for blue channel + * + * @overload black_threshold(red, green, blue, alpha:) + * @param red [Numeric] the number for red channel + * @param green [Numeric] the number for green channel + * @param blue [Numeric] the number for blue channel + * @param alpha [Numeric] the number for alpha channel + * + * @return [Numeric] a new image + * @see Image#white_threshold */ VALUE Image_black_threshold(int argc, VALUE *argv, VALUE self) { return threshold_image(argc, argv, self, BlackThresholdImage); @@ -1501,12 +1397,12 @@ * @param mark the source image * @param x_offset pointer to x offset * @param y_offset pointer to y offset */ static void -get_offsets_from_gravity(GravityType gravity, Image *image, Image *mark - , long *x_offset, long *y_offset) +get_offsets_from_gravity(GravityType gravity, Image *image, Image *mark, + long *x_offset, long *y_offset) { switch (gravity) { case ForgetGravity: @@ -1581,12 +1477,12 @@ * @param src the source image * @param x_offset pointer to x offset * @param y_offset pointer to y offset */ static void -get_composite_offsets(int argc, VALUE *argv, Image *dest, Image *src - , long *x_offset, long *y_offset) +get_composite_offsets(int argc, VALUE *argv, Image *dest, Image *src, + long *x_offset, long *y_offset) { GravityType gravity; int exc = 0; if (CLASS_OF(argv[0]) == Class_GravityType) @@ -1611,15 +1507,15 @@ } // Gravity not specified at all. Offsets are measured from the // NorthWest corner. The arguments must be numbers. else { - (void)rb_protect(check_for_long_value, argv[0], &exc); + rb_protect(check_for_long_value, argv[0], &exc); if (exc) { - rb_raise(rb_eTypeError, "expected GravityType, got %s" - , rb_class2name(CLASS_OF(argv[0]))); + rb_raise(rb_eTypeError, "expected GravityType, got %s", + rb_class2name(CLASS_OF(argv[0]))); } *x_offset = NUM2LONG(argv[0]); if (argc > 1) { *y_offset = NUM2LONG(argv[1]); @@ -1670,11 +1566,11 @@ { prec = 2; fw += 3; } - sz = (size_t)sprintf(geometry, "%*.*f", -fw, prec, src_percent); + sz = (size_t)snprintf(geometry, geometry_l, "%*.*f", -fw, prec, src_percent); assert(sz < geometry_l); sz = strcspn(geometry, " "); // if dst_percent was nil don't add to the geometry @@ -1687,11 +1583,11 @@ prec = 2; fw += 3; } - sz += (size_t)sprintf(geometry+sz, "x%*.*f", -fw, prec, dst_percent); + sz += (size_t)snprintf(geometry+sz, geometry_l-sz, "x%*.*f", -fw, prec, dst_percent); assert(sz < geometry_l); sz = strcspn(geometry, " "); } if (sz < geometry_l) @@ -1715,63 +1611,61 @@ * @param y_off the y offset * @param op the composite operator to use * @return a new image */ static VALUE -special_composite(Image *image, Image *overlay, double image_pct, double overlay_pct - , long x_off, long y_off, CompositeOperator op) +special_composite(Image *image, Image *overlay, double image_pct, double overlay_pct, + long x_off, long y_off, CompositeOperator op) { Image *new_image; char geometry[20]; #if defined(IMAGEMAGICK_7) ExceptionInfo *exception; #endif blend_geometry(geometry, sizeof(geometry), image_pct, overlay_pct); - (void) CloneString(&overlay->geometry, geometry); - (void) SetImageArtifact(overlay,"compose:args", geometry); + CloneString(&overlay->geometry, geometry); + SetImageArtifact(overlay, "compose:args", geometry); new_image = rm_clone_image(image); - (void) SetImageArtifact(new_image,"compose:args", geometry); // 6.9 appears to get this info from canvas (dest) image + SetImageArtifact(new_image, "compose:args", geometry); // 6.9 appears to get this info from canvas (dest) image #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) CompositeImage(new_image, overlay, op, MagickTrue, x_off, y_off, exception); + CompositeImage(new_image, overlay, op, MagickTrue, x_off, y_off, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) CompositeImage(new_image, op, overlay, x_off, y_off); + CompositeImage(new_image, op, overlay, x_off, y_off); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Corresponds to the composite -blend operation. + * Adds the overlay image to the target image according to src_percent and dst_percent. * - * Ruby usage: - * - @verbatim Image#blend(overlay, src_percent, dst_percent) @endverbatim - * - @verbatim Image#blend(overlay, src_percent, dst_percent, x_offset) @endverbatim - * - @verbatim Image#blend(overlay, src_percent, dst_percent, x_offset, y_offset) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, gravity) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, gravity, x_offset) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, gravity, x_offset, y_offset) @endverbatim + * - The default value for dst_percent is 100%-src_percent * - * Notes: - * - Default x_offset is 0 - * - Default y_offset is 0 - * - Percent can be a number or a string in the form "NN%" - * - The default value for dst_percent is 100%-src_percent - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload blend(overlay, src_percent, dst_percent, gravity = Magick::NorthWestGravity, x_offset = 0, y_offset = 0) + * @param overlay [Magick::Image, Magick::ImageList] The source image for the composite operation. + * Either an imagelist or an image. If an imagelist, uses the current image. + * @param src_percent [Float, String] Either a non-negative number a string in the form "NN%". + * If src_percentage is a number it is interpreted as a percentage. + * Both 0.25 and "25%" mean 25%. This argument is required. + * @param dst_percent [Float, String] Either a non-negative number a string in the form "NN%". + * If src_percentage is a number it is interpreted as a percentage. + * Both 0.25 and "25%" mean 25%. This argument may omitted if no other arguments follow it. + * In this case the default is 100%-src_percentage. + * @param gravity [Magick::GravityType] the gravity for offset. the offsets are measured from the NorthWest corner by default. + * @param x_offset [Numeric] The offset that measured from the left-hand side of the target image. + * @param y_offset [Numeric] The offset that measured from the top of the target image. + * @return [Magick::Image] a new image */ VALUE Image_blend(int argc, VALUE *argv, VALUE self) { VALUE ovly; @@ -1797,45 +1691,37 @@ } switch (argc) { case 3: - dst_percent = rm_percentage(argv[2],1.0) * 100.0; - src_percent = rm_percentage(argv[1],1.0) * 100.0; + dst_percent = rm_percentage(argv[2], 1.0) * 100.0; + src_percent = rm_percentage(argv[1], 1.0) * 100.0; break; case 2: - src_percent = rm_percentage(argv[1],1.0) * 100.0; + src_percent = rm_percentage(argv[1], 1.0) * 100.0; dst_percent = FMAX(100.0 - src_percent, 0); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc); break; } RB_GC_GUARD(ovly); - return special_composite(image, overlay, src_percent, dst_percent - , x_offset, y_offset, BlendCompositeOp); + return special_composite(image, overlay, src_percent, dst_percent, + x_offset, y_offset, BlendCompositeOp); } /** - * Call BlueShiftImage. + * Simulate a scene at nighttime in the moonlight. * - * Ruby usage: - * - @verbatim Image#blue_shift @endverbatim - * - @verbatim Image#blue_shift(factor) @endverbatim - * - * Notes: - * - Default factor is 1.5 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload blue_shift(factor = 1.5) + * @param factor [Float] Larger values increase the effect. + * @return [Magick::Image] a new image */ VALUE Image_blue_shift(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -1864,27 +1750,24 @@ return rm_image_new(new_image); } /** - * Call BlurImageChannel. + * Blurs the specified channel. + * Convolves the image with a Gaussian operator of the given radius and standard deviation (sigma). * - * Ruby usage: - * - @verbatim Image#blur_channel @endverbatim - * - @verbatim Image#blur_channel(radius) @endverbatim - * - @verbatim Image#blur_channel(radius, sigma) @endverbatim - * - @verbatim Image#blur_channel(radius, sigma, channel) @endverbatim + * @overload blur_channel(radius = 0.0, sigma = 1.0, channel = Magick::AllChannels) + * @param radius [Float] the radius value + * @param sigma [Float] the sigma value + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default channel is AllChannels + * @overload blur_channel(radius = 0.0, sigma = 1.0, *channels) + * @param radius [Float] the radius value + * @param sigma [Float] the sigma value + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_blur_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -1917,36 +1800,23 @@ END_CHANNEL_MASK(image); #else new_image = BlurImageChannel(image, channels, radius, sigma, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Blur the image. * - * Ruby usage: - * - @verbatim Image#blur_image @endverbatim - * - @verbatim Image#blur_image(radius) @endverbatim - * - @verbatim Image#blur_image(radius, sigma) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - The "blur" name is used for the attribute - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload blur_image(radius = 0.0, sigma = 1.0) + * @param radius [Float] the radius value + * @param sigma [Float] the sigma value + * @return [Magick::Image] a new image */ VALUE Image_blur_image(int argc, VALUE *argv, VALUE self) { return effect_image(self, argc, argv, BlurImage); @@ -1991,81 +1861,61 @@ new_image = BorderImage(image, &rect, image->compose, exception); #else new_image = BorderImage(image, &rect, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); new_image->border_color = old_border; UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } image->border_color = old_border; return rm_image_new(new_image); } /** - * Surrounds the image with a border of the specified width, height, and named - * color. + * Surrounds the image with a border of the specified width, height, and named color. + * In-place form of {Image#border}. * - * Ruby usage: - * - @verbatim Image#border!(width, height, color) @endverbatim - * - * @param self this object - * @param width the width of the border - * @param height the height of the border - * @param color the color of the border - * @return self - * @see border - * @see Image_border + * @param width [Numeric] the width of the border + * @param height [Numeric] the height of the border + * @param color [Magick::Pixel, String] the color of the border */ VALUE Image_border_bang(VALUE self, VALUE width, VALUE height, VALUE color) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return border(True, self, width, height, color); } /** - * Surrounds the image with a border of the specified width, height, and named - * color. + * Surrounds the image with a border of the specified width, height, and named color. * - * Ruby usage: - * - @verbatim Image#border(width, height, color) @endverbatim - * - * @param self this object - * @param width the width of the border - * @param height the height of the border - * @param color the color of the border - * @return a new image - * @see border - * @see Image_border_bang + * @param width [Numeric] the width of the border + * @param height [Numeric] the height of the border + * @param color [Magick::Pixel, String] the color of the border + * @return [Magick::Image] a new image */ VALUE Image_border(VALUE self, VALUE width, VALUE height, VALUE color) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return border(False, self, width, height, color); } /** * Return the name of the border color as a String. * - * Ruby usage: - * - @verbatim Image#border_color @endverbatim - * - * @param self this object - * @return the name of the border color + * @return [String] the name of the border color */ VALUE Image_border_color(VALUE self) { Image *image = rm_check_destroyed(self); @@ -2074,16 +1924,12 @@ /** * Set the the border color. * - * Ruby usage: - * - @verbatim Image#border_color= @endverbatim - * - * @param self this object - * @param color the color - * @return color + * @param [Magick::Pixel, String] color the color + * @return [Magick::Pixel, String] the given color */ VALUE Image_border_color_eq(VALUE self, VALUE color) { Image *image = rm_check_frozen(self); @@ -2091,17 +1937,13 @@ return color; } /** - * returns the bounding box of an image canvas. + * Returns the bounding box of an image canvas. * - * Ruby usage: - * - @verbatim Image#bounding_box @endverbatim - * - * @param self this object - * @return the bounding box + * @return [Magick::Rectangle] the bounding box */ VALUE Image_bounding_box(VALUE self) { Image *image; @@ -2109,40 +1951,54 @@ ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); box = GetImageBoundingBox(image, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return Import_RectangleInfo(&box); } /** - * do a screen capture. + * Reads an image from an X window. + * Unless you identify a window to capture via the optional arguments block, when capture is invoked + * the cursor will turn into a cross. Click the cursor on the window to be captured. * - * Ruby usage: - * - @verbatim Image.capture @endverbatim - * - @verbatim Image.capture(silent) { optional parms } @endverbatim - * - @verbatim Image.capture(silent,frame) { optional parms } @endverbatim - * - @verbatim Image.capture(silent,frame,descend) { optional parms } @endverbatim - * - @verbatim Image.capture(silent,frame,descend,screen) { optional parms } @endverbatim - * - @verbatim Image.capture(silent,frame,descend,screen,borders) { optional parms } @endverbatim + * @overload capture(silent = false, frame = false, descend = false, screen = false, borders = false) + * @param silent [Boolean] If true, suppress the beeps that signal the start and finish of the + * capture process. + * @param frame [Boolean] If true, include the window frame. + * @param descend [Boolean] If true, obtain image by descending window hierarchy. + * @param screen [Boolean] If true, specifies that the GetImage request used to obtain the image + * should be done on the root window, rather than directly on the specified window. In this way, + * you can obtain pieces of other windows that overlap the specified window, and more + * importantly, you can capture menus or other popups that are independent windows but appear + * over the specified window. + * @param borders [Boolean] If true, include the border in the image. * - * Notes: - * - Default silent is false - * - Default frame is false - * - Default descent is false - * - Default screen is false - * - Default borders if false + * @overload capture(silent = false, frame = false, descend = false, screen = false, borders = false) + * This yields {Magick::Image::Info} to block with its object's scope. + * @param silent [Boolean] If true, suppress the beeps that signal the start and finish of the + * capture process. + * @param frame [Boolean] If true, include the window frame. + * @param descend [Boolean] If true, obtain image by descending window hierarchy. + * @param screen [Boolean] If true, specifies that the GetImage request used to obtain the image + * should be done on the root window, rather than directly on the specified window. In this way, + * you can obtain pieces of other windows that overlap the specified window, and more + * importantly, you can capture menus or other popups that are independent windows but appear + * over the specified window. + * @param borders [Boolean] If true, include the border in the image. + * @yield [] * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image + * @example + * img = Image.capture { + * self.filename = "root" + * } */ VALUE Image_capture(int argc, VALUE *argv, VALUE self ATTRIBUTE_UNUSED) { Image *new_image; @@ -2184,11 +2040,11 @@ // If an error occurs, IM will call our error handler and we raise an exception. #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); new_image = XImportImage(image_info, &ximage_info, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else new_image = XImportImage(image_info, &ximage_info); rm_check_image_exception(new_image, DestroyOnError); #endif @@ -2201,18 +2057,25 @@ return rm_image_new(new_image); } /** - * parse geometry string, compute new image geometry. + * This method supports resizing a method by specifying constraints. + * For example, you can specify that the image should be resized such that the aspect ratio should + * be retained but the resulting image should be no larger than 640 pixels wide and 480 pixels tall. * - * Ruby usage: - * - @verbatim Image#change_geometry(geometry_string) { |cols, rows, image| } @endverbatim - * - * @param self this object - * @param geom_arg the geometry string - * @return new image geometry + * @param geom_arg [String] the geometry string + * @yield [column, row, image] + * @yieldparam column [Numeric] The desired column size + * @yieldparam row [Numeric] The desired row size + * @yieldparam image [Magick::Image] self + * @see https://www.imagemagick.org/Magick++/Geometry.html + * @example + * image.change_geometry!('320x240') { |cols, rows, img| + * img.resize!(cols, rows) + * } + * @note {Magick::Image#change_geometry!} is an alias for {Magick::Image#change_geometry}. */ VALUE Image_change_geometry(VALUE self, VALUE geom_arg) { Image *image; @@ -2221,17 +2084,17 @@ char *geometry; unsigned int flags; VALUE ary; image = rm_check_destroyed(self); - geom_str = rm_to_s(geom_arg); - geometry = StringValuePtr(geom_str); + geom_str = rb_String(geom_arg); + geometry = StringValueCStr(geom_str); memset(&rect, 0, sizeof(rect)); SetGeometry(image, &rect); - flags = ParseMetaGeometry(geometry, &rect.x,&rect.y, &rect.width,&rect.height); + flags = ParseMetaGeometry(geometry, &rect.x, &rect.y, &rect.width, &rect.height); if (flags == NoValue) { rb_raise(rb_eArgError, "invalid geometry string `%s'", geometry); } @@ -2246,18 +2109,13 @@ return rb_yield(ary); } /** - * Return true if any pixel in the image has been altered since the image was - * constituted. + * Return true if any pixel in the image has been altered since the image was constituted. * - * Ruby usage: - * - @verbatim Image#changed? @endverbatim - * - * @param self this object - * @return true if altered, false otherwise + * @return [Boolean] true if altered, false otherwise */ VALUE Image_changed_q(VALUE self) { Image *image = rm_check_destroyed(self); @@ -2265,19 +2123,15 @@ return okay; } /** - * Extract a channel from the image. A channel is a particular color component - * of each pixel in the image. + * Extract a channel from the image. A channel is a particular color component of each pixel in the + * image. * - * Ruby usage: - * - @verbatim Image#channel @endverbatim - * - * @param self this object - * @param channel_arg the type of the channel to extract - * @return the channel of the specified type + * @param channel_arg [Magick::ChannelType] the type of the channel to extract + * @return [Magick::Image] a new image */ VALUE Image_channel(VALUE self, VALUE channel_arg) { Image *image, *new_image; @@ -2288,42 +2142,36 @@ image = rm_check_destroyed(self); VALUE_TO_ENUM(channel_arg, channel, ChannelType); - new_image = rm_clone_image(image); - #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SeparateImage(new_image, channel, exception); + new_image = SeparateImage(image, channel, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) SeparateImageChannel(new_image, channel); + new_image = rm_clone_image(image); + SeparateImageChannel(new_image, channel); rm_check_image_exception(new_image, DestroyOnError); #endif - rm_ensure_result(new_image); return rm_image_new(new_image); } /** - * GetImageChannelDepth. + * Returns the maximum depth for the specified channel or channels. * - * Ruby usage: - * - @verbatim Image#channel_depth @endverbatim - * - @verbatim Image#channel_depth(channel_depth) @endverbatim + * @overload channel_depth(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel_depth is AllChannels + * @overload channel_depth(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return the channel depth + * @return [Numeric] the channel depth */ VALUE Image_channel_depth(int argc, VALUE *argv, VALUE self) { Image *image; @@ -2347,37 +2195,29 @@ channel_depth = GetImageDepth(image, exception); END_CHANNEL_MASK(image); #else channel_depth = GetImageChannelDepth(image, channels, exception); #endif - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return ULONG2NUM(channel_depth); } /** - * Return an array [min, max] where 'min' and 'max' are the minimum and maximum - * values of all channels. + * Returns the minimum and maximum intensity values for the specified channel or channels. * - * Ruby usage: - * - @verbatim Image#channel_extrema @endverbatim - * - @verbatim Image#channel_extrema(channel) @endverbatim + * @overload channel_extrema(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels - * - GM's implementation is very different from ImageMagick. This method - * follows the IM API very closely and then shoehorn's the GM API to - * more-or-less fit. Note that IM allows you to specify more than one - * channel argument. GM does not. + * @overload channel_extrema(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return [min,max] of the channel + * @return [Array<Numeric>] The first element in the array is the minimum value. The second element is the + * maximum value. */ VALUE Image_channel_extrema(int argc, VALUE *argv, VALUE self) { Image *image; @@ -2397,18 +2237,18 @@ } exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); - (void) GetImageExtrema(image, &min, &max, exception); + GetImageExtrema(image, &min, &max, exception); END_CHANNEL_MASK(image); #else - (void) GetImageChannelExtrema(image, channels, &min, &max, exception); + GetImageChannelExtrema(image, channels, &min, &max, exception); #endif - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); ary = rb_ary_new2(2); rb_ary_store(ary, 0, ULONG2NUM(min)); rb_ary_store(ary, 1, ULONG2NUM(max)); @@ -2417,23 +2257,20 @@ return ary; } /** - * Return an array of the mean and standard deviation for the channel. + * Returns the mean and standard deviation values for the specified channel or channels. * - * Ruby usage: - * - @verbatim Image#channel_mean @endverbatim - * - @verbatim Image#channel_mean(channel) @endverbatim + * @overload channel_mean(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload channel_mean(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return an array [mean, std. deviation] + * @return [Array<Float>] The first element in the array is the mean value. The second element is the + * standard deviation. */ VALUE Image_channel_mean(int argc, VALUE *argv, VALUE self) { Image *image; @@ -2453,18 +2290,18 @@ } exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); - (void) GetImageMean(image, &mean, &stddev, exception); + GetImageMean(image, &mean, &stddev, exception); END_CHANNEL_MASK(image); #else - (void) GetImageChannelMean(image, channels, &mean, &stddev, exception); + GetImageChannelMean(image, channels, &mean, &stddev, exception); #endif - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); ary = rb_ary_new2(2); rb_ary_store(ary, 0, rb_float_new(mean)); rb_ary_store(ary, 1, rb_float_new(stddev)); @@ -2474,26 +2311,22 @@ } /** * Return an array of the entropy for the channel. * - * Ruby usage: - * - @verbatim Image#channel_entropy @endverbatim - * - @verbatim Image#channel_entropy(channel) @endverbatim + * @overload channel_entropy(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload channel_entropy(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return an array [mean, std. deviation] + * @return [Array<Float>] The first element in the array is the average entropy of the selected channels. */ +#if defined(HAVE_GETIMAGECHANNELENTROPY) || defined(IMAGEMAGICK_7) VALUE Image_channel_entropy(int argc, VALUE *argv, VALUE self) { -#if defined(HAVE_GETIMAGECHANNELENTROPY) || defined(IMAGEMAGICK_7) Image *image; ChannelType channels; ExceptionInfo *exception; double entropy; VALUE ary; @@ -2509,128 +2342,98 @@ } exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); - (void) GetImageEntropy(image, &entropy, exception); + GetImageEntropy(image, &entropy, exception); END_CHANNEL_MASK(image); #else - (void) GetImageChannelEntropy(image, channels, &entropy, exception); + GetImageChannelEntropy(image, channels, &entropy, exception); #endif - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); ary = rb_ary_new2(1); rb_ary_store(ary, 0, rb_float_new(entropy)); RB_GC_GUARD(ary); return ary; +} #else +VALUE +Image_channel_entropy(int argc ATTRIBUTE_UNUSED, VALUE *argv ATTRIBUTE_UNUSED, VALUE self ATTRIBUTE_UNUSED) +{ rm_not_implemented(); - return (VALUE) 0; - argc = argc; - argv = argv; - self = self; -#endif } +#endif - /** - * Return a new image that is a copy of the input image with the edges - * highlighted. + * Return a new image that is a copy of the input image with the edges highlighted. * - * Ruby usage: - * - @verbatim Image#charcoal @endverbatim - * - @verbatim Image#charcoal(radius) @endverbatim - * - @verbatim Image#charcoal(radius, sigma) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload charcoal(radius = 0.0, sigma = 1.0) + * @param radius [Float] The radius of the pixel neighborhood. + * @param sigma [Float] The standard deviation of the Gaussian, in pixels. + * @return [Magick::Image] a new image */ VALUE Image_charcoal(int argc, VALUE *argv, VALUE self) { return effect_image(self, argc, argv, CharcoalImage); } /** - * If the target image has been destroyed, raise Magick::DestroyedImageError. + * Raises {Magick::DestroyedImageError} if the image has been destroyed. Returns nil otherwise. * - * Ruby usage: - * - @verbatim Image#check_destroyed @endverbatim - * - * @param self this object - * @return nil - * @throw Magick::DestroyedImageError + * @return [nil] nil + * @raise [Magick::DestroyedImageError] raise if the image has been destroyed */ VALUE Image_check_destroyed(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return Qnil; } /** - * Remove a region of an image and collapses the image to occupy the removed - * portion. + * Remove a region of an image and collapses the image to occupy the removed portion. * - * Ruby usage: - * - @verbatim Image#chop @endverbatim - * - * @param self this object - * @param x x position of start of region - * @param y y position of start of region - * @param width width of region - * @param height height of region - * @return a new image + * @param x [Numeric] x position of start of region + * @param y [Numeric] y position of start of region + * @param width [Numeric] width of region + * @param height [Numeric] height of region + * @return [Magick::Image] a new image */ VALUE Image_chop(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return xform_image(False, self, x, y, width, height, ChopImage); } /** - * Return the red, green, blue, and white-point chromaticity values as a - * Magick::ChromaticityInfo. + * Return the red, green, blue, and white-point chromaticity values as a {Magick::Chromaticity}. * - * Ruby usage: - * - @verbatim Image#chromaticity @endverbatim - * - * @param self this object - * @return the chromaticity values + * @return [Magick::Chromaticity] the chromaticity values */ VALUE Image_chromaticity(VALUE self) { Image *image = rm_check_destroyed(self); return ChromaticityInfo_new(&image->chromaticity); } /** - * Set the red, green, blue, and white-point chromaticity values from a - * Magick::ChromaticityInfo. + * Set the red, green, blue, and white-point chromaticity values from a {Magick::Chromaticity}. * - * Ruby usage: - * - @verbatim Image#chromaticity= @endverbatim - * - * @param self this object - * @param chroma the chromaticity - * @return chroma + * @param [Magick::Chromaticity] chroma the chromaticity + * @return [Magick::Chromaticity] the given value */ VALUE Image_chromaticity_eq(VALUE self, VALUE chroma) { Image *image = rm_check_frozen(self); @@ -2638,17 +2441,14 @@ return chroma; } /** - * Copy an image, along with its frozen and tainted state. + * Same as {Magick::Image#dup} except the frozen state of the original is propagated to the new + * copy. * - * Ruby usage: - * - @verbatim Image#clone @endverbatim - * - * @param self this object - * @return a clone of this object + * @return [Magick::Image] a clone of this object */ VALUE Image_clone(VALUE self) { VALUE clone; @@ -2664,19 +2464,31 @@ return clone; } /** - * Equivalent to -clut option. + * Replace the channel values in the target image with a lookup of its replacement value in an LUT + * gradient image. * - * Ruby usage: - * - @verbatim Image#clut_channel @endverbatim + * The LUT image should be either a single row or column image of replacement colors. + * The lookup is controlled by the -interpolate setting, especially for an LUT which is not the full + * length needed by the IM installed Quality (Q) level. Good settings for this is the default + * 'bilinear' or 'bicubic' interpolation setting for a smooth color gradient, or 'integer' for a + * direct unsmoothed lookup of color values. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self + * This method is especially suited to replacing a grayscale image with specific color gradient from + * the CLUT image. + * + * @overload clut_channel(clut_image, channel = Magick::AllChannels) + * @param clut_image [Magick::Image] The LUT gradient image. + * @param channel [Magick::ChannelType] a ChannelType arguments. + * + * @overload clut_channel(clut_image, *channels) + * @param clut_image [Magick::Image] The LUT gradient image. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] self */ VALUE Image_clut_channel(int argc, VALUE *argv, VALUE self) { Image *image, *clut; @@ -2689,11 +2501,11 @@ image = rm_check_frozen(self); // check_destroyed before confirming the arguments if (argc >= 1) { - (void) rm_check_destroyed(argv[0]); + rm_check_destroyed(argv[0]); channels = extract_channels(&argc, argv); if (argc != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or more)", argc); } @@ -2708,12 +2520,12 @@ #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(image, channels); okay = ClutImage(image, clut, image->interpolate, exception); END_CHANNEL_MASK(image); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else okay = ClutImageChannel(image, channels, clut); rm_check_image_exception(image, RetainOnError); rm_check_image_exception(clut, RetainOnError); #endif @@ -2725,20 +2537,14 @@ return self; } /** - * Call GetImageHistogram. + * Computes the number of times each unique color appears in the image. * - * Ruby usage: - * - @verbatim Image_color_histogram(VALUE self); @endverbatim - * - * Notes: - * - returns hash @verbatim {aPixel=>count} @endverbatim - * - * @param self this object - * @return a histogram + * @return [Hash] Each key in the hash is a pixel representing a color that appears in the image. + * The value associated with the key is the number of times that color appears in the image. */ VALUE Image_color_histogram(VALUE self) { Image *image, *dc_copy = NULL; @@ -2758,33 +2564,33 @@ // If image not DirectClass make a DirectClass copy. if (image->storage_class != DirectClass) { dc_copy = rm_clone_image(image); #if defined(IMAGEMAGICK_7) - (void) SetImageStorageClass(dc_copy, DirectClass, exception); + SetImageStorageClass(dc_copy, DirectClass, exception); #else - (void) SetImageStorageClass(dc_copy, DirectClass); + SetImageStorageClass(dc_copy, DirectClass); #endif image = dc_copy; } histogram = GetImageHistogram(image, &colors, exception); if (histogram == NULL) { if (dc_copy) { - (void) DestroyImage(dc_copy); + DestroyImage(dc_copy); } rb_raise(rb_eNoMemError, "not enough memory to continue"); } if (rm_should_raise_exception(exception, DestroyExceptionRetention)) { - (void) RelinquishMagickMemory(histogram); + RelinquishMagickMemory(histogram); if (dc_copy) { - (void) DestroyImage(dc_copy); + DestroyImage(dc_copy); } rm_raise_exception(exception); } @@ -2794,22 +2600,22 @@ #if defined(IMAGEMAGICK_7) pixel = Pixel_from_PixelColor(&histogram[x]); #else pixel = Pixel_from_PixelColor(&histogram[x].pixel); #endif - (void) rb_hash_aset(hash, pixel, ULONG2NUM((unsigned long)histogram[x].count)); + rb_hash_aset(hash, pixel, ULONG2NUM((unsigned long)histogram[x].count)); } /* Christy evidently didn't agree with Bob's memory management. */ - (void) RelinquishMagickMemory(histogram); + RelinquishMagickMemory(histogram); if (dc_copy) { // Do not trace destruction - (void) DestroyImage(dc_copy); + DestroyImage(dc_copy); } RB_GC_GUARD(hash); RB_GC_GUARD(pixel); @@ -2820,11 +2626,11 @@ /** * Store all the profiles in the profile in the target image. Called from * Image_color_profile_eq and Image_iptc_profile_eq. * * No Ruby usage (internal function) - * + * * @param self this object * @param name profile name * @param profile an IPTC or ICC profile * @return self */ @@ -2844,42 +2650,41 @@ profile_blob = rm_str2cstr(profile, &profile_length); exception = AcquireExceptionInfo(); m = GetMagickInfo(name, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); if (!m) { - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rb_raise(rb_eArgError, "unknown name: %s", name); } info = CloneImageInfo(NULL); if (!info) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } - strncpy(info->magick, m->name, MaxTextExtent); - info->magick[MaxTextExtent-1] = '\0'; + strlcpy(info->magick, m->name, sizeof(info->magick)); profile_image = BlobToImage(info, profile_blob, (size_t)profile_length, exception); - (void) DestroyImageInfo(info); - CHECK_EXCEPTION() + DestroyImageInfo(info); + CHECK_EXCEPTION(); ResetImageProfileIterator(profile_image); profile_name = GetNextImageProfile(profile_image); while (profile_name) { /* Hack for versions of ImageMagick where the meta coder would change the iptc profile into an 8bim profile */ if (rm_strcasecmp("8bim", profile_name) == 0 && rm_strcasecmp("iptc", name) == 0) { #if defined(IMAGEMAGICK_7) - (void) ProfileImage(image, name, profile_blob, profile_length, exception); + ProfileImage(image, name, profile_blob, profile_length, exception); if (rm_should_raise_exception(exception, RetainExceptionRetention)) #else - (void) ProfileImage(image, name, profile_blob, profile_length, MagickFalse); + ProfileImage(image, name, profile_blob, profile_length, MagickFalse); if (rm_should_raise_exception(&image->exception, RetainExceptionRetention)) #endif { break; } @@ -2888,51 +2693,46 @@ { profile_data = GetImageProfile(profile_image, profile_name); if (profile_data) { #if defined(IMAGEMAGICK_7) - (void) ProfileImage(image, name, GetStringInfoDatum(profile_data), GetStringInfoLength(profile_data), exception); + ProfileImage(image, name, GetStringInfoDatum(profile_data), GetStringInfoLength(profile_data), exception); if (rm_should_raise_exception(exception, RetainExceptionRetention)) #else - (void) ProfileImage(image, name, GetStringInfoDatum(profile_data), GetStringInfoLength(profile_data), MagickFalse); + ProfileImage(image, name, GetStringInfoDatum(profile_data), GetStringInfoLength(profile_data), MagickFalse); if (rm_should_raise_exception(&image->exception, RetainExceptionRetention)) #endif { break; } } } profile_name = GetNextImageProfile(profile_image); } - (void) DestroyImage(profile_image); + DestroyImage(profile_image); #if defined(IMAGEMAGICK_7) - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_check_image_exception(image, RetainOnError); #endif return self; } /** * Return the ICC color profile as a String. * - * Ruby usage: - * - @verbatim Image#color_profile @endverbatim + * - If there is no profile, returns "" + * - This method has no real use but is retained for compatibility with earlier releases of RMagick, + * where it had no real use either. * - * Notes: - * - If there is no profile, returns "" - * - This method has no real use but is retained for compatibility with - * earlier releases of RMagick, where it had no real use either. - * - * @param self this object - * @return the ICC color profile + * @return [String, nil] the ICC color profile */ VALUE Image_color_profile(VALUE self) { Image *image; @@ -2951,56 +2751,42 @@ /** * Set the ICC color profile. * - * Ruby usage: - * - @verbatim Image#color_profile=(String) @endverbatim + * - Pass nil to remove any existing profile. + * - Removes any existing profile before adding the new one. * - * Notes: - * - Pass nil to remove any existing profile. - * - Removes any existing profile before adding the new one. - * - * @param self this object - * @param profile the profile to set, as a Ruby string - * @return profile + * @param profile [String] the profile to set + * @return [String] the given profile */ VALUE Image_color_profile_eq(VALUE self, VALUE profile) { - (void) Image_delete_profile(self, rb_str_new2("ICC")); + Image_delete_profile(self, rb_str_new2("ICC")); if (profile != Qnil) { - (void) set_profile(self, "ICC", profile); + set_profile(self, "ICC", profile); } return profile; } /** - * Change the color value of any pixel that matches target_color and is an - * immediate neighbor. + * Change the color value of any pixel that matches target_color and is an immediate neighbor. * - * Ruby usage: - * - @verbatim Image#color_flood_fill(target_color, fill_color, x, y, method) @endverbatim - * - * Notes: - * - Use fuzz= to specify the tolerance amount - * - Accepts either the FloodfillMethod or the FillToBorderMethod - * - * @param self this object - * @param target_color the color - * @param fill_color the color to fill - * @param xv the x position - * @param yv the y position - * @param method the method to call - * @return a new image - * @see Image_opaque + * @param target_color [Magick::Pixel, String] the target color + * @param fill_color [Magick::Pixel, String] the color to fill + * @param xv [Numeric] the x position + * @param yv [Numeric] the y position + * @param method [Magick::PaintMethod] the method to call + * @return [Magick::Image] a new image + * @see Image#opaque */ VALUE -Image_color_flood_fill( VALUE self, VALUE target_color, VALUE fill_color - , VALUE xv, VALUE yv, VALUE method) +Image_color_flood_fill(VALUE self, VALUE target_color, VALUE fill_color, + VALUE xv, VALUE yv, VALUE method) { Image *image, *new_image; PixelColor target; DrawInfo *draw_info; PixelColor fill; @@ -3021,12 +2807,12 @@ x = NUM2LONG(xv); y = NUM2LONG(yv); if ((unsigned long)x > image->columns || (unsigned long)y > image->rows) { - rb_raise(rb_eArgError, "target out of range. %lux%lu given, image is %lux%lu" - , x, y, image->columns, image->rows); + rb_raise(rb_eArgError, "target out of range. %lux%lu given, image is %"RMIuSIZE"x%"RMIuSIZE"", + x, y, image->columns, image->rows); } VALUE_TO_ENUM(method, fill_method, PaintMethod); if (!(fill_method == FloodfillMethod || fill_method == FillToBorderMethod)) { @@ -3059,37 +2845,43 @@ target_mpp.blue = (MagickRealType) target.blue; } #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) FloodfillPaintImage(new_image, draw_info, &target_mpp, x, y, invert, exception); - (void) DestroyDrawInfo(draw_info); + FloodfillPaintImage(new_image, draw_info, &target_mpp, x, y, invert, exception); + DestroyDrawInfo(draw_info); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &target_mpp, x, y, invert); + FloodfillPaintImage(new_image, DefaultChannels, draw_info, &target_mpp, x, y, invert); - (void) DestroyDrawInfo(draw_info); + DestroyDrawInfo(draw_info); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Blend the fill color specified by "target" with each pixel in the image. - * Specify the percentage blend for each r, g, b component. + * Blend the fill color specified by "target" with each pixel in the image. Specify the percentage + * blend for each r, g, b component. * - * Ruby usage: - * - @verbatim Image#colorize(r, g, b, target) @endverbatim - * - @verbatim Image#colorize(r, g, b, matte, target) @endverbatim + * @overload colorize(red, green, blue, target) + * @param red [Float] The percentage of the fill color red + * @param green [Float] The percentage of the fill color green + * @param blue [Float] The percentage of the fill color blue + * @param target [Magick::Pixel, String] the color name * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload colorize(red, green, blue, matte, target) + * @param red [Float] The percentage of the fill color red + * @param green [Float] The percentage of the fill color green + * @param blue [Float] The percentage of the fill color blue + * @param matte [Float] The percentage of the fill color transparency + * @param target [Magick::Pixel, String] the color name + * + * @return [Magick::Image] a new image */ VALUE Image_colorize(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -3104,20 +2896,20 @@ { red = floor(100*NUM2DBL(argv[0])+0.5); green = floor(100*NUM2DBL(argv[1])+0.5); blue = floor(100*NUM2DBL(argv[2])+0.5); Color_to_PixelColor(&target, argv[3]); - sprintf(opacity, "%f/%f/%f", red, green, blue); + snprintf(opacity, sizeof(opacity), "%f/%f/%f", red, green, blue); } else if (argc == 5) { red = floor(100*NUM2DBL(argv[0])+0.5); green = floor(100*NUM2DBL(argv[1])+0.5); blue = floor(100*NUM2DBL(argv[2])+0.5); matte = floor(100*NUM2DBL(argv[3])+0.5); Color_to_PixelColor(&target, argv[4]); - sprintf(opacity, "%f/%f/%f/%f", red, green, blue, matte); + snprintf(opacity, sizeof(opacity), "%f/%f/%f/%f", red, green, blue, matte); } else { rb_raise(rb_eArgError, "wrong number of arguments (%d for 4 or 5)", argc); } @@ -3127,34 +2919,32 @@ new_image = ColorizeImage(image, opacity, &target, exception); #else new_image = ColorizeImage(image, opacity, target, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Return the color in the colormap at the specified index. If a new color is - * specified, replaces the color at the index with the new color. + * Return the color in the colormap at the specified index. If a new color is specified, replaces + * the color at the index with the new color. * - * Ruby usage: - * - @verbatim Image#colormap(index) @endverbatim - * - @verbatim Image#colormap(index, new-color) @endverbatim + * @overload colormap(index) + * @param index [Numeric] A number between 0 and the number of colors in the color map. If the + * value is out of range, colormap raises an IndexError. You can get the number of colors in + * the color map from the colors attribute. * - * Notes: - * - The "new-color" argument can be either a color name or a Magick::Pixel. + * @overload colormap(index, new_color) + * @param index [Numeric] A number between 0 and the number of colors in the color map. If the + * value is out of range, colormap raises an IndexError. You can get the number of colors in + * the color map from the colors attribute. + * @param new_color [Magick::Pixel, String] the color name * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return the name of the color + * @return [String] the name of the color at the specified location in the color map */ VALUE Image_colormap(int argc, VALUE *argv, VALUE self) { Image *image; @@ -3230,31 +3020,26 @@ return rm_pixelcolor_to_color_name(image, &color); } /** - * Get image colors. + * Get the number of colors in the colormap. * - * Ruby usage: - * - @verbatim Image#colors @endverbatim - * - * @param self this object - * @return the colors + * @return [Numeric] the number of colors */ -DEF_ATTR_READER(Image, colors, ulong) +VALUE +Image_colors(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, colors, ulong); +} /** - * Return the Image pixel interpretation. If the colorspace is RGB the pixels - * are red, green, blue. If matte is true, then red, green, blue, and index. If - * it is CMYK, the pixels are cyan, yellow, magenta, black. Otherwise the - * colorspace is ignored. + * Return the Image pixel interpretation. If the colorspace is RGB the pixels are red, green, + * blue. If matte is true, then red, green, blue, and index. If it is CMYK, the pixels are cyan, + * yellow, magenta, black. Otherwise the colorspace is ignored. * - * Ruby usage: - * - @verbatim Image#colorspace @endverbatim - * - * @param self this object - * @return the colorspace + * @return [Magick::ColorspaceType] the colorspace */ VALUE Image_colorspace(VALUE self) { Image *image; @@ -3265,17 +3050,12 @@ /** * Set the image's colorspace. * - * Ruby usage: - * - @verbatim Image#colorspace=Magick::ColorspaceType @endverbatim - * - * @param self this object - * @param colorspace the colorspace - * @return colorspace - * @see Magick::colorSpace in Magick++'s Magick::colorSpace + * @param colorspace [Magick::ColorspaceType] the colorspace + * @return [Magick::ColorspaceType] the given colorspace */ VALUE Image_colorspace_eq(VALUE self, VALUE colorspace) { Image *image; @@ -3287,59 +3067,80 @@ image = rm_check_frozen(self); VALUE_TO_ENUM(colorspace, new_cs, ColorspaceType); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) TransformImageColorspace(image, new_cs, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + TransformImageColorspace(image, new_cs, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) TransformImageColorspace(image, new_cs); + TransformImageColorspace(image, new_cs); rm_check_image_exception(image, RetainOnError); #endif return colorspace; } /** * Get image columns. * - * Ruby usage: - * - @verbatim Image#columns @endverbatim - * - * @param self this object - * @return the columns + * @return [Numeric] the columns */ -DEF_ATTR_READER(Image, columns, int) +VALUE +Image_columns(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, columns, int); +} /** - * Compare one or more channels in two images and returns the specified - * distortion metric and a comparison image. + * Compare one or more channels in two images and returns the specified distortion metric and a + * comparison image. * - * Ruby usage: - * - @verbatim Image#compare_channel(ref_image, metric) { optional arguments } @endverbatim - * - @verbatim Image#compare_channel(ref_image, metric, channel) { optional arguments } @endverbatim - * - @verbatim Image#compare_channel(ref_image, metric, channel, ...) { optional arguments } @endverbatim + * @overload compare_channel(image, metric, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param metric [Magick::MetricType] The desired distortion metric. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - If no channels are specified, the default is AllChannels. That case is - * the equivalent of the CompareImages method in ImageMagick. - * - Originally this method was called channel_compare, but that doesn't match - * the general naming convention that methods which accept multiple optional - * ChannelType arguments have names that end in _channel. So I renamed the - * method to compare_channel but kept channel_compare as an alias. - * - The optional arguments are specified thusly: - * - self.highlight_color color - * - self.lowlight-color color - * where color is either a color name or a Pixel. + * @overload compare_channel(image, metric, channel = Magick::AllChannels) + * If present a block, compare_channel yields to a block in which you can set optional arguments + * by setting attributes on self. + * - self.highlight_color = color + * - Emphasize pixel differences with this color. The default is partially transparent red. + * - self.lowlight_color = color + * - Demphasize pixel differences with this color. The default is partially transparent white. + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param metric [Magick::MetricType] The desired distortion metric. + * @param channel [Magick::ChannelType] a ChannelType arguments. + * @yield [] * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return an array of [difference_image,distortion] + * @overload compare_channel(image, metric, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param metric [Magick::MetricType] The desired distortion metric. + * @param channel [Magick::ChannelType] a ChannelType arguments. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @overload compare_channel(image, metric, *channels) + * If present a block, compare_channel yields to a block in which you can set optional arguments + * by setting attributes on self. + * - self.highlight_color = color + * - Emphasize pixel differences with this color. The default is partially transparent red. + * - self.lowlight_color = color + * - Demphasize pixel differences with this color. The default is partially transparent white. + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param metric [Magick::MetricType] The desired distortion metric. + * @param channel [Magick::ChannelType] a ChannelType arguments. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * @yield [] + * + * @return [Array] The first element is a difference image, the second is a the value of the + * computed distortion represented as a Float. */ VALUE Image_compare_channel(int argc, VALUE *argv, VALUE self) { Image *image, *r_image, *difference_image; @@ -3376,15 +3177,12 @@ END_CHANNEL_MASK(image); #else difference_image = CompareImageChannels(image, r_image, channels, metric_type, &distortion, exception); #endif rm_check_exception(exception, difference_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(difference_image); - ary = rb_ary_new2(2); rb_ary_store(ary, 0, rm_image_new(difference_image)); rb_ary_store(ary, 1, rb_float_new(distortion)); RB_GC_GUARD(ary); @@ -3395,15 +3193,11 @@ /** * Return the composite operator attribute. * - * Ruby usage: - * - @verbatim Image#compose @endverbatim - * - * @param self this object - * @return the composite operator + * @return [Magick::CompositeOperator] the composite operator */ VALUE Image_compose(VALUE self) { Image *image = rm_check_destroyed(self); @@ -3412,16 +3206,12 @@ /** * Set the composite operator attribute. * - * Ruby usage: - * - @verbatim Image#compose=composite_op @endverbatim - * - * @param self this object - * @param compose_arg the composite operator - * @return compose_arg + * @param compose_arg [Magick::CompositeOperator] the composite operator + * @return [Magick::CompositeOperator] the given value */ VALUE Image_compose_eq(VALUE self, VALUE compose_arg) { Image *image = rm_check_frozen(self); @@ -3443,11 +3233,11 @@ * * @param bang whether the bang (!) version of the method was called * @param argc number of input arguments * @param argv array of input arguments * @param self this object - * @param channels + * @param channels * @return self if bang, otherwise new composited image * @see Image_composite * @see Image_composite_bang */ static VALUE @@ -3582,16 +3372,16 @@ if (bang) { #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(image, channels); - (void) CompositeImage(image, comp_image, operator, MagickTrue, x_offset, y_offset, exception); + CompositeImage(image, comp_image, operator, MagickTrue, x_offset, y_offset, exception); END_CHANNEL_MASK(image); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) CompositeImageChannel(image, channels, operator, comp_image, x_offset, y_offset); + CompositeImageChannel(image, channels, operator, comp_image, x_offset, y_offset); rm_check_image_exception(image, RetainOnError); #endif return self; } @@ -3600,79 +3390,111 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) CompositeImage(new_image, comp_image, operator, MagickTrue, x_offset, y_offset, exception); + CompositeImage(new_image, comp_image, operator, MagickTrue, x_offset, y_offset, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) CompositeImageChannel(new_image, channels, operator, comp_image, x_offset, y_offset); + CompositeImageChannel(new_image, channels, operator, comp_image, x_offset, y_offset); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } } /** - * Call CompositeImage. + * Composites src onto dest using the specified composite operator. + * In-place form of {Magick::Image#composite}. * - * Ruby usage: - * - @verbatim Image#composite!(image, x_off, y_off, composite_op) @endverbatim - * - @verbatim Image#composite!(image, gravity, composite_op) @endverbatim - * - @verbatim Image#composite!(image, gravity, x_off, y_off, composite_op) @endverbatim + * @overload composite!(image, x_off, y_off, composite_op) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see composite - * @see Image_composite + * @overload composite!(image, gravity, composite_op) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * + * @overload composite!(image, gravity, x_off, y_off, composite_op) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator. + * + * @return [Magick::Image] a new image + * @see Image#composite */ VALUE Image_composite_bang(int argc, VALUE *argv, VALUE self) { return composite(True, argc, argv, self, DefaultChannels); } /** - * Call CompositeImage. + * Composites src onto dest using the specified composite operator. * - * Ruby usage: - * - @verbatim Image#composite(image, x_off, y_off, composite_op) @endverbatim - * - @verbatim Image#composite(image, gravity, composite_op) @endverbatim - * - @verbatim Image#composite(image, gravity, x_off, y_off, composite_op) @endverbatim + * @overload composite(image, x_off, y_off, composite_op) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see composite - * @see Image_composite_bang + * @overload composite(image, gravity, composite_op) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * + * @overload composite(image, gravity, x_off, y_off, composite_op) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator. + * + * @return [Magick::Image] a new image + * @see Image#composite! */ VALUE Image_composite(int argc, VALUE *argv, VALUE self) { return composite(False, argc, argv, self, DefaultChannels); } /** - * Composite the source over the destination image as dictated by the affine - * transform. + * Composite the source over the destination image as dictated by the affine transform. * - * Ruby usage: - * - @verbatim Image#composite_affine(composite, affine_matrix) @endverbatim - * - * @param self this object - * @param source the source image - * @param affine_matrix affine transform matrix - * @return a new image + * @param source [Magick::Image] the source image + * @param affine_matrix [Magick::AffineMatrix] affine transform matrix + * @return [Magick::Image] a new image */ VALUE Image_composite_affine(VALUE self, VALUE source, VALUE affine_matrix) { Image *image, *composite_image, *new_image; @@ -3687,15 +3509,15 @@ Export_AffineMatrix(&affine, affine_matrix); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) DrawAffineImage(new_image, composite_image, &affine, exception); + DrawAffineImage(new_image, composite_image, &affine, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) DrawAffineImage(new_image, composite_image, &affine); + DrawAffineImage(new_image, composite_image, &affine); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } @@ -3721,11 +3543,11 @@ composite_channel(int bang, int argc, VALUE *argv, VALUE self) { ChannelType channels; // Check destroyed before validating the arguments - (void) rm_check_destroyed(self); + rm_check_destroyed(self); channels = extract_channels(&argc, argv); // There must be 3, 4, or 5 remaining arguments. if (argc < 3) { @@ -3739,70 +3561,197 @@ return composite(bang, argc, argv, self, channels); } /** - * Call CompositeImageChannel. + * Composite the source over the destination image channel as dictated by the affine transform. * - * Ruby usage: - * - @verbatim Image#composite_channel(src_image, geometry, composite_operator) @endverbatim - * - @verbatim Image#composite_channel(src_image, geometry, composite_operator, channel) @endverbatim - * - @verbatim Image#composite_channel(src_image, geometry, composite_operator, channel, ...) @endverbatim + * @overload composite_channel(image, x_off, y_off, composite_op, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see composite_channel - * @see Image_composite_channel_bang + * @overload composite_channel(image, x_off, y_off, composite_op, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @overload composite_channel(image, gravity, composite_op, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. + * + * @overload composite_channel(image, gravity, composite_op, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @overload composite_channel(image, gravity, x_off, y_off, composite_op, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. + * + * @overload composite_channel(image, gravity, x_off, y_off, composite_op, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image + * @see Image#composite */ VALUE Image_composite_channel(int argc, VALUE *argv, VALUE self) { return composite_channel(False, argc, argv, self); } /** - * Call CompositeImageChannel. + * Composite the source over the destination image channel as dictated by the affine transform. + * In-place form of {Image#composite_channel}. * - * Ruby usage: - * - @verbatim Image#composite_channel!(src_image, geometry, composite_operator) @endverbatim - * - @verbatim Image#composite_channel!(src_image, geometry, composite_operator, channel) @endverbatim - * - @verbatim Image#composite_channel!(src_image, geometry, composite_operator, channel, ...) @endverbatim + * @overload composite_channel!(image, x_off, y_off, composite_op, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see composite_channel - * @see Image_composite_channel + * @overload composite_channel!(image, x_off, y_off, composite_op, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @overload composite_channel!(image, gravity, composite_op, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. + * + * @overload composite_channel!(image, gravity, composite_op, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @overload composite_channel!(image, gravity, x_off, y_off, composite_op, channel = Magick::AllChannels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. + * + * @overload composite_channel!(image, gravity, x_off, y_off, composite_op, *channels) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param gravity [Magick::GravityType] A GravityType value that specifies the location of img on + * image. + * @param x_off [Numeric] the x-offset of the composited image, measured from the upper-left + * corner of the image. + * @param y_off [Numeric] the y-offset of the composited image, measured from the upper-left + * corner of the image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image + * @see Image#composite_channel + * @see Image#composite! */ VALUE Image_composite_channel_bang(int argc, VALUE *argv, VALUE self) { return composite_channel(True, argc, argv, self); } /** - * Composite using MathematicsCompositeOp. + * Merge the source and destination images according to the formula + * a*Sc*Dc + b*Sc + c*Dc + d + * where Sc is the source pixel and Dc is the destination pixel. * - * Ruby usage: - * - @verbatim img.composite_mathematics(comp_img, A, B, C, D, gravity) @endverbatim - * - @verbatim img.composite_mathematics(comp_img, A, B, C, D, x_off, y_off) @endverbatim - * - @verbatim img.composite_mathematics(comp_img, A, B, C, D, gravity, x_off, y_off) @endverbatim + * @overload composite_mathematics(image, a, b, c, d, gravity) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param a [Float] See the description. + * @param b [Float] See the description. + * @param c [Float] See the description. + * @param d [Float] See the description. + * @param gravity [Magick::GravityType] the gravity type * - * Notes: - * - Default x_off is 0 - * - Default y_off is 0 - * - New in ImageMagick 6.5.4-3. + * @overload composite_mathematics(image, a, b, c, d, x_off, y_off) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param a [Float] See the description. + * @param b [Float] See the description. + * @param c [Float] See the description. + * @param d [Float] See the description. + * @param x_off [Numeric] The x-offset of the composited image, measured relative to the gravity + * argument. + * @param y_off [Numeric] The y-offset of the composited image, measured relative to the gravity + * argument. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload composite_mathematics(image, a, b, c, d, gravity, x_off, y_off) + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param a [Float] See the description. + * @param b [Float] See the description. + * @param c [Float] See the description. + * @param d [Float] See the description. + * @param gravity [Magick::GravityType] the gravity type + * @param x_off [Numeric] The x-offset of the composited image, measured relative to the gravity + * argument. + * @param y_off [Numeric] The y-offset of the composited image, measured relative to the gravity + * argument. + * + * @return [Magick::Image] a new image */ VALUE Image_composite_mathematics(int argc, VALUE *argv, VALUE self) { Image *composite_image; @@ -3811,14 +3760,10 @@ signed long y_off = 0L; GravityType gravity = NorthWestGravity; char compose_args[200]; rm_check_destroyed(self); - if (argc > 0) - { - composite_image = rm_check_destroyed(rm_cur_image(argv[0])); - } switch (argc) { case 8: VALUE_TO_ENUM(argv[5], gravity, GravityType); @@ -3835,13 +3780,14 @@ default: rb_raise(rb_eArgError, "wrong number of arguments (got %d, expected 6 to 8)", argc); break; } + composite_image = rm_check_destroyed(rm_cur_image(argv[0])); - (void) sprintf(compose_args, "%-.16g,%-.16g,%-.16g,%-.16g", NUM2DBL(argv[1]), NUM2DBL(argv[2]), NUM2DBL(argv[3]), NUM2DBL(argv[4])); - SetImageArtifact(composite_image,"compose:args", compose_args); + snprintf(compose_args, sizeof(compose_args), "%-.16g,%-.16g,%-.16g,%-.16g", NUM2DBL(argv[1]), NUM2DBL(argv[2]), NUM2DBL(argv[3]), NUM2DBL(argv[4])); + SetImageArtifact(composite_image, "compose:args", compose_args); // Call composite(False, gravity, x_off, y_off, MathematicsCompositeOp, DefaultChannels) args[0] = argv[0]; args[1] = GravityType_find(gravity); args[2] = LONG2FIX(x_off); @@ -3892,15 +3838,10 @@ else { image = rm_check_destroyed(self); } - if (argc > 0) - { - comp_image = rm_check_destroyed(rm_cur_image(argv[0])); - } - channels = extract_channels(&argc, argv); switch (argc) { case 2: @@ -3913,16 +3854,18 @@ default: raise_ChannelType_error(argv[argc-1]); break; } + comp_image = rm_check_destroyed(rm_cur_image(argv[0])); + if (!bang) { image = rm_clone_image(image); } - (void) SetImageArtifact(comp_image,"modify-outside-overlay", "false"); + SetImageArtifact(comp_image, "modify-outside-overlay", "false"); status = MagickTrue; columns = comp_image->columns; #if defined(IMAGEMAGICK_7) @@ -3945,108 +3888,102 @@ #endif } } #if defined(IMAGEMAGICK_7) - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif return bang ? self : rm_image_new(image); } /** - * Emulate the -tile option to the composite command. + * Composites multiple copies of the source image across and down the image, + * producing the same results as ImageMagick's composite command with the -tile option. * - * Ruby usage: - * - @verbatim Image#composite_tiled(src) @endverbatim - * - @verbatim Image#composite_tiled(src, composite_op) @endverbatim - * - @verbatim Image#composite_tiled(src, composite_op, channel) @endverbatim - * - @verbatim Image#composite_tiled(src, composite_op, channel, ...) @endverbatim + * @overload composite_tiled(src, composite_op = Magick::OverCompositeOp, channel = Magick::AllChannels) + * @param src [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see composite_tiled - * @see Image_composite_tiled_bang + * @overload composite_tiled(src, composite_op = Magick::OverCompositeOp, *channels) + * @param src [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image + * @see Image#composite_tiled! */ VALUE Image_composite_tiled(int argc, VALUE *argv, VALUE self) { return composite_tiled(False, argc, argv, self); } /** - * Emulate the -tile option to the composite command. + * Composites multiple copies of the source image across and down the image, producing the same + * results as ImageMagick's composite command with the -tile option. + * In-place form of {Magick::Image#composite_tiled}. * - * Ruby usage: - * - @verbatim Image#composite_tiled!(src) @endverbatim - * - @verbatim Image#composite_tiled!(src, composite_op) @endverbatim - * - @verbatim Image#composite_tiled!(src, composite_op, channel) @endverbatim - * - @verbatim Image#composite_tiled!(src, composite_op, channel, ...) @endverbatim + * @overload composite_tiled!(src, composite_op = Magick::OverCompositeOp, channel = Magick::AllChannels) + * @param src [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see composite_tiled - * @see Image_composite_tiled_bang + * @overload composite_tiled!(src, composite_op = Magick::OverCompositeOp, *channels) + * @param src [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param composite_op [Magick::CompositeOperator] the composite operator + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image + * @see Image#composite_tiled */ VALUE Image_composite_tiled_bang(int argc, VALUE *argv, VALUE self) { return composite_tiled(True, argc, argv, self); } /** - * Get/set the compression attribute. + * Get the compression attribute. * - * Ruby usage: - * - @verbatim Image#compression @endverbatim - * - * @param self this object - * @return the compression + * @return [Magick::CompressionType] the compression */ VALUE Image_compression(VALUE self) { Image *image = rm_check_destroyed(self); return CompressionType_find(image->compression); } /** - * Get/set the compression attribute. + * Set the compression attribute. * - * Ruby usage: - * - @verbatim Image#compression= @endverbatim - * - * @param self this object - * @param compression the compression - * @return compression + * @param compression [Magick::CompressionType] the compression + * @return [Magick::CompressionType] the given compression */ VALUE Image_compression_eq(VALUE self, VALUE compression) { Image *image = rm_check_frozen(self); VALUE_TO_ENUM(compression, image->compression, CompressionType); return compression; } /** - * call CompressImageColormap. + * Removes duplicate or unused entries in the colormap. + * Only PseudoClass images have a colormap. + * If the image is DirectClass then compress_colormap! converts it to PseudoClass. * - * Ruby usage: - * - @verbatim Image#compress_colormap! @endverbatim - * - * Notes: - * - API was CompressColormap until 5.4.9 - * - * @param self this object - * @return self + * @return [Magick::Image] self */ VALUE Image_compress_colormap_bang(VALUE self) { Image *image; @@ -4058,12 +3995,12 @@ image = rm_check_frozen(self); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); okay = CompressImageColormap(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else okay = CompressImageColormap(image); rm_check_image_exception(image, RetainOnError); #endif if (!okay) @@ -4073,43 +4010,38 @@ return self; } /** - * Creates an Image from the supplied pixel data. The pixel data must be in - * scanline order, top-to-bottom. The pixel data is an array of either all Fixed - * or all Float elements. If Fixed, the elements must be in the range - * [0..QuantumRange]. If Float, the elements must be normalized [0..1]. The - * "map" argument reflects the expected ordering of the pixel array. It can be - * any combination or order of R = red, G = green, B = blue, A = alpha, - * C = cyan, Y = yellow, M = magenta, K = black, or I = intensity (for - * grayscale). + * Creates an Image from the supplied pixel data. The pixel data must be in scanline order, + * top-to-bottom. The pixel data is an array of either all Fixed or all Float elements. If Fixed, + * the elements must be in the range [0..QuantumRange]. If Float, the elements must be normalized + * [0..1]. The "map" argument reflects the expected ordering of the pixel array. It can be any + * combination or order of R = red, G = green, B = blue, A = alpha, C = cyan, Y = yellow, M = + * magenta, K = black, or I = intensity (for grayscale). * * The pixel array must have width X height X strlen(map) elements. * - * Ruby usage: - * - @verbatim Image.constitute(width, height, map, pixels) @endverbatim - * - * @param class the Ruby class for an Image (unused) - * @param width_arg the width of the array - * @param height_arg the height of the array - * @param map_arg the map (expected ordering of the pixel array) - * @param pixels_arg the pixel array - * @return a new image - * @throw ArgumentError - * @throw TypeError + * @param width_arg [Numeric] The number of columns in the image + * @param height_arg [Numeric] The number of rows in the image + * @param map_arg [String] A string describing the expected ordering of the pixel array. + * It can be any combination or order of R = red, G = green, B = blue, A = alpha, C = cyan, Y = + * yellow, M = magenta, K = black, or I = intensity (for grayscale). + * @param pixels_arg [Array<Magick::Pixel>] The pixel data in the array must be stored in scanline order, + * left-to-right and top-to-bottom. The elements in the array must be either all Integers or all + * Floats. If the elements are Integers, the Integers must be in the range [0..QuantumRange]. If + * the elements are Floats, they must be in the range [0..1]. + * @return [Magick::Image] a new image */ VALUE -Image_constitute(VALUE class ATTRIBUTE_UNUSED, VALUE width_arg, VALUE height_arg - , VALUE map_arg, VALUE pixels_arg) +Image_constitute(VALUE class ATTRIBUTE_UNUSED, VALUE width_arg, VALUE height_arg, + VALUE map_arg, VALUE pixels_arg) { Image *new_image; VALUE pixel, pixel0; - unsigned long width, height; - long x, npixels; + long width, height, x, npixels, map_l; char *map; - long map_l; volatile union { double *f; Quantum *i; void *v; @@ -4120,25 +4052,25 @@ // rb_Array converts objects that are not Arrays to Arrays if possible, // and raises TypeError if it can't. pixels_arg = rb_Array(pixels_arg); - width = NUM2ULONG(width_arg); - height = NUM2ULONG(height_arg); + width = NUM2LONG(width_arg); + height = NUM2LONG(height_arg); - if (width == 0 || height == 0) + if (width <= 0 || height <= 0) { - rb_raise(rb_eArgError, "width and height must be non-zero"); + rb_raise(rb_eArgError, "width and height must be greater than zero"); } map = rm_str2cstr(map_arg, &map_l); - npixels = (long)(width * height * map_l); + npixels = width * height * map_l; if (RARRAY_LEN(pixels_arg) != npixels) { - rb_raise(rb_eArgError, "wrong number of array elements (%ld for %ld)" - , RARRAY_LEN(pixels_arg), npixels); + rb_raise(rb_eArgError, "wrong number of array elements (%ld for %ld)", + RARRAY_LEN(pixels_arg), npixels); } // Inspect the first element in the pixels array to determine the expected // type of all the elements. Allocate the pixel buffer. pixel0 = rb_ary_entry(pixels_arg, 0); @@ -4154,12 +4086,12 @@ stg_type = QuantumPixel; pixel_class = rb_cInteger; } else { - rb_raise(rb_eTypeError, "element 0 in pixel array is %s, must be numeric" - , rb_class2name(CLASS_OF(pixel0))); + rb_raise(rb_eTypeError, "element 0 in pixel array is %s, must be numeric", + rb_class2name(CLASS_OF(pixel0))); } // Convert the array elements to the appropriate C type, store in pixel @@ -4168,12 +4100,12 @@ { pixel = rb_ary_entry(pixels_arg, x); if (rb_obj_is_kind_of(pixel, pixel_class) != Qtrue) { xfree(pixels.v); - rb_raise(rb_eTypeError, "element %ld in pixel array is %s, expected %s" - , x, rb_class2name(CLASS_OF(pixel)),rb_class2name(CLASS_OF(pixel0))); + rb_raise(rb_eTypeError, "element %ld in pixel array is %s, expected %s", + x, rb_class2name(CLASS_OF(pixel)), rb_class2name(CLASS_OF(pixel0))); } if (pixel_class == rb_cFloat) { pixels.f[x] = (float) NUM2DBL(pixel); if (pixels.f[x] < 0.0 || pixels.f[x] > 1.0) @@ -4206,42 +4138,42 @@ if (rm_should_raise_exception(exception, RetainExceptionRetention)) { xfree(pixels.v); #if defined(IMAGEMAGICK_7) - (void) DestroyImage(new_image); + DestroyImage(new_image); rm_raise_exception(exception); #else rm_check_image_exception(new_image, DestroyOnError); #endif } #if defined(IMAGEMAGICK_7) - (void) SetImageBackgroundColor(new_image, exception); + SetImageBackgroundColor(new_image, exception); #else - (void) SetImageBackgroundColor(new_image); + SetImageBackgroundColor(new_image); exception = &new_image->exception; #endif if (rm_should_raise_exception(exception, RetainExceptionRetention)) { xfree(pixels.v); #if defined(IMAGEMAGICK_7) - (void) DestroyImage(new_image); + DestroyImage(new_image); rm_raise_exception(exception); #else rm_check_image_exception(new_image, DestroyOnError); #endif } #if defined(IMAGEMAGICK_7) - (void) ImportImagePixels(new_image, 0, 0, width, height, map, stg_type, (const void *)pixels.v, exception); + ImportImagePixels(new_image, 0, 0, width, height, map, stg_type, (const void *)pixels.v, exception); xfree(pixels.v); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) ImportImagePixels(new_image, 0, 0, width, height, map, stg_type, (const void *)pixels.v); + ImportImagePixels(new_image, 0, 0, width, height, map, stg_type, (const void *)pixels.v); xfree(pixels.v); rm_check_image_exception(new_image, DestroyOnError); #endif RB_GC_GUARD(pixel); @@ -4250,25 +4182,16 @@ return rm_image_new(new_image); } /** - * Enhance the intensity differences between the lighter and darker elements of - * the image. Set sharpen to "true" to increase the image contrast otherwise the - * contrast is reduced. + * Enhance the intensity differences between the lighter and darker elements of the image. * - * Ruby usage: - * - @verbatim Image#contrast @endverbatim - * - @verbatim Image#contrast(sharpen) @endverbatim - * - * Notes: - * - Default sharpen is 0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload contrast(sharpen = false) + * @param sharpen [Boolean] If sharpen is true, the contrast is increased, otherwise it is + * reduced. + * @return [Magick::Image] a new image */ VALUE Image_contrast(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -4289,15 +4212,15 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) ContrastImage(new_image, sharpen, exception); + ContrastImage(new_image, sharpen, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) ContrastImage(new_image, sharpen); + ContrastImage(new_image, sharpen); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } @@ -4366,28 +4289,32 @@ return; } /** - * Call ContrastStretchImageChannel. + * This method is a simple image enhancement technique that attempts to improve the contrast in an + * image by `stretching' the range of intensity values it contains to span a desired range of + * values. It differs from the more sophisticated histogram equalization in that it can only apply + * a linear scaling function to the image pixel values. * - * Ruby usage: - * - @verbatim Image#contrast_stretch_channel(black_point) @endverbatim - * - @verbatim Image#contrast_stretch_channel(black_point, white_point) @endverbatim - * - @verbatim Image#contrast_stretch_channel(black_point, white_point, channel) @endverbatim - * - @verbatim Image#contrast_stretch_channel(black_point, white_point, channel, ...) @endverbatim + * @overload contrast_stretch_channel(black_point, white_point = pixels - black_point, channel = Magick::AllChannels) + * @param black_point [Float, String] black out at most this many pixels. Specify an absolute + * number of pixels as a numeric value, or a percentage as a string in the form 'NN%'. + * @param white_point [Float, String] burn at most this many pixels. Specify an absolute number + * of pixels as a numeric value, or a percentage as a string in the form 'NN%'. This argument + * is optional. If not specified the default is `(columns * rows) - black_point`. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default white_point is pixels-black_point - * - Default channel is AllChannels - * - Both black_point and white_point can be specified as Floats or as - * percentages, i.e. "10%" + * @overload contrast_stretch_channel(black_point, white_point = pixels - black_point, *channels) + * @param black_point [Float, String] black out at most this many pixels. Specify an absolute + * number of pixels as a numeric value, or a percentage as a string in the form 'NN%'. + * @param white_point [Float, String] burn at most this many pixels. Specify an absolute number of + * pixels as a numeric value, or a percentage as a string in the form 'NN%'. This argument is + * optional. If not specified the default is all pixels - black_point pixels. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_contrast_stretch_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -4409,34 +4336,32 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) ContrastStretchImage(new_image, black_point, white_point, exception); + ContrastStretchImage(new_image, black_point, white_point, exception); END_CHANNEL_MASK(new_image); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) ContrastStretchImageChannel(new_image, channels, black_point, white_point); + ContrastStretchImageChannel(new_image, channels, black_point, white_point); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } -/** Apply a user supplied kernel to the image according to the given mophology method. +/** + * Apply a user supplied kernel to the image according to the given mophology method. * - * Ruby Usage: - * - @verbatim Image#morphology(method, iterations, kernel) @endverbatim - * - * @param self this object - * @param method is one of morphology methods defined by Magick::MorphologyMethod - * @param iterations apply the operation this many times (or no change). - * A value of -1 means loop until no change found. - * How this is applied may depend on the morphology method. - * Typically this is a value of 1. - * @param kernel morphology kernel to apply + * @param method_v [Magick::MorphologyMethod] the morphology method + * @param iterations [Numeric] apply the operation this many times (or no change). + * A value of -1 means loop until no change found. + * How this is applied may depend on the morphology method. + * Typically this is a value of 1. + * @param kernel_v [Magick::KernelInfo] morphology kernel to apply + * @return [Magick::Image] a new image */ VALUE Image_morphology(VALUE self, VALUE method_v, VALUE iterations, VALUE kernel_v) { @@ -4448,23 +4373,21 @@ } return Image_morphology_channel(self, default_channels_const, method_v, iterations, kernel_v); } -/** Apply a user supplied kernel to the image channel according to the given mophology method. +/** + * Apply a user supplied kernel to the image channel according to the given mophology method. * - * Ruby Usage: - * - @verbatim Image#morphology_channel(channel, method, iterations, kernel) @endverbatim - * - * @param self this object - * @param channel is a channel type defined by Magick::ChannelType - * @param method is one of morphology methods defined by Magick::MorphologyMethod - * @param iterations apply the operation this many times (or no change). - * A value of -1 means loop until no change found. - * How this is applied may depend on the morphology method. - * Typically this is a value of 1. - * @param kernel morphology kernel to apply + * @param channel_v [Magick::ChannelType] a channel type + * @param method_v [Magick::MorphologyMethod] the morphology method + * @param iterations [Numeric] apply the operation this many times (or no change). + * A value of -1 means loop until no change found. + * How this is applied may depend on the morphology method. + * Typically this is a value of 1. + * @param kernel_v [Magick::KernelInfo] morphology kernel to apply + * @return [Magick::Image] a new image */ VALUE Image_morphology_channel(VALUE self, VALUE channel_v, VALUE method_v, VALUE iterations, VALUE kernel_v) { @@ -4501,13 +4424,12 @@ END_CHANNEL_MASK(image); #else new_image = MorphologyImageChannel(image, channel, method, NUM2LONG(iterations), kernel, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); return rm_image_new(new_image); } #if defined(IMAGEMAGICK_7) // TODO: Move this to KernelInfo class as a constructor? @@ -4518,12 +4440,12 @@ KernelInfo *kernel; ExceptionInfo *exception; exception = AcquireExceptionInfo(); kernel = AcquireKernelInfo((const char *) NULL, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); if (!kernel) { rb_raise(rb_eNoMemError, "not enough memory to initialize KernelInfo"); } @@ -4532,11 +4454,11 @@ kernel->x = (ssize_t)(order - 1) / 2; kernel->y = (ssize_t)(order - 1) / 2; kernel->values = (MagickRealType *) AcquireAlignedMemory(order, order*sizeof(*kernel->values)); if (!kernel->values) { - (void) DestroyKernelInfo(kernel); + DestroyKernelInfo(kernel); rb_raise(rb_eNoMemError, "not enough memory to initialize KernelInfo values"); } for (x = 0; x < order*order; x++) { @@ -4545,11 +4467,11 @@ { kernel->values[x] = NUM2DBL(element); } else { - (void) DestroyKernelInfo(kernel); + DestroyKernelInfo(kernel); rb_raise(rb_eTypeError, "type mismatch: %s given", rb_class2name(CLASS_OF(element))); } } return kernel; @@ -4557,17 +4479,13 @@ #endif /** * Apply a custom convolution kernel to the image. * - * Ruby usage: - * - @verbatim Image#convolve(order, kernel) @endverbatim - * - * @param self this object - * @param order_arg the number of rows and columns in the kernel - * @param kernel_arg an order**2 array of doubles - * @return a new image + * @param order_arg [Numeric] the number of rows and columns in the kernel + * @param kernel_arg [Array<Float>] An `order*order` matrix of {Float} values. + * @return [Magick::Image] a new image */ VALUE Image_convolve(VALUE self, VALUE order_arg, VALUE kernel_arg) { Image *image, *new_image; @@ -4596,11 +4514,11 @@ kernel = convolve_create_kernel_info(order, kernel_arg); #else // Convert the kernel array argument to an array of doubles kernel = (double *)ALLOC_N(double, order*order); - for (x = 0; x < order*order; x++) + for (x = 0; x < (unsigned)(order * order); x++) { VALUE element = rb_ary_entry(kernel_arg, (long)x); if (rm_check_num2dbl(element)) { kernel[x] = NUM2DBL(element); @@ -4622,31 +4540,30 @@ new_image = ConvolveImage(image, order, kernel, exception); xfree((void *)kernel); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * call ConvolveImageChannel. + * Applies a custom convolution kernel to the specified channel or channels in the image. * - * Ruby usage: - * - @verbatim Image#convolve_channel(order, kernel) @endverbatim - * - @verbatim Image#convolve_channel(order, kernel, channel) @endverbatim - * - @verbatim Image#convolve_channel(order, kernel, channel, ...) @endverbatim + * @overload convolve_channel(order, kernel, channel = Magick::AllChannels) + * @param order_arg [Numeric] the number of rows and columns in the kernel + * @param kernel_arg [Array<Float>] An `order*order` matrix of {Float} values. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload convolve_channel(order, kernel, *channels) + * @param order_arg [Numeric] the number of rows and columns in the kernel + * @param kernel_arg [Array<Float>] An `order*order` matrix of {Float} values. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image */ VALUE Image_convolve_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -4679,21 +4596,20 @@ if (order <= 0) { rb_raise(rb_eArgError, "order must be non-zero and positive"); } - ary = argv[1]; - + ary = rb_Array(argv[1]); rm_check_ary_len(ary, (long)(order*order)); #if defined(IMAGEMAGICK_7) kernel = convolve_create_kernel_info(order, ary); #else kernel = ALLOC_N(double, (long)(order*order)); // Convert the kernel array argument to an array of doubles - for (x = 0; x < order*order; x++) + for (x = 0; x < (unsigned)(order * order); x++) { VALUE element = rb_ary_entry(ary, (long)x); if (rm_check_num2dbl(element)) { kernel[x] = NUM2DBL(element); @@ -4711,57 +4627,45 @@ #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); new_image = ConvolveImage(image, kernel, exception); CHANGE_RESULT_CHANNEL_MASK(new_image); END_CHANNEL_MASK(image); - (void) DestroyKernelInfo(kernel); + DestroyKernelInfo(kernel); #else new_image = ConvolveImageChannel(image, channels, order, kernel, exception); xfree((void *)kernel); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - RB_GC_GUARD(ary); return rm_image_new(new_image); } /** - * Alias for dup. + * Alias for {Magick::Image#dup}. * - * Ruby usage: - * - @verbatim Image#copy @endverbatim - * - * @param self this object - * @return a copy of self - * @see Image_dup + * @return [Magick::Image] a new image */ VALUE Image_copy(VALUE self) { return rb_funcall(self, rm_ID_dup, 0); } /** * Initialize copy, clone, dup. * - * Ruby usage: - * - @verbatim Image#initialize_copy @endverbatim - * - * @param copy the destination image - * @param orig the source image - * @return copy - * @see Image_copy - * @see Image_clone - * @see Image_dup + * @param orig [Magick::Image] the source image + * @return [Magick::Image] self + * @see Image#copy + * @see Image#clone + * @see Image#dup */ VALUE Image_init_copy(VALUE copy, VALUE orig) { Image *image, *new_image; @@ -4775,60 +4679,86 @@ /** * Extract a region of the image defined by width, height, x, y. * - * Ruby usage: - * - @verbatim Image#crop(x, y, width, height) @endverbatim - * - @verbatim Image#crop(gravity, width, height) @endverbatim + * @overload crop(reset = false, x, y, width, height) + * @param reset [Boolean] true if reset the cropped image page canvas and position + * @param x [Numeric] x position of start of region + * @param y [Numeric] y position of start of region + * @param width [Numeric] width of region + * @param height [Numeric] height of region * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see cropper - * @see Image_crop_bang + * @overload crop(reset = false, gravity, width, height) + * @param reset [Boolean] true if reset the cropped image page canvas and position + * @param gravity [Magick::GravityType] the gravity type + * @param width [Numeric] width of region + * @param height [Numeric] height of region + + * @overload crop(reset = false, gravity, x, y, width, height) + * @param reset [Boolean] true if reset the cropped image page canvas and position + * @param gravity [Magick::GravityType] the gravity type + * @param x [Numeric] x position of start of region + * @param y [Numeric] y position of start of region + * @param width [Numeric] width of region + * @param height [Numeric] height of region + * + * @return [Magick::Image] a new image + * @see Image#crop! */ VALUE Image_crop(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return cropper(False, argc, argv, self); } /** * Extract a region of the image defined by width, height, x, y. + * In-place form of {Image#crop}. * - * Ruby usage: - * - @verbatim Image#crop!(x, y, width, height) @endverbatim - * - @verbatim Image#crop!(gravity, width, height) @endverbatim + * @overload crop!(reset = false, x, y, width, height) + * @param reset [Boolean] true if reset the cropped image page canvas and position + * @param x [Numeric] x position of start of region + * @param y [Numeric] y position of start of region + * @param width [Numeric] width of region + * @param height [Numeric] height of region * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see cropper - * @see Image_crop + * @overload crop!(reset = false, gravity, width, height) + * @param reset [Boolean] true if reset the cropped image page canvas and position + * @param gravity [Magick::GravityType] the gravity type + * @param width [Numeric] width of region + * @param height [Numeric] height of region + + * @overload crop!(reset = false, gravity, x, y, width, height) + * @param reset [Boolean] true if reset the cropped image page canvas and position + * @param gravity [Magick::GravityType] the gravity type + * @param x [Numeric] x position of start of region + * @param y [Numeric] y position of start of region + * @param width [Numeric] width of region + * @param height [Numeric] height of region + * + * @return [Magick::Image] a new image + * @see Image#crop! */ VALUE Image_crop_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return cropper(True, argc, argv, self); } /** - * Call CycleColormapImage. + * Displaces the colormap by a given number of positions. + * If you cycle the colormap a number of times you can produce a psychedelic effect. * - * Ruby usage: - * - @verbatim Image#cycle_colormap @endverbatim + * The returned image is always a PseudoClass image, regardless of the type of the original image. * - * @param self this object - * @param amount amount to cycle the colormap - * @return a new image + * @param amount [Numeric] amount to cycle the colormap + * @return [Magick::Image] a new image */ VALUE Image_cycle_colormap(VALUE self, VALUE amount) { Image *image, *new_image; @@ -4842,66 +4772,59 @@ image = rm_check_destroyed(self); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) CycleColormapImage(new_image, amt, exception); + CycleColormapImage(new_image, amt, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) CycleColormapImage(new_image, amt); + CycleColormapImage(new_image, amt); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Get the x & y resolutions. + * Get the vertical and horizontal resolution in pixels of the image. + * The default is "72x72". * - * Ruby usage: - * - @verbatim Image#density @endverbatim - * - * @param self this object - * @return a string in the form "XresxYres" + * @return [String] a string of geometry in the form "XresxYres" + * @see https://www.imagemagick.org/Magick++/Geometry.html */ VALUE Image_density(VALUE self) { Image *image; char density[128]; image = rm_check_destroyed(self); #if defined(IMAGEMAGICK_7) - sprintf(density, "%gx%g", image->resolution.x, image->resolution.y); + snprintf(density, sizeof(density), "%gx%g", image->resolution.x, image->resolution.y); #else - sprintf(density, "%gx%g", image->x_resolution, image->y_resolution); + snprintf(density, sizeof(density), "%gx%g", image->x_resolution, image->y_resolution); #endif return rb_str_new2(density); } /** - * Set the x & y resolutions in the image. + * Set the vertical and horizontal resolution in pixels of the image. * - * Ruby usage: - * - @verbatim Image#density="XxY" @endverbatim - * - @verbatim Image#density=aGeometry @endverbatim + * - The density is a string of the form "XresxYres" or simply "Xres". + * - If the y resolution is not specified, set it equal to the x resolution. + * - This is equivalent to PerlMagick's handling of density. + * - The density can also be a Geometry object. The width attribute is used for the x + * resolution. The height attribute is used for the y resolution. If the height attribute is + * missing, the width attribute is used for both. * - * Notes: - * - The density is a string of the form "XresxYres" or simply "Xres". - * - If the y resolution is not specified, set it equal to the x resolution. - * - This is equivalent to PerlMagick's handling of density. - * - The density can also be a Geometry object. The width attribute is used - * for the x resolution. The height attribute is used for the y resolution. - * If the height attribute is missing, the width attribute is used for both. - * - * @param self this object - * @param density_arg The density String or Geometry - * @return density_arg + * @param density_arg [String, Magick::Geometry] The density String or Geometry + * @return [String, Magick::Geometry] the given value + * @see https://www.imagemagick.org/Magick++/Geometry.html */ VALUE Image_density_eq(VALUE self, VALUE density_arg) { Image *image; @@ -4939,11 +4862,11 @@ } // Convert the argument to a string else { - density = StringValuePtr(density_arg); + density = StringValueCStr(density_arg); if (!IsGeometry(density)) { rb_raise(rb_eArgError, "invalid density geometry %s", density); } @@ -4969,83 +4892,75 @@ return density_arg; } /** - * call DecipherImage. + * Decipher an enciphered image. * - * Ruby usage: - * - @verbatim Image#decipher(passphrase) @endverbatim - * - * @param self this object - * @param passphrase the passphrase - * @return a new deciphered image + * @param passphrase [String] The passphrase used to encipher the image. + * @return [Magick::Image] a new deciphered image */ VALUE Image_decipher(VALUE self, VALUE passphrase) { Image *image, *new_image; char *pf; ExceptionInfo *exception; MagickBooleanType okay; image = rm_check_destroyed(self); - pf = StringValuePtr(passphrase); // ensure passphrase is a string + pf = StringValueCStr(passphrase); // ensure passphrase is a string exception = AcquireExceptionInfo(); new_image = rm_clone_image(image); okay = DecipherImage(new_image, pf, exception); rm_check_exception(exception, new_image, DestroyOnError); if (!okay) { - (void) DestroyImage(new_image); + DestroyImage(new_image); rb_raise(rb_eRuntimeError, "DecipherImage failed for unknown reason."); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Call SetImageArtifact. + * Associates makes a copy of the given string arguments and + * inserts it into the artifact tree. * - * Ruby usage: - * - @verbatim value = Image#define(artifact, value) @endverbatim + * - Normally a script should never call this method. Any calls to + * SetImageArtifact will be part of the methods in which they're needed, or + * be called via the OptionalMethodArguments class. + * - If value is nil, the artifact will be removed * - * Notes: - * - Normally a script should never call this method. Any calls to - * SetImageArtifact will be part of the methods in which they're needed, or - * be called via the OptionalMethodArguments class. - * - If value is nil, the artifact will be removed - * - * @param self this object - * @param artifact the artifact to set - * @param value the value to which to set the artifact - * @return the value + * @param artifact [String] the artifact to set + * @param value [String] the value to which to set the artifact + * @return [String] the given `value` */ VALUE Image_define(VALUE self, VALUE artifact, VALUE value) { Image *image; char *key, *val; MagickBooleanType status; image = rm_check_frozen(self); artifact = rb_String(artifact); - key = StringValuePtr(artifact); + key = StringValueCStr(artifact); if (value == Qnil) { - (void) DeleteImageArtifact(image, key); + DeleteImageArtifact(image, key); } else { value = rb_String(value); - val = StringValuePtr(value); + val = StringValueCStr(value); status = SetImageArtifact(image, key, val); if (!status) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } @@ -5053,23 +4968,42 @@ return value; } -DEF_ATTR_ACCESSOR(Image, delay, ulong) +/** + * Get the Number of ticks which must expire before displaying the next image in an animated + * sequence. The default number of ticks is 0. By default there are 100 ticks per second but this + * number can be changed via the ticks_per_second attribute. + * + * @return [Numeric] The current delay value. + */ +VALUE +Image_delay(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, delay, ulong); +} +/** + * Set the Number of ticks which must expire before displaying the next image in an animated + * sequence. + * + * @param val [Numeric] the delay value + * @return [Numeric] the given value + */ +VALUE +Image_delay_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, delay, ulong); +} + /** * Delete the image composite mask. * - * Ruby usage: - * - @verbatim Image#delete_compose_mask() @endverbatim - * - * @param self this object - * @return self - * @see Image_add_compose_mask - * @see SetImageMask in ImageMagick + * @return [Magick::Image] self + * @see Image#add_compose_mask */ VALUE Image_delete_compose_mask(VALUE self) { Image *image; @@ -5079,55 +5013,47 @@ image = rm_check_frozen(self); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SetImageMask(image, CompositePixelMask, NULL, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageMask(image, CompositePixelMask, NULL, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageMask(image, NULL); + SetImageMask(image, NULL); rm_check_image_exception(image, RetainOnError); #endif return self; } /** - * Call ProfileImage. + * Deletes the specified profile. * - * Ruby usage: - * - @verbatim Image#delete_profile(name) @endverbatim - * - * @param self this object - * @param name the name of the profile to be deleted - * @return self + * @param name [String] The profile name, "IPTC" or "ICC" for example. + * Specify "*" to delete all the profiles in the image. + * @return [Magick::Image] self + * @see Image#add_profile */ VALUE Image_delete_profile(VALUE self, VALUE name) { Image *image = rm_check_frozen(self); - (void) DeleteImageProfile(image, StringValuePtr(name)); + DeleteImageProfile(image, StringValueCStr(name)); return self; } /** - * Return the image depth (8 or 16). + * Return the image depth (8, 16 or 32). * - * Ruby usage: - * - @verbatim Image#depth @endverbatim + * - If all pixels have lower-order bytes equal to higher-order bytes, the depth will be reported as + * 8 even if the depth field in the Image structure says 16. * - * Notes: - * - If all pixels have lower-order bytes equal to higher-order bytes, the - * depth will be reported as 8 even if the depth field in the Image - * structure says 16. - * - * @param self this object - * @return the depth + * @return [Numeric] the depth */ VALUE Image_depth(VALUE self) { Image *image; @@ -5136,34 +5062,27 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); depth = GetImageDepth(image, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return INT2FIX(depth); } /** - * Implement convert -deskew option. + * Straightens an image. A threshold of 40% works for most images. * - * Ruby usage: - * - @verbatim Image#deskew @endverbatim - * - @verbatim Image#deskew(threshold) @endverbatim - * - @verbatim Image#deskew(threshold, auto-crop-width) @endverbatim - * - * Notes: - * - Default threshold is 0.40 - * - Default auto-crop-width is the auto crop width of the image - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload deskew(threshold = 0.40, auto_crop_width = nil) + * @param threshold [Float] A percentage of QuantumRange. Either a Float between 0 and 1.0, + * inclusive, or a string in the form "NN%" where NN is between 0 and 100. + * @param auto_crop_width [Float] Specify a value for this argument to cause the deskewed image to + * be auto-cropped. The argument is the pixel width of the image background (e.g. 40). + * @return [Magick::Image] a new image */ VALUE Image_deskew(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -5177,41 +5096,34 @@ switch (argc) { case 2: width = NUM2ULONG(argv[1]); memset(auto_crop_width, 0, sizeof(auto_crop_width)); - sprintf(auto_crop_width, "%ld", width); + snprintf(auto_crop_width, sizeof(auto_crop_width), "%lu", width); SetImageArtifact(image, "deskew:auto-crop", auto_crop_width); case 1: - threshold = rm_percentage(argv[0],1.0) * QuantumRange; + threshold = rm_percentage(argv[0], 1.0) * QuantumRange; case 0: break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc); break; } exception = AcquireExceptionInfo(); new_image = DeskewImage(image, threshold, exception); - CHECK_EXCEPTION() - rm_ensure_result(new_image); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - return rm_image_new(new_image); } /** - * Reduce the speckle noise in an image while preserving the edges of the - * original image. + * Reduce the speckle noise in an image while preserving the edges of the original image. * - * Ruby usage: - * - @verbatim Image#despeckle @endverbatim - * - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_despeckle(VALUE self) { Image *image, *new_image; @@ -5220,27 +5132,20 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = DespeckleImage(image, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Free all the memory associated with an image. * - * Ruby usage: - * - @verbatim Image#destroy! @endverbatim - * - * @param self this object - * @return self + * @return [Magick::Image] self */ VALUE Image_destroy_bang(VALUE self) { Image *image; @@ -5254,15 +5159,11 @@ /** * Return true if the image has been destroyed, false otherwise. * - * Ruby usage: - * - @verbatim Image#destroyed? @endverbatim - * - * @param self this object - * @return true if destroyed, false otherwise + * @return [Boolean] true if destroyed, false otherwise */ VALUE Image_destroyed_q(VALUE self) { Image *image; @@ -5271,22 +5172,25 @@ return image ? Qfalse : Qtrue; } /** - * Call the IsImagesEqual function. + * Compares two images and computes statistics about their difference. * - * Ruby usage: - * - @verbatim Image#difference @endverbatim - * - * Notes: - * - "other" can be either an Image or an Image - * - * @param self this object - * @param other another Image - * @return An array with 3 values: [mean error per pixel, normalized mean error, - * normalized maximum error] + * @param other [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an imagelist, + * uses the current image. + * @return [Array<Float>] An array of three {Float} values: + * - mean error per pixel + * - The mean error for any single pixel in the image. + * - normalized mean error + * - The normalized mean quantization error for any single pixel in the image. This distance measure + * is normalized to a range between 0 and 1. It is independent of the range of red, green, and + * blue values in the image. + * - normalized maximum error + * - The normalized maximum quantization error for any single pixel in the image. This distance + * measure is normalized to a range between 0 and 1. It is independent of the range of red, + * green, and blue values in your image. */ VALUE Image_difference(VALUE self, VALUE other) { Image *image; @@ -5300,15 +5204,15 @@ other = rm_cur_image(other); image2 = rm_check_destroyed(other); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) IsImagesEqual(image, image2, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + IsImagesEqual(image, image2, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) IsImagesEqual(image, image2); + IsImagesEqual(image, image2); rm_check_image_exception(image, RetainOnError); #endif mean = rb_float_new(image->error.mean_error_per_pixel); nmean = rb_float_new(image->error.normalized_mean_error); @@ -5323,41 +5227,33 @@ /** * Get image directory. * - * Ruby usage: - * - @verbatim Image#directory @endverbatim - * - * @param self this object - * @return the directory + * @return [String] the directory */ -DEF_ATTR_READER(Image, directory, str) +VALUE +Image_directory(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, directory, str); +} /** - * Implement the -displace option of xMagick's composite command. + * Uses displacement_map to move color from img to the output image. + * This method corresponds to the -displace option of ImageMagick's composite command. * - * Ruby usage: - * - @verbatim Image#displace(displacement_map, x_amp) @endverbatim - * - @verbatim Image#displace(displacement_map, x_amp, y_amp) @endverbatim - * - @verbatim Image#displace(displacement_map, x_amp, y_amp, x_offset) @endverbatim - * - @verbatim Image#displace(displacement_map, x_amp, y_amp, x_offset, y_offset) @endverbatim - * - @verbatim Image#displace(displacement_map, x_amp, y_amp, gravity) @endverbatim - * - @verbatim Image#displace(displacement_map, x_amp, y_amp, gravity, x_offset) @endverbatim - * - @verbatim Image#displace(displacement_map, x_amp, y_amp, gravity, x_offset, y_offset) @endverbatim - * - * Notes: - * - If y_amp is omitted the default is x_amp. - * - Default x_offset is 0 - * - Default y_offset is 0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see special_composite + * @overload displace(displacement_map, x_amp, y_amp = x_amp, gravity = Magick::NorthWestGravity, x_offset = 0, y_offset = 0) + * @param displacement_map [Magick::Image, Magick::ImageList] The source image for the composite + * operation. Either an imagelist or an image. If an imagelist, uses the current image. + * @param x_amp [Float] The maximum displacement on the x-axis. + * @param y_amp [Float] The maximum displacement on the y-axis. + * @param gravity [Magick::GravityType] the gravity for offset. the offsets are measured from the + * NorthWest corner by default. + * @param x_offset [Numeric] The offset that measured from the left-hand side of the target image. + * @param y_offset [Numeric] The offset that measured from the top of the target image. + * @return [Magick::Image] a new image */ VALUE Image_displace(int argc, VALUE *argv, VALUE self) { Image *image, *displacement_map; @@ -5394,34 +5290,32 @@ break; } RB_GC_GUARD(dmap); - return special_composite(image, displacement_map, x_amplitude, y_amplitude - , x_offset, y_offset, DisplaceCompositeOp); + return special_composite(image, displacement_map, x_amplitude, y_amplitude, + x_offset, y_offset, DisplaceCompositeOp); } /** - * Extract pixel data from the image and returns it as an array of pixels. The - * "x", "y", "width" and "height" parameters specify the rectangle to be - * extracted. The "map" parameter reflects the expected ordering of the pixel - * array. It can be any combination or order of R = red, G = green, B = blue, - * A = alpha, C = cyan, Y = yellow, M = magenta, K = black, or I = intensity - * (for grayscale). If the "float" parameter is specified and true, the pixel - * data is returned as floating-point numbers in the range [0..1]. By default - * the pixel data is returned as integers in the range [0..QuantumRange]. + * Extract pixel data from the image and returns it as an array of pixels. The "x", "y", "width" and + * "height" parameters specify the rectangle to be extracted. The "map" parameter reflects the + * expected ordering of the pixel array. It can be any combination or order of R = red, G = green, + * B = blue, A = alpha, C = cyan, Y = yellow, M = magenta, K = black, or I = intensity (for + * grayscale). If the "float" parameter is specified and true, the pixel data is returned as + * floating-point numbers in the range [0..1]. By default the pixel data is returned as integers in + * the range [0..QuantumRange]. * - * Ruby usage: - * - @verbatim Image#dispatch(x, y, columns, rows, map) @endverbatim - * - @verbatim Image#dispatch(x, y, columns, rows, map, float) @endverbatim - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return an Array of pixel data - * @throw ArgumentError + * @overload dispatch(x, y, columns, rows, map, float = false) + * @param x [Numeric] The offset of the rectangle from the upper-left corner of the image. + * @param y [Numeric] The offset of the rectangle from the upper-left corner of the image. + * @param columns [Numeric] The width of the rectangle. + * @param rows [Numeric] The height of the rectangle. + * @param map [String] + * @param float [Boolean] + * @return [Array<Numeric>] an Array of pixel data */ VALUE Image_dispatch(int argc, VALUE *argv, VALUE self) { Image *image; @@ -5438,11 +5332,11 @@ Quantum *i; double *f; void *v; } pixels; - (void) rm_check_destroyed(self); + rm_check_destroyed(self); if (argc < 5 || argc > 6) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 5 or 6)", argc); } @@ -5473,27 +5367,27 @@ if (!okay) { goto exit; } - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); // Convert the pixel data to the appropriate Ruby type if (stg_type == QuantumPixel) { for (n = 0; n < npixels; n++) { - (void) rb_ary_push(pixels_ary, QUANTUM2NUM(pixels.i[n])); + rb_ary_push(pixels_ary, QUANTUM2NUM(pixels.i[n])); } } else { for (n = 0; n < npixels; n++) { - (void) rb_ary_push(pixels_ary, rb_float_new(pixels.f[n])); + rb_ary_push(pixels_ary, rb_float_new(pixels.f[n])); } } exit: xfree((void *)pixels.v); @@ -5505,15 +5399,11 @@ /** * Display the image to an X window screen. * - * Ruby usage: - * - @verbatim Image#display @endverbatim - * - * @param self this object - * @return self + * @return [Magick::Image] self */ VALUE Image_display(VALUE self) { Image *image; @@ -5525,23 +5415,23 @@ image = rm_check_destroyed(self); if (image->rows == 0 || image->columns == 0) { - rb_raise(rb_eArgError, "invalid image geometry (%lux%lu)", image->rows, image->columns); + rb_raise(rb_eArgError, "invalid image geometry (%"RMIuSIZE"x%"RMIuSIZE")", image->rows, image->columns); } info_obj = rm_info_new(); Data_Get_Struct(info_obj, Info, info); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) DisplayImages(info, image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + DisplayImages(info, image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) DisplayImages(info, image); + DisplayImages(info, image); rm_check_image_exception(image, RetainOnError); #endif RB_GC_GUARD(info_obj); @@ -5550,15 +5440,11 @@ /** * Return the dispose attribute as a DisposeType enum. * - * Ruby usage: - * - @verbatim Image#dispose @endverbatim - * - * @param self this object - * @return the dispose + * @return [Magick::DisposeType] the dispose */ VALUE Image_dispose(VALUE self) { Image *image = rm_check_destroyed(self); @@ -5567,16 +5453,12 @@ /** * Set the dispose attribute. * - * Ruby usage: - * - @verbatim Image#dispose= @endverbatim - * - * @param self this object - * @param dispose the dispose - * @return dispose + * @param dispose [Magick::DisposeType] the dispose + * @return [Magick::DisposeType] the given dispose */ VALUE Image_dispose_eq(VALUE self, VALUE dispose) { Image *image = rm_check_frozen(self); @@ -5584,33 +5466,31 @@ return dispose; } /** - * Corresponds to the composite_image -dissolve operation. + * Composites the overlay image into the target image. + * The opacity of img is multiplied by dst_percentage and opacity of overlay is multiplied by + * src_percentage. * - * Ruby usage: - * - @verbatim Image#dissolve(overlay, src_percent) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, x_offset) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, x_offset, y_offset) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, gravity) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, gravity, x_offset) @endverbatim - * - @verbatim Image#dissolve(overlay, src_percent, dst_percent, gravity, x_offset, y_offset) @endverbatim + * This method corresponds to the -dissolve option of ImageMagick's composite command. * - * Notes: - * - `percent' can be a number or a string in the form "NN%" - * - Default dst_percent is -1.0 (tells blend_geometry to leave it out of the - * geometry string) - * - Default x_offset is 0 - * - Default y_offset is 0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see special_composite + * @overload dissolve(overlay, src_percent, dst_percent = -1.0, gravity = Magick::NorthWestGravity, x_offset = 0, y_offset = 0) + * @param overlay [Magick::Image, Magick::ImageList] The source image for the composite operation. + * Either an imagelist or an image. If an imagelist, uses the current image. + * @param src_percent [Float, String] Either a non-negative number a string in the form "NN%". + * If src_percentage is a number it is interpreted as a percentage. + * Both 0.25 and "25%" mean 25%. This argument is required. + * @param dst_percent [Float, String] Either a non-negative number a string in the form "NN%". + * If src_percentage is a number it is interpreted as a percentage. + * Both 0.25 and "25%" mean 25%. This argument may omitted if no other arguments follow it. + * In this case the default is 100%-src_percentage. + * @param gravity [Magick::GravityType] the gravity for offset. the offsets are measured from the + * NorthWest corner by default. + * @param x_offset [Numeric] The offset that measured from the left-hand side of the target image. + * @param y_offset [Numeric] The offset that measured from the top of the target image. + * @return [Magick::Image] a new image */ VALUE Image_dissolve(int argc, VALUE *argv, VALUE self) { Image *image, *overlay; @@ -5636,48 +5516,70 @@ } switch (argc) { case 3: - dst_percent = rm_percentage(argv[2],1.0) * 100.0; + dst_percent = rm_percentage(argv[2], 1.0) * 100.0; case 2: - src_percent = rm_percentage(argv[1],1.0) * 100.0; + src_percent = rm_percentage(argv[1], 1.0) * 100.0; break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc); break; } - composite_image = special_composite(image, overlay, src_percent, dst_percent - , x_offset, y_offset, DissolveCompositeOp); + composite_image = special_composite(image, overlay, src_percent, dst_percent, + x_offset, y_offset, DissolveCompositeOp); RB_GC_GUARD(composite_image); RB_GC_GUARD(ovly); return composite_image; } /** - * Call DistortImage. + * Distort an image using the specified distortion type and its required arguments. + * This method is equivalent to ImageMagick's -distort option. * - * Ruby usage: - * - @verbatim Image#distort(type, points) { optional arguments } @endverbatim - * - @verbatim Image#distort(type, points, bestfit) { optional arguments } @endverbatim + * @overload distort(type, points, bestfit = false) + * @param type [Magick::DistortMethod] a DistortMethod value + * @param points [Array<Numeric>] an Array of Numeric values. The size of the array depends on the + * distortion type. + * @param bestfit [Boolean] If bestfit is enabled, and the distortion allows it, the destination + * image is adjusted to ensure the whole source image will just fit within the final destination + * image, which will be sized and offset accordingly. Also in many cases the virtual offset of + * the source image will be taken into account in the mapping. * - * Notes: - * - Default bestfit is false - * - Points is an Array of Numeric values - * - Optional arguments are: - * - self.define "distort:viewport", WxH+X+Y - * - self.define "distort:scale", N - * - self.verbose true + * @overload distort(type, points, bestfit = false) + * If present a block, distort yields to a block in which you can set optional arguments by + * setting attributes on self. + * - self.define("distort:viewport", "WxH+X+Y") + * - Specify the size and offset of the generated viewport image of the distorted image space. W and + * H are the width and height, and X and Y are the offset. + * - self.define("distort:scale", N) + * - N is an integer factor. Scale the output image (viewport or otherwise) by that factor without + * changing the viewed contents of the distorted image. This can be used either for + * 'super-sampling' the image for a higher quality result, or for panning and zooming around + * the image (with appropriate viewport changes, or post-distort cropping and resizing). + * - self.verbose(true) + * - Attempt to output the internal coefficients, and the -fx equivalent to the distortion, for + expert study, and debugging purposes. This many not be available for all distorts. + * @param type [Magick::DistortMethod] a DistortMethod value + * @param points [Array<Numeric>] an Array of Numeric values. The size of the array depends on the distortion type. + * @param bestfit [Boolean] If bestfit is enabled, and the distortion allows it, the destination + * image is adjusted to ensure the whole source image will just fit within the final destination + * image, which will be sized and offset accordingly. Also in many cases the virtual offset of + * the source image will be taken into account in the mapping. + * @yield [] * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image + * @example + * img.distort(Magick::ScaleRotateTranslateDistortion, [0]) do + * self.define "distort:viewport", "44x44+15+0" + * self.define "distort:scale", 2 + * end */ VALUE Image_distort(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -5724,34 +5626,35 @@ exception = AcquireExceptionInfo(); new_image = DistortImage(image, distortion_method, npoints, points, bestfit, exception); xfree(points); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); + DestroyExceptionInfo(exception); RB_GC_GUARD(pts); return rm_image_new(new_image); } /** - * Call GetImageChannelDistortion. + * Compares one or more image channels of an image to a reconstructed image and returns the + * specified distortion metric. * - * Ruby usage: - * - @verbatim Image#distortion_channel(reconstructed_image, metric) @endverbatim - * - @verbatim Image#distortion_channel(reconstructed_image, metric, channel) @endverbatim - * - @verbatim Image#distortion_channel(reconstructed_image, metric, channel, ...) @endverbatim + * @overload distortion_channel(reconstructed_image, metric, channel = Magick::AllChannels) + * @param reconstructed_image [Magick::Image, Magick::ImageList] Either an imagelist or an + * image. If an imagelist, uses the current image. + * @param metric [Magick::MetricType] The desired distortion metric. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload distortion_channel(reconstructed_image, metric, *channels) + * @param reconstructed_image [Magick::Image, Magick::ImageList] Either an imagelist or an + * image. If an imagelist, uses the current image. + * @param metric [Magick::MetricType] The desired distortion metric. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return the image channel distortion (Ruby float) + * @return [Float] the image channel distortion */ VALUE Image_distortion_channel(int argc, VALUE *argv, VALUE self) { Image *image, *reconstruct; @@ -5781,38 +5684,30 @@ exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); difference_image = CompareImages(image, reconstruct, metric, &distortion, exception); END_CHANNEL_MASK(image); - (void) DestroyImage(difference_image); + DestroyImage(difference_image); #else - (void) GetImageChannelDistortion(image, reconstruct, channels, metric, &distortion, exception); + GetImageChannelDistortion(image, reconstruct, channels, metric, &distortion, exception); #endif - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); RB_GC_GUARD(rec); return rb_float_new(distortion); } /** * Implement marshalling. * - * Ruby usage: - * - @verbatim Image#_dump(aDepth) @endverbatim - * - * Notes: - * - Uses ImageToBlob - use the MIFF format in the blob since it's the most - * general - * - * @param self this object - * @param depth the depth to which to dump (unused) - * @return a string representing the dumped image + * @param depth [Object] unused + * @return [String] a string representing the dumped image */ VALUE Image__dump(VALUE self, VALUE depth ATTRIBUTE_UNUSED) { Image *image; @@ -5828,21 +5723,21 @@ info = CloneImageInfo(NULL); if (!info) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } - strcpy(info->magick, image->magick); + strlcpy(info->magick, image->magick, sizeof(info->magick)); exception = AcquireExceptionInfo(); blob = ImageToBlob(info, image, &length, exception); // Free ImageInfo first - error handling may raise an exception - (void) DestroyImageInfo(info); + DestroyImageInfo(info); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); if (!blob) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } @@ -5852,64 +5747,49 @@ // string stored as a byte, followed by the // magick string itself. mi.id = DUMPED_IMAGE_ID; mi.mj = DUMPED_IMAGE_MAJOR_VERS; mi.mi = DUMPED_IMAGE_MINOR_VERS; - strcpy(mi.magick, image->magick); - mi.len = (unsigned char) min((size_t)UCHAR_MAX, strlen(mi.magick)); + strlcpy(mi.magick, image->magick, sizeof(mi.magick)); + mi.len = (unsigned char) min((size_t)UCHAR_MAX, rm_strnlen_s(mi.magick, sizeof(mi.magick))); // Concatenate the blob onto the header & return the result - str = rb_str_new((char *)&mi, (long)(mi.len+offsetof(DumpedImage,magick))); + str = rb_str_new((char *)&mi, (long)(mi.len+offsetof(DumpedImage, magick))); str = rb_str_buf_cat(str, (char *)blob, (long)length); magick_free((void*)blob); RB_GC_GUARD(str); return str; } /** - * Construct a new image object and call initialize_copy. + * Duplicates a image. * - * Ruby usage: - * - @verbatim Image#dup @endverbatim - * - * @param self this object - * @return a new image - * @see Image_copy - * @see Image_init_copy + * @return [Magick::Image] a new image */ VALUE Image_dup(VALUE self) { VALUE dup; - (void) rm_check_destroyed(self); + rm_check_destroyed(self); dup = Data_Wrap_Struct(CLASS_OF(self), NULL, rm_image_destroy, NULL); - if (rb_obj_tainted(self)) - { - (void) rb_obj_taint(dup); - } - RB_GC_GUARD(dup); return rb_funcall(dup, rm_ID_initialize_copy, 1, self); } /** - * Iterate over image profiles. + * Calls block once for each profile in the image, passing the profile name and value as parameters. * - * Ruby usage: - * - @verbatim Image#each_profile @endverbatim - * - * Notes: - * - ImageMagick only - * - * @param self this object - * @return iterator over image profiles + * @yield [name, val] + * @yieldparam name [String] the profile name + * @yieldparam val [String] the profile value + * @return [Object] the last value returned by the block */ VALUE Image_each_profile(VALUE self) { Image *image; @@ -5947,24 +5827,15 @@ return val; } /** - * Find edges in an image. "radius" defines the radius of the convolution - * filter. + * Find edges in an image. "radius" defines the radius of the convolution filter. * - * Ruby usage: - * - @verbatim Image#edge @endverbatim - * - @verbatim Image#edge(radius) @endverbatim - * - * Notes: - * - Default radius is 0 (have edge select a suitable radius) - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload edge(radius = 0.0) + * @param radius [Float] The radius of the convolution filter. + * @return [Magick::Image] a new image */ VALUE Image_edge(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -5985,15 +5856,12 @@ exception = AcquireExceptionInfo(); new_image = EdgeImage(image, radius, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** @@ -6035,73 +5903,58 @@ } exception = AcquireExceptionInfo(); new_image = (effector)(image, radius, sigma, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Create a grayscale image with a three-dimensional effect. + * Adds a 3-dimensional effect. * - * Ruby usage: - * - @verbatim Image#emboss @endverbatim - * - @verbatim Image#emboss(radius) @endverbatim - * - @verbatim Image#emboss(radius, sigma) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see effect_image + * @overload emboss(radius = 0.0, sigma = 1.0) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @return [Magick::Image] a new image */ VALUE Image_emboss(int argc, VALUE *argv, VALUE self) { return effect_image(self, argc, argv, EmbossImage); } /** - * Call EncipherImage. + * Encipher an image. * - * Ruby usage: - * - @verbatim Image#encipher(passphrase) @endverbatim - * - * @param self this object - * @param passphrase the passphrase with which to encipher - * @return a new image + * @param passphrase [String] the passphrase with which to encipher + * @return [Magick::Image] a new image + * @example + * enciphered_img = img.encipher("magic word") */ VALUE Image_encipher(VALUE self, VALUE passphrase) { Image *image, *new_image; char *pf; ExceptionInfo *exception; MagickBooleanType okay; image = rm_check_destroyed(self); - pf = StringValuePtr(passphrase); // ensure passphrase is a string + pf = StringValueCStr(passphrase); // ensure passphrase is a string exception = AcquireExceptionInfo(); new_image = rm_clone_image(image); okay = EncipherImage(new_image, pf, exception); rm_check_exception(exception, new_image, DestroyOnError); if (!okay) { - (void) DestroyImage(new_image); + DestroyImage(new_image); rb_raise(rb_eRuntimeError, "EncipherImage failed for unknown reason."); } DestroyExceptionInfo(exception); @@ -6111,15 +5964,11 @@ /** * Return endian option for images that support it. * - * Ruby usage: - * - @verbatim Image#endian @endverbatim - * - * @param self this object - * @return the endian option + * @return [Magick::EndianType] the endian option */ VALUE Image_endian(VALUE self) { Image *image = rm_check_destroyed(self); @@ -6128,16 +5977,12 @@ /** * Set endian option for images that support it. * - * Ruby usage: - * - @verbatim Image#endian= @endverbatim - * - * @param self this object - * @param type the endian type - * @return type + * @param type [Magick::EndianType] the endian type + * @return [Magick::EndianType] the given type */ VALUE Image_endian_eq(VALUE self, VALUE type) { Image *image = rm_check_frozen(self); @@ -6146,15 +5991,11 @@ } /** * Apply a digital filter that improves the quality of a noisy image. * - * Ruby usage: - * - @verbatim Image#enhance @endverbatim - * - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_enhance(VALUE self) { Image *image, *new_image; @@ -6163,27 +6004,20 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = EnhanceImage(image, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Apply a histogram equalization to the image. * - * Ruby usage: - * - @verbatim Image#equalize @endverbatim - * - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_equalize(VALUE self) { Image *image, *new_image; @@ -6194,37 +6028,32 @@ image = rm_check_destroyed(self); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) EqualizeImage(new_image, exception); + EqualizeImage(new_image, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) EqualizeImage(new_image); + EqualizeImage(new_image); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Call EqualizeImageChannel. + * Applies a histogram equalization to the image. Only the specified channels are equalized. * - * Ruby usage: - * - @verbatim Image#equalize_channel @endverbatim - * - @verbatim Image#equalize_channel(channel) @endverbatim - * - @verbatim Image#equalize_channel(channel, ...) @endverbatim + * @overload equalize_channel(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload equalize_channel(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_equalize_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -6243,16 +6072,16 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) EqualizeImage(new_image, exception); + EqualizeImage(new_image, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) EqualizeImageChannel(new_image, channels); + EqualizeImageChannel(new_image, channels); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); @@ -6260,18 +6089,11 @@ /** * Reset the image to the background color. * - * Ruby usage: - * - @verbatim Image#erase! @endverbatim - * - * Notes: - * - One of the very few Image methods that do not return a new image. - * - * @param self this object - * @return self + * @return [Magick::Image] self */ VALUE Image_erase_bang(VALUE self) { Image *image; @@ -6281,15 +6103,15 @@ image = rm_check_frozen(self); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SetImageBackgroundColor(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageBackgroundColor(image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageBackgroundColor(image); + SetImageBackgroundColor(image); rm_check_image_exception(image, RetainOnError); #endif return self; } @@ -6321,11 +6143,11 @@ { Image *image, *new_image; RectangleInfo rect; ExceptionInfo *exception; - memset(&rect,'\0', sizeof(rect)); + memset(&rect, '\0', sizeof(rect)); rect.x = NUM2LONG(x); rect.y = NUM2LONG(y); rect.width = NUM2ULONG(width); rect.height = NUM2ULONG(height); @@ -6333,95 +6155,87 @@ exception = AcquireExceptionInfo(); new_image = ExcerptImage(image, &rect, exception); rm_check_exception(exception, new_image, DestroyOnError); DestroyExceptionInfo(exception); - rm_ensure_result(new_image); if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Lightweight crop. + * This method is very similar to crop. + * It extracts the rectangle specified by its arguments from the image and returns it as a new + * image. However, excerpt does not respect the virtual page offset and does not update the page + * offset and is more efficient than cropping. * - * Ruby usage: - * - @verbatim Image#excerpt(x, y, width, height) @endverbatim - * - * @param self this object - * @param x the x position for the start of the rectangle - * @param y the y position for the start of the rectangle - * @param width the width of the rectancle - * @param height the height of the rectangle - * @return self if bang, otherwise a new image - * @see excerpt - * @see Image_excerpt_bang - * @see Image_crop - * @see Image_crop_bang + * @param x [Numeric] the x position for the start of the rectangle + * @param y [Numeric] the y position for the start of the rectangle + * @param width [Numeric] the width of the rectancle + * @param height [Numeric] the height of the rectangle + * @return [Magick::Image] a new image + * @see Image#excerpt! + * @see Image#crop + * @see Image#crop! */ VALUE Image_excerpt(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return excerpt(False, self, x, y, width, height); } /** - * Lightweight crop. + * In-place form of {Magick::Image#excerpt}. * - * Ruby usage: - * - @verbatim Image#excerpt!(x, y, width, height) @endverbatim + * This method is very similar to crop. + * It extracts the rectangle specified by its arguments from the image and returns it as a new + * image. However, excerpt does not respect the virtual page offset and does not update the page + * offset and is more efficient than cropping. * - * @param self this object - * @param x the x position for the start of the rectangle - * @param y the y position for the start of the rectangle - * @param width the width of the rectancle - * @param height the height of the rectangle - * @return self - * @see excerpt - * @see Image_excerpt - * @see Image_crop - * @see Image_crop_bang + * @param x [Numeric] the x position for the start of the rectangle + * @param y [Numeric] the y position for the start of the rectangle + * @param width [Numeric] the width of the rectancle + * @param height [Numeric] the height of the rectangle + * @return [Magick::Image] self + * @see Image#excerpt + * @see Image#crop + * @see Image#crop! */ VALUE Image_excerpt_bang(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return excerpt(True, self, x, y, width, height); } /** - * Extract image pixels in the form of an array. + * Extracts the pixel data from the specified rectangle and returns it as an array of Integer + * values. The array returned by {Magick::Image#export_pixels} is suitable for use as an argument + * to {Magick::Image#import_pixels}. * - * Ruby usage: - * - @verbatim Image#export_pixels @endverbatim - * - @verbatim Image#export_pixels(x) @endverbatim - * - @verbatim Image#export_pixels(x, y) @endverbatim - * - @verbatim Image#export_pixels(x, y, cols) @endverbatim - * - @verbatim Image#export_pixels(x, y, cols, rows) @endverbatim - * - @verbatim Image#export_pixels(x, y, cols, rows, map) @endverbatim - * - * Notes: - * - Default x is 0 - * - Default y is 0 - * - Default cols is self.columns - * - Default rows is self.rows - * - Default map is "RGB" - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return array of pixels + * @overload export_pixels(x = 0, y = 0, cols = self.columns, rows = self.rows, map = "RGB") + * @param x [Numeric] The offset of the rectangle from the upper-left corner of the image. + * @param y [Numeric] The offset of the rectangle from the upper-left corner of the image. + * @param cols [Numeric] The width of the rectangle. + * @param rows [Numeric] The height of the rectangle. + + * @param map [String] A string that describes which pixel channel data is desired and the order + * in which it should be stored. It can be any combination or order of R = red, G = green, B = + * blue, A = alpha, C = cyan, Y = yellow, M = magenta, K = black, I = intensity (for grayscale), + * or P = pad. + * @return [Array<Numeric>] array of pixels */ VALUE Image_export_pixels(int argc, VALUE *argv, VALUE self) { Image *image; @@ -6440,11 +6254,11 @@ rows = image->rows; switch (argc) { case 5: - map = StringValuePtr(argv[4]); + map = StringValueCStr(argv[4]); case 4: rows = NUM2ULONG(argv[3]); case 3: cols = NUM2ULONG(argv[2]); case 2: @@ -6452,11 +6266,11 @@ case 1: x_off = NUM2LONG(argv[0]); case 0: break; default: - rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 5)", argc); + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 5)", argc); break; } if ( x_off < 0 || (unsigned long)x_off > image->columns || y_off < 0 || (unsigned long)y_off > image->rows @@ -6477,22 +6291,22 @@ okay = ExportImagePixels(image, x_off, y_off, cols, rows, map, QuantumPixel, (void *)pixels, exception); if (!okay) { xfree((void *)pixels); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); // Should never get here... rm_magick_error("ExportImagePixels failed with no explanation."); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); ary = rb_ary_new2(npixels); for (n = 0; n < npixels; n++) { - (void) rb_ary_push(ary, QUANTUM2NUM(pixels[n])); + rb_ary_push(ary, QUANTUM2NUM(pixels[n])); } xfree((void *)pixels); RB_GC_GUARD(ary); @@ -6500,35 +6314,31 @@ return ary; } /** - * Call ExtentImage. + * If width or height is greater than the target image's width or height, extends the width and + * height of the target image to the specified values. The new pixels are set to the background + * color. If width or height is less than the target image's width or height, crops the target + * image. * - * Ruby usage: - * - @verbatim Image#extent(width, height) @endverbatim - * - @verbatim Image#extent(width, height, x) @endverbatim - * - @verbatim Image#extent(width, height, x, y) @endverbatim - * - * Notes: - * - Default x is 0 - * - Default y is 0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload extent(width, height, x = 0, y = 0) + * @param width [Numeric] The width of the new image + * @param height [Numeric] The height of the new image + * @param x [Numeric] The upper-left corner of the new image is positioned + * @param y [Numeric] The upper-left corner of the new image is positioned + * @return [Magick::Image] a new image */ VALUE Image_extent(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; RectangleInfo geometry; long height, width; ExceptionInfo *exception; - (void) rm_check_destroyed(self); + rm_check_destroyed(self); if (argc < 2 || argc > 4) { rb_raise(rb_eArgError, "wrong number of arguments (expected 2 to 4, got %d)", argc); } @@ -6553,51 +6363,42 @@ { rb_raise(rb_eArgError, "invalid extent geometry %ldx%ld", width, height); } else { - rb_raise(rb_eArgError, "invalid extent geometry %ldx%ld+%ld+%ld" - , width, height, geometry.x, geometry.y); + rb_raise(rb_eArgError, "invalid extent geometry %ldx%ld+%"RMIdSIZE"+%"RMIdSIZE"", + width, height, geometry.x, geometry.y); } } Data_Get_Struct(self, Image, image); exception = AcquireExceptionInfo(); new_image = ExtentImage(image, &geometry, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); + DestroyExceptionInfo(exception); + return rm_image_new(new_image); } /** - * Extract image pixels to a Ruby string. + * Extracts the pixel data from the specified rectangle and returns it as a string. * - * Ruby usage: - * - @verbatim Image#export_pixels_to_str @endverbatim - * - @verbatim Image#export_pixels_to_str(x) @endverbatim - * - @verbatim Image#export_pixels_to_str(x, y) @endverbatim - * - @verbatim Image#export_pixels_to_str(x, y, cols) @endverbatim - * - @verbatim Image#export_pixels_to_str(x, y, cols, rows) @endverbatim - * - @verbatim Image#export_pixels_to_str(x, y, cols, rows, map) @endverbatim - * - @verbatim Image#export_pixels_to_str(x, y, cols, rows, map, type) @endverbatim - * - * Notes: - * - Default x is 0 - * - Default y is 0 - * - Default cols is self.columns - * - Default rows is self.rows - * - Default map is "RGB" - * - Default type is Magick::CharPixel - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return pixels as a string + * @overload export_pixels_to_str(x = 0, y = 0, cols = self.columns, rows = self.rows, map = "RGB", type = Magick::CharPixel) + * @param x [Numeric] The offset of the rectangle from the upper-left corner of the image. + * @param y [Numeric] The offset of the rectangle from the upper-left corner of the image. + * @param cols [Numeric] The width of the rectangle. + * @param rows [Numeric] The height of the rectangle. + * @param map [String] A string that describes which pixel channel data is desired and the order + * in which it should be stored. It can be any combination or order of R = red, G = green, B = + * blue, A = alpha, C = cyan, Y = yellow, M = magenta, K = black, I = intensity (for grayscale), + * or P = pad. + * @param type [Magick::StorageType] A StorageType value that specifies the C datatype to which + * the pixel data will be converted. + * @return [String] the pixel data */ VALUE Image_export_pixels_to_str(int argc, VALUE *argv, VALUE self) { Image *image; @@ -6607,11 +6408,10 @@ size_t sz; unsigned int okay; const char *map = "RGB"; StorageType type = CharPixel; VALUE string; - char *str; ExceptionInfo *exception; image = rm_check_destroyed(self); cols = image->columns; rows = image->rows; @@ -6619,11 +6419,11 @@ switch (argc) { case 6: VALUE_TO_ENUM(argv[5], type, StorageType); case 5: - map = StringValuePtr(argv[4]); + map = StringValueCStr(argv[4]); case 4: rows = NUM2ULONG(argv[3]); case 3: cols = NUM2ULONG(argv[2]); case 2: @@ -6673,60 +6473,51 @@ } // Allocate a string long enough to hold the exported pixel data. // Get a pointer to the buffer. string = rb_str_new2(""); - (void) rb_str_resize(string, (long)(sz * npixels)); - str = StringValuePtr(string); + rb_str_resize(string, (long)(sz * npixels)); exception = AcquireExceptionInfo(); - okay = ExportImagePixels(image, x_off, y_off, cols, rows, map, type, (void *)str, exception); + okay = ExportImagePixels(image, x_off, y_off, cols, rows, map, type, (void *)RSTRING_PTR(string), exception); if (!okay) { // Let GC have the string buffer. - (void) rb_str_resize(string, 0); - CHECK_EXCEPTION() + rb_str_resize(string, 0); + CHECK_EXCEPTION(); // Should never get here... rm_magick_error("ExportImagePixels failed with no explanation."); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); RB_GC_GUARD(string); return string; } /** * The extract_info attribute reader. * - * Ruby usage: - * - @verbatim Image#extract_info @endverbatim - * - * @param self this object - * @return extract_info + * @return [Magick::Rectangle] the Rectangle object */ VALUE Image_extract_info(VALUE self) { Image *image = rm_check_destroyed(self); return Import_RectangleInfo(&image->extract_info); } /** - * The extract_info attribute reader. + * Set the extract_info attribute. * - * Ruby usage: - * - @verbatim Image#extract_info= @endverbatim - * - * @param self this object - * @param rect extract_info - * @return rect + * @param rect [Magick::Rectangle] the Rectangle object + * @return [Magick::Rectangle] the given value */ VALUE Image_extract_info_eq(VALUE self, VALUE rect) { Image *image = rm_check_frozen(self); @@ -6736,27 +6527,23 @@ /** * Get image filename. * - * Ruby usage: - * - @verbatim Image#filename @endverbatim - * - * @param self this object - * @return the filename + * @return [String] the filename */ -DEF_ATTR_READER(Image, filename, str) +VALUE +Image_filename(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, filename, str); +} /** - * Return the image filesize. + * Return the image file size. * - * Ruby usage: - * - @verbatim Image#filesize @endverbatim - * - * @param self this object - * @return the filesize + * @return [Numeric] the file size */ VALUE Image_filesize(VALUE self) { Image *image = rm_check_destroyed(self); return INT2FIX(GetBlobSize(image)); @@ -6764,15 +6551,11 @@ /** * Get filter type. * - * Ruby usage: - * - @verbatim Image#filter @endverbatim - * - * @param self this object - * @return the filter + * @return [Magick::FilterType] the filter */ VALUE Image_filter(VALUE self) { Image *image = rm_check_destroyed(self); @@ -6781,16 +6564,12 @@ /** * Set filter type. * - * Ruby usage: - * - @verbatim Image#filter= @endverbatim - * - * @param self this object - * @param filter the filter - * @return filter + * @param filter [Magick::FilterType] the filter + * @return [Magick::FilterType] the given filter */ VALUE Image_filter_eq(VALUE self, VALUE filter) { Image *image = rm_check_frozen(self); @@ -6798,25 +6577,24 @@ return filter; } /** - * Search for a region in the image that is "similar" to the target image. + * This interesting method searches for a rectangle in the image that is similar to the target. + * For the rectangle to be similar each pixel in the rectangle must match the corresponding pixel in + * the target image within the range specified by the fuzz attributes of the image and the target + * image. * - * Ruby usage: - * - @verbatim Image#find_similar_region(target) @endverbatim - * - @verbatim Image#find_similar_region(target, x) @endverbatim - * - @verbatim Image#find_similar_region(target, x, y) @endverbatim - * - * Notes: - * - Default x is 0 - * - Default y is 0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return the region + * @overload find_similar_region(target, x = 0, y = 0) + * @param target [Magick::Image, Magick::ImageList] An image that forms the target of the + * search. This image can be any size. Either an imagelist or an image. If an imagelist, uses + * the current image. + * @param x [Numeric] The starting x-offsets for the search. + * @param y [Numeric] The starting y-offsets for the search. + * @return [Array<Numeric>, nil] If the search succeeds, the return value is an array with 2 elements. + * These elements are the x- and y-offsets of the matching rectangle. + * If the search fails the return value is nil. */ VALUE Image_find_similar_region(int argc, VALUE *argv, VALUE self) { Image *image, *target; @@ -6843,11 +6621,11 @@ } exception = AcquireExceptionInfo(); okay = IsEquivalentImage(image, target, &x, &y, exception); CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); if (!okay) { return Qnil; } @@ -6886,125 +6664,94 @@ Data_Get_Struct(self, Image, image); exception = AcquireExceptionInfo(); new_image = (flipflopper)(image, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Create a vertical mirror image by reflecting the pixels around the central - * x-axis. + * Create a vertical mirror image by reflecting the pixels around the central x-axis. * - * Ruby usage: - * - @verbatim Image#flip @endverbatim - * - * @param self this object - * @return a new image - * @see flipflop - * @see Image_flip_bang - * @see Image_flop - * @see Image_flop_bang + * @return [Magick::Image] a new image + * @see Image#flip! + * @see Image#flop + * @see Image#flop! */ VALUE Image_flip(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return flipflop(False, self, FlipImage); } /** - * Create a vertical mirror image by reflecting the pixels around the central - * x-axis. + * Create a vertical mirror image by reflecting the pixels around the central x-axis. + * In-place form of {Image#flip}. * - * Ruby usage: - * - @verbatim Image#flip! @endverbatim - * - * @param self this object - * @return self - * @see flipflop - * @see Image_flip - * @see Image_flop - * @see Image_flop_bang + * @return [Magick::Image] a new image + * @see Image#flip + * @see Image#flop + * @see Image#flop! */ VALUE Image_flip_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return flipflop(True, self, FlipImage); } /** - * Create a horizonal mirror image by reflecting the pixels around the central - * y-axis. + * Create a horizonal mirror image by reflecting the pixels around the central y-axis. * - * Ruby usage: - * - @verbatim Image#flop @endverbatim - * - * @param self this object - * @return a new image - * @see flipflop - * @see Image_flop_bang - * @see Image_flip - * @see Image_flip_bang + * @return [Magick::Image] a new image + * @see Image#flop! + * @see Image#flip + * @see Image#flip! */ VALUE Image_flop(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return flipflop(False, self, FlopImage); } /** - * Create a horizonal mirror image by reflecting the pixels around the central - * y-axis. + * Create a horizonal mirror image by reflecting the pixels around the central y-axis. + * In-place form of {Image#flop}. * - * Ruby usage: - * - @verbatim Image#flop! @endverbatim - * - * @param self this object - * @return self - * @see flipflop - * @see Image_flop - * @see Image_flip - * @see Image_flip_bang + * @return [Magick::Image] a new image + * @see Image#flop + * @see Image#flip + * @see Image#flip! */ VALUE Image_flop_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return flipflop(True, self, FlopImage); } /** - * Return the image encoding format. + * Return the image encoding format. For example, "GIF" or "PNG". * - * Ruby usage: - * - @verbatim Image#format @endverbatim - * - * Notes: - * - This is what PerlMagick does for "format". - * - * @param self this object - * @return the encoding format + * @return [String, nil] the encoding format */ VALUE Image_format(VALUE self) { Image *image; @@ -7016,27 +6763,23 @@ if (*image->magick) { // Deliberately ignore the exception info! exception = AcquireExceptionInfo(); magick_info = GetMagickInfo(image->magick, exception); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return magick_info ? rb_str_new2(magick_info->name) : Qnil; } return Qnil; } /** - * Set the image encoding format. + * Set the image encoding format. For example, "GIF" or "PNG". * - * Ruby usage: - * - @verbatim Image#format= @endverbatim - * - * @param self this object - * @param magick the encoding format - * @return magick + * @param magick [String] the encoding format + * @return [String] the given value */ VALUE Image_format_eq(VALUE self, VALUE magick) { Image *image; @@ -7044,64 +6787,41 @@ char *mgk; ExceptionInfo *exception; image = rm_check_frozen(self); - mgk = StringValuePtr(magick); + mgk = StringValueCStr(magick); exception = AcquireExceptionInfo(); m = GetMagickInfo(mgk, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); if (!m) { rb_raise(rb_eArgError, "unknown format: %s", mgk); } - strncpy(image->magick, m->name, MaxTextExtent-1); + strlcpy(image->magick, m->name, sizeof(image->magick)); return magick; } /** - * Add a simulated three-dimensional border around the image. "Width" and - * "height" specify the width and height of the frame. The "x" and "y" arguments - * position the image within the frame. If the image is supposed to be centered - * in the frame, x and y should be 1/2 the width and height of the frame. (I.e., - * if the frame is 50 pixels high and 50 pixels wide, x and y should both be - * 25). "Inner_bevel" and "outer_bevel" indicate the width of the inner and - * outer shadows of the frame. They should be much smaller than the frame and - * cannot be > 1/2 the frame width or height of the image. + * Add a simulated three-dimensional border around the image. * - * Ruby usage: - * - @verbatim Image#frame @endverbatim - * - @verbatim Image#frame(width) @endverbatim - * - @verbatim Image#frame(width, height) @endverbatim - * - @verbatim Image#frame(width, height, x) @endverbatim - * - @verbatim Image#frame(width, height, x, y) @endverbatim - * - @verbatim Image#frame(width, height, x, y, inner_bevel) @endverbatim - * - @verbatim Image#frame(width, height, x, y, inner_bevel, outer_bevel) @endverbatim - * - @verbatim Image#frame(width, height, x, y, inner_bevel, outer_bevel, color) @endverbatim - * - * Notes: - * - The defaults are the same as they are in Magick++ - * - Default width is image-columns+25*2 - * - Default height is image-rows+25*2 - * - Default x is 25 - * - Default y is 25 - * - Default inner is 6 - * - Default outer is 6 - * - Default color is image matte_color (which defaults to "#bdbdbd", whatever - * self.matte_color was set to when the image was created, or whatever - * image.matte_color is currently set to) - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image. + * @overload frame(width = self.columns+25*2, height = self.rows+25*2, x = 25, y = 25, inner_bevel = 6, outer_bevel = 6, color = self.matte_color) + * @param width [Numeric] The width of the left and right sides. + * @param height [Numeric] The height of the top and bottom sides. + * @param x [Numeric] The offset of the image from the upper-left outside corner of the border. + * @param y [Numeric] The offset of the image from the upper-left outside corner of the border. + * @param inner_bevel [Numeric] The width of the inner shadows of the border. + * @param outer_bevel [Numeric] The width of the outer shadows of the border. + * @param color [Magick::Pixel, String] The border color. + * @return [Magick::Image] a new image. */ VALUE Image_frame(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7145,28 +6865,29 @@ new_image = FrameImage(image, &frame_info, image->compose, exception); #else new_image = FrameImage(image, &frame_info, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call BlobToImage. + * Convert direct to memory image formats from string data. * - * Ruby usage: - * - @verbatim Image.from_blob(blob) <{ parm block }> @endverbatim + * @overload from_blob(blob) + * @param blob [String] the blob data * - * @param class the Ruby Image class (unused) - * @param blob_arg the blob as a Ruby string - * @return an array of new images + * @overload from_blob(blob) + * This yields {Magick::Image::Info} to block with its object's scope. + * @param blob [String] the blob data + * @yield [] + * + * @return [Array<Magick::Image>] an array of new images + * @see Image#to_blob */ VALUE Image_from_blob(VALUE class ATTRIBUTE_UNUSED, VALUE blob_arg) { Image *images; @@ -7184,11 +6905,11 @@ exception = AcquireExceptionInfo(); images = BlobToImage(info, blob, (size_t)length, exception); rm_check_exception(exception, images, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_ensure_result(images); rm_set_user_artifact(images, info); RB_GC_GUARD(info_obj); @@ -7198,22 +6919,27 @@ /** * Set the function on a channel. * - * Ruby usage: - * - @verbatim Image#function_channel(function, args) @endverbatim - * - @verbatim Image#function_channel(function, args, channel) @endverbatim - * - @verbatim Image#function_channel(function, args, channel, ...) @endverbatim + * @overload function_channel(function, *args, channel = Magick::AllChannels) + * @param function [Magick::MagickFunction] the function + * @param *args [Float] One or more floating-point numbers. + * The number of parameters depends on the function. See the ImageMagick documentation for + * details. + + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload function_channel(function, *args, *channels) + * @param function [Magick::MagickFunction] the function + * @param *args [Float] One or more floating-point numbers. + * The number of parameters depends on the function. See the ImageMagick documentation for + * details. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image + * @see https://www.imagemagick.org/script/command-line-options.php#function */ VALUE Image_function_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7276,47 +7002,45 @@ exception = AcquireExceptionInfo(); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(new_image, channels); - (void) FunctionImage(new_image, function, nparms, parms, exception); + FunctionImage(new_image, function, nparms, parms, exception); END_CHANNEL_MASK(new_image); #else - (void) FunctionImageChannel(new_image, channels, function, nparms, parms, exception); + FunctionImageChannel(new_image, channels, function, nparms, parms, exception); #endif - (void) xfree(parms); + xfree(parms); rm_check_exception(exception, new_image, DestroyOnError); DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Get image fuzz. + * Get the number of algorithms search for a target color. + * By default the color must be exact. + * Use this attribute to match colors that are close to the target color in RGB space. * - * Ruby usage: - * - @verbatim Image#fuzz @endverbatim - * - * @param self this object - * @return the fuzz - * @see Info_fuzz + * @return [Float] the fuzz + * @see Info#fuzz */ -DEF_ATTR_READER(Image, fuzz, dbl) +VALUE +Image_fuzz(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, fuzz, dbl); +} /** - * Set image fuzz. + * Set the number of algorithms search for a target color. * - * Ruby usage: - * - @verbatim Image#fuzz=number @endverbatim - * - @verbatim Image#fuzz=NN% @endverbatim - * - * @param self this object - * @param fuzz the fuzz - * @return fuzz - * @see Info_fuzz_eq + * @param fuzz [String, Float] The argument may be a floating-point numeric value or a string in the + * form "NN%". + * @return [String, Float] the given value + * @see Info#fuzz= */ VALUE Image_fuzz_eq(VALUE self, VALUE fuzz) { Image *image = rm_check_frozen(self); @@ -7326,22 +7050,19 @@ /** * Apply fx on the image. * - * Ruby usage: - * - @verbatim Image#fx(expression) @endverbatim - * - @verbatim Image#fx(expression, channel) @endverbatim - * - @verbatim Image#fx(expression, channel, ...) @endverbatim + * @overload fx(expression, channel = Magick::AllChannels) + * @param expression [String] A mathematical expression + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload fx(expression, *channels) + * @param expression [String] A mathematical expression + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_fx(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7360,11 +7081,11 @@ else if (argc > 1) { raise_ChannelType_error(argv[argc-1]); } - expression = StringValuePtr(argv[0]); + expression = StringValueCStr(argv[0]); exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); new_image = FxImage(image, expression, exception); @@ -7372,36 +7093,53 @@ END_CHANNEL_MASK(image); #else new_image = FxImageChannel(image, channels, expression, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } +/** + * Get the gamma level of the image. + * + * @return [Float] the gamma level + */ +VALUE +Image_gamma(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, gamma, dbl); +} -DEF_ATTR_ACCESSOR(Image, gamma, dbl) +/** + * Set the gamma level of the image. + * + * @param val [Float] the gamma level + * @return [Float] the gamma level + */ +VALUE +Image_gamma_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, gamma, dbl); +} /** * Apply gamma to a channel. * - * Ruby usage: - * - @verbatim Image#gamma_channel(gamma) @endverbatim - * - @verbatim Image#gamma_channel(gamma, channel) @endverbatim - * - @verbatim Image#gamma_channel(gamma, channel, ...) @endverbatim + * @overload gamma_channel(gamma, channel = Magick::AllChannels) + * @param Values gamma [Float] typically range from 0.8 to 2.3. You can also reduce the influence + * of a particular channel with a gamma value of 0. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload gamma_channel(gamma, *channels) + * @param Values gamma [Float] typically range from 0.8 to 2.3. You can also reduce the influence + * of a particular channel with a gamma value of 0. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_gamma_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7428,40 +7166,28 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) GammaImage(new_image, gamma, exception); + GammaImage(new_image, gamma, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) GammaImageChannel(new_image, channels, gamma); + GammaImageChannel(new_image, channels, gamma); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** * gamma-correct an image. * - * Ruby usage: - * - @verbatim Image#gamma_correct(red_gamma) @endverbatim - * - @verbatim Image#gamma_correct(red_gamma, green_gamma) @endverbatim - * - @verbatim Image#gamma_correct(red_gamma, green_gamma, blue_gamma) @endverbatim - * - * Notes: - * - Default green_gamma is red_gamma - * - Default blue_gamma is green_gamma - * - For backward compatibility accept a 4th argument but ignore it. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload gamma_correct(red_gamma, green_gamma = red_gamma, blue_gamma = green_gamma) + * @return [Magick::Image] a new image */ VALUE Image_gamma_correct(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7501,40 +7227,40 @@ if ((red_gamma == green_gamma) && (green_gamma == blue_gamma)) { #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(new_image, (ChannelType) (RedChannel | GreenChannel | BlueChannel)); - (void) GammaImage(new_image, red_gamma, exception); + GammaImage(new_image, red_gamma, exception); END_CHANNEL_MASK(new_image); #else - (void) GammaImageChannel(new_image, (ChannelType) (RedChannel | GreenChannel | BlueChannel), red_gamma); + GammaImageChannel(new_image, (ChannelType) (RedChannel | GreenChannel | BlueChannel), red_gamma); #endif } else { #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(new_image, RedChannel); - (void) GammaImage(new_image, red_gamma, exception); + GammaImage(new_image, red_gamma, exception); END_CHANNEL_MASK(new_image); BEGIN_CHANNEL_MASK(new_image, GreenChannel); - (void) GammaImage(new_image, green_gamma, exception); + GammaImage(new_image, green_gamma, exception); END_CHANNEL_MASK(new_image); BEGIN_CHANNEL_MASK(new_image, BlueChannel); - (void) GammaImage(new_image, blue_gamma, exception); + GammaImage(new_image, blue_gamma, exception); END_CHANNEL_MASK(new_image); #else - (void) GammaImageChannel(new_image, RedChannel, red_gamma); - (void) GammaImageChannel(new_image, GreenChannel, green_gamma); - (void) GammaImageChannel(new_image, BlueChannel, blue_gamma); + GammaImageChannel(new_image, RedChannel, red_gamma); + GammaImageChannel(new_image, GreenChannel, green_gamma); + GammaImageChannel(new_image, BlueChannel, blue_gamma); #endif } #if defined(IMAGEMAGICK_7) - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); @@ -7542,48 +7268,36 @@ /** * Blur the image. * - * Ruby usage: - * - @verbatim Image#gaussian_blur @endverbatim - * - @verbatim Image#gaussian_blur(radius) @endverbatim - * - @verbatim Image#gaussian_blur(radius, sigma) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see effect_image + * @overload gaussian_blur(radius = 0.0, sigma = 1.0) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @return [Magick::Image] a new image */ VALUE Image_gaussian_blur(int argc, VALUE *argv, VALUE self) { return effect_image(self, argc, argv, GaussianBlurImage); } /** * Blur the image on a channel. - * Ruby usage: - * - @verbatim Image#gaussian_blur_channel @endverbatim - * - @verbatim Image#gaussian_blur_channel(radius) @endverbatim - * - @verbatim Image#gaussian_blur_channel(radius, sigma) @endverbatim - * - @verbatim Image#gaussian_blur_channel(radius, sigma, channel) @endverbatim - * - @verbatim Image#gaussian_blur_channel(radius, sigma, channel, ...) @endverbatim * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default channel is AllChannels - * - New in IM 6.0.0 + * @overload gaussian_blur_channel(radius = 0.0, sigma = 1.0, channel = Magick::AllChannels) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @param channel [Magick::ChannelType] a ChannelType arguments. * + * @overload gaussian_blur_channel(radius = 0.0, sigma = 1.0, *channels) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * + * @return [Magick::Image] a new image */ VALUE Image_gaussian_blur_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7619,37 +7333,35 @@ #else new_image = GaussianBlurImageChannel(image, channels, radius, sigma, exception); rm_check_exception(exception, new_image, DestroyOnError); #endif - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** * Get the preferred size of the image when encoding. * - * Ruby usage: - * - @verbatim Image#geometry @endverbatim - * - * @param self this object - * @return the geometry + * @return [String] the geometry + * @see https://www.imagemagick.org/Magick++/Geometry.html */ -DEF_ATTR_READER(Image, geometry, str) +VALUE +Image_geometry(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, geometry, str); +} /** * Set the preferred size of the image when encoding. * - * Ruby usage: - * - @verbatim Image#geometry= @endverbatim - * - * @param self this object - * @param geometry the geometry - * @return geometry + * @param geometry [String] the geometry + * @return [String] the given geometry + * @see https://www.imagemagick.org/Magick++/Geometry.html */ VALUE Image_geometry_eq(VALUE self, VALUE geometry) { Image *image; @@ -7664,12 +7376,12 @@ image->geometry = NULL; return self; } - geom_str = rm_to_s(geometry); - geom = StringValuePtr(geom_str); + geom_str = rb_String(geometry); + geom = StringValueCStr(geom_str); if (!IsGeometry(geom)) { rb_raise(rb_eTypeError, "invalid geometry: %s", geom); } magick_clone_string(&image->geometry, geom); @@ -7679,28 +7391,19 @@ return geometry; } /** - * Call AcquireImagePixels. + * Gets the pixels from the specified rectangle within the image. * - * Ruby usage: - * - @verbatim Image#get_pixels(x, y, columns. rows) @endverbatim - * - * Notes: - * - This is the complement of store_pixels. Notice that the return value is - * an array object even when only one pixel is returned. store_pixels calls - * GetImagePixels, then SyncImage - * - * @param self this object - * @param x_arg x position of start of region - * @param y_arg y position of start of region - * @param cols_arg width of region - * @param rows_arg height of region - * @return An array of Magick::Pixel objects corresponding to the pixels in the - * rectangle defined by the geometry parameters. - * @see Image_store_pixels + * @param x_arg [Numeric] x position of start of region + * @param y_arg [Numeric] y position of start of region + * @param cols_arg [Numeric] width of region + * @param rows_arg [Numeric] height of region + * @return [Array<Magick::Pixel>] An array of Magick::Pixel objects corresponding to the pixels in the rectangle + * defined by the geometry parameters. + * @see Image#store_pixels */ VALUE Image_get_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg, VALUE rows_arg) { Image *image; @@ -7711,31 +7414,32 @@ VALUE pixel_ary; #if defined(IMAGEMAGICK_7) const Quantum *pixels; #else const PixelPacket *pixels; + const IndexPacket *indexes; #endif image = rm_check_destroyed(self); x = NUM2LONG(x_arg); y = NUM2LONG(y_arg); columns = NUM2ULONG(cols_arg); rows = NUM2ULONG(rows_arg); if ((x+columns) > image->columns || (y+rows) > image->rows) { - rb_raise(rb_eRangeError, "geometry (%lux%lu%+ld%+ld) exceeds image bounds" - , columns, rows, x, y); + rb_raise(rb_eRangeError, "geometry (%lux%lu%+ld%+ld) exceeds image bounds", + columns, rows, x, y); } // Cast AcquireImagePixels to get rid of the const qualifier. We're not going // to change the pixels but I don't want to make "pixels" const. exception = AcquireExceptionInfo(); pixels = GetVirtualPixels(image, x, y, columns, rows, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); // If the function failed, return a 0-length array. if (!pixels) { return rb_ary_new(); @@ -7743,25 +7447,40 @@ // Allocate an array big enough to contain the PixelPackets. size = (long)(columns * rows); pixel_ary = rb_ary_new2(size); +#if defined(IMAGEMAGICK_6) + indexes = GetVirtualIndexQueue(image); +#endif + // Convert the PixelPackets to Magick::Pixel objects for (n = 0; n < size; n++) { #if defined(IMAGEMAGICK_7) PixelPacket color; memset(&color, 0, sizeof(color)); color.red = GetPixelRed(image, pixels); color.green = GetPixelGreen(image, pixels); color.blue = GetPixelBlue(image, pixels); color.alpha = GetPixelAlpha(image, pixels); + color.black = GetPixelBlack(image, pixels); rb_ary_store(pixel_ary, n, Pixel_from_PixelPacket(&color)); pixels += GetPixelChannels(image); #else - rb_ary_store(pixel_ary, n, Pixel_from_PixelPacket(&pixels[n])); + MagickPixel mpp; + mpp.red = GetPixelRed(pixels); + mpp.green = GetPixelGreen(pixels); + mpp.blue = GetPixelBlue(pixels); + mpp.opacity = GetPixelOpacity(pixels); + if (indexes) + { + mpp.index = GetPixelIndex(indexes + n); + } + rb_ary_store(pixel_ary, n, Pixel_from_MagickPixel(&mpp)); + pixels++; #endif } return pixel_ary; } @@ -7785,12 +7504,12 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); return r ? Qtrue : Qfalse; } @@ -7817,19 +7536,13 @@ } #endif /** - * Return true if all the pixels in the image have the same red, green, and blue - * intensities. + * Return true if all the pixels in the image have the same red, green, and blue intensities. * - * Ruby usage: - * - @verbatim Image#gray? @endverbatim - * - * @param self this object - * @return true if image is gray, false otherwise - * @see has_attribute + * @return [Boolean] true if image is gray, false otherwise */ VALUE Image_gray_q(VALUE self) { #if defined(HAVE_SETIMAGEGRAY) @@ -7860,16 +7573,11 @@ /** * Return true if has 1024 unique colors or less. * - * Ruby usage: - * - @verbatim Image#histogram? @endverbatim - * - * @param self this object - * @return true if image has <=1024 unique colors - * @see has_attribute + * @return [Boolean] true if image has <= 1024 unique colors */ VALUE Image_histogram_q(VALUE self) { return has_attribute(self, IsHistogramImage); @@ -7877,21 +7585,12 @@ /** * Implode the image by the specified percentage. * - * Ruby usage: - * - @verbatim Image#implode @endverbatim - * - @verbatim Image#implode(amount) @endverbatim - * - * Notes: - * - Default amount is 0.50 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload implode(amount = 0.50) + * @return [Magick::Image] a new image */ VALUE Image_implode(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -7915,29 +7614,32 @@ new_image = ImplodeImage(image, amount, image->interpolate, exception); #else new_image = ImplodeImage(image, amount, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Store image pixel data from an array. * - * Ruby usage: - * - @verbatim Image#import_pixels @endverbatim - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see Image_export_pixels + * @overload store_pixels(x, y, columns, rows, map, pixels, type = Magick::CharPixel) + * @param x [Numeric] The x-offset of the rectangle to be replaced. + * @param y [Numeric] The y-offset of the rectangle to be replaced. + * @param columns [Numeric] The number of columns in the rectangle. + * @param rows [Numeric] The number of rows in the rectangle. + * @param map [String] his string reflects the expected ordering of the pixel array. + * @param pixels [Array] An array of pixels. + * The number of pixels in the array must be the same as the number + * of pixels in the rectangle, that is, rows*columns. + * @param type [Magick::StorageType] A StorageType value that specifies the C datatype to which + * the pixel data will be converted. + * @return [Magick::Image] self + * @see Image#export_pixels */ VALUE Image_import_pixels(int argc, VALUE *argv, VALUE self) { Image *image; @@ -7966,11 +7668,11 @@ case 6: x_off = NUM2LONG(argv[0]); y_off = NUM2LONG(argv[1]); cols = NUM2ULONG(argv[2]); rows = NUM2ULONG(argv[3]); - map = StringValuePtr(argv[4]); + map = StringValueCStr(argv[4]); pixel_arg = argv[5]; break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 6 or 7)", argc); break; @@ -7979,11 +7681,11 @@ if (x_off < 0 || y_off < 0 || cols <= 0 || rows <= 0) { rb_raise(rb_eArgError, "invalid import geometry"); } - map_l = strlen(map); + map_l = rm_strnlen_s(map, MaxTextExtent); npixels = cols * rows * map_l; // Assume that any object that responds to :to_str is a string buffer containing // binary pixel data. if (rb_respond_to(pixel_arg, rb_intern("to_str"))) @@ -8022,12 +7724,12 @@ { rb_raise(rb_eArgError, "pixel buffer must contain an exact multiple of the map length"); } if ((unsigned long)(buffer_l / type_sz) < npixels) { - rb_raise(rb_eArgError, "pixel buffer too small (need %lu channel values, got %ld)" - , npixels, buffer_l/type_sz); + rb_raise(rb_eArgError, "pixel buffer too small (need %lu channel values, got %"RMIuSIZE")", + npixels, buffer_l/type_sz); } } // Otherwise convert the argument to an array and convert the array elements // to binary pixel data. else @@ -8040,12 +7742,12 @@ { rb_raise(rb_eArgError, "pixel array must contain an exact multiple of the map length"); } if ((unsigned long)RARRAY_LEN(pixel_ary) < npixels) { - rb_raise(rb_eArgError, "pixel array too small (need %lu elements, got %ld)" - , npixels, RARRAY_LEN(pixel_ary)); + rb_raise(rb_eArgError, "pixel array too small (need %lu elements, got %ld)", + npixels, RARRAY_LEN(pixel_ary)); } if (stg_type == DoublePixel || stg_type == FloatPixel) { fpixels = ALLOC_N(double, npixels); @@ -8105,20 +7807,20 @@ } if (!okay) { #if defined(IMAGEMAGICK_7) - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else rm_check_image_exception(image, RetainOnError); #endif // Shouldn't get here... rm_magick_error("ImportImagePixels failed with no explanation."); } #if defined(IMAGEMAGICK_7) - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif RB_GC_GUARD(pixel_arg); RB_GC_GUARD(pixel_ary); @@ -8147,103 +7849,103 @@ int x = 0; // # bytes used in buffer // Print magick filename if different from current filename. if (*image->magick_filename != '\0' && strcmp(image->magick_filename, image->filename) != 0) { - x += sprintf(buffer+x, "%.1024s=>", image->magick_filename); + x += snprintf(buffer+x, len-x, "%.1024s=>", image->magick_filename); } // Print current filename. - x += sprintf(buffer+x, "%.1024s", image->filename); + x += snprintf(buffer+x, len-x, "%.1024s", image->filename); // Print scene number. if ((GetPreviousImageInList(image) != NULL) && (GetNextImageInList(image) != NULL) && image->scene > 0) { - x += sprintf(buffer+x, "[%lu]", image->scene); + x += snprintf(buffer+x, len-x, "[%"RMIuSIZE"]", image->scene); } // Print format - x += sprintf(buffer+x, " %s ", image->magick); + x += snprintf(buffer+x, len-x, " %s ", image->magick); // Print magick columnsXrows if different from current. if (image->magick_columns != 0 || image->magick_rows != 0) { if (image->magick_columns != image->columns || image->magick_rows != image->rows) { - x += sprintf(buffer+x, "%lux%lu=>", image->magick_columns, image->magick_rows); + x += snprintf(buffer+x, len-x, "%"RMIuSIZE"x%"RMIuSIZE"=>", image->magick_columns, image->magick_rows); } } - x += sprintf(buffer+x, "%lux%lu ", image->columns, image->rows); + x += snprintf(buffer+x, len-x, "%"RMIuSIZE"x%"RMIuSIZE" ", image->columns, image->rows); // Print current columnsXrows if ( image->page.width != 0 || image->page.height != 0 || image->page.x != 0 || image->page.y != 0) { - x += sprintf(buffer+x, "%lux%lu%+ld%+ld ", image->page.width, image->page.height - , image->page.x, image->page.y); + x += snprintf(buffer+x, len-x, "%"RMIuSIZE"x%"RMIuSIZE"+%"RMIdSIZE"+%"RMIdSIZE" ", + image->page.width, image->page.height, + image->page.x, image->page.y); } if (image->storage_class == DirectClass) { - x += sprintf(buffer+x, "DirectClass "); + x += snprintf(buffer+x, len-x, "DirectClass "); if (image->total_colors != 0) { if (image->total_colors >= (unsigned long)(1 << 24)) { - x += sprintf(buffer+x, "%lumc ", image->total_colors/1024/1024); + x += snprintf(buffer+x, len-x, "%"RMIuSIZE"mc ", image->total_colors/1024/1024); } else { if (image->total_colors >= (unsigned long)(1 << 16)) { - x += sprintf(buffer+x, "%lukc ", image->total_colors/1024); + x += snprintf(buffer+x, len-x, "%"RMIuSIZE"kc ", image->total_colors/1024); } else { - x += sprintf(buffer+x, "%luc ", image->total_colors); + x += snprintf(buffer+x, len-x, "%"RMIuSIZE"c ", image->total_colors); } } } } else { // Cast `image->colors' to long to suppress gcc warnings when // building with GM. GM defines that field as an unsigned int. if (image->total_colors <= image->colors) { - x += sprintf(buffer+x, "PseudoClass %ldc ", (long) image->colors); + x += snprintf(buffer+x, len-x, "PseudoClass %ldc ", (long) image->colors); } else { - x += sprintf(buffer+x, "PseudoClass %lu=>%ldc ", image->total_colors - , (long)image->colors); + x += snprintf(buffer+x, len-x, "PseudoClass %"RMIuSIZE"=>%"RMIuSIZE"c ", image->total_colors, image->colors); if (image->error.mean_error_per_pixel != 0.0) { - x += sprintf(buffer+x, "%ld/%.6f/%.6fdb " - , (long) (image->error.mean_error_per_pixel+0.5) - , image->error.normalized_mean_error - , image->error.normalized_maximum_error); + x += snprintf(buffer+x, len-x, "%ld/%.6f/%.6fdb ", + (long) (image->error.mean_error_per_pixel+0.5), + image->error.normalized_mean_error, + image->error.normalized_maximum_error); } } } // Print bit depth quantum_depth = GetImageQuantumDepth(image, MagickTrue); - x += sprintf(buffer+x, "%lu-bit", quantum_depth); + x += snprintf(buffer+x, len-x, "%lu-bit", quantum_depth); // Print blob info if appropriate. if (GetBlobSize(image) != 0) { if (GetBlobSize(image) >= (1 << 24)) { - x += sprintf(buffer+x, " %lumb", (unsigned long) (GetBlobSize(image)/1024/1024)); + x += snprintf(buffer+x, len-x, " %lumb", (unsigned long) (GetBlobSize(image)/1024/1024)); } else if (GetBlobSize(image) >= 1024) { - x += sprintf(buffer+x, " %lukb", (unsigned long) (GetBlobSize(image)/1024)); + x += snprintf(buffer+x, len-x, " %lukb", (unsigned long) (GetBlobSize(image)/1024)); } else { - x += sprintf(buffer+x, " %lub", (unsigned long) GetBlobSize(image)); + x += snprintf(buffer+x, len-x, " %lub", (unsigned long) GetBlobSize(image)); } } if (len-1-x > 6) @@ -8253,11 +7955,11 @@ if (value) { strcpy(buffer+x, " user:"); x += 6; value_l = len - x - 1; - value_l = min(strlen(value), value_l); + value_l = min(rm_strnlen_s(value, MaxTextExtent), value_l); memcpy(buffer+x, value, value_l); x += value_l; } } @@ -8267,22 +7969,13 @@ return; } /** - * Override Object#inspect - return a string description of the image. + * Override {Object#inspect} - return a string description of the image. * - * Ruby usage: - * - @verbatim Image#inspect @endverbatim - * - * Notes: - * - This is essentially the IdentifyImage except the description is built in - * a char buffer instead of being written to a file. - * - * @param self this object - * @return the string - * @see build_inspect_string + * @return [String] the string */ VALUE Image_inspect(VALUE self) { Image *image; @@ -8297,35 +7990,32 @@ return rb_str_new2(buffer); } /** - * Get the interlace attribute. + * Get the type of interlacing scheme (default NoInterlace). + * This option is used to specify the type of interlacing scheme for raw image formats such as RGB + * or YUV. + * NoInterlace means do not interlace, LineInterlace uses scanline interlacing, and PlaneInterlace + * uses plane interlacing. PartitionInterlace is like PlaneInterlace except the different planes are + * saved to individual files (e.g. image.R, image.G, and image.B). * - * Ruby usage: - * - @verbatim Image#interlace @endverbatim - * - * @param self this object - * @return the interlace + * @return [Magick::InterlaceType] the interlace */ VALUE Image_interlace(VALUE self) { Image *image = rm_check_destroyed(self); return InterlaceType_find(image->interlace); } /** - * Set the interlace attribute. + * Set the type of interlacing scheme. * - * Ruby usage: - * - @verbatim Image#interlace= @endverbatim - * - * @param self this object - * @param interlace the interlace - * @return interlace + * @param interlace [Magick::InterlaceType] the interlace + * @return [Magick::InterlaceType] the given value */ VALUE Image_interlace_eq(VALUE self, VALUE interlace) { Image *image = rm_check_frozen(self); @@ -8335,15 +8025,11 @@ /** * Return the IPTC profile as a String. * - * Ruby usage: - * - @verbatim Image#iptc_profile @endverbatim - * - * @param self - * @return the IPTC profile if it exists, otherwise nil + * @return [String, nil] the IPTC profile if it exists, otherwise nil */ VALUE Image_iptc_profile(VALUE self) { Image *image; @@ -8363,57 +8049,50 @@ /** * Set the IPTC profile. The argument is a string. * - * Ruby usage: - * - @verbatim Image#iptc_profile= @endverbatim - * - * Notes: - * - Pass nil to remove any existing profile - * - * @param self - * @param profile the IPTC profile (as a string) - * @return profile + * @param profile [String] the IPTC profile + * @return [String] the given profile */ VALUE Image_iptc_profile_eq(VALUE self, VALUE profile) { - (void) Image_delete_profile(self, rb_str_new2("iptc")); + Image_delete_profile(self, rb_str_new2("iptc")); if (profile != Qnil) { - (void) set_profile(self, "iptc", profile); + set_profile(self, "iptc", profile); } return profile; } /* * These are undocumented methods. The writer is * called only by Image#iterations=. * The reader is only used by the unit tests! */ -DEF_ATTR_ACCESSOR(Image, iterations, int) +VALUE +Image_iterations(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, iterations, int); +} +VALUE +Image_iterations_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, iterations, int); +} /** - * Adjust the levels of an image given these points: black, mid, and white. + * Adjusts the levels of an image by scaling the colors falling between specified white and black + * points to the full available quantum range. * - * Ruby usage: - * - @verbatim Image#level @endverbatim - * - @verbatim Image#level(black_point) @endverbatim - * - @verbatim Image#level(black_point, white_point) @endverbatim - * - @verbatim Image#level(black_point, white_point, gamma) @endverbatim - * - * Notes: - * - Default black_point is 0.0 - * - Default white_point is QuantumRange - * - Default gamma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload level2(black_point = 0.0, white_point = Magick::QuantumRange, gamma = 1.0) + * @param black_point [Float] A black point level in the range 0 - QuantumRange. + * @param white_point [Float] A white point level in the range 0..QuantumRange. + * @param gamma [Float] A gamma correction in the range 0.0 - 10.0. + * @return [Magick::Image] a new image */ VALUE Image_level2(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -8449,42 +8128,33 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) LevelImage(new_image, black_point, white_point, gamma_val, exception); + LevelImage(new_image, black_point, white_point, gamma_val, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - sprintf(level, "%gx%g+%g", black_point, white_point, gamma_val); - (void) LevelImage(new_image, level); + snprintf(level, sizeof(level), "%gx%g+%g", black_point, white_point, gamma_val); + LevelImage(new_image, level); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Similar to Image#level but applies to a single channel only. + * Similar to {Image#level2} but applies to a single channel only. * - * Ruby usage: - * - @verbatim Image#level_channel(aChannelType) @endverbatim - * - @verbatim Image#level_channel(aChannelType, black) @endverbatim - * - @verbatim Image#level_channel(aChannelType, black, white) @endverbatim - * - @verbatim Image#level_channel(aChannelType, black, white, gamma) @endverbatim - * - * Notes: - * - Default black is 0.0 - * - Default white is QuantumRange - * - Default gamma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see Image_level2 + * @overload level_channel(aChannelType, black = 0.0, white = 1.0, gamma = Magick::QuantumRange) + * @param aChannelType [Magick::ChannelType] A ChannelType value. + * @param black [Float] A black point level in the range 0..QuantumRange. + * @param white [Float] A white point level in the range 0..QuantumRange. + * @param gamma [Float] A gamma correction in the range 0.0 - 10.0. + * @return [Magick::Image] a new image + * @see Image#level2 */ VALUE Image_level_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -8522,44 +8192,41 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channel); - (void) LevelImage(new_image, black_point, white_point, gamma_val, exception); + LevelImage(new_image, black_point, white_point, gamma_val, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) LevelImageChannel(new_image, channel, black_point, white_point, gamma_val); + LevelImageChannel(new_image, channel, black_point, white_point, gamma_val); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Implement +level_colors blank_color,white_color. + * When invert is true, black and white will be mapped to the black_color and white_color colors, + * compressing all other colors linearly. When invert is false, black and white will be mapped to + * the black_color and white_color colors, stretching all other colors linearly. * - * Ruby usage: - * - @verbatim Image#level_colors @endverbatim - * - @verbatim Image#level_colors(black_color) @endverbatim - * - @verbatim Image#level_colors(black_color, white_color) @endverbatim - * - @verbatim Image#level_colors(black_color, white_color, invert) @endverbatim - * - @verbatim Image#level_colors(black_color, white_color, invert, channel) @endverbatim - * - @verbatim Image#level_colors(black_color, white_color, invert, channel, ...) @endverbatim + * @overload level_colors(black_color = "black", white_color = "white", invert = true, channel = Magick::AllChannels) + * @param black_color [Magick::Pixel, String] The color to be mapped to black + * @param white_color [Magick::Pixel, String] The color to be mapped to white + * @param invert See the description above + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default black_color is "black" - * - Default white_color is "white" - * - Default invert is true - * - Default channel is AllChannels + * @overload level_colors(black_color = "black", white_color = "white", invert = true, *channels) + * @param black_color [Magick::Pixel, String] The color to be mapped to black + * @param white_color [Magick::Pixel, String] The color to be mapped to white + * @param invert See the description above + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_level_colors(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -8609,11 +8276,11 @@ exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); status = LevelImageColors(new_image, &black_color, &white_color, invert, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else status = LevelColorsImageChannel(new_image, channels, &black_color, &white_color, invert); rm_check_image_exception(new_image, DestroyOnError); #endif if (!status) @@ -8625,28 +8292,24 @@ } /** - * Levelize on a channel. + * Maps black and white to the specified points. The reverse of {Image#level_channel}. * - * Ruby usage: - * - @verbatim Image#levelize_channel(black_point) @endverbatim - * - @verbatim Image#levelize_channel(black_point, white_point) @endverbatim - * - @verbatim Image#levelize_channel(black_point, white_point, gamma) @endverbatim - * - @verbatim Image#levelize_channel(black_point, white_point, gamma, channel) @endverbatim - * - @verbatim Image#levelize_channel(black_point, white_point, gamma, channel, ...) @endverbatim + * @overload levelize_channel(black_point, white_point = Magick::QuantumRange - black_point, gamma = 1.0, channel = Magick::AllChannels) + * @param black [Float] A black point level in the range 0..QuantumRange. + * @param white [Float] A white point level in the range 0..QuantumRange. + * @param gamma [Float] A gamma correction in the range 0.0 - 10.0. * - * Notes: - * - Default white_point is QuantumRange - * - Default gamma is 1.0 - * - Default channel is AllChannels + * @overload levelize_channel(black_point, white_point = Magick::QuantumRange - black_point, gamma = 1.0, *channels) + * @param black [Float] A black point level in the range 0..QuantumRange. + * @param white [Float] A white point level in the range 0..QuantumRange. + * @param gamma [Float] A gamma correction in the range 0.0 - 10.0. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_levelize_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -8688,11 +8351,11 @@ exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); status = LevelizeImage(new_image, black_point, white_point, gamma, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else status = LevelizeImageChannel(new_image, channels, black_point, white_point, gamma); rm_check_image_exception(new_image, DestroyOnError); #endif @@ -8703,25 +8366,22 @@ return rm_image_new(new_image); } /** - * Call LinearStretchImage. + * Linear with saturation stretch. * - * Ruby usage: - * - @verbatim Image_linear_stretch(black_point) @endverbatim - * - @verbatim Image_linear_stretch(black_point , white_point) @endverbatim - * - * Notes: - * - Default white_point is pixels-black_point - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see Image_contrast_stretch_channel. - * @see get_black_white_point + * @overload linear_stretch(black_point, white_point = pixels - black_point) + * @param black_point [Float, String] black out at most this many pixels. + * Specify an absolute number of pixels as a numeric value, or a percentage as a string in the + * form 'NN%'. + * @param white_point [Float, String] burn at most this many pixels. + * Specify an absolute number of pixels as a numeric value, or a percentage as a string in the + * form 'NN%'. + * This argument is optional. If not specified the default is `(columns * rows) - black_point`. + * @return [Magick::Image] a new image + * @see Image#contrast_stretch_channel */ VALUE Image_linear_stretch(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -8734,38 +8394,32 @@ get_black_white_point(image, argc, argv, &black_point, &white_point); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) LinearStretchImage(new_image, black_point, white_point, exception); + LinearStretchImage(new_image, black_point, white_point, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) LinearStretchImage(new_image, black_point, white_point); + LinearStretchImage(new_image, black_point, white_point); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Call the LiquidRescaleImage API. + * Rescale image with seam carving. * - * Ruby usage: - * - @verbatim Image#liquid_rescale(columns, rows) @endverbatim - * - @verbatim Image#liquid_rescale(columns, rows, delta_x) @endverbatim - * - @verbatim Image#liquid_rescale(columns, rows, delta_x, rigidity) @endverbatim - * - * Notes: - * - Default delta_x is 0.0 - * - Default rigidity is 0.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload liquid_rescale(columns, rows, delta_x = 0.0, rigidity = 0.0) + * @param columns [Numeric] The desired width height. Should not exceed 200% of the original + * dimension. + * @param rows [Numeric] The desired height. Should not exceed 200% of the original dimension. + * @param delta_x [Float] Maximum seam transversal step (0 means straight seams). + * @param rigidity [Float] Introduce a bias for non-straight seams (typically 0). + * @return [Magick::Image] a new image */ VALUE Image_liquid_rescale(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -8793,29 +8447,21 @@ exception = AcquireExceptionInfo(); new_image = LiquidRescaleImage(image, cols, rows, delta_x, rigidity, exception); rm_check_exception(exception, new_image, DestroyOnError); DestroyExceptionInfo(exception); - rm_ensure_result(new_image); return rm_image_new(new_image); } /** * Implement marshalling. * - * Ruby usage: - * - @verbatim Image._load @endverbatim - * - * Notes: - * - calls BlobToImage - * - * @param class Ruby class for Image - * @param str the marshalled string - * @return a new image - * @see Image__dump + * @param str [String] the marshalled string + * @return [Magic::Image] a new image + * @see Image#_dump */ VALUE Image__load(VALUE class ATTRIBUTE_UNUSED, VALUE str) { Image *image; @@ -8844,13 +8490,13 @@ mi.mi = ((DumpedImage *)blob)->mi; if ( mi.mj != DUMPED_IMAGE_MAJOR_VERS || mi.mi > DUMPED_IMAGE_MINOR_VERS) { rb_raise(rb_eTypeError, "incompatible image format (can't be read)\n" - "\tformat version %d.%d required; %d.%d given" - , DUMPED_IMAGE_MAJOR_VERS, DUMPED_IMAGE_MINOR_VERS - , mi.mj, mi.mi); + "\tformat version %d.%d required; %d.%d given", + DUMPED_IMAGE_MAJOR_VERS, DUMPED_IMAGE_MINOR_VERS, + mi.mj, mi.mi); } mi.len = ((DumpedImage *)blob)->len; // Must be bigger than the header @@ -8864,21 +8510,18 @@ memcpy(info->magick, ((DumpedImage *)blob)->magick, mi.len); info->magick[mi.len] = '\0'; exception = AcquireExceptionInfo(); - blob += offsetof(DumpedImage,magick) + mi.len; - length -= offsetof(DumpedImage,magick) + mi.len; + blob += offsetof(DumpedImage, magick) + mi.len; + length -= offsetof(DumpedImage, magick) + mi.len; image = BlobToImage(info, blob, (size_t) length, exception); - (void) DestroyImageInfo(info); + DestroyImageInfo(info); rm_check_exception(exception, image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(image); - return rm_image_new(image); } /** @@ -8902,71 +8545,58 @@ exception = AcquireExceptionInfo(); new_image = (magnifier)(image, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** * Scale an image proportionally to twice its size. * - * Ruby usage: - * - @verbatim Image#magnify @endverbatim - * - * @param self this object - * @return a new image - * @see magnify - * @see Image_magnify_bang + * @return [Magick::Image] a new image + * @see Image#magnify! */ VALUE Image_magnify(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return magnify(False, self, MagnifyImage); } /** * Scale an image proportionally to twice its size. + * In-place form of {Image#magnify}. * - * Ruby usage: - * - @verbatim Image#magnify! @endverbatim - * - * @param self this object - * @return self - * @see magnify - * @see Image_magnify + * @return [Magick::Image] self + * @see Image#magnify */ VALUE Image_magnify_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return magnify(True, self, MagnifyImage); } /** - * Support Marshal.dump >= 1.8. + * Support Marshal.dump. * - * Ruby usage: - * - @verbatim Image#marshal_dump @endverbatim - * - * @param self this object - * @return [img.filename, img.to_blob] + * @return [Array<String>] The first element in the array is the file name. The second element is the string + * of blob. */ VALUE Image_marshal_dump(VALUE self) { Image *image; @@ -8990,28 +8620,24 @@ exception = AcquireExceptionInfo(); blob = ImageToBlob(info, image, &length, exception); // Destroy info before raising an exception DestroyImageInfo(info); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); rb_ary_store(ary, 1, rb_str_new((char *)blob, (long)length)); magick_free((void*)blob); return ary; } /** - * Support Marshal.load >= 1.8. + * Support Marshal.load. * - * Ruby usage: - * - @verbatim Image#marshal_load @endverbatim - * - * @param self this object - * @param ary the array returned from marshal_dump + * @param ary [Array<String>] the array returned from {Image#marshal_dump} * @return self */ VALUE Image_marshal_load(VALUE self, VALUE ary) { @@ -9027,21 +8653,24 @@ } filename = rb_ary_shift(ary); blob = rb_ary_shift(ary); + filename = StringValue(filename); + blob = StringValue(blob); + exception = AcquireExceptionInfo(); if (filename != Qnil) { - strcpy(info->filename, RSTRING_PTR(filename)); + strlcpy(info->filename, RSTRING_PTR(filename), sizeof(info->filename)); } image = BlobToImage(info, RSTRING_PTR(blob), RSTRING_LEN(blob), exception); // Destroy info before raising an exception DestroyImageInfo(info); CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); UPDATE_DATA_PTR(self, image); return self; } @@ -9071,11 +8700,11 @@ #else mask = GetImageClipMask(image, exception); #endif rm_check_exception(exception, mask, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return mask ? rm_image_new(mask) : Qnil; } /** @@ -9106,25 +8735,25 @@ // Resize if necessary if (clip_mask->columns != image->columns || clip_mask->rows != image->rows) { resized_image = ResizeImage(clip_mask, image->columns, image->rows, image->filter, exception); - (void) DestroyImage(clip_mask); + DestroyImage(clip_mask); rm_check_exception(exception, resized_image, DestroyOnError); rm_ensure_result(resized_image); clip_mask = resized_image; } - (void) SetImageMask(image, WritePixelMask, clip_mask, exception); - (void) DestroyImage(clip_mask); + SetImageMask(image, WritePixelMask, clip_mask, exception); + DestroyImage(clip_mask); } else { - (void) SetImageMask(image, WritePixelMask, NULL, exception); + SetImageMask(image, WritePixelMask, NULL, exception); } - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); // Always return a copy of the mask! return get_image_mask(image); } #else @@ -9145,16 +8774,16 @@ // Resize if necessary if (clip_mask->columns != image->columns || clip_mask->rows != image->rows) { exception = AcquireExceptionInfo(); - resized_image = ResizeImage(clip_mask, image->columns, image->rows - , UndefinedFilter, 0.0, exception); + resized_image = ResizeImage(clip_mask, image->columns, image->rows, + UndefinedFilter, 0.0, exception); rm_check_exception(exception, resized_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_ensure_result(resized_image); - (void) DestroyImage(clip_mask); + DestroyImage(clip_mask); clip_mask = resized_image; } // The following section is copied from mogrify.c (6.2.8-8) exception = AcquireExceptionInfo(); @@ -9181,26 +8810,26 @@ } SyncAuthenticPixels(clip_mask, exception); rm_check_exception(exception, clip_mask, DestroyOnError); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); SetImageStorageClass(clip_mask, DirectClass); rm_check_image_exception(clip_mask, DestroyOnError); clip_mask->matte = MagickTrue; // SetImageClipMask clones the clip_mask image. We can // destroy our copy after SetImageClipMask is done with it. - (void) SetImageClipMask(image, clip_mask); - (void) DestroyImage(clip_mask); + SetImageClipMask(image, clip_mask); + DestroyImage(clip_mask); } else { - (void) SetImageClipMask(image, NULL); + SetImageClipMask(image, NULL); } RB_GC_GUARD(mask); // Always return a copy of the mask! @@ -9208,28 +8837,29 @@ } #endif /** - * Associate a clip mask with the image. + * Get/Sets an image clip mask created from the specified mask image. + * The mask image must have the same dimensions as the image being masked. + * If not, the mask image is resized to match. If the mask image has an alpha channel the opacity of + * each pixel is used to define the mask. Otherwise, the intensity (gray level) of each pixel is + * used. * - * Ruby usage: - * - @verbatim Image#mask @endverbatim - * - @verbatim Image#mask(mask-image) @endverbatim + * In general, if the mask image does not have an alpha channel, a white pixel in the mask prevents + * changes to the corresponding pixel in the image being masked, while a black pixel allows changes. + * A pixel that is neither black nor white will allow partial changes depending on its intensity. * - * Notes: - * - Omit the argument to get a copy of the current clip mask. - * - Pass "nil" for the mask-image to remove the current clip mask. - * - If the clip mask is not the same size as the target image, resizes the - * clip mask to match the target. - * - Distinguish from Image#clip_mask= + * @overload mask() + * Get an image clip mask. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return copy of the current clip-mask or nil - * @see get_image_mask + * @overload mask(image) + * Set an image clip mask. + * @param image [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * + * @return [Magick::Image] the mask image */ VALUE Image_mask(int argc, VALUE *argv, VALUE self) { VALUE mask; @@ -9252,15 +8882,11 @@ /** * Return the matte color. * - * Ruby usage: - * - @verbatim Image#matte_color @endverbatim - * - * @param self this object - * @return the matte color + * @return [String] the matte color */ VALUE Image_matte_color(VALUE self) { Image *image = rm_check_destroyed(self); @@ -9268,16 +8894,12 @@ } /** * Set the matte color. * - * Ruby usage: - * - @verbatim Image#matte_color= @endverbatim - * - * @param self this object - * @param color the matte color - * @return color + * @param color [Magick::Pixel, String] the matte color + * @return [Magick::Pixel, String] the given color */ VALUE Image_matte_color_eq(VALUE self, VALUE color) { Image *image = rm_check_frozen(self); @@ -9285,22 +8907,19 @@ return color; } /** - * Call MatteFloodFillImage. + * Makes transparent all the pixels that are the same color as the pixel at x, y, and are neighbors. * - * Ruby usage: - * - @verbatim Image#matte_flood_fill(color x, y, method_obj, alpha: alpha) @endverbatim - * - * @param self this object - * @param color the color - * @param alpha the alpha - * @param x_obj x position - * @param y_obj y position - * @param method_obj which method to call: FloodfillMethod or FillToBorderMethod - * @return a new image + * @overload Image#matte_flood_fill(color, x, y, method_obj, alpha:) + * @param color [Magick::Pixel, String] the color name + * @param x_obj [Numeric] x position + * @param y_obj [Numeric] y position + * @param method_obj [Magick::PaintMethod] which method to call: FloodfillMethod or FillToBorderMethod + * @param alpha [Numeric] the alpha + * @return [Magick::Image] a new image */ VALUE Image_matte_flood_fill(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -9333,12 +8952,12 @@ } x = NUM2LONG(argv[1]); y = NUM2LONG(argv[2]); if ((unsigned long)x > image->columns || (unsigned long)y > image->rows) { - rb_raise(rb_eArgError, "target out of range. %ldx%ld given, image is %lux%lu" - , x, y, image->columns, image->rows); + rb_raise(rb_eArgError, "target out of range. %ldx%ld given, image is %"RMIuSIZE"x%"RMIuSIZE"", + x, y, image->columns, image->rows); } new_image = rm_clone_image(image); @@ -9370,42 +8989,33 @@ } #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, OpacityChannel); - (void) FloodfillPaintImage(new_image, draw_info, &target_mpp, x, y, invert, exception); + FloodfillPaintImage(new_image, draw_info, &target_mpp, x, y, invert, exception); END_CHANNEL_MASK(new_image); - (void) DestroyDrawInfo(draw_info); + DestroyDrawInfo(draw_info); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) FloodfillPaintImage(new_image, OpacityChannel, draw_info, &target_mpp, x, y, invert); - (void) DestroyDrawInfo(draw_info); + FloodfillPaintImage(new_image, OpacityChannel, draw_info, &target_mpp, x, y, invert); + DestroyDrawInfo(draw_info); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Apply a digital filter that improves the quality of a noisy image. Each pixel - * is replaced by the median in a set of neighboring pixels as defined by - * radius. + * Apply a digital filter that improves the quality of a noisy image. Each pixel is replaced by the + * median in a set of neighboring pixels as defined by radius. * - * Ruby usage: - * - @verbatim Image#median_filter @endverbatim - * - @verbatim Image#median_filter(radius) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload median_filter(radius = 0.0) + * @param radius [Numeric] The filter radius. + * @return [Magick::Image] a new image */ VALUE Image_median_filter(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -9425,40 +9035,32 @@ } exception = AcquireExceptionInfo(); new_image = StatisticImage(image, MedianStatistic, (size_t)radius, (size_t)radius, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Get image mean error per pixel + * Get the mean error per pixel computed when a image is color reduced. * - * Ruby usage: - * - @verbatim Image#mean_error_per_pixel @endverbatim - * - * @param self this object - * @return the mean error per pixel + * @return [Float] the mean error per pixel */ -DEF_ATTR_READERF(Image, mean_error_per_pixel, error.mean_error_per_pixel, dbl) +VALUE +Image_mean_error_per_pixel(VALUE self) +{ + IMPLEMENT_ATTR_READERF(Image, mean_error_per_pixel, error.mean_error_per_pixel, dbl); +} /** - * Return the officially registered (or de facto) MIME media-type corresponding - * to the image format. + * Return the officially registered (or de facto) MIME media-type corresponding to the image format. * - * Ruby usage: - * - @verbatim Image#mime_type @endverbatim - * - * @param self this object - * @return the mime type + * @return [String, nil] the mime type */ VALUE Image_mime_type(VALUE self) { Image *image; @@ -9483,63 +9085,43 @@ /** * Scale an image proportionally to half its size. * - * Ruby usage: - * - @verbatim Image#minify @endverbatim - * - * @return minify: a new image 1/2x the size of the input image - * @return minify!: self, 1/2x - * @return a new image - * @see Image_minify_bang + * @return [Magick::Image] a new image + * @see Image#minify! */ VALUE Image_minify(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return magnify(False, self, MinifyImage); } /** - * Scale an image proportionally to half its size. + * Scale an image proportionally to half its size. In-place form of {Image#minify}. * - * Ruby usage: - * - @verbatim Image#minify! @endverbatim - * - * @param self this object - * @return self - * @see Image_minify + * @return [Magick::Image] self + * @see Image#minify */ VALUE Image_minify_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return magnify(True, self, MinifyImage); } /** - * Control the brightness, saturation, and hue of an image. + * Changes the brightness, saturation, and hue. * - * Ruby usage: - * - @verbatim Image#modulate @endverbatim - * - @verbatim Image#modulate(brightness) @endverbatim - * - @verbatim Image#modulate(brightness, saturation) @endverbatim - * - @verbatim Image#modulate(brightness, saturation, hue) @endverbatim - * - * Notes: - * - Default brightness is 100.0 - * - Default saturation is 100.0 - * - Default hue is 100.0 - * - all three arguments are optional and default to 100% - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload modulate(brightness = 1.0, saturation = 1.0, hue = 1.0) + * @param brightness [Float] The percent change in the brightness + * @param saturation [Float] The percent change in the saturation + * @param hue [Float] The percent change in the hue + * @return [Magick::Image] a new image */ VALUE Image_modulate(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -9570,42 +9152,42 @@ if (pct_brightness <= 0.0) { rb_raise(rb_eArgError, "brightness is %g%%, must be positive", pct_brightness); } - sprintf(modulate, "%f%%,%f%%,%f%%", pct_brightness, pct_saturation, pct_hue); + snprintf(modulate, sizeof(modulate), "%f%%,%f%%,%f%%", pct_brightness, pct_saturation, pct_hue); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) ModulateImage(new_image, modulate, exception); + ModulateImage(new_image, modulate, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) ModulateImage(new_image, modulate); + ModulateImage(new_image, modulate); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** * Establish a progress monitor. * - * Ruby usage: - * - @verbatim Image#monitor= proc @endverbatim + * - A progress monitor is a callable object. Save the monitor proc as the client_data and establish + * `progress_monitor' as the monitor exit. When `progress_monitor' is called, retrieve the proc + * and call it. * - * Notes: - * - A progress monitor is a callable object. Save the monitor proc as the - * client_data and establish `progress_monitor' as the monitor exit. When - * `progress_monitor' is called, retrieve the proc and call it. - * - * @param self this object - * @param monitor the progress monitor - * @return monitor + * @param monitor [Proc] the progress monitor + * @return [Proc] the given value + * @example + * img.monitor = Proc.new do |method, offset, span| + * print "%s is %3.0f%% complete.\n", method, (offset.to_f/span)*100) + * true + * end */ VALUE Image_monitor_eq(VALUE self, VALUE monitor) { Image *image = rm_check_frozen(self); @@ -9614,26 +9196,22 @@ { image->progress_monitor = NULL; } else { - (void) SetImageProgressMonitor(image, rm_progress_monitor, (void *)monitor); + SetImageProgressMonitor(image, rm_progress_monitor, (void *)monitor); } return monitor; } /** - * Return true if all the pixels in the image have the same red, green, and blue - * intensities and the intensity is either 0 or QuantumRange. + * Return true if all the pixels in the image have the same red, green, and blue intensities and the + * intensity is either 0 or {Magick::QuantumRange}. * - * Ruby usage: - * - @verbatim Image#monochrome? @endverbatim - * - * @param self this object - * @return true if monochrome, false otherwise + * @return [Boolean] true if monochrome, false otherwise */ VALUE Image_monochrome_q(VALUE self) { #if defined(IMAGEMAGICK_7) @@ -9645,17 +9223,17 @@ /** * Tile size and offset within an image montage. Only valid for montage images. * - * Ruby usage: - * - @verbatim Image#montage @endverbatim - * - * @param self this object - * @return the tile size and offset + * @return [String] the tile size and offset */ -DEF_ATTR_READER(Image, montage, str) +VALUE +Image_montage(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, montage, str); +} /** * Called from Image_motion_blur and Image_sketch. * @@ -9668,12 +9246,12 @@ * @return a new image * @see Image_motion_blur * @see Image_sketch */ static VALUE -motion_blur(int argc, VALUE *argv, VALUE self - , Image *fp(const Image *, const double, const double, const double, ExceptionInfo *)) +motion_blur(int argc, VALUE *argv, VALUE self, + Image *fp(const Image *, const double, const double, const double, ExceptionInfo *)) { Image *image, *new_image; double radius = 0.0; double sigma = 1.0; double angle = 0.0; @@ -9702,64 +9280,43 @@ Data_Get_Struct(self, Image, image); exception = AcquireExceptionInfo(); new_image = (fp)(image, radius, sigma, angle, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Simulate motion blur. Convolve the image with a Gaussian operator of the - * given radius and standard deviation (sigma). For reasonable results, radius - * should be larger than sigma. Use a radius of 0 and motion_blur selects a - * suitable radius for you. Angle gives the angle of the blurring motion. + * Simulate motion blur. Convolve the image with a Gaussian operator of the given radius and + * standard deviation (sigma). For reasonable results, radius should be larger than sigma. Use a + * radius of 0 and motion_blur selects a suitable radius for you. Angle gives the angle of the + * blurring motion. * - * Ruby usage: - * - @verbatim Image#motion_blur @endverbatim - * - @verbatim Image#motion_blur(radius) @endverbatim - * - @verbatim Image#motion_blur(radius, sigma) @endverbatim - * - @verbatim Image#motion_blur(radius, sigma, angle) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default angle is 0.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload motion_blur(radius = 0.0, sigma = 1.0, angle = 0.0) + * @param radius [Float] The radius + * @param sigma [Float] The standard deviation + * @param angle [Float] The angle (in degrees) + * @return [Magick::Image] a new image */ VALUE Image_motion_blur(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return motion_blur(argc, argv, self, MotionBlurImage); } /** - * Negate the colors in the reference image. The grayscale option means that - * only grayscale values within the image are negated. + * Negate the colors in the reference image. The grayscale option means that only grayscale values + * within the image are negated. * - * Ruby usage: - * - @verbatim Image#negate @endverbatim - * - @verbatim Image#negate(grayscale) @endverbatim - * - * Notes: - * - Default grayscale is false. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload negate(grayscale = false) + * @param grayscale [Boolean] If the grayscale argument is true, only the grayscale values are negated. + * @return [Magick::Image] a new image */ VALUE Image_negate(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -9780,15 +9337,15 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) NegateImage(new_image, grayscale, exception); + NegateImage(new_image, grayscale, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) NegateImage(new_image, grayscale); + NegateImage(new_image, grayscale); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } @@ -9796,27 +9353,22 @@ /** * Negate the colors on a particular channel. The grayscale option means that * only grayscale values within the image are negated. * - * Ruby usage: - * - @verbatim Image#negate_channel(grayscale=false, channel=AllChannels) @endverbatim + * @overload negate_channel(grayscale = false, channel = Magick::AllChannels) + * @param grayscale [Boolean] If the grayscale argument is true, only the grayscale values are + * negated. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Ruby usage: - * - @verbatim Image#negate_channel @endverbatim - * - @verbatim Image#negate_channel(grayscale) @endverbatim - * - @verbatim Image#negate_channel(grayscale, channel) @endverbatim - * - @verbatim Image#negate_channel(grayscale, channel, ...) @endverbatim + * @overload negate_channel(grayscale = false, *channels) + * @param grayscale [Boolean] If the grayscale argument is true, only the grayscale values are + * negated. + * @param channel [Magick::ChannelType] a ChannelType arguments. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * Notes: - * - Default grayscale is false. - * - Default channel is AllChannels. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_negate_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -9841,35 +9393,28 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - BEGIN_CHANNEL_MASK(image, channels); - (void) NegateImage(new_image, grayscale, exception); - END_CHANNEL_MASK(image); + BEGIN_CHANNEL_MASK(new_image, channels); + NegateImage(new_image, grayscale, exception); + END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) NegateImageChannel(new_image, channels, grayscale); + NegateImageChannel(new_image, channels, grayscale); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** * "Allocate" a new Image object * - * No Ruby usage (internal function) - * - * Notes: - * - Actually we defer allocating the image until the initialize method so we - * can run the parm block if it's present. - * - * @param class the Ruby class for an Image - * @return a newly allocated image + * @return [Magick::Image] a newly allocated image */ VALUE Image_alloc(VALUE class) { VALUE image_obj; @@ -9880,29 +9425,23 @@ return image_obj; } /** - * Initialize a new Image object If the fill argument is omitted, fill with - * background color. + * Initialize a new Image object If the fill argument is omitted, fill with background color. * - * Ruby usage: - * - @verbatim Image#initialize(cols,rows) @endverbatim - * - @verbatim Image#initialize(cols,rows,fill) @endverbatim - * - * Notes: - * - Default fill is false - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self + * @overload initialize(cols, rows, fill = nil) + * @param cols [Numeric] the image width + * @param rows [Numeric] the image height + * @param fill [Magick::HatchFill, Magick::SolidFill] if object is given as fill argument, + * background color will be filled using it. + * @return [Magick::Image] self */ VALUE Image_initialize(int argc, VALUE *argv, VALUE self) { - VALUE fill = 0; + VALUE fill = Qnil; Info *info; VALUE info_obj; Image *image; unsigned long cols, rows; #if defined(IMAGEMAGICK_7) @@ -9938,34 +9477,34 @@ UPDATE_DATA_PTR(self, image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); SetImageExtent(image, cols, rows, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else SetImageExtent(image, cols, rows); #endif // If the caller did not supply a fill argument, call SetImageBackgroundColor // to fill the image using the background color. The background color can // be set by specifying it when creating the Info parm block. - if (!fill) + if (NIL_P(fill)) { #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SetImageBackgroundColor(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageBackgroundColor(image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageBackgroundColor(image); + SetImageBackgroundColor(image); #endif } // fillobj.fill(self) else { - (void) rb_funcall(fill, rm_ID_fill, 1, self); + rb_funcall(fill, rm_ID_fill, 1, self); } RB_GC_GUARD(fill); RB_GC_GUARD(info_obj); @@ -9986,30 +9525,23 @@ * @return a new image */ VALUE rm_image_new(Image *image) { - if (!image) - { - rb_bug("rm_image_new called with NULL argument"); - } + rm_ensure_result(image); - (void) rm_trace_creation(image); + rm_trace_creation(image); return Data_Wrap_Struct(Class_Image, NULL, rm_image_destroy, image); } /** - * Enhance the contrast of a color image by adjusting the pixels color to span - * the entire range of colors available. + * Enhance the contrast of a color image by adjusting the pixels color to span the entire range of + * colors available. * - * Ruby usage: - * - @verbatim Image#normalize @endverbatim - * - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_normalize(VALUE self) { Image *image, *new_image; @@ -10020,36 +9552,29 @@ image = rm_check_destroyed(self); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) NormalizeImage(new_image, exception); + NormalizeImage(new_image, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) NormalizeImage(new_image); + NormalizeImage(new_image); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Call NormalizeImageChannel. + * Enhances the contrast of a color image by adjusting the pixel color to span the entire range of + * colors available. Only the specified channels are normalized. * - * Ruby usage: - * - @verbatim Image#normalize_channel @endverbatim - * - @verbatim Image#normalize_channel(channel) @endverbatim - * - * Notes: - * - Default channel is AllChannels - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload normalize_channel(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. + * @return [Magick::Image] a new image */ VALUE Image_normalize_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -10069,54 +9594,50 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) NormalizeImage(new_image, exception); + NormalizeImage(new_image, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) NormalizeImageChannel(new_image, channels); + NormalizeImageChannel(new_image, channels); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Get image normalized mean error + * Get the normalized mean error per pixel computed when an image is color reduced. * - * Ruby usage: - * - @verbatim Image#normalized_mean_error @endverbatim - * - * @param self this object - * @return the normalized mean error + * @return [Float] the normalized mean error */ -DEF_ATTR_READERF(Image, normalized_mean_error, error.normalized_mean_error, dbl) +VALUE +Image_normalized_mean_error(VALUE self) +{ + IMPLEMENT_ATTR_READERF(Image, normalized_mean_error, error.normalized_mean_error, dbl); +} /** - * Get image normalized maximum error + * Get The normalized maximum error per pixel computed when an image is color reduced. * - * Ruby usage: - * - @verbatim Image#normalized_maximum_error @endverbatim - * - * @param self this object - * @return the normalized maximum error + * @return [Float] the normalized maximum error */ -DEF_ATTR_READERF(Image, normalized_maximum_error, error.normalized_maximum_error, dbl) +VALUE +Image_normalized_maximum_error(VALUE self) +{ + IMPLEMENT_ATTR_READERF(Image, normalized_maximum_error, error.normalized_maximum_error, dbl); +} /** * Return the number of unique colors in the image. * - * Ruby usage: - * - @verbatim Image#number_colors @endverbatim - * - * @param self this object - * @return number of unique colors + * @return [Numeric] number of unique colors */ VALUE Image_number_colors(VALUE self) { Image *image; @@ -10125,35 +9646,48 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); n = (unsigned long) GetNumberColors(image, NULL, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return ULONG2NUM(n); } -DEF_ATTR_ACCESSOR(Image, offset, long) +/** + * Get the number of bytes to skip over when reading raw image. + * + * @return [Number] the offset + */ +VALUE +Image_offset(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, offset, long); +} +/** + * Set the number of bytes to skip over when reading raw image. + * + * @param val [Number] the offset + * @return [Number] the given offset + */ +VALUE +Image_offset_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, offset, long); +} + /** * Apply a special effect filter that simulates an oil painting. * - * Ruby usage: - * - @verbatim Image#oil_paint @endverbatim - * - @verbatim Image#oil_paint(radius) @endverbatim - * - * Notes: - * - Default radius is 3.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload oil_paint(radius = 3.0) + * @param radius [Float] The radius of the Gaussian in pixels. + * @return [Magick::Image] a new image */ VALUE Image_oil_paint(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -10181,35 +9715,27 @@ new_image = OilPaintImage(image, radius, sigma, exception); #else new_image = OilPaintImage(image, radius, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Change any pixel that matches target with the color defined by fill. * - * Ruby usage: - * - @verbatim Image#opaque(target-color-name, fill-color-name) @endverbatim - * - @verbatim Image#opaque(target-pixel, fill-pixel) @endverbatim + * - By default a pixel must match the specified target color exactly. + * - Use {Image#fuzz=} to set the amount of tolerance acceptable to consider two colors as the + * same. * - * Notes: - * - By default a pixel must match the specified target color exactly. - * - Use Image_fuzz_eq to set the amount of tolerance acceptable to consider - * two colors as the same. - * - * @param self this object - * @param target either the color name or the pixel - * @param fill the color for filling - * @see Image_fuzz_eq + * @param target [Magick::Pixel, String] the color name + * @param fill [Magick::Pixel, String] the color for filling + * @return [Magick::Image] a new image + * @see Image#fuzz= */ VALUE Image_opaque(VALUE self, VALUE target, VALUE fill) { Image *image, *new_image; @@ -10230,11 +9756,11 @@ #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); okay = OpaquePaintImage(new_image, &target_pp, &fill_pp, MagickFalse, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else okay = OpaquePaintImageChannel(new_image, DefaultChannels, &target_pp, &fill_pp, MagickFalse); rm_check_image_exception(new_image, DestroyOnError); #endif @@ -10248,29 +9774,30 @@ return rm_image_new(new_image); } /** - * Improved Image#opaque available in ImageMagick 6.3.7-10. + * Changes all pixels having the target color to the fill color. + * If invert is true, changes all the pixels that are not the target color to the fill color. * - * Ruby usage: - * - @verbatim Image#opaque_channel @endverbatim - * - @verbatim opaque_channel(target, fill) @endverbatim - * - @verbatim opaque_channel(target, fill, invert) @endverbatim - * - @verbatim opaque_channel(target, fill, invert, fuzz) @endverbatim - * - @verbatim opaque_channel(target, fill, invert, fuzz, channel) @endverbatim - * - @verbatim opaque_channel(target, fill, invert, fuzz, channel, ...) @endverbatim + * @overload opaque_channel(target, fill, invert = false, fuzz = self.fuzz, channel = Magick::AllChannels) + * @param target [Magick::Pixel, String] the color name + * @param fill [Magick::Pixel, String] the color for filling + * @param invert [Boolean] If true, the target pixels are all the pixels that are not the target + * color. The default is the value of the target image's fuzz attribute + * @param fuzz [Float] Colors within this distance are considered equal to the target color. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default invert is false - * - Default fuzz is the image's fuzz (see Image_fuzz_eq) - * - Default channel is AllChannels + * @overload opaque_channel(target, fill, invert, fuzz, *channels) + * @param target [Magick::Pixel, String] the color name + * @param fill [Magick::Pixel, String] the color for filling + * @param invert [Boolean] If true, the target pixels are all the pixels that are not the target + * color. The default is the value of the target image's fuzz attribute + * @param fuzz [Float] Colors within this distance are considered equal to the target color. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_opaque_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -10317,15 +9844,15 @@ new_image->fuzz = fuzz; #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - okay = OpaquePaintImage(new_image, &target_pp, &fill_pp, MagickFalse, exception); + okay = OpaquePaintImage(new_image, &target_pp, &fill_pp, invert, exception); END_CHANNEL_MASK(new_image); new_image->fuzz = keep; rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else okay = OpaquePaintImageChannel(new_image, channels, &target_pp, &fill_pp, invert); new_image->fuzz = keep; rm_check_image_exception(new_image, DestroyOnError); @@ -10341,18 +9868,13 @@ return rm_image_new(new_image); } /** - * Return true if any of the pixels in the image have an opacity value other - * than opaque ( 0 ). + * Returns true if all of the pixels in the receiver have an opacity value of OpaqueOpacity. * - * Ruby usage: - * - @verbatim Image#opaque? @endverbatim - * - * @param self this object - * @return true if opaque, false otherwise + * @return [Boolean] true if opaque, false otherwise */ VALUE Image_opaque_q(VALUE self) { #if defined(IMAGEMAGICK_7) @@ -10362,29 +9884,18 @@ #endif } /** - * Perform ordered dither on image. + * Dithers the image to a predefined pattern. The threshold_map argument defines the pattern to use. * - * Ruby usage: - * - @verbatim Image#ordered_dither @endverbatim - * - @verbatim Image#ordered_dither(threshold_map) @endverbatim + * - Default threshold_map is '2x2' + * - Order of threshold_map must be 2, 3, or 4. * - * Notes: - * - Default threshold_map is '2x2' - * - Order of threshold_map must be 2, 3, or 4. - * - If using ImageMagick >= 6.3.0, order can be any of the threshold strings - * listed by "convert -list Thresholds" - * - Does not call OrderedDitherImages anymore. Sometime after ImageMagick - * 6.0.0 it quit working. Uses the same routines as ImageMagick and - * GraphicsMagick for their "ordered-dither" option. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload ordered_dither(threshold_map = '2x2') + * @param threshold_map [String, Numeric] the threshold + * @return [Magick::Image] a new image */ VALUE Image_ordered_dither(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -10400,11 +9911,11 @@ } if (argc == 1) { if (TYPE(argv[0]) == T_STRING) { - threshold_map = StringValuePtr(argv[0]); + threshold_map = StringValueCStr(argv[0]); } else { order = NUM2INT(argv[0]); if (order == 3) @@ -10424,27 +9935,23 @@ new_image = rm_clone_image(image); exception = AcquireExceptionInfo(); - (void) OrderedDitherImage(new_image, threshold_map, exception); + OrderedDitherImage(new_image, threshold_map, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Return the orientation attribute as an OrientationType enum value. + * Get the value of the Exif Orientation Tag. * - * Ruby usage: - * - @verbatim Image#orientation @endverbatim - * - * @param self this object - * @return the orientation + * @return [Magick::OrientationType] the orientation */ VALUE Image_orientation(VALUE self) { Image *image = rm_check_destroyed(self); @@ -10453,16 +9960,12 @@ /** * Set the orientation attribute. * - * Ruby usage: - * - @verbatim Image#orientation= @endverbatim - * - * @param self this object - * @param orientation the orientation - * @return orientation + * @param orientation [Magick::OrientationType] the orientation + * @return [Magick::OrientationType] the given value */ VALUE Image_orientation_eq(VALUE self, VALUE orientation) { Image *image = rm_check_frozen(self); @@ -10472,15 +9975,11 @@ /** * The page attribute getter. * - * Ruby usage: - * - @verbatim Image#page @endverbatim - * - * @param self - * @return the page rectangle + * @return [Magick::Rectang] the page rectangle */ VALUE Image_page(VALUE self) { Image *image = rm_check_destroyed(self); @@ -10489,16 +9988,12 @@ /** * The page attribute setter. * - * Ruby usage: - * - @verbatim Image#page= @endverbatim - * - * @param self this object - * @param rect the page rectangle - * @return rect + * @param rect [Magick::Rectang] the page rectangle + * @return [Magick::Rectang] the given value */ VALUE Image_page_eq(VALUE self, VALUE rect) { Image *image = rm_check_frozen(self); @@ -10506,27 +10001,22 @@ return rect; } /** - * Improved version of Image#transparent available in ImageMagick 6.3.7-10. + * Changes the opacity value of all the pixels that match color to the value specified by opacity. + * If invert is true, changes the pixels that don't match color. * - * Ruby usage: - * - @verbatim Image#paint_transparent(target) @endverbatim - * - @verbatim Image#paint_transparent(target, alpha: alpha) @endverbatim - * - @verbatim Image#paint_transparent(target, invert, alpha: alpha) @endverbatim - * - @verbatim Image#paint_transparent(target, invert, fuzz, alpha: alpha) @endverbatim - * - * Notes: - * - Default alpha is TransparentAlpha - * - Default invert is false - * - Default fuzz is the image's fuzz (see Image_fuzz_eq) - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload paint_transparent(target, invert, fuzz, alpha: Magick::TransparentAlpha) + * @param target [Magick::Pixel, String] the color name + * @param invert [Boolean] If true, the target pixels are all the pixels that are not the target + * color. + * @param fuzz [Float] By default the pixel must match exactly, but you can specify a tolerance + * level by passing a positive value. + * @param alpha [Numeric] The new alpha value, either an alpha value or a number between 0 and + * QuantumRange. The default is TransparentAlpha. + * @return [Magick::Image] a new image */ VALUE Image_paint_transparent(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -10583,11 +10073,11 @@ #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); okay = TransparentPaintImage(new_image, (const MagickPixel *)&color, alpha, invert, exception); new_image->fuzz = keep; rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else okay = TransparentPaintImage(new_image, (const MagickPixel *)&color, QuantumRange - alpha, invert); new_image->fuzz = keep; // Is it possible for TransparentPaintImage to silently fail? @@ -10606,15 +10096,11 @@ /** * Return true if the image is PseudoClass and has 256 unique colors or less. * - * Ruby usage: - * - @verbatim Image#palette? @endverbatim - * - * @param self this object - * @return true if palette, otherwise false + * @return [Boolean] true if palette, otherwise false */ VALUE Image_palette_q(VALUE self) { #if defined(IMAGEMAGICK_7) @@ -10624,51 +10110,43 @@ #endif } /** - * Call ImagePing. + * Returns all the properties of an image or image sequence except for the pixels. * - * Ruby usage: - * - @verbatim Image.ping(file) @endverbatim - * - * @param class the Ruby class for an Image - * @param file_arg the file containing image info - * @return an array of 1 or more new image objects (without pixel data) - * @see Image_read - * @see rd_image + * @return [Array<Magick::Image>] an array of 1 or more new image objects (without pixel data) + * @see Image#read */ VALUE Image_ping(VALUE class, VALUE file_arg) { return rd_image(class, file_arg, PingImage); } /** - * Get/set the color of the pixel at x,y. + * Get/set the color of the pixel at x, y. * - * Ruby usage: - * - @verbatim Image#pixel_color(x, y) @endverbatim - * - @verbatim Image#pixel_color(x, y, color) @endverbatim + * @overload pixel_color(x, y) + * Get the color + * @param x [Numeric] The x-coordinates of the pixel. + * @param y [Numeric] The y-coordinates of the pixel. + * @return [Magick::Pixel] the pixel at x, y. * - * Notes: - * - Without color, does a get. With color, does a set. - * - "color", if present, may be either a color name or a Magick::Pixel. - * - Based on Magick++'s Magick::pixelColor methods - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return Magick::Pixel for pixel x,y. If called to set a new color, the - * return value is the old color. + * @overload pixel_color(x, y, color) + * Set the color + * @param x [Numeric] The x-coordinates of the pixel. + * @param y [Numeric] The y-coordinates of the pixel. + * @param color [Magick::Pixel, String] the color + * @return [Magick::Pixel] the old color at x, y. */ VALUE Image_pixel_color(int argc, VALUE *argv, VALUE self) { Image *image; - PixelColor new_color; + Pixel new_color; PixelPacket old_color; ExceptionInfo *exception; long x, y; unsigned int set = False; MagickBooleanType okay; @@ -10676,10 +10154,12 @@ Quantum *pixel; const Quantum *old_pixel; #else PixelPacket *pixel; const PixelPacket *old_pixel; + MagickPixel mpp; + IndexPacket *indexes; #endif memset(&old_color, 0, sizeof(old_color)); image = rm_check_destroyed(self); @@ -10689,11 +10169,11 @@ case 3: rb_check_frozen(self); set = True; // Replace with new color? The arg can be either a color name or // a Magick::Pixel. - Color_to_PixelColor(&new_color, argv[2]); + Color_to_Pixel(&new_color, argv[2]); case 2: break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 3)", argc); break; @@ -10705,33 +10185,45 @@ // Get the color of a pixel if (!set) { exception = AcquireExceptionInfo(); old_pixel = GetVirtualPixels(image, x, y, 1, 1, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #if defined(IMAGEMAGICK_7) old_color.red = GetPixelRed(image, old_pixel); old_color.green = GetPixelGreen(image, old_pixel); old_color.blue = GetPixelBlue(image, old_pixel); old_color.alpha = GetPixelAlpha(image, old_pixel); + old_color.black = GetPixelBlack(image, old_pixel); + return Pixel_from_PixelPacket(&old_color); #else old_color = *old_pixel; + indexes = GetAuthenticIndexQueue(image); // PseudoClass if (image->storage_class == PseudoClass) { - IndexPacket *indexes = GetAuthenticIndexQueue(image); old_color = image->colormap[(unsigned long)*indexes]; } if (!image->matte) { old_color.opacity = OpaqueOpacity; } + + rm_init_magickpixel(image, &mpp); + mpp.red = GetPixelRed(&old_color); + mpp.green = GetPixelGreen(&old_color); + mpp.blue = GetPixelBlue(&old_color); + mpp.opacity = GetPixelOpacity(&old_color); + if (indexes) + { + mpp.index = GetPixelIndex(indexes); + } + return Pixel_from_MagickPixel(&mpp); #endif - return Pixel_from_PixelPacket(&old_color); } // ImageMagick segfaults if the pixel location is out of bounds. // Do what IM does and return the background color. if (x < 0 || y < 0 || (unsigned long)x >= image->columns || (unsigned long)y >= image->rows) @@ -10745,14 +10237,14 @@ if (image->storage_class == PseudoClass) { #if defined(IMAGEMAGICK_7) okay = SetImageStorageClass(image, DirectClass, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); if (!okay) { - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rb_raise(Class_ImageMagickError, "SetImageStorageClass failed. Can't set pixel color."); } #else okay = SetImageStorageClass(image, DirectClass); rm_check_image_exception(image, RetainOnError); @@ -10766,73 +10258,74 @@ #if defined(IMAGEMAGICK_6) exception = AcquireExceptionInfo(); #endif pixel = GetAuthenticPixels(image, x, y, 1, 1, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); if (pixel) { #if defined(IMAGEMAGICK_7) old_color.red = GetPixelRed(image, pixel); old_color.green = GetPixelGreen(image, pixel); old_color.blue = GetPixelBlue(image, pixel); old_color.alpha = GetPixelAlpha(image, pixel); + old_color.black = GetPixelBlack(image, pixel); SetPixelRed(image, new_color.red, pixel); SetPixelGreen(image, new_color.green, pixel); SetPixelBlue(image, new_color.blue, pixel); SetPixelAlpha(image, new_color.alpha, pixel); + SetPixelBlack(image, new_color.black, pixel); #else old_color = *pixel; + indexes = GetAuthenticIndexQueue(image); if (!image->matte) { old_color.opacity = OpaqueOpacity; } - *pixel = new_color; + + SetPixelRed(pixel, new_color.red); + SetPixelGreen(pixel, new_color.green); + SetPixelBlue(pixel, new_color.blue); + SetPixelOpacity(pixel, new_color.opacity); + if (indexes) + { + SetPixelIndex(indexes, new_color.black); + } #endif SyncAuthenticPixels(image, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return Pixel_from_PixelPacket(&old_color); } /** - * Get the "interpolate" field in the Image structure. + * Get the "interpolate" field. * - * Ruby usage: - * - @verbatim Image.pixel_interpolation_method @endverbatim - * - * @param self this object - * @return the interpolate field - * @see Image_pixel_interpolation_method_eq - * @see Image.interpolate_pixel_color + * @return [Magick::PixelInterpolateMethod] the interpolate field + * @see Image#pixel_interpolation_method= */ VALUE Image_pixel_interpolation_method(VALUE self) { Image *image = rm_check_destroyed(self); return PixelInterpolateMethod_find(image->interpolate); } /** - * Set the "interpolate" field in the Image structure. + * Set the "interpolate" field. * - * Ruby usage: - * - @verbatim Image.pixel_interpolation_method=method @endverbatim - * - * @param self this object - * @param method the interpolate field - * @return method - * @see Image_pixel_interpolation_method - * @see Image.interpolate_pixel_color + * @param method [Magick::PixelInterpolateMethod] the interpolate field + * @return [Magick::PixelInterpolateMethod] the given method + * @see Image#pixel_interpolation_method */ VALUE Image_pixel_interpolation_method_eq(VALUE self, VALUE method) { Image *image = rm_check_frozen(self); @@ -10840,36 +10333,42 @@ return method; } /** - * Call PolaroidImage. + * Produce an image that looks like a Polaroid instant picture. If the image has a "Caption" + * property, the value is used as a caption. * - * Ruby usage: - * - @verbatim Image#polaroid { optional parms } @endverbatim - * - @verbatim Image#polaroid(angle) { optional parms } @endverbatim + * The following annotate attributes control the label rendering: + * align, decorate, density, encoding, fill, font, font_family, font_stretch, font_style, + * font_weight, gravity, pointsize, stroke, stroke_width, text_antialias, undercolor. * - * Notes: - * - Default angle is -5 - * - Accepts an options block to get Draw attributes for drawing the label. - * Specify self.border_color to set a non-default border color. + * @overload polaroid(angle = -5.0) + * @param angle [Float] The resulting image is rotated by this amount, measured in degrees. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload polaroid(angle = -5.0) + * If present a block, optional arguments may be specified in a block associated with the method. + * These arguments control the shadow color and how the label is rendered. + * By default the shadow color is gray75. To specify a different shadow color, + * use self.shadow_color. + * To specify a different border color (that is, the color of the image border) use self.border_color. + * Both of these methods accept either a color name or a Pixel argument. + * @param angle [Float] The resulting image is rotated by this amount, measured in degrees. + * @yield [] + * + * @return [Magick::Image] a new image */ VALUE Image_polaroid(int argc, VALUE *argv, VALUE self) { Image *image, *clone, *new_image; VALUE options; double angle = -5.0; Draw *draw; ExceptionInfo *exception; #if defined(IMAGEMAGICK_7) - char *caption = (char *) NULL; + const char *caption; #endif image = rm_check_destroyed(self); switch (argc) @@ -10890,41 +10389,33 @@ clone->background_color = draw->shadow_color; clone->border_color = draw->info->border_color; exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) + caption = GetImageProperty(clone, "Caption", exception); new_image = PolaroidImage(clone, draw->info, caption, angle, image->interpolate, exception); #else new_image = PolaroidImage(clone, draw->info, angle, exception); #endif rm_check_exception(exception, clone, DestroyOnError); - (void) DestroyImage(clone); - (void) DestroyExceptionInfo(exception); + DestroyImage(clone); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - RB_GC_GUARD(options); return rm_image_new(new_image); } /** - * Call PosterizeImage. + * Reduces the image to a limited number of colors for a "poster" effect. * - * Ruby usage: - * - @verbatim Image#posterize(levels=4, dither=false) @endverbatim - * - * Notes: - * - Default levels is 4 - * - Default dither is false - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload posterize(levels = 4, dither = false) + * @param levels [Numeric] number of input arguments + * @param dither [Boolean] array of input arguments + * @return a new image */ VALUE Image_posterize(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -10953,31 +10444,28 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); dither_method = dither ? RiemersmaDitherMethod : NoDitherMethod; - (void) PosterizeImage(new_image, levels, dither_method, exception); + PosterizeImage(new_image, levels, dither_method, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) PosterizeImage(new_image, levels, dither); + PosterizeImage(new_image, levels, dither); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Call PreviewImage. + * Creates an image that contains 9 small versions of the receiver image. The center image is the + * unchanged receiver. The other 8 images are variations created by transforming the receiver + * according to the specified preview type with varying parameters. * - * Ruby usage: - * - @verbatim Image#preview(preview) @endverbatim - * - * @param self this object - * @param preview the preview - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_preview(VALUE self, VALUE preview) { Image *image, *new_image; @@ -10989,29 +10477,23 @@ exception = AcquireExceptionInfo(); new_image = PreviewImage(image, preview_type, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Set the image profile. If "profile" is nil, deletes the profile. Otherwise - * "profile" must be a string containing the specified profile. + * Set the image profile. If "profile" is nil, deletes the profile. Otherwise "profile" must be a + * string containing the specified profile. * - * Ruby usage: - * - @verbatim Image#profile!(name, profile) @endverbatim - * - * @param self this object - * @param name the profile name - * @param profile the profile - * @return self + * @param name [String] The profile name, or "*" to represent all the profiles in the image. + * @param profile [String] The profile value, or nil to cause the profile to be removed. + * @return [Magick::Image] self */ VALUE Image_profile_bang(VALUE self, VALUE name, VALUE profile) { @@ -11019,41 +10501,32 @@ { return Image_delete_profile(self, name); } else { - return set_profile(self, StringValuePtr(name), profile); + return set_profile(self, StringValueCStr(name), profile); } } /** * Get image quality. * - * Ruby usage: - * - @verbatim Image#quality @endverbatim - * - * @param self this object - * @return the quality + * @return [Numeric] the quality */ -DEF_ATTR_READER(Image, quality, ulong) +VALUE +Image_quality(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, quality, ulong); +} /** - * Return image depth to nearest quantum. + * Return the image depth to the nearest Quantum (8, 16, or 32). * - * Ruby usage: - * - @verbatim Image#quantum_depth -> 8, 16, or 32 @endverbatim - * - * Notes: - * - IM 6.0.0 introduced GetImageQuantumDepth - * - IM 6.0.5 added a 2nd argument. The MagickFalse argument gives the 6.0.5 - * version the same behavior as before. - * - * @param self this object - * @return image depth + * @return [Numeric] image depth */ VALUE Image_quantum_depth(VALUE self) { Image *image; @@ -11065,27 +10538,28 @@ return ULONG2NUM(quantum_depth); } /** - * This method is an adapter method that calls the EvaluateImageChannel method. + * Performs the requested integer arithmetic operation on the selected channel of the image. + * This method allows simple arithmetic operations on the component values of all pixels in an + * image. + * Of course, you could also do this in Ruby using get_pixels and store_pixels, or view, but + * quantum_operator will be faster, especially for large numbers of pixels, since it does not need + * to convert the pixels from C to Ruby. * - * Ruby usage: - * - @verbatim Image#quantum_operator(operator, rvalue) @endverbatim - * - @verbatim Image#quantum_operator(operator, rvalue, channel) @endverbatim - * - @verbatim Image#quantum_operator(operator, rvalue, channel, ...) @endverbatim + * @overload quantum_operator(operator, rvalue, channel = Magick::AllChannels) + * @param operator [Magick::QuantumExpressionOperator] the operator + * @param rvalue [Float] the operation rvalue. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Historically this method used QuantumOperatorRegionImage in - * GraphicsMagick. By necessity this method implements the "lowest common - * denominator" of the two implementations. - * - Default channel is AllChannels + * @overload quantum_operator(operator, rvalue, *channels) + * @param operator [Magick::QuantumExpressionOperator] the operator + * @param rvalue [Float] the operation rvalue. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self + * @return [Magick::Image] self */ VALUE Image_quantum_operator(int argc, VALUE *argv, VALUE self) { Image *image; @@ -11227,45 +10701,40 @@ } exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channel); - (void) EvaluateImage(image, qop, rvalue, exception); + EvaluateImage(image, qop, rvalue, exception); END_CHANNEL_MASK(image); #else - (void) EvaluateImageChannel(image, channel, qop, rvalue, exception); + EvaluateImageChannel(image, channel, qop, rvalue, exception); #endif - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return self; } /** - * Call QuantizeImage. + * Analyzes the colors within a reference image and chooses a fixed number of colors to represent + * the image. The goal of the algorithm is to minimize the difference between the input and output + * image while minimizing the processing time. * - * Ruby usage: - * - @verbatim Image#quantize @endverbatim - * - @verbatim Image#quantize(number_colors) @endverbatim - * - @verbatim Image#quantize(number_colors, colorspace) @endverbatim - * - @verbatim Image#quantize(number_colors, colorspace, dither) @endverbatim - * - @verbatim Image#quantize(number_colors, colorspace, dither, tree_depth) @endverbatim - * - @verbatim Image#quantize(number_colors, colorspace, dither, tree_depth, measure_error) @endverbatim - * - * Notes: - * - Default number_colors is 256 - * - Default colorspace is Magick::RGBColorspace - * - Default dither is true - * - Default tree_depth is 0 - * - Default measure_error is false - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload quantize(number_colors = 256, colorspace = Magick::RGBColorspace, dither = true, tree_depth = 0, measure_error = false) + * @param number_colors [Numeric] The maximum number of colors in the result image. + * @param colorspace [Magick::ColorspaceType] The colorspace to quantize in. + * @param dither [Boolean] If true, Magick::RiemersmaDitherMethod will be used as + * DitherMethod. otherwise NoDitherMethod. + * @param tree_depth [Numeric] The tree depth to use while quantizing. The values 0 and 1 support + * automatic tree depth determination. The tree depth may be forced via values ranging from 2 to + * 8. The ideal tree depth depends on the characteristics of the input image, and may be + * determined through experimentation. + * @param measure_error [Boolean] Set to true to calculate quantization errors when quantizing the + * image. + * @return [Magick::Image] a new image */ VALUE Image_quantize(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -11312,31 +10781,27 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) QuantizeImage(&quantize_info, new_image, exception); + QuantizeImage(&quantize_info, new_image, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) QuantizeImage(&quantize_info, new_image); + QuantizeImage(&quantize_info, new_image); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Call RadialBlurImage. + * Applies a radial blur to the image. * - * Ruby usage: - * - @verbatim Image#radial_blur(angle) @endverbatim - * - * @param self this object - * @param angle the angle (in degrees) - * @return a new image + * @param angle_obj [Float] the angle (in degrees) + * @return [Magick::Image] a new image */ VALUE Image_radial_blur(VALUE self, VALUE angle_obj) { Image *image, *new_image; @@ -11350,35 +10815,28 @@ new_image = RotationalBlurImage(image, angle, exception); #else new_image = RadialBlurImage(image, angle, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call RadialBlurImageChannel. + * Applies a radial blur to the selected image channels. * - * Ruby usage: - * - @verbatim Image#radial_blur_channel(angle) @endverbatim - * - @verbatim Image#radial_blur_channel(angle, channel) @endverbatim - * - @verbatim Image#radial_blur_channel(angle, channel, ...) @endverbatim + * @overload radial_blur_channel(angle, channel = Magick::AllChannels) + * @param angle [Float] the angle (in degrees) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels - * - Angle is in degrees + * @overload radial_blur_channel(angle, *channels) + * @param angle [Float] the angle (in degrees) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_radial_blur_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -11411,32 +10869,30 @@ new_image = RotationalBlurImageChannel(image, channels, angle, exception); #else new_image = RadialBlurImageChannel(image, channels, angle, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Call RandomThresholdImageChannel. + * Changes the value of individual pixels based on the intensity of each pixel compared to a random + * threshold. The result is a low-contrast, two color image. * - * Ruby usage: - * - @verbatim Image#random_threshold_channel(geometry_str) @endverbatim - * - @verbatim Image#random_threshold_channel(geometry_str, channel) @endverbatim - * - @verbatim Image#random_threshold_channel(geometry_str, channel, ...) @endverbatim + * @overload random_threshold_channel(geometry_str, channel = Magick::AllChannels) + * @param geometry_str [String] A geometry string containing LOWxHIGH thresholds. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload random_threshold_channel(geometry_str, *channels) + * @param geometry_str [String] A geometry string containing LOWxHIGH thresholds. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image + * @see https://www.imagemagick.org/Magick++/Geometry.html */ VALUE Image_random_threshold_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -11458,60 +10914,49 @@ { raise_ChannelType_error(argv[argc-1]); } // Accept any argument that has a to_s method. - geom_str = rm_to_s(argv[0]); - thresholds = StringValuePtr(geom_str); + geom_str = rb_String(argv[0]); + thresholds = StringValueCStr(geom_str); new_image = rm_clone_image(image); exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(new_image, channels); { GeometryInfo geometry_info; - (void) ParseGeometry(thresholds,&geometry_info); - (void) RandomThresholdImage(new_image, geometry_info.rho, geometry_info.sigma, exception); + ParseGeometry(thresholds, &geometry_info); + RandomThresholdImage(new_image, geometry_info.rho, geometry_info.sigma, exception); } END_CHANNEL_MASK(new_image); #else - (void) RandomThresholdImageChannel(new_image, channels, thresholds, exception); + RandomThresholdImageChannel(new_image, channels, thresholds, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); RB_GC_GUARD(geom_str); return rm_image_new(new_image); } /** - * Create a simulated three-dimensional button-like effect by lightening and - * darkening the edges of the image. The "width" and "height" arguments define - * the width of the vertical and horizontal edge of the effect. If "raised" is - * true, creates a raised effect, otherwise a lowered effect. + * Create a simulated three-dimensional button-like effect by lightening and darkening the edges of + * the image. The "width" and "height" arguments define the width of the vertical and horizontal + * edge of the effect. If "raised" is true, creates a raised effect, otherwise a lowered effect. * - * Ruby usage: - * - @verbatim Image#raise @endverbatim - * - @verbatim Image#raise(width) @endverbatim - * - @verbatim Image#raise(width, height) @endverbatim - * - @verbatim Image#raise(width, height, raised) @endverbatim - * - * Notes: - * - Default width is 6 - * - Default height is 6 - * - Default raised is true - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload raise(width = 6, height = 6, raised = true) + * @param width [Numeric] The width of the raised edge in pixels. + * @param height [Numeric] The height of the raised edge in pixels. + * @param raised [Boolean] If true, the image is raised, otherwise lowered. + * @return [Magick::Image] a new image */ VALUE Image_raise(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -11543,32 +10988,27 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) RaiseImage(new_image, &rect, raised, exception); + RaiseImage(new_image, &rect, raised, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) RaiseImage(new_image, &rect, raised); + RaiseImage(new_image, &rect, raised); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** * Call ReadImage. * - * Ruby usage: - * - @verbatim Image.read(file) @endverbatim - * - * @param class the Ruby class for an Image - * @param file_arg the file containing image data - * @return an array of 1 or more new image objects - * @see rd_image + * @param file_arg [File, String] the file containing image data or file name + * @return [Array<Magick::Image>] an array of 1 or more new image objects */ VALUE Image_read(VALUE class, VALUE file_arg) { return rd_image(class, file_arg, ReadImage); @@ -11582,15 +11022,14 @@ * * @param arg the bad arg given * @return 0 */ static VALUE -file_arg_rescue(VALUE arg) +file_arg_rescue(VALUE arg, VALUE raised_exc ATTRIBUTE_UNUSED) { rb_raise(rb_eTypeError, "argument must be path name or open file (%s given)", rb_class2name(CLASS_OF(arg))); - return(VALUE)0; } /** * Transform arguments, call either ReadImage or PingImage. @@ -11607,10 +11046,17 @@ * @return an array of 1 or more new image objects * @see Image_read * @see Image_ping * @see array_from_images */ + +#if !defined(_WIN32) +void sig_handler(int sig ATTRIBUTE_UNUSED) +{ +} +#endif + static VALUE rd_image(VALUE class ATTRIBUTE_UNUSED, VALUE file, reader_t reader) { char *filename; long filename_l; @@ -11649,30 +11095,37 @@ SetImageInfoFile(info, NULL); } exception = AcquireExceptionInfo(); +#if !defined(_WIN32) + signal(SIGCHLD, sig_handler); +#endif + images = (reader)(info, exception); + +#if !defined(_WIN32) + signal(SIGCHLD, SIG_DFL); +#endif + rm_check_exception(exception, images, DestroyOnError); rm_set_user_artifact(images, info); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); RB_GC_GUARD(info_obj); return array_from_images(images); } /** - * Call RecolorImage. + * Use this method to translate, scale, shear, or rotate image colors. Although you can use variable + * sized matrices, typically you use a 5x5 for an RGBA image and a 6x6 for CMYKA. Populate the last + * row with normalized values to translate. * - * Ruby usage: - * - @verbatim Image#recolor(matrix) @endverbatim - * - * @param self this object - * @param color_matrix the matrix - * @return a new image + * @param color_matrix [Array<Float>] An array of Float values representing the recolor matrix. + * @return [Magick::Image] a new image */ VALUE Image_recolor(VALUE self, VALUE color_matrix) { Image *image, *new_image; @@ -11710,55 +11163,45 @@ kernel_info = AcquireKernelInfo(NULL, exception); if (rm_should_raise_exception(exception, RetainExceptionRetention)) { if (kernel_info != (KernelInfo *) NULL) { - (void) DestroyKernelInfo(kernel_info); + DestroyKernelInfo(kernel_info); } xfree((void *)matrix); rm_raise_exception(exception); } #else kernel_info = AcquireKernelInfo(NULL); #endif if (kernel_info == (KernelInfo *) NULL) { xfree((void *) matrix); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return Qnil; } kernel_info->width = order; kernel_info->height = order; kernel_info->values = (double *) matrix; new_image = ColorMatrixImage(image, kernel_info, exception); kernel_info->values = (double *) NULL; - (void) DestroyKernelInfo(kernel_info); + DestroyKernelInfo(kernel_info); xfree((void *) matrix); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** * Read a Base64-encoded image. * - * Ruby usage: - * - @verbatim Image.read_inline(content) @endverbatim - * - * Notes: - * - This is similar to, but not the same as ReadInlineImage. ReadInlineImage - * requires a comma preceeding the image data. This method allows but does - * not require a comma. - * - * @param self this object - * @param content the content - * @return an array of new images - * @see array_from_images + * @param content [String] the content + * @return [Array<Magick::Image>] an array of new images */ VALUE Image_read_inline(VALUE self ATTRIBUTE_UNUSED, VALUE content) { VALUE info_obj; @@ -11803,11 +11246,11 @@ images = BlobToImage(info, blob, blob_l, exception); magick_free((void *)blob); rm_check_exception(exception, images, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rm_set_user_artifact(images, info); RB_GC_GUARD(info_obj); return array_from_images(images); @@ -11833,11 +11276,11 @@ image_ary = rb_ary_new(); while (images) { image = RemoveFirstImageFromList(&images); image_obj = rm_image_new(image); - (void) rb_ary_push(image_ary, image_obj); + rb_ary_push(image_ary, image_obj); } RB_GC_GUARD(image_obj); RB_GC_GUARD(image_ary); @@ -11846,16 +11289,13 @@ /** * Smooth the contours of an image while still preserving edge information. * - * Ruby usage: - * - @verbatim Image#reduce_noise(radius) @endverbatim - * - * @param self this object - * @param radius the radius - * @return a new image + * @param radius [Numeric] A neighbor is defined by radius. Use a radius of 0 and reduce_noise + * selects a suitable radius for you. + * @return [Magick::Image] a new image */ VALUE Image_reduce_noise(VALUE self, VALUE radius) { Image *image, *new_image; @@ -11866,30 +11306,26 @@ exception = AcquireExceptionInfo(); new_image = StatisticImage(image, NonpeakStatistic, radius_size, radius_size, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Call RemapImage. + * Reduce the number of colors in img to the colors used by remap_image. If a dither method is + * specified then the given colors are dithered over the image as necessary, otherwise the closest + * color (in RGB colorspace) is selected to replace that pixel in the image. * - * Ruby usage: - * - @verbatim Image#remap(remap_image) @endverbatim - * - @verbatim Image#remap(remap_image, dither_method) @endverbatim - * - * Notes: - * - Default dither_method is RiemersmaDitherMethod - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self + * @overload remap(remap_image, dither_method = Magick::RiemersmaDitherMethod) + * @param remap_image [Magick::Image, Magick::ImageList] The reference image or imagelist. If an + * imagelist, uses the current image. + * @param dither_method [Magick::DitherMethod] this object + * @return self */ VALUE Image_remap(int argc, VALUE *argv, VALUE self) { Image *image, *remap_image; @@ -11897,16 +11333,10 @@ #if defined(IMAGEMAGICK_7) ExceptionInfo *exception; #endif image = rm_check_frozen(self); - if (argc > 0) - { - VALUE t = rm_cur_image(argv[0]); - remap_image = rm_check_destroyed(t); - RB_GC_GUARD(t); - } GetQuantizeInfo(&quantize_info); switch (argc) { @@ -11921,61 +11351,88 @@ default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc); break; } + remap_image = rm_check_destroyed(rm_cur_image(argv[0])); + #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) RemapImage(&quantize_info, image, remap_image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + RemapImage(&quantize_info, image, remap_image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) RemapImage(&quantize_info, image, remap_image); + RemapImage(&quantize_info, image, remap_image); rm_check_image_exception(image, RetainOnError); #endif return self; } /** - * Get rendering_intent. + * Get the type of rendering intent. * - * Ruby usage: - * - @verbatim Image#rendering_intent @endverbatim - * - * @param self this object - * @return the rendering intent + * @return [Magick::RenderingIntent] the rendering intent */ VALUE Image_rendering_intent(VALUE self) { Image *image = rm_check_destroyed(self); return RenderingIntent_find(image->rendering_intent); } /** - * Set rendering_intent. + * Set the type of rendering intent.. * - * Ruby usage: - * - @verbatim Image#rendering_intent= @endverbatim - * - * @param self this object - * @param ri the rendering intent - * @return ri + * @param ri [Magick::RenderingIntent] the rendering intent + * @return [Magick::RenderingIntent] the given value */ VALUE Image_rendering_intent_eq(VALUE self, VALUE ri) { Image *image = rm_check_frozen(self); VALUE_TO_ENUM(ri, image->rendering_intent, RenderingIntent); return ri; } +#if defined(IMAGEMAGICK_7) /** + * Create new blurred image. + * + * No Ruby usage (internal function) + * + * @param image the image + * @param blur the blur + * @return NULL if not apply blur, otherwise a new image + */ +static Image* +blurred_image(Image* image, double blur) +{ + ExceptionInfo *exception; + Image *new_image; + + exception = AcquireExceptionInfo(); + if (blur > 1.0) + { + new_image = BlurImage(image, blur, blur, exception); + } + else + { + new_image = SharpenImage(image, blur, blur, exception); + } + rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); + + return new_image; +} +#endif + + +/** * Resample image to specified horizontal resolution, vertical resolution, * filter and blur factor. * * No Ruby usage (internal function) * @@ -11998,11 +11455,13 @@ Data_Get_Struct(self, Image, image); // Set up defaults filter = image->filter; -#if defined(IMAGEMAGICK_6) +#if defined(IMAGEMAGICK_7) + blur = 1.0; +#else blur = image->blur; #endif x_resolution = 72.0; y_resolution = 72.0; @@ -12051,85 +11510,73 @@ break; } exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) - new_image = ResampleImage(image, x_resolution, y_resolution, filter, exception); + Image *preprocess = blurred_image(image, blur); + new_image = ResampleImage(preprocess, x_resolution, y_resolution, filter, exception); + DestroyImage(preprocess); #else new_image = ResampleImage(image, x_resolution, y_resolution, filter, blur, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Resample image to specified horizontal resolution, vertical resolution, - * filter and blur factor. + * Resample image to specified horizontal resolution, vertical resolution, filter and blur factor. * - * Ruby usage: - * - @verbatim Image#resample @endverbatim - * - @verbatim Image#resample(resolution) @endverbatim - * - @verbatim Image#resample(x_resolution, y_resolution) @endverbatim - * - @verbatim Image#resample(x_resolution, y_resolution, filter) @endverbatim - * - @verbatim Image#resample(x_resolution, y_resolution, filter, blur) @endverbatim + * Resize the image so that its rendered size remains the same as the original at the specified + * target resolution. For example, if a 300 DPI image renders at 3 inches by 2 inches on a 300 DPI + * device, when the image has been resampled to 72 DPI, it will render at 3 inches by 2 inches on a + * 72 DPI device. Note that only a small number of image formats (e.g. JPEG, PNG, and TIFF) are + * capable of storing the image resolution. For formats which do not support an image resolution, + * the original resolution of the image must be specified via the density attribute prior to + * specifying the resample resolution. * - * Notes: - * - Default filter is image->filter - * - Default blur is image->blur - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see resample - * @see Image_resample_bang + * @overload resample(x_resolution = 72.0, y_resolution = 72.0, filter = self.filter, blur = self.blur) + * @param x_resolution [Float] the target horizontal resolution. + * @param y_resolution [Float] the target vertical resolution. + * @param filter [Magick::FilterType] the filter type + * @param blur [Float] the blur size + * @return [Magick] a new image + * @see Image#resample! */ VALUE Image_resample(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return resample(False, argc, argv, self); } /** - * Resample image to specified horizontal resolution, vertical resolution, - * filter and blur factor. + * Resample image to specified horizontal resolution, vertical resolution, filter and blur factor. + * In-place form of {Image#resample}. * - * Ruby usage: - * - @verbatim Image#resample @endverbatim - * - @verbatim Image#resample(resolution) @endverbatim - * - @verbatim Image#resample(x_resolution, y_resolution) @endverbatim - * - @verbatim Image#resample(x_resolution, y_resolution, filter) @endverbatim - * - @verbatim Image#resample(x_resolution, y_resolution, filter, blur) @endverbatim - * - * Notes: - * - Default filter is image->filter - * - Default blur is image->blur - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see resample - * @see Image_resample + * @overload resample!(x_resolution = 72.0, y_resolution = 72.0, filter = self.filter, blur = self.blur) + * @param x_resolution [Float] the target horizontal resolution. + * @param y_resolution [Float] the target vertical resolution. + * @param filter [Magick::FilterType] the filter type + * @param blur [Float] the blur size + * @return [Magick] a new image + * @see Image#resample */ VALUE Image_resample_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return resample(True, argc, argv, self); } /** @@ -12158,11 +11605,13 @@ Data_Get_Struct(self, Image, image); // Set up defaults filter = image->filter; -#if defined(IMAGEMAGICK_6) +#if defined(IMAGEMAGICK_7) + blur = 1.0; +#else blur = image->blur; #endif rows = image->rows; columns = image->columns; @@ -12200,98 +11649,88 @@ break; } exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) - new_image = ResizeImage(image, columns, rows, filter, exception); + Image *preprocess = blurred_image(image, blur); + new_image = ResizeImage(preprocess, columns, rows, filter, exception); + DestroyImage(preprocess); #else new_image = ResizeImage(image, columns, rows, filter, blur, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Scale an image to the desired dimensions using the specified filter and blur - * factor. + * Scale an image to the desired dimensions using the specified filter and blur factor. * - * Ruby usage: - * - @verbatim Image#resize(scale) @endverbatim - * - @verbatim Image#resize(cols, rows) @endverbatim - * - @verbatim Image#resize(cols, rows, filter) @endverbatim - * - @verbatim Image#resize(cols, rows, filter, blur) @endverbatim + * @overload resize(scale) + * @param scale [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. The scale factor 0.5 makes the new image 50% of the size of the receiver. * - * Notes: - * - Default filter is image->filter - * - Default blur is image->blur + * @overload resize(cols, rows, filter, blur) + * @param cols [Float] The desired width + * @param rows [Float] The desired height. + * @param filter [Magick::FilterType] the filter type + * @param blur [Float] the blur size * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see resize - * @see Image_resize_bang + * @return [Magick::Image] a new image + * @see Image#resize! */ VALUE Image_resize(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return resize(False, argc, argv, self); } /** - * Scale an image to the desired dimensions using the specified filter and blur - * factor. + * Scale an image to the desired dimensions using the specified filter and blur factor. + * In-place form of {Image#resize}. * - * Ruby usage: - * - @verbatim Image#resize!(scale) @endverbatim - * - @verbatim Image#resize!(cols, rows) @endverbatim - * - @verbatim Image#resize!(cols, rows, filter) @endverbatim - * - @verbatim Image#resize!(cols, rows, filter, blur) @endverbatim + * @overload resize!(scale) + * @param scale [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. The scale factor 0.5 makes the new image 50% of the size of the receiver. * - * Notes: - * - Default filter is image->filter - * - Default blur is image->blur + * @overload resize!(cols, rows, filter, blur) + * @param cols [Float] The desired width + * @param rows [Float] The desired height. + * @param filter [Magick::FilterType] the filter type + * @param blur [Float] the blur size * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see resize - * @see Image_resize + * @return [Magick::Image] a new image + * @see Image#resize! */ VALUE Image_resize_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return resize(True, argc, argv, self); } /** * Offset an image as defined by x_offset and y_offset. * - * Ruby usage: - * - @verbatim Image#roll(x_offset, y_offset) @endverbatim - * - * @param self this object - * @param x_offset the x offset - * @param y_offset the y offset - * @return a new image + * @param x_offset [Numeric] the x offset + * @param y_offset [Numeric] the y offset + * @return [Magick::Image] a new image */ VALUE Image_roll(VALUE self, VALUE x_offset, VALUE y_offset) { Image *image, *new_image; @@ -12302,15 +11741,12 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = RollImage(image, x, y, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** @@ -12363,177 +11799,177 @@ exception = AcquireExceptionInfo(); new_image = RotateImage(image, degrees, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Rotate the image. + * Rotate the receiver by the specified angle. Positive angles rotate clockwise while negative + * angles rotate counter-clockwise. New pixels introduced by the rotation are the same color as the + * current background color. Set the background color to "none" to make the new pixels transparent + * black. * - * Ruby usage: - * - @verbatim Image#rotate(degrees) @endverbatim - * - @verbatim Image#rotate(degrees, '<') @endverbatim - * - @verbatim Image#rotate(degrees, '>') @endverbatim + * @overload rotate(degrees) + * @param degrees [Float] The number of degrees to rotate the image. * - * Notes: - * - If the 2nd argument is '<' rotate only if width < height. If the 2nd - * argument is '>' rotate only if width > height. - * - Default is to always rotate + * @overload rotate(degrees, qualifier) + * @param degrees [Float] The number of degrees to rotate the image. + * @param qualifier [String] If present, either ">" or "<". If ">", rotates the image only if the + * image's width exceeds its height. If "<" rotates the image only if its height exceeds its + * width. If this argument is omitted the image is always rotated. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see rotate - * @see Image_rotate_bang + * @return [Magick::Image] a new image + * @see Image#rotate! */ VALUE Image_rotate(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return rotate(False, argc, argv, self); } /** * Rotate the image. + * In-place form of {Image#rotate}. * - * Ruby usage: - * - @verbatim Image#rotate!(degrees) @endverbatim - * - @verbatim Image#rotate!(degrees, '<') @endverbatim - * - @verbatim Image#rotate!(degrees, '>') @endverbatim + * @overload rotate!(degrees) + * @param degrees [Float] The number of degrees to rotate the image. * - * Notes: - * - If the 2nd argument is '<' rotate only if width < height. If the 2nd - * argument is '>' rotate only if width > height. - * - Default is to always rotate + * @overload rotate!(degrees, qualifier) + * @param degrees [Float] The number of degrees to rotate the image. + * @param qualifier [String] If present, either ">" or "<". If ">", rotates the image only if the + * image's width exceeds its height. If "<" rotates the image only if its height exceeds its + * width. If this argument is omitted the image is always rotated. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see rotate - * @see Image_rotate + * @return [Magick::Image] a new image + * @see Image#rotate! */ VALUE Image_rotate_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return rotate(True, argc, argv, self); } /** * Return image rows. * - * Ruby usage: - * - @verbatim Image#rows @endverbatim - * - * @param self this object - * @return the image rows + * @return [Numeric] the image rows */ -DEF_ATTR_READER(Image, rows, int) +VALUE +Image_rows(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, rows, int); +} /** - * Scale an image to the desired dimensions with pixel sampling. + * Scale an image to the desired dimensions with pixel sampling. Unlike other scaling methods, this + * method does not introduce any additional color into the scaled image. * - * Ruby usage: - * - @verbatim Image#sample(scale) @endverbatim - * - @verbatim Image#sample(cols, rows) @endverbatim + * @overload sample(scale) + * @param scale [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. The scale factor 0.5 makes the new image 50% of the size of the receiver. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see scale - * @see Image_sample_bang + * @overload sample(cols, rows) + * @param cols [Numeric] The desired width. + * @param rows [Numeric] The desired height. + * + * @return [Magick::Image] a new image + * @see Image#sample! */ VALUE Image_sample(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return scale(False, argc, argv, self, SampleImage); } /** * Scale an image to the desired dimensions with pixel sampling. + * In-place form of {Image#sample}. * - * Ruby usage: - * - @verbatim Image#sample!(scale) @endverbatim - * - @verbatim Image#sample!(cols, rows) @endverbatim + * @overload sample!(scale) + * @param scale [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. The scale factor 0.5 makes the new image 50% of the size of the receiver. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see scale - * @see Image_sample + * @overload sample!(cols, rows) + * @param cols [Numeric] The desired width. + * @param rows [Numeric] The desired height. + * + * @return [Magick::Image] a new image + * @see Image#sample */ VALUE Image_sample_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return scale(True, argc, argv, self, SampleImage); } /** - * Change the size of an image to the given dimensions. + * Change the size of an image to the given dimensions. Alias of {Image#sample}. * - * Ruby usage: - * - @verbatim Image#scale(scale) @endverbatim - * - @verbatim Image#scale(cols, rows) @endverbatim + * @overload scale(scale) + * @param scale [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. The scale factor 0.5 makes the new image 50% of the size of the receiver. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see scale - * @see Image_scale_bang + * @overload scale(cols, rows) + * @param cols [Numeric] The desired width. + * @param rows [Numeric] The desired height. + * + * @return [Magick::Image] a new image + * @see Image#sample + * @see Image#scale! */ VALUE Image_scale(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return scale(False, argc, argv, self, ScaleImage); } /** - * Change the size of an image to the given dimensions. + * Change the size of an image to the given dimensions. Alias of {Image#sample!}. * - * Ruby usage: - * - @verbatim Image#scale!(scale) @endverbatim - * - @verbatim Image#scale!(cols, rows) @endverbatim + * @overload scale!(scale) + * @param scale [Float] You can use this argument instead of specifying the desired width and + * height. The percentage size change. For example, 1.25 makes the new image 125% of the size of + * the receiver. The scale factor 0.5 makes the new image 50% of the size of the receiver. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see scale - * @see Image_scale + * @overload scale!(cols, rows) + * @param cols [Numeric] The desired width. + * @param rows [Numeric] The desired height. + * + * @return [Magick::Image] a new image + * @see Image#sample + * @see Image#scale! */ VALUE Image_scale_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return scale(True, argc, argv, self, ScaleImage); } /** @@ -12597,53 +12033,55 @@ } exception = AcquireExceptionInfo(); new_image = (scaler)(image, columns, rows, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Return image scene. + * Return the scene number assigned to the image the last time the image was written to a + * multi-image image file. * - * Ruby usage: - * - @verbatim Image#scene @endverbatim - * - * @param self this object - * @return the image scene + * @return [Numeric] the image scene */ -DEF_ATTR_READER(Image, scene, ulong) +VALUE +Image_scene(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, scene, ulong); +} /** - * Call SelectiveBlurImageChannel. + * Selectively blur pixels within a contrast threshold. * - * Ruby usage: - * - @verbatim Image#selective_blur_channel(radius, sigma, threshold) @endverbatim - * - @verbatim Image#selective_blur_channel(radius, sigma, threshold, channel) @endverbatim - * - @verbatim Image#selective_blur_channel(radius, sigma, threshold, channel, ...) @endverbatim + * @overload selective_blur_channel(radius, sigma, threshold, channel = Magick::AllChannels) + * @param radius [Float] the radius value + * @param sigma [Float] the sigma value + * @param threshold [Float, String] Either a number between 0.0 and 1.0 or a string in the form + * "NN%" + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload selective_blur_channel(radius, sigma, threshold, *channels) + * @param radius [Float] the radius value + * @param sigma [Float] the sigma value + * @param threshold [Float, String] Either a number between 0.0 and 1.0 or a string in the form + * "NN%" + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_selective_blur_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -12664,11 +12102,11 @@ radius = NUM2DBL(argv[0]); sigma = NUM2DBL(argv[1]); // threshold is either a floating-point number or a string in the form "NN%". // Either way it's supposed to represent a percentage of the QuantumRange. - threshold = rm_percentage(argv[2],1.0) * QuantumRange; + threshold = rm_percentage(argv[2], 1.0) * QuantumRange; exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) BEGIN_CHANNEL_MASK(image, channels); new_image = SelectiveBlurImage(image, radius, sigma, threshold, exception); @@ -12676,26 +12114,21 @@ END_CHANNEL_MASK(image); #else new_image = SelectiveBlurImageChannel(image, channels, radius, sigma, threshold, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Call SetImageChannelDepth. + * Sets the depth of the image channel. * - * Ruby usage: - * - @verbatim Image#set_channel_depth(channel, depth) @endverbatim - * - * @param self this object - * @param channel_arg the channel - * @param depth the depth + * @param channel_arg [Magick::ChannelType] the channel + * @param depth [Numeric] the depth * @return self */ VALUE Image_set_channel_depth(VALUE self, VALUE channel_arg, VALUE depth) { @@ -12712,38 +12145,33 @@ channel_depth = NUM2ULONG(depth); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(image, channel); - (void) SetImageDepth(image, channel_depth, exception); + SetImageDepth(image, channel_depth, exception); END_CHANNEL_MASK(image); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageChannelDepth(image, channel, channel_depth); + SetImageChannelDepth(image, channel, channel_depth); rm_check_image_exception(image, RetainOnError); #endif return self; } /** - * Call SeparateImages. + * Constructs a grayscale image for each channel specified. * - * Ruby usage: - * - @verbatim separate @endverbatim - * - @verbatim separate(channel) @endverbatim - * - @verbatim separate(channel, ...) @endverbatim + * @overload separate(channel = Magick::AllChannels) + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default channel is AllChannels + * @overload separate(*channels) + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new ImageList + * @return [Magick::ImageList] a new ImageList */ VALUE Image_separate(int argc, VALUE *argv, VALUE self) { Image *image, *new_images; @@ -12768,30 +12196,23 @@ #else new_images = SeparateImages(image, channels, exception); #endif rm_check_exception(exception, new_images, DestroyOnError); DestroyExceptionInfo(exception); - rm_ensure_result(new_images); return rm_imagelist_from_images(new_images); } /** - * Call SepiaToneImage. + * Applies a special effect to the image, similar to the effect achieved in a photo darkroom by + * sepia toning. * - * Ruby usage: - * - @verbatim Image#sepiatone @endverbatim - * - @verbatim Image#sepiatone(threshold) @endverbatim - * - * Notes: - * - Default threshold is QuantumRange - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload sepiatone(threshold = Magick::QuantumRange) + * @param threshold [Float] Threshold ranges from 0 to QuantumRange and is a measure of the extent + * of the sepia toning. A threshold of 80% is a good starting point for a reasonable tone. + * @return [Magick::Image] a new image */ VALUE Image_sepiatone(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -12812,39 +12233,31 @@ } exception = AcquireExceptionInfo(); new_image = SepiaToneImage(image, threshold, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call SegmentImage. + * Segments an image by analyzing the histograms of the color components and identifying units that + * are homogeneous with the fuzzy c-means technique. * - * Ruby usage: - * - @verbatim Image#segment @endverbatim - * - @verbatim Image#segment(colorspace) @endverbatim - * - @verbatim Image#segment(colorspace,cluster_threshold) @endverbatim - * - @verbatim Image#segment(colorspace,cluster_threshold,smoothing_threshold) @endverbatim - * - @verbatim Image#segment(colorspace,cluster_threshold,smoothing_threshold,verbose) @endverbatim - * - * Notes: - * - Default colorspace is RGBColorspace - * - Default cluster_threshold is 1.0 - * - Default smoothing_threshold is 1.5 - * - Default verbose is false - * - The default values are the same as Magick++ - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload segment(colorspace = Magick::RGBColorspace, cluster_threshold = 1.0, smoothing_threshold = 1.5, verbose = false) + * @param colorspace [Magick::ColorspaceType] A ColorspaceType value. Empirical evidence suggests + * that distances in YUV or YIQ correspond to perceptual color differences more closely than do + * distances in RGB space. The image is then returned to RGB colorspace after color reduction. + * @param cluster_threshold [Float] The number of pixels in each cluster must exceed the the + * cluster threshold to be considered valid. + * @param smoothing_threshold [Float] The smoothing threshold eliminates noise in the second + * derivative of the histogram. As the value is increased, you can expect a smoother second + * derivative. + * @param verbose [Boolean] If true, segment prints detailed information about the identified classes. + * @return [Magick::Image] a new image */ VALUE Image_segment(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -12876,37 +12289,34 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SegmentImage(new_image, colorspace, verbose, cluster_threshold, smoothing_threshold, exception); + SegmentImage(new_image, colorspace, verbose, cluster_threshold, smoothing_threshold, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) SegmentImage(new_image, colorspace, verbose, cluster_threshold, smoothing_threshold); + SegmentImage(new_image, colorspace, verbose, cluster_threshold, smoothing_threshold); rm_check_image_exception(new_image, DestroyOnError); #endif - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Traverse the attributes and yield to the block. If no block, return a hash - * of all the attribute keys & values. + * If called with an associated block, properties runs the block once for each property defined for + * the image. The block arguments are the property name and its value. If there is no block, + * properties returns a hash with one element for each property. The hash key is the property name + * and the associated value is the property value. * - * Ruby usage: - * - @verbatim Image#properties [{ |k,v| block }] @endverbatim + * @overload properties + * @return [Hash] the properties * - * Notes: - * - I use the word "properties" to distinguish between these "user-added" - * attribute strings and Image object attributes. - * - * @param self this object - * @return self if block, else hash of attribute keys and values. + * @overload properties + * @yield [] + * @return [Magick::Image] self */ VALUE Image_properties(VALUE self) { Image *image; @@ -12933,18 +12343,18 @@ #if defined(IMAGEMAGICK_7) value = GetImageProperty(image, property, exception); #else value = GetImageProperty(image, property); #endif - (void) rb_ary_store(ary, 0, rb_str_new2(property)); - (void) rb_ary_store(ary, 1, rb_str_new2(value)); - (void) rb_yield(ary); + rb_ary_store(ary, 0, rb_str_new2(property)); + rb_ary_store(ary, 1, rb_str_new2(value)); + rb_yield(ary); property = GetNextImageProperty(image); } #if defined(IMAGEMAGICK_7) - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else rm_check_image_exception(image, RetainOnError); #endif RB_GC_GUARD(ary); @@ -12963,16 +12373,16 @@ #if defined(IMAGEMAGICK_7) value = GetImageProperty(image, property, exception); #else value = GetImageProperty(image, property); #endif - (void) rb_hash_aset(attr_hash, rb_str_new2(property), rb_str_new2(value)); + rb_hash_aset(attr_hash, rb_str_new2(property), rb_str_new2(value)); property = GetNextImageProperty(image); } #if defined(IMAGEMAGICK_7) - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else rm_check_image_exception(image, RetainOnError); #endif RB_GC_GUARD(attr_hash); @@ -12982,37 +12392,28 @@ } /** - * Shine a distant light on an image to create a three-dimensional effect. You - * control the positioning of the light with azimuth and elevation; azimuth is - * measured in degrees off the x axis and elevation is measured in pixels above - * the Z axis. + * Shine a distant light on an image to create a three-dimensional effect. You control the + * positioning of the light with azimuth and elevation; azimuth is measured in degrees off the x + * axis and elevation is measured in pixels above the Z axis. * - * Ruby usage: - * - @verbatim Image#shade @endverbatim - * - @verbatim Image#shade(shading) @endverbatim - * - @verbatim Image#shade(shading, azimuth) @endverbatim - * - @verbatim Image#shade(shading, azimuth, elevation) @endverbatim - * - * Notes: - * - Default shading is false - * - Default azimuth is 30 - * - Default elevation is 30 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload shade(shading = false, azimuth = 30.0, elevation = 30.0) + * @param shading [Boolean] If true, shade shades the intensity of each pixel. + * @param azimuth [Float] The light source direction. The azimuth is measured in degrees. 0 is at + * 9 o'clock. Increasing values move the light source counter-clockwise. + * @param elevation [Float] The light source direction. The azimuth is measured in degrees. 0 is + * at 9 o'clock. Increasing values move the light source counter-clockwise. + * @return [Magick::Image] a new image */ VALUE Image_shade(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; double azimuth = 30.0, elevation = 30.0; - unsigned int shading=MagickFalse; + unsigned int shading = MagickFalse; ExceptionInfo *exception; image = rm_check_destroyed(self); switch (argc) { @@ -13030,43 +12431,29 @@ } exception = AcquireExceptionInfo(); new_image = ShadeImage(image, shading, azimuth, elevation, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call ShadowImage. X- and y-offsets are the pixel offset. Alpha is either a - * number between 0 and 1 or a string "NN%". Sigma is the std. dev. of the - * Gaussian, in pixels. + * Call ShadowImage. X- and y-offsets are the pixel offset. Alpha is either a number between 0 and 1 + * or a string "NN%". Sigma is the std. dev. of the Gaussian, in pixels. * - * Ruby usage: - * - @verbatim Image#shadow @endverbatim - * - @verbatim Image#shadow(x_offset) @endverbatim - * - @verbatim Image#shadow(x_offset, y_offset) @endverbatim - * - @verbatim Image#shadow(x_offset, y_offset, sigma) @endverbatim - * - @verbatim Image#shadow(x_offset, y_offset, sigma, alpha) @endverbatim - * - * Notes: - * - Default x_offset is 4 - * - Default y_offset is 4 - * - Default sigma is 4.0 - * - Default alpha is 1.0 - * - The defaults are taken from the mogrify.c source, except for alpha, - * which has no default. - * - Introduced in ImageMagick 6.1.7 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload Image#shadow(x_offset = 4, y_offset = 4, sigma = 4.0, alpha = 1.0) + * @param x_offset [Numeric] The shadow x-offset + * @param y_offset [Numeric] The shadow y-offset + * @param sigma [Float] The standard deviation of the Gaussian operator used to produce the + * shadow. The higher the number, the "blurrier" the shadow, but the longer it takes to produce + * the shadow. Must be > 0.0. + * @param alpha [String, Float] The percent alpha of the shadow. The argument may be a + * floating-point numeric value or a string in the form "NN%". + * @return [Magick::Image] a new image */ VALUE Image_shadow(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13078,11 +12465,11 @@ image = rm_check_destroyed(self); switch (argc) { case 4: - alpha = rm_percentage(argv[3],1.0); // Clamp to 1.0 < x <= 100.0 + alpha = rm_percentage(argv[3], 1.0); // Clamp to 1.0 < x <= 100.0 if (fabs(alpha) < 0.01) { rb_warning("shadow will be transparent - alpha %g very small", alpha); } alpha = FMIN(alpha, 1.0); @@ -13102,35 +12489,23 @@ } exception = AcquireExceptionInfo(); new_image = ShadowImage(image, alpha, sigma, x_offset, y_offset, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Sharpen an image. * - * Ruby usage: - * - @verbatim Image#sharpen @endverbatim - * - @verbatim Image#sharpen(radius) @endverbatim - * - @verbatim Image#sharpen(radius, sigma) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see effect_image + * @overload sharpen(radius = 0.0, sigma = 1.0) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @return [Magick::Image] a new image */ VALUE Image_sharpen(int argc, VALUE *argv, VALUE self) { return effect_image(self, argc, argv, SharpenImage); @@ -13138,26 +12513,21 @@ /** * Sharpen image on a channel. * - * Ruby usage: - * - @verbatim Image#sharpen_channel @endverbatim - * - @verbatim Image#sharpen_channel(radius) @endverbatim - * - @verbatim Image#sharpen_channel(radius, sigma) @endverbatim - * - @verbatim Image#sharpen_channel(radius, sigma, channel) @endverbatim - * - @verbatim Image#sharpen_channel(radius, sigma, channel, ...) @endverbatim + * @overload sharpen_channel(radius = 0.0, sigma = 1.0, channel = Magick::AllChannels) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default channel is AllChannels + * @overload sharpen_channel(radius = 0.0, sigma = 1.0, *channels) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The sigma (standard deviation) of the Gaussian operator. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_sharpen_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13192,70 +12562,62 @@ #else new_image = SharpenImageChannel(image, channels, radius, sigma, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** - * Shave pixels from the image edges, leaving a rectangle of the specified width - * & height in the center. + * Shave pixels from the image edges, leaving a rectangle of the specified width & height in the + * center. * - * Ruby usage: - * - @verbatim Image#shave(width, height) @endverbatim - * - * @param self this object - * @param width the width to leave - * @param height the hight to leave - * @return a new image - * @see xform_image - * @see Image_shave_bang + * @param width [Numeric] the width to leave + * @param height [Numeric] the hight to leave + * @return [Magick::Image] a new image + * @see Image#shave! */ VALUE Image_shave(VALUE self, VALUE width, VALUE height) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return xform_image(False, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage); } /** - * Shave pixels from the image edges, leaving a rectangle of the specified width - * & height in the center. + * Shave pixels from the image edges, leaving a rectangle of the specified width & height in the + * center. + * In-place form of {Image#shave}. * - * Ruby usage: - * - @verbatim Image#shave!(width, height) @endverbatim - * - * @param self this object - * @param width the width to leave - * @param height the hight to leave - * @return self - * @see xform_image - * @see Image_shave + * @param width [Numeric] the width to leave + * @param height [Numeric] the hight to leave + * @return [Magick::Image] a new image + * @see Image#shave */ VALUE Image_shave_bang(VALUE self, VALUE width, VALUE height) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return xform_image(True, self, INT2FIX(0), INT2FIX(0), width, height, ShaveImage); } /** - * Call ShearImage. + * Shearing slides one edge of an image along the X or Y axis, creating a parallelogram. An X + * direction shear slides an edge along the X axis, while a Y direction shear slides an edge along + * the Y axis. The amount of the shear is controlled by a shear angle. For X direction shears, + * x_shear is measured relative to the Y axis, and similarly, for Y direction shears y_shear is + * measured relative to the X axis. Empty triangles left over from shearing the image are filled + * with the background color. * - * Ruby usage: - * - @verbatim Image#shear(x_shear, y_shear) @endverbatim - * - * @param self this object - * @param x_shear the x shear (in degrees) - * @param y_shear the y shear (in degrees) - * @return a new image + * @param x_shear [Float] the x shear (in degrees) + * @param y_shear [Float] the y shear (in degrees) + * @return [Magick::Image] a new image */ VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image, *new_image; @@ -13266,39 +12628,43 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, x, y, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call SigmoidalContrastImageChannel. + * Adjusts the contrast of an image channel with a non-linear sigmoidal contrast + * algorithm. Increases the contrast of the image using a sigmoidal transfer function without + * saturating highlights or shadows. * - * Ruby usage: - * - @verbatim Image#sigmoidal_contrast_channel @endverbatim - * - @verbatim Image#sigmoidal_contrast_channel(contrast) @endverbatim - * - @verbatim Image#sigmoidal_contrast_channel(contrast, midpoint) @endverbatim - * - @verbatim Image#sigmoidal_contrast_channel(contrast, midpoint, sharpen) @endverbatim - * - @verbatim Image#sigmoidal_contrast_channel(contrast, midpoint, sharpen, channel) @endverbatim - * - @verbatim Image#sigmoidal_contrast_channel(contrast, midpoint, sharpen, channel, ...) @endverbatim + * @overload sigmoidal_contrast_channel(contrast = 3.0, midpoint = 50.0, sharpen = false, channel = Magick::AllChannels) + + * @param contrast [Float] indicates how much to increase the contrast + * (0 is none; 3 is typical; 20 is pushing it) + * @param midpoint [Float] indicates where midtones fall in the resultant image (0 is white; 50% + * is middle-gray; 100% is black). Note that "50%" means "50% of the quantum range." This argument + * is a number between 0 and QuantumRange. To specify "50%" use QuantumRange * 0.50. + * @param sharpen [Boolean] Set sharpen to true to increase the image contrast otherwise the + * contrast is reduced. + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * Notes: - * - Default contrast is 3.0 - * - Default midpoint is 50.0 - * - Default sharpen is false - * - Default channel is AllChannels + * @overload sigmoidal_contrast_channel(contrast = 3.0, midpoint = 50.0, sharpen = false, *channels) + * @param contrast [Float] indicates how much to increase the contrast + * (0 is none; 3 is typical; 20 is pushing it) + * @param midpoint [Float] indicates where midtones fall in the resultant image (0 is white; 50% + * is middle-gray; 100% is black). Note that "50%" means "50% of the quantum range." This argument + * is a number between 0 and QuantumRange. To specify "50%" use QuantumRange * 0.50. + * @param sharpen [Boolean] Set sharpen to true to increase the image contrast otherwise the + * contrast is reduced. + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_sigmoidal_contrast_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13331,32 +12697,28 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); BEGIN_CHANNEL_MASK(new_image, channels); - (void) SigmoidalContrastImage(new_image, sharpen, contrast, midpoint, exception); + SigmoidalContrastImage(new_image, sharpen, contrast, midpoint, exception); END_CHANNEL_MASK(new_image); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) SigmoidalContrastImageChannel(new_image, channels, sharpen, contrast, midpoint); + SigmoidalContrastImageChannel(new_image, channels, sharpen, contrast, midpoint); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** - * Compute a message digest from an image pixel stream with an implementation of - * the NIST SHA-256 Message Digest algorithm. + * Compute a message digest from an image pixel stream with an implementation of the NIST SHA-256 + * Message Digest algorithm. * - * Ruby usage: - * - @verbatim Image#signature @endverbatim - * - * @param self this object - * @return the message digest + * @return [String, nil] the message digest */ VALUE Image_signature(VALUE self) { Image *image; @@ -13367,15 +12729,15 @@ image = rm_check_destroyed(self); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SignatureImage(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SignatureImage(image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SignatureImage(image); + SignatureImage(image); rm_check_image_exception(image, RetainOnError); #endif signature = rm_get_property(image, "signature"); if (!signature) { @@ -13384,54 +12746,36 @@ return rb_str_new(signature, 64); } /** - * Call SketchImage. + * Simulates a pencil sketch. For best results start with a grayscale image. * - * Ruby usage: - * - @verbatim Image#sketch @endverbatim - * - @verbatim Image#sketch(radius) @endverbatim - * - @verbatim Image#sketch(radius, sigma) @endverbatim - * - @verbatim Image#sketch(radius, sigma, angle) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default angle is 0.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see motion_blur + * @overload sketch(radius = 0.0, sigma = 1.0, angle = 0.0) + * @param radius [Float] The radius + * @param sigma [Float] The standard deviation + * @param angle [Float] The angle (in degrees) + * @return [Magick::Image] a new image + * @see motion_blur */ VALUE Image_sketch(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return motion_blur(argc, argv, self, SketchImage); } /** - * Apply a special effect to the image, similar to the effect achieved in a - * photo darkroom by selectively exposing areas of photo sensitive paper to - * light. Threshold ranges from 0 to QuantumRange and is a measure of the extent - * of the solarization. + * Apply a special effect to the image, similar to the effect achieved in a photo darkroom by + * selectively exposing areas of photo sensitive paper to light. Threshold ranges from 0 to + * QuantumRange and is a measure of the extent of the solarization. * - * Ruby usage: - * - @verbatim Image#solarize @endverbatim - * - @verbatim Image#solarize(threshold) @endverbatim - * - * Notes: - * - Default threshold is 50.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload solarize(threshold = 50.0) + * @param threshold [Float] Ranges from 0 to QuantumRange and is a measure of the extent of the + * solarization. + * @return a new image */ VALUE Image_solarize(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13458,31 +12802,27 @@ new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SolarizeImage(new_image, threshold, exception); + SolarizeImage(new_image, threshold, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) SolarizeImage(new_image, threshold); + SolarizeImage(new_image, threshold); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } /** * Compare two images. * - * Ruby usage: - * - @verbatim Image#<=> @endverbatim - * - * @param self this image - * @param other other image - * @return -1, 0, 1 + * @param other [Object] other image + * @return [-1, 0, 1, nil] the result of compare */ VALUE Image_spaceship(VALUE self, VALUE other) { Image *imageA, *imageB; @@ -13502,18 +12842,18 @@ imageB = rm_check_destroyed(other); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SignatureImage(imageA, exception); + SignatureImage(imageA, exception); CHECK_EXCEPTION(); - (void) SignatureImage(imageB, exception); + SignatureImage(imageB, exception); CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) SignatureImage(imageA); - (void) SignatureImage(imageB); + SignatureImage(imageA); + SignatureImage(imageB); #endif sigA = rm_get_property(imageA, "signature"); sigB = rm_get_property(imageB, "signature"); if (!sigA || !sigB) { @@ -13579,31 +12919,29 @@ return ncolors; } /** - * Call SparseColorInterpolate. + * Fills the image with the specified color or colors, starting at the x,y coordinates associated + * with the color and using the specified interpolation method. * - * Ruby usage: - * - @verbatim Image#sparse_color(method, x1, y1, color) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, x2, y2, color) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, x2, y2, color, ...) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, channel) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, x2, y2, color, channel) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, x2, y2, color, ..., channel) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, channel, ...) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, x2, y2, color, channel, ...) @endverbatim - * - @verbatim Image#sparse_color(method, x1, y1, color, x2, y2, color, ..., channel, ...) @endverbatim + * @overload sparse_color(method, x1, y1, color) + * @overload sparse_color(method, x1, y1, color, x2, y2, color) + * @overload sparse_color(method, x1, y1, color, x2, y2, color, ...) + * @overload sparse_color(method, x1, y1, color, channel) + * @overload sparse_color(method, x1, y1, color, x2, y2, color, channel) + * @overload sparse_color(method, x1, y1, color, x2, y2, color, ..., channel) + * @overload sparse_color(method, x1, y1, color, channel, ...) + * @overload sparse_color(method, x1, y1, color, x2, y2, color, channel, ...) + * @overload sparse_color(method, x1, y1, color, x2, y2, color, ..., channel, ...) + * @param method [Magick::SparseColorMethod] the method + * @param x1 [Float] One or more x. + * @param y1 [Float] One or more y. + * @param color [Magick::Pixel, String] One or more color + * @param channel [Magick::ChannelType] one or more ChannelType arguments * - * Notes: - * - Default channel is AllChannels - * - As usual, 'color' can be either a color name or a pixel - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_sparse_color(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13623,11 +12961,10 @@ // After the channel arguments have been removed, and not counting the first // (method) argument, the number of arguments should be a multiple of 3. if (argc < 4 || argc % 3 != 1) { - exp = argc - 1; exp = (argc + 2) / 3 * 3; exp = max(exp, 3); rb_raise(rb_eArgError, "wrong number of arguments (expected at least %d, got %d)", n+exp+1, n+argc); } @@ -13697,35 +13034,29 @@ #else new_image = SparseColorImage(image, channels, method, nargs, args, exception); #endif xfree((void *) args); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); + DestroyExceptionInfo(exception); return rm_image_new(new_image); } /** * Splice a solid color into the part of the image specified by the x, y, width, * and height arguments. If the color argument is specified it must be a color * name or Pixel. * - * Ruby usage: - * - @verbatim Image#splice(x, y, width, height) @endverbatim - * - @verbatim Image#splice(x, y, width, height, color) @endverbatim - * - * Notes: - * - Default color is the background color. - * - Splice is the inverse of chop - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see Image_chop + * @overload splice(x, y, width, height, color = self.background_color) + * @param x [Numeric] Describe the rectangle to be spliced. + * @param y [Numeric] Describe the rectangle to be spliced. + * @param width [Numeric] Describe the rectangle to be spliced. + * @param height [Numeric] Describe the rectangle to be spliced. + * @param color [Magick::Pixel, String] The color to be spliced. + * @return [Magick::Image] a new image + * @see Image#chop */ VALUE Image_splice(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13762,33 +13093,22 @@ image->background_color = color; new_image = SpliceImage(image, &rectangle, exception); image->background_color = old_color; rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Randomly displace each pixel in a block defined by "radius". * - * Ruby usage: - * - @verbatim Image#spread @endverbatim - * - @verbatim Image#spread(radius) @endverbatim - * - * Notes: - * - Default radius is 3.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload spread(radius = 3.0) + * @param radius [Float] The radius + * @return [Magick::Image] a new image */ VALUE Image_spread(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -13812,32 +13132,51 @@ new_image = SpreadImage(image, image->interpolate, radius, exception); #else new_image = SpreadImage(image, radius, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); - rm_ensure_result(new_image); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - return rm_image_new(new_image); } -DEF_ATTR_ACCESSOR(Image, start_loop, bool) +/** + * Get the Boolean value that indicates the first image in an animation. + * + * @return [Boolean] true or false + */ +VALUE +Image_start_loop(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, start_loop, boolean); +} +/** + * Set the Boolean value that indicates the first image in an animation. + * + * @param val [Boolean] true or false + * @return [Boolean] the given value + */ +VALUE +Image_start_loop_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, start_loop, boolean); +} + /** - * Hide a digital watermark within the image. Recover the hidden watermark later - * to prove that the authenticity of an image. + * Hides a digital watermark in the receiver. You can retrieve the watermark by reading the file + * with the stegano: prefix, thereby proving the authenticity of the file. * - * Ruby usage: - * - @verbatim Image#stegano(watermark, offset) @endverbatim + * The watermarked image must be saved in a lossless RGB format such as MIFF, or PNG. You cannot + * save a watermarked image in a lossy format such as JPEG or a pseudocolor format such as GIF. Once + * written, the file must not be modified or processed in any way. * - * @param self this object - * @param watermark_image the watermark image - * @param offset the start position within the image to hide the watermark. - * @return a new image + * @param watermark_image [Magick::Image, Magick::ImageList] Either an imagelist or an image + * @param offset [Numeric] the start position within the image to hide the watermark. + * @return [Magick::Image] a new image */ VALUE Image_stegano(VALUE self, VALUE watermark_image, VALUE offset) { Image *image, *new_image; @@ -13854,31 +13193,24 @@ exception = AcquireExceptionInfo(); new_image = SteganoImage(image, watermark, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - RB_GC_GUARD(wm_image); return rm_image_new(new_image); } /** - * Combine two images and produces a single image that is the composite of a - * left and right image of a stereo pair. Special red-green stereo glasses are - * required to view this effect. + * Combine two images and produces a single image that is the composite of a left and right image of + * a stereo pair. Special red-green stereo glasses are required to view this effect. * - * Ruby usage: - * - @verbatim Image#stereo(offset_image) @endverbatim - * - * @param self this object - * @param offset_image_arg the other image - * @return a new image + * @param offset_image_arg [Magick::Image, Magick::ImageList] Either an imagelist or an image. + * @return [Magick::Image] a new image */ VALUE Image_stereo(VALUE self, VALUE offset_image_arg) { Image *image, *new_image; @@ -13893,31 +13225,24 @@ exception = AcquireExceptionInfo(); new_image = StereoImage(image, offset, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - RB_GC_GUARD(offset_image); return rm_image_new(new_image); } /** - * Return the image's storage class (a.k.a. storage type, class type). + * Return the image's storage class (a.k.a. storage type, class type). If DirectClass then the + * pixels contain valid RGB or CMYK colors. If PseudoClass then the image has a colormap referenced + * by the pixel's index member. * - * Ruby usage: - * - @verbatim Image#class_type @endverbatim - * - * Notes: - * - Based on Magick++'s Magick::Magick::classType - * - * @param self this object - * @return the storage class + * @return [Magick::ClassType] the storage class */ VALUE Image_class_type(VALUE self) { Image *image = rm_check_destroyed(self); @@ -13926,19 +13251,12 @@ /** * Change the image's storage class. * - * Ruby usage: - * - @verbatim Image#class_type= @endverbatim - * - * Notes: - * - Based on Magick++'s Magick::Magick::classType - * - * @param self this object - * @param new_class_type the storage class - * @return new_class_type + * @param new_class_type [Magick::ClassType] the storage class + * @return [Magick::ClassType] the given value */ VALUE Image_class_type_eq(VALUE self, VALUE new_class_type) { Image *image; @@ -13962,63 +13280,57 @@ #endif if (image->storage_class == PseudoClass && class_type == DirectClass) { #if defined(IMAGEMAGICK_7) - (void) SyncImage(image, exception); - CHECK_EXCEPTION() + SyncImage(image, exception); + CHECK_EXCEPTION(); #else - (void) SyncImage(image); + SyncImage(image); #endif magick_free(image->colormap); image->colormap = NULL; } else if (image->storage_class == DirectClass && class_type == PseudoClass) { GetQuantizeInfo(&qinfo); qinfo.number_colors = QuantumRange+1; #if defined(IMAGEMAGICK_7) - (void) QuantizeImage(&qinfo, image, exception); - CHECK_EXCEPTION() + QuantizeImage(&qinfo, image, exception); + CHECK_EXCEPTION(); #else - (void) QuantizeImage(&qinfo, image); + QuantizeImage(&qinfo, image); #endif } #if defined(IMAGEMAGICK_7) - (void) SetImageStorageClass(image, class_type, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageStorageClass(image, class_type, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageStorageClass(image, class_type); + SetImageStorageClass(image, class_type); #endif return new_class_type; } /** - * Replace the pixels in the specified rectangle. + * Replace the pixels in the specified rectangle with the pixels in the pixels array. * - * Ruby usage: - * - @verbatim Image#store_pixels(x,y,cols,rows,new_pixels) @endverbatim + * - This is the complement of get_pixels. The array object returned by get_pixels is suitable for + * use as the "new_pixels" argument. * - * Notes: - * - Calls GetImagePixels, then SyncImagePixels after replacing the pixels. - * - This is the complement of get_pixels. The array object returned by - * get_pixels is suitable for use as the "new_pixels" argument. - * - * @param self this object - * @param x_arg x position of start of region - * @param y_arg y position of start of region - * @param cols_arg width of region - * @param rows_arg height of region - * @param new_pixels the replacing pixels - * @return self + * @param x_arg [Numeric] x position of start of region + * @param y_arg [Numeric] y position of start of region + * @param cols_arg [Numeric] width of region + * @param rows_arg [Numeric] height of region + * @param new_pixels [Array<Magick::Pixel>] the replacing pixels + * @return [Magick::Image] self */ VALUE -Image_store_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg - , VALUE rows_arg, VALUE new_pixels) +Image_store_pixels(VALUE self, VALUE x_arg, VALUE y_arg, VALUE cols_arg, + VALUE rows_arg, VALUE new_pixels) { Image *image; Pixel *pixel; VALUE new_pixel; long n, size; @@ -14038,24 +13350,25 @@ y = NUM2LONG(y_arg); cols = NUM2ULONG(cols_arg); rows = NUM2ULONG(rows_arg); if (x < 0 || y < 0 || x+cols > image->columns || y+rows > image->rows) { - rb_raise(rb_eRangeError, "geometry (%lux%lu%+ld%+ld) exceeds image bounds" - , cols, rows, x, y); + rb_raise(rb_eRangeError, "geometry (%lux%lu%+ld%+ld) exceeds image bounds", + cols, rows, x, y); } size = (long)(cols * rows); + new_pixels = rb_Array(new_pixels); rm_check_ary_len(new_pixels, size); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); okay = SetImageStorageClass(image, DirectClass, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); if (!okay) { - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); rb_raise(Class_ImageMagickError, "SetImageStorageClass failed. Can't store pixels."); } #else okay = SetImageStorageClass(image, DirectClass); rm_check_image_exception(image, RetainOnError); @@ -14068,34 +13381,50 @@ // Get a pointer to the pixels. Replace the values with the PixelPackets // from the pixels argument. { pixels = GetAuthenticPixels(image, x, y, cols, rows, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); if (pixels) { +#if defined(IMAGEMAGICK_6) + IndexPacket *indexes = GetAuthenticIndexQueue(image); +#endif for (n = 0; n < size; n++) { new_pixel = rb_ary_entry(new_pixels, n); + if (CLASS_OF(new_pixel) != Class_Pixel) + { + DestroyExceptionInfo(exception); + rb_raise(rb_eTypeError, "Item in array should be a Pixel."); + } Data_Get_Struct(new_pixel, Pixel, pixel); #if defined(IMAGEMAGICK_7) SetPixelRed(image, pixel->red, pixels); SetPixelGreen(image, pixel->green, pixels); SetPixelBlue(image, pixel->blue, pixels); SetPixelAlpha(image, pixel->alpha, pixels); + SetPixelBlack(image, pixel->black, pixels); pixels += GetPixelChannels(image); #else - *pixels = *pixel; + SetPixelRed(pixels, pixel->red); + SetPixelGreen(pixels, pixel->green); + SetPixelBlue(pixels, pixel->blue); + SetPixelOpacity(pixels, pixel->opacity); + if (indexes) + { + SetPixelIndex(indexes + n, pixel->black); + } pixels++; #endif } SyncAuthenticPixels(image, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); } RB_GC_GUARD(new_pixel); return self; @@ -14103,15 +13432,11 @@ /** * Strips an image of all profiles and comments. * - * Ruby usage: - * - @verbatim Image#strip! @endverbatim - * - * @param self this object - * @return self + * @return [Magick::Image] self */ VALUE Image_strip_bang(VALUE self) { #if defined(IMAGEMAGICK_7) @@ -14120,32 +13445,28 @@ Image *image = rm_check_frozen(self); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) StripImage(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + StripImage(image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) StripImage(image); + StripImage(image); rm_check_image_exception(image, RetainOnError); #endif return self; } /** - * Swirl the pixels about the center of the image, where degrees indicates the - * sweep of the arc through which each pixel is moved. You get a more dramatic - * effect as the degrees move from 1 to 360. + * Swirl the pixels about the center of the image, where degrees indicates the sweep of the arc + * through which each pixel is moved. You get a more dramatic effect as the degrees move from 1 to + * 360. * - * Ruby usage: - * - @verbatim Image#swirl(degrees) @endverbatim - * - * @param self this object - * @param degrees the degrees - * @return a new image + * @param degrees_obj [Float] the degrees + * @return [Magick::Image] a new image */ VALUE Image_swirl(VALUE self, VALUE degrees_obj) { Image *image, *new_image; @@ -14160,43 +13481,35 @@ new_image = SwirlImage(image, degrees, image->interpolate, exception); #else new_image = SwirlImage(image, degrees, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Emulates Magick++'s floodFillTexture. * - * If the FloodfillMethod method is specified, flood-fills texture across pixels - * starting at the target pixel and matching the specified color. + * If the FloodfillMethod method is specified, flood-fills texture across pixels starting at the + * target pixel and matching the specified color. * - * If the FillToBorderMethod method is specified, flood-fills 'texture across - * pixels starting at the target pixel and stopping at pixels matching the - * specified color.' + * If the FillToBorderMethod method is specified, flood-fills 'texture across pixels starting at the + * target pixel and stopping at pixels matching the specified color.' * - * Ruby usage: - * - @verbatim Image#texture_flood_fill(color, texture, x, y, method) @endverbatim - * - * @param self this object - * @param color_obj the color - * @param texture_obj the texture to fill - * @param x_obj the x position - * @param y_obj the y position - * @param method_obj the method to call (FloodfillMethod or FillToBorderMethod) - * @return a new image + * @param color_obj [Magick::Pixel, String] the color + * @param texture_obj [Magick::Image, Magick::ImageList] the texture to fill + * @param x_obj [Numeric] the x position + * @param y_obj [Numeric] the y position + * @param method_obj [Magick::PaintMethod] the method to call (FloodfillMethod or FillToBorderMethod) + * @return [Magick::Image] a new image */ VALUE -Image_texture_flood_fill(VALUE self, VALUE color_obj, VALUE texture_obj - , VALUE x_obj, VALUE y_obj, VALUE method_obj) +Image_texture_flood_fill(VALUE self, VALUE color_obj, VALUE texture_obj, + VALUE x_obj, VALUE y_obj, VALUE method_obj) { Image *image, *new_image; Image *texture_image; PixelColor color; VALUE texture; @@ -14218,12 +13531,12 @@ x = NUM2LONG(x_obj); y = NUM2LONG(y_obj); if ((unsigned long)x > image->columns || (unsigned long)y > image->rows) { - rb_raise(rb_eArgError, "target out of range. %ldx%ld given, image is %lux%lu" - , x, y, image->columns, image->rows); + rb_raise(rb_eArgError, "target out of range. %ldx%ld given, image is %"RMIuSIZE"x%"RMIuSIZE"", + x, y, image->columns, image->rows); } VALUE_TO_ENUM(method_obj, method, PaintMethod); if (method != FillToBorderMethod && method != FloodfillMethod) { @@ -14257,37 +13570,33 @@ color_mpp.blue = (MagickRealType) color.blue; } #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) FloodfillPaintImage(new_image, draw_info, &color_mpp, x, y, invert, exception); - (void) DestroyDrawInfo(draw_info); + FloodfillPaintImage(new_image, draw_info, &color_mpp, x, y, invert, exception); + DestroyDrawInfo(draw_info); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &color_mpp, x, y, invert); + FloodfillPaintImage(new_image, DefaultChannels, draw_info, &color_mpp, x, y, invert); - (void) DestroyDrawInfo(draw_info); + DestroyDrawInfo(draw_info); rm_check_image_exception(new_image, DestroyOnError); #endif RB_GC_GUARD(texture); return rm_image_new(new_image); } /** - * Change the value of individual pixels based on the intensity of each pixel - * compared to threshold. The result is a high-contrast, two color image. + * Change the value of individual pixels based on the intensity of each pixel compared to + * threshold. The result is a high-contrast, two color image. * - * Ruby usage: - * - @verbatim Image#threshold(threshold) @endverbatim - * - * @param self this object - * @param threshold the threshold - * @return a new image + * @param threshold_obj [Float] the threshold + * @return [Magick::Image] a new image */ VALUE Image_threshold(VALUE self, VALUE threshold_obj) { Image *image, *new_image; @@ -14299,15 +13608,15 @@ image = rm_check_destroyed(self); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) BilevelImage(new_image, threshold, exception); + BilevelImage(new_image, threshold, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) BilevelImageChannel(new_image, DefaultChannels, threshold); + BilevelImageChannel(new_image, DefaultChannels, threshold); rm_check_image_exception(new_image, DestroyOnError); #endif return rm_image_new(new_image); } @@ -14341,26 +13650,26 @@ case 4: red = NUM2DBL(argv[0]); green = NUM2DBL(argv[1]); blue = NUM2DBL(argv[2]); alpha = get_named_alpha_value(argv[3]); - sprintf(ctarg, "%f,%f,%f,%f", red, green, blue, QuantumRange - alpha); + snprintf(ctarg, sizeof(ctarg), "%f,%f,%f,%f", red, green, blue, QuantumRange - alpha); break; case 3: red = NUM2DBL(argv[0]); green = NUM2DBL(argv[1]); blue = NUM2DBL(argv[2]); - sprintf(ctarg, "%f,%f,%f", red, green, blue); + snprintf(ctarg, sizeof(ctarg), "%f,%f,%f", red, green, blue); break; case 2: red = NUM2DBL(argv[0]); green = NUM2DBL(argv[1]); - sprintf(ctarg, "%f,%f", red, green); + snprintf(ctarg, sizeof(ctarg), "%f,%f", red, green); break; case 1: red = NUM2DBL(argv[0]); - sprintf(ctarg, "%f", red); + snprintf(ctarg, sizeof(ctarg), "%f", red); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 4)", argc); } @@ -14368,11 +13677,11 @@ #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); (thresholder)(new_image, ctarg, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else (thresholder)(new_image, ctarg); rm_check_image_exception(new_image, DestroyOnError); #endif @@ -14436,104 +13745,98 @@ default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc); break; } - snprintf(image_geometry, sizeof(image_geometry), "%ldx%ld", columns, rows); + snprintf(image_geometry, sizeof(image_geometry), "%lux%lu", columns, rows); exception = AcquireExceptionInfo(); - (void) ParseRegionGeometry(image, image_geometry, &geometry, exception); + ParseRegionGeometry(image, image_geometry, &geometry, exception); rm_check_exception(exception, image, RetainOnError); new_image = ThumbnailImage(image, geometry.width, geometry.height, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Fast resize for thumbnail images. + * The thumbnail method is a fast resizing method suitable for use when the size of the resulting + * image is < 10% of the original. * - * Ruby usage: - * - @verbatim Image#thumbnail(scale) @endverbatim - * - @verbatim Image#thumbnail(cols, rows) @endverbatim + * @overload thumbnail(scale) + * @param scale [Float] The desired size represented as a floating-point number. For example, to + * make a thumbnail that is 9.5% of the size of the original image, use 0.095. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see thumbnail - * @see Image_thumbnail_bang + * @overload thumbnail(cols, rows) + * @param cols [Numeric] The desired width in pixels. + * + * @return [Magick::Image] a new image + * @see Image#thumbnail! */ VALUE Image_thumbnail(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return thumbnail(False, argc, argv, self); } /** - * Fast resize for thumbnail images. + * The thumbnail method is a fast resizing method suitable for use when the size of the resulting + * image is < 10% of the original. In-place form of {Image#thumbnail}. * - * Ruby usage: - * - @verbatim Image#thumbnail!(scale) @endverbatim - * - @verbatim Image#thumbnail!(cols, rows) @endverbatim + * @overload thumbnail!(scale) + * @param scale [Float] The desired size represented as a floating-point number. For example, to + * make a thumbnail that is 9.5% of the size of the original image, use 0.095. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see thumbnail - * @see Image_thumbnail + * @overload thumbnail!(cols, rows) + * @param cols [Numeric] The desired width in pixels. + * + * @return [Magick::Image] a new image + * @see Image#thumbnail */ VALUE Image_thumbnail_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return thumbnail(True, argc, argv, self); } /** - * The ticks_per_second attribute reader. + * Get the number of ticks per second. + * This attribute is used in conjunction with the delay attribute to establish the amount of time + * that must elapse between frames in an animation.The default is 100. * - * Ruby usage: - * - @verbatim Image#ticks_per_second @endverbatim - * - * @param self this object - * @return ticks per second + * @return [Numeric] ticks per second */ VALUE Image_ticks_per_second(VALUE self) { Image *image = rm_check_destroyed(self); return INT2FIX(image->ticks_per_second); } /** - * The ticks_per_second attribute writer. + * Set the number of ticks per second. + * This attribute is used in conjunction with the delay attribute to establish the amount of time + * that must elapse between frames in an animation.The default is 100. * - * Ruby usage: - * - @verbatim Image#ticks_per_second= @endverbatim - * - * @param self this object - * @param tps ticks per second - * @return tps + * @param tps [Numeric] ticks per second + * @return [Numeric] the given value */ VALUE Image_ticks_per_second_eq(VALUE self, VALUE tps) { Image *image = rm_check_frozen(self); @@ -14541,28 +13844,21 @@ return tps; } /** - * Call TintImage. + * Applies a color vector to each pixel in the image. * - * Ruby usage: - * - @verbatim Image#tint(tint, red_alpha) @endverbatim - * - @verbatim Image#tint(tint, red_alpha, green_alpha) @endverbatim - * - @verbatim Image#tint(tint, red_alpha, green_alpha, blue_alpha) @endverbatim - * - @verbatim Image#tint(tint, red_alpha, green_alpha, blue_alpha, alpha_alpha) @endverbatim + * - Alpha values are percentages: 0.10 -> 10%. * - * Notes: - * - Default green_alpha is red_alpha - * - Default blue_alpha is red_alpha - * - Default alpha_alpha is 1.0 - * - Alpha values are percentages: 0.10 -> 10%. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload tint(tint, red_alpha, green_alpha = red_alpha, blue_alpha = red_alpha, alpha_alpha = 1.0) + * @param tint [Magick::Pixel, String] the color name + * @param red_alpha [Float] the red value + * @param green_alpha [Float] the green value + * @param blue_alpha [Float] the blue value + * @param alpha_alpha [Float] the alpha value + * @return a new image */ VALUE Image_tint(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -14606,43 +13902,36 @@ { rb_raise(rb_eArgError, "alpha percentages must be non-negative."); } snprintf(alpha, sizeof(alpha), - "%g,%g,%g,%g", red_pct_opaque*100.0, green_pct_opaque*100.0 - , blue_pct_opaque*100.0, alpha_pct_opaque*100.0); + "%g,%g,%g,%g", red_pct_opaque*100.0, green_pct_opaque*100.0, + blue_pct_opaque*100.0, alpha_pct_opaque*100.0); Color_to_PixelColor(&tint, argv[0]); exception = AcquireExceptionInfo(); #if defined(IMAGEMAGICK_7) new_image = TintImage(image, alpha, &tint, exception); #else new_image = TintImage(image, alpha, tint, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Return a "blob" (a String) from the image. * - * Ruby usage: - * - @verbatim Image#to_blob @endverbatim + * - The magick member of the Image structure determines the format of the + * returned blob (GIG, JPEG, PNG, etc.) * - * Notes: - * - The magick member of the Image structure determines the format of the - * returned blob (GIG, JPEG, PNG, etc.) - * - * @param self this object - * @return the blob + * @return [String] the blob + * @see Image#from_blob */ VALUE Image_to_blob(VALUE self) { Image *image; @@ -14666,51 +13955,51 @@ // Copy the depth and magick fields to the Image if (info->depth != 0) { #if defined(IMAGEMAGICK_7) - (void) SetImageDepth(image, info->depth, exception); - CHECK_EXCEPTION() + SetImageDepth(image, info->depth, exception); + CHECK_EXCEPTION(); #else - (void) SetImageDepth(image, info->depth); + SetImageDepth(image, info->depth); rm_check_image_exception(image, RetainOnError); #endif } if (*info->magick) { - (void) SetImageInfo(info, MagickTrue, exception); - CHECK_EXCEPTION() + SetImageInfo(info, MagickTrue, exception); + CHECK_EXCEPTION(); if (*info->magick == '\0') { return Qnil; } - strncpy(image->magick, info->magick, sizeof(info->magick)-1); + strlcpy(image->magick, info->magick, sizeof(image->magick)); } // Fix #2844 - libjpeg exits when image is 0x0 magick_info = GetMagickInfo(image->magick, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); if (magick_info) { if ( (!rm_strcasecmp(magick_info->name, "JPEG") || !rm_strcasecmp(magick_info->name, "JPG")) && (image->rows == 0 || image->columns == 0)) { - rb_raise(rb_eRuntimeError, "Can't convert %lux%lu %.4s image to a blob" - , image->columns, image->rows, magick_info->name); + rb_raise(rb_eRuntimeError, "Can't convert %"RMIuSIZE"x%"RMIuSIZE" %.4s image to a blob", + image->columns, image->rows, magick_info->name); } } rm_sync_image_options(image, info); blob = ImageToBlob(info, image, &length, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); if (length == 0 || !blob) { return Qnil; } @@ -14725,22 +14014,14 @@ return blob_str; } /** - * Return a color name for the color intensity specified by the Magick::Pixel - * argument. + * Return a color name for the color intensity specified by the Magick::Pixel argument. * - * Ruby usage: - * - @verbatim Image#to_color(pixel) @endverbatim - * - * Notes: - * - Respects depth and matte attributes - * - * @param self this object - * @param pixel_arg the pixel - * @return the color name + * @param pixel_arg [Magick::Pixel, String] the pixel + * @return [String] the color name */ VALUE Image_to_color(VALUE self, VALUE pixel_arg) { Image *image; @@ -14759,52 +14040,37 @@ // QueryColorname returns False if the color represented by the PixelPacket // doesn't have a "real" name, just a sequence of hex digits. We don't care // about that. - (void) QueryColorname(image, &pixel, AllCompliance, name, exception); - CHECK_EXCEPTION() + QueryColorname(image, &pixel, AllCompliance, name, exception); + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rb_str_new2(name); } /** - * Alias for Image#number_colors. + * Alias for {Image#number_colors}. * - * Ruby usage: - * - @verbatim Image#total_colors @endverbatim - * - * Notes: - * - This used to be a direct reference to the `total_colors' field in Image - * but that field is not reliable. - * - * @param self this object - * @return number of unique colors - * @see Image_number_colors + * @return [Numeric] number of unique colors + * @see Image#number_colors */ VALUE Image_total_colors(VALUE self) { return Image_number_colors(self); } /** - * Return value from GetImageTotalInkDensity. + * Return the total ink density for a CMYK image. * - * Ruby usage: - * - @verbatim Image#total_ink_density @endverbatim - * - * Notes: - * - Raises an exception if the image is not CMYK - * - * @param self this object - * @return the total ink density + * @return [Float] the total ink density */ VALUE Image_total_ink_density(VALUE self) { Image *image; @@ -14816,40 +14082,35 @@ image = rm_check_destroyed(self); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); density = GetImageTotalInkDensity(image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else density = GetImageTotalInkDensity(image); rm_check_image_exception(image, RetainOnError); #endif return rb_float_new(density); } /** - * Call TransparentPaintImage. + * Changes the opacity value of all the pixels that match color to the value specified by + * opacity. By default the pixel must match exactly, but you can specify a tolerance level by + * setting the fuzz attribute on the image. * - * Ruby usage: - * - @verbatim Image#transparent(color-name) @endverbatim - * - @verbatim Image#transparent(color-name, alpha: alpha) @endverbatim - * - @verbatim Image#transparent(pixel) @endverbatim - * - @verbatim Image#transparent(pixel, alpha: alpha) @endverbatim + * - Default alpha is Magick::TransparentAlpha. + * - Can use Magick::OpaqueAlpha or Magick::TransparentAlpha, or any + * value >= 0 && <= QuantumRange. + * - Use Image#fuzz= to define the tolerance level. * - * Notes: - * - Default alpha is Magick::TransparentAlpha. - * - Can use Magick::OpaqueAlpha or Magick::TransparentAlpha, or any - * value >= 0 && <= QuantumRange. - * - Use Image#fuzz= to define the tolerance level. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload transparent(color, alpha: Magick::TransparentAlpha) + * @param color [Magick::Pixel, String] The color + * @param alpha alpha [Numeric] the alpha + * @return [Magick::Image] a new image */ VALUE Image_transparent(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -14879,11 +14140,11 @@ #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); okay = TransparentPaintImage(new_image, &color, alpha, MagickFalse, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else okay = TransparentPaintImage(new_image, &color, QuantumRange - alpha, MagickFalse); rm_check_image_exception(new_image, DestroyOnError); #endif if (!okay) @@ -14896,26 +14157,24 @@ return rm_image_new(new_image); } /** - * Call TransparentPaintImageChroma. + * Changes the opacity value associated with any pixel between low and high to the value defined by + * opacity. * - * Ruby usage: - * - @verbatim Image#transparent_chroma(low, high) @endverbatim - * - @verbatim Image#transparent_chroma(low, high, alpha: alpha) @endverbatim - * - @verbatim Image#transparent_chroma(low, high, invert, alpha: alpha) @endverbatim + * As there is one fuzz value for the all the channels, the transparent method is not suitable for + * the operations like chroma, where the tolerance for similarity of two color components (RGB) can + * be different, Thus we define this method take two target pixels (one low and one high) and all + * the pixels of an image which are lying between these two pixels are made transparent. * - * Notes: - * - Default alpha is TransparentAlpha - * - Default invert is false - * - Available in ImageMagick >= 6.4.5-6 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload transparent_chroma(low, high, invert, alpha: Magick::TransparentAlpha) + * @param low [Magick::Pixel, String] The low ends of the pixel range + * @param high [Magick::Pixel, String] The high ends of the pixel range + * @param invert [Boolean] If true, all pixels outside the range are set to opacity. + * @param alpha [Numeric] The desired alpha. + * @return [Magick::Image] a new image */ VALUE Image_transparent_chroma(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -14955,11 +14214,11 @@ #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); okay = TransparentPaintImageChroma(new_image, &low, &high, alpha, invert, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else okay = TransparentPaintImageChroma(new_image, &low, &high, QuantumRange - alpha, invert); rm_check_image_exception(new_image, DestroyOnError); #endif if (!okay) @@ -14974,15 +14233,11 @@ /** * Return the name of the transparent color as a String. * - * Ruby usage: - * - @verbatim Image#transparent_color @endverbatim - * - * @param self this object - * @return the name of the transparent color + * @return [String] the name of the transparent color */ VALUE Image_transparent_color(VALUE self) { Image *image = rm_check_destroyed(self); @@ -14991,16 +14246,12 @@ /** * Set the the transparent color to the specified color spec. * - * Ruby usage: - * - @verbatim Image#transparent_color= @endverbatim - * - * @param self this object - * @param color the transparent color - * @return color + * @param color [Magick::Pixel, String] the transparent color + * @return [Magick::Pixel, String] the given color */ VALUE Image_transparent_color_eq(VALUE self, VALUE color) { Image *image = rm_check_frozen(self); @@ -15008,80 +14259,66 @@ return color; } /** - * Call TransposeImage. + * Creates a horizontal mirror image by reflecting the pixels around the central y-axis while + * rotating them by 90 degrees. * - * Ruby usage: - * - @verbatim Image#transpose @endverbatim - * - * @param self this object - * @return a new image - * @see crisscross - * @see Image_transpose_bang + * @return [Magick::Image] a new image + * @see Image#transpose! */ VALUE Image_transpose(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return crisscross(False, self, TransposeImage); } /** - * Call TransposeImage. + * Creates a horizontal mirror image by reflecting the pixels around the central y-axis while + * rotating them by 90 degrees. + * In-place form of {Image#transpose}. * - * Ruby usage: - * - @verbatim Image#transpose! @endverbatim - * - * @param self this object - * @return self - * @see crisscross - * @see Image_transpose + * @return [Magick::Image] a new image + * @see Image#transpose */ VALUE Image_transpose_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return crisscross(True, self, TransposeImage); } /** - * Call TransverseImage. + * Creates a vertical mirror image by reflecting the pixels around the central x-axis while rotating + * them by 270 degrees * - * Ruby usage: - * - @verbatim Image#transverse @endverbatim - * - * @param self this object - * @return a new image - * @see crisscross - * @see Image_transverse_bang + * @return [Magick::Image] a new image + * @see Image#transverse! */ VALUE Image_transverse(VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return crisscross(False, self, TransverseImage); } /** - * Call TransverseImage. + * Creates a vertical mirror image by reflecting the pixels around the central x-axis while rotating + * them by 270 degrees + * In-place form of {Image#transverse}. * - * Ruby usage: - * - @verbatim Image#transverse! @endverbatim - * - * @param self this object - * @return self - * @see crisscross - * @see Image_transverse_bang + * @return [Magick::Image] a new image + * @see Image#transverse */ VALUE Image_transverse_bang(VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return crisscross(True, self, TransverseImage); } /** @@ -15121,125 +14358,102 @@ Data_Get_Struct(self, Image, image); exception = AcquireExceptionInfo(); new_image = TrimImage(image, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - rm_ensure_result(new_image); if (reset_page) { ResetImagePage(new_image, "0x0+0+0"); } if (bang) { UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); } /** - * Convenient front-end to CropImage. + * Removes the edges that are exactly the same color as the corner pixels. Use the fuzz attribute to + * make trim remove edges that are nearly the same color as the corner pixels. * - * Ruby usage: - * - @verbatim Image#trim @endverbatim - * - @verbatim Image#trim(reset_page) @endverbatim - * - * Notes: - * - Default reset_page is false - * - Respects fuzz attribute. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see trimmer - * @see Image_trim_bang + * @overload trim(reset = false) + * @param reset [Boolean] The trim method retains the offset information in the cropped + * image. This may cause the image to appear to be surrounded by blank or black space when viewed + * with an external viewer. This only occurs when the image is saved in a format (such as GIF) + * that saves offset information. To reset the offset data, use true as the argument to trim. + * @return [Magick::Image] a new image + * @see Image#trim! */ VALUE Image_trim(int argc, VALUE *argv, VALUE self) { - (void) rm_check_destroyed(self); + rm_check_destroyed(self); return trimmer(False, argc, argv, self); } /** - * Convenient front-end to CropImage. + * Removes the edges that are exactly the same color as the corner pixels. Use the fuzz attribute to + * make trim remove edges that are nearly the same color as the corner pixels. * - * Ruby usage: - * - @verbatim Image#trim! @endverbatim - * - @verbatim Image#trim!(reset_page) @endverbatim - * - * Notes: - * - Default reset_page is false - * - Respects fuzz attribute. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return self - * @see trimmer - * @see Image_trim + * @overload trim!(reset = false) + * @param reset [Boolean] The trim method retains the offset information in the cropped + * image. This may cause the image to appear to be surrounded by blank or black space when viewed + * with an external viewer. This only occurs when the image is saved in a format (such as GIF) + * that saves offset information. To reset the offset data, use true as the argument to trim. + * @return [Magick::Image] a new image + * @see Image#trim */ VALUE Image_trim_bang(int argc, VALUE *argv, VALUE self) { - (void) rm_check_frozen(self); + rm_check_frozen(self); return trimmer(True, argc, argv, self); } /** - * Get the image gravity attribute. + * Get the direction that the image gravitates within the composite. * - * Ruby usage: - * - @verbatim Image#gravity @endverbatim - * - * @param self this object - * @return the image gravity + * @return [Magick::GravityType] the image gravity */ VALUE Image_gravity(VALUE self) { Image *image = rm_check_destroyed(self); return GravityType_find(image->gravity); } /** - * Set the image gravity attribute. + * Set the direction that the image gravitates within the composite. * - * Ruby usage: - * - @verbatim Image#gravity= @endverbatim - * - * @param self this object - * @param gravity the image gravity - * @return the image gravity + * @param gravity [Magick::GravityType] the image gravity + * @return [Magick::GravityType] the given value */ VALUE Image_gravity_eq(VALUE self, VALUE gravity) { Image *image = rm_check_frozen(self); VALUE_TO_ENUM(gravity, image->gravity, GravityType); return gravity; } /** - * Call GetImageType to get the image type. + * Get the image type classification. + * For example, GrayscaleType. + * Don't confuse this attribute with the format, that is "GIF" or "JPG". * - * Ruby usage: - * - @verbatim Image#image_type @endverbatim - * - * @param self this object - * @return the image type + * @return [Magick::ImageType] the image type */ VALUE Image_image_type(VALUE self) { Image *image; ImageType type; @@ -15251,28 +14465,24 @@ #if defined(IMAGEMAGICK_7) type = GetImageType(image); #else exception = AcquireExceptionInfo(); type = GetImageType(image, exception); - CHECK_EXCEPTION() + CHECK_EXCEPTION(); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #endif return ImageType_find(type); } /** - * Call SetImageType to set the image type. + * Set the image type classification. * - * Ruby usage: - * - @verbatim Image#image_type= @endverbatim - * - * @param self this object - * @param image_type the image type - * @return the image type + * @param image_type [Magick::ImageType] the image type + * @return [Magick::ImageType] the given type */ VALUE Image_image_type_eq(VALUE self, VALUE image_type) { Image *image; ImageType type; @@ -15283,55 +14493,44 @@ image = rm_check_frozen(self); VALUE_TO_ENUM(image_type, type, ImageType); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); SetImageType(image, type, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else SetImageType(image, type); #endif return image_type; } /** - * Call RemoveImageArtifact. + * Removes an artifact from the image and returns its value. * - * Ruby usage: - * - @verbatim Image#undefine(artifact) @endverbatim - * - * Notes: - * - Normally a script should never call this method. - * - * @param self this object - * @param artifact the artifact - * @return self - * @see Image_define + * @param artifact [String] the artifact + * @return [Magick::Image] self + * @see Image#define */ VALUE Image_undefine(VALUE self, VALUE artifact) { Image *image; char *key; - long key_l; image = rm_check_frozen(self); - key = rm_str2cstr(artifact, &key_l); - (void) DeleteImageArtifact(image, key); + key = StringValueCStr(artifact); + DeleteImageArtifact(image, key); return self; } /** - * Call UniqueImageColors. + * Constructs a new image with one pixel for each unique color in the image. The new image has 1 + * row. The row has 1 column for each unique pixel in the image. * - * Ruby usage: - * - @verbatim Image#unique_colors @endverbatim - * - * @param self this object - * @return a new image + * @return [Magick::Image] a new image */ VALUE Image_unique_colors(VALUE self) { Image *image, *new_image; @@ -15340,44 +14539,34 @@ image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = UniqueImageColors(image, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Get the resolution type field. + * Get the units of image resolution. * - * Ruby usage: - * - @verbatim Image#units @endverbatim - * - * @param self this object - * @return the resolution type + * @return [Magick::ResolutionType] the resolution type */ VALUE Image_units(VALUE self) { Image *image = rm_check_destroyed(self); return ResolutionType_find(image->units); } /** - * Set the resolution type field. + * Set the units of image resolution. * - * Ruby usage: - * - @verbatim Image#units= @endverbatim - * - * @param self this object - * @param restype the resolution type - * @return restype + * @param restype [Magick::ResolutionType] the resolution type + * @return [Magick::ResolutionType] the given value */ VALUE Image_units_eq(VALUE self, VALUE restype) { ResolutionType units; @@ -15433,13 +14622,13 @@ return restype; } /** - * Sharpen an image. "amount" is the percentage of the difference between the - * original and the blur image that is added back into the original. "threshold" - * is the threshold in pixels needed to apply the diffence amount. + * Sharpen an image. "amount" is the percentage of the difference between the original and the blur + * image that is added back into the original. "threshold" is the threshold in pixels needed to + * apply the diffence amount. * * No Ruby usage (internal function) * * @param argc number of input arguments * @param argv array of input arguments @@ -15448,12 +14637,12 @@ * @param amount the amount * @param threshold the threshold * @see Image_unsharp_mask */ static void -unsharp_mask_args(int argc, VALUE *argv, double *radius, double *sigma - , double *amount, double *threshold) +unsharp_mask_args(int argc, VALUE *argv, double *radius, double *sigma, + double *amount, double *threshold) { switch (argc) { case 4: *threshold = NUM2DBL(argv[3]); @@ -15489,32 +14678,22 @@ } } /** - * Sharpen an image. "amount" is the percentage of the difference between the - * original and the blur image that is added back into the original. "threshold" - * is the threshold in pixels needed to apply the diffence amount. + * Sharpen an image. "amount" is the percentage of the difference between the original and the blur + * image that is added back into the original. "threshold" is the threshold in pixels needed to + * apply the diffence amount. * - * Ruby usage: - * - @verbatim Image#unsharp_mask @endverbatim - * - @verbatim Image#unsharp_mask(radius) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma, amount) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma, amount, threshold) @endverbatim - * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default amount is 1.0 - * - Default threshold is 0.05 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see unsharp_mask_args + * @overload unsharp_mask(radius = 0.0, sigma = 1.0, amount = 1.0, threshold = 0.05) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The standard deviation of the Gaussian operator. + * @param amount [Float] The percentage of the blurred image to be added to the receiver, + * specified as a fraction between 0 and 1.0 + * @param threshold [Float] The threshold needed to apply the amount, specified as a fraction + * between 0 and 1.0 + * @return [Magick::Image] a new image */ VALUE Image_unsharp_mask(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -15526,43 +14705,42 @@ unsharp_mask_args(argc, argv, &radius, &sigma, &amount, &threshold); exception = AcquireExceptionInfo(); new_image = UnsharpMaskImage(image, radius, sigma, amount, threshold, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Call UnsharpMaskImageChannel. + * Sharpen an image. "amount" is the percentage of the difference between the original and the blur + * image that is added back into the original. "threshold" is the threshold in pixels needed to + * apply the diffence amount. * - * Ruby usage: - * - @verbatim Image#unsharp_mask @endverbatim - * - @verbatim Image#unsharp_mask(radius) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma, amount) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma, amount, threshold) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma, amount, threshold, channel) @endverbatim - * - @verbatim Image#unsharp_mask(radius, sigma, amount, threshold, channel, ...) @endverbatim + * Only the specified channels are sharpened. * - * Notes: - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - Default amount is 1.0 - * - Default threshold is 0.05 - * - Default channel is AllChannels + * @overload unsharp_mask(radius = 0.0, sigma = 1.0, amount = 1.0, threshold = 0.05, channel = Magick::AllChannels) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The standard deviation of the Gaussian operator. + * @param amount [Float] The percentage of the blurred image to be added to the receiver, + * specified as a fraction between 0 and 1.0 + * @param threshold [Float] The threshold needed to apply the amount, specified as a fraction + * between 0 and 1.0 + * @param channel [Magick::ChannelType] a ChannelType arguments. * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see unsharp_mask_args + * @overload unsharp_mask(radius = 0.0, sigma = 1.0, amount = 1.0, threshold = 0.05, *channels) + * @param radius [Float] The radius of the Gaussian operator. + * @param sigma [Float] The standard deviation of the Gaussian operator. + * @param amount [Float] The percentage of the blurred image to be added to the receiver, + * specified as a fraction between 0 and 1.0 + * @param threshold [Float] The threshold needed to apply the amount, specified as a fraction + * between 0 and 1.0 + * @param *channels [Magick::ChannelType] one or more ChannelType arguments. + * + * @return [Magick::Image] a new image */ VALUE Image_unsharp_mask_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -15587,40 +14765,25 @@ END_CHANNEL_MASK(image); #else new_image = UnsharpMaskImageChannel(image, channels, radius, sigma, amount, threshold, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** * Soften the edges of an image. * - * Ruby usage: - * - @verbatim Image#vignette @endverbatim - * - @verbatim Image#vignette(horz_radius) @endverbatim - * - @verbatim Image#vignette(horz_radius, vert_radius) @endverbatim - * - @verbatim Image#vignette(horz_radius, vert_radius, radius) @endverbatim - * - @verbatim Image#vignette(horz_radius, vert_radius, radius, sigma) @endverbatim - * - * Notes: - * - Default horz_radius is image-columns*0.1+0.5 - * - Default vert_radius is image-rows*0.1+0.5 - * - Default radius is 0.0 - * - Default sigma is 1.0 - * - The outer edges of the image are replaced by the background color. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload vignette(horz_radius = self.columns*0.1+0.5, vert_radius = self.rows*0.1+0.5, radius = 0.0, sigma = 1.0) + * @param horz_radius [Float] Influences the amount of background color in the horizontal dimension. + * @param vert_radius [Float] Influences the amount of background color in the vertical dimension. + * @param radius [Float] Controls the amount of blurring. + * @param sigma [Float] Controls the amount of blurring. + * @return [Magick::Image] a new image */ VALUE Image_vignette(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -15652,27 +14815,21 @@ exception = AcquireExceptionInfo(); new_image = VignetteImage(image, radius, sigma, horz_radius, vert_radius, exception); rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Get the VirtualPixelMethod for the image. + * Get the "virtual pixels" behave. + * Virtual pixels are pixels that are outside the boundaries of the image. * - * Ruby usage: - * - @verbatim Image#virtual_pixel_method @endverbatim - * - * @param self this object - * @return the VirtualPixelMethod + * @return [Magick::VirtualPixelMethod] the VirtualPixelMethod */ VALUE Image_virtual_pixel_method(VALUE self) { Image *image; @@ -15683,18 +14840,15 @@ return VirtualPixelMethod_find(vpm); } /** - * Set the virtual pixel method for the image. + * Specify how "virtual pixels" behave. + * Virtual pixels are pixels that are outside the boundaries of the image. * - * Ruby usage: - * - @verbatim Image#virtual_pixel_method= @endverbatim - * - * @param self this object - * @param method the VirtualPixelMethod - * @return method + * @param method [Magick::VirtualPixelMethod] the VirtualPixelMethod + * @return [Magick::VirtualPixelMethod] the given method */ VALUE Image_virtual_pixel_method_eq(VALUE self, VALUE method) { Image *image; @@ -15705,42 +14859,60 @@ image = rm_check_frozen(self); VALUE_TO_ENUM(method, vpm, VirtualPixelMethod); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) SetImageVirtualPixelMethod(image, vpm, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + SetImageVirtualPixelMethod(image, vpm, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) SetImageVirtualPixelMethod(image, vpm); + SetImageVirtualPixelMethod(image, vpm); rm_check_image_exception(image, RetainOnError); #endif return method; } /** - * Add a watermark to an image. + * Composites a watermark image on the target image using the Modulate composite operator. This + * composite operation operates in the HSL colorspace and combines part of the lightness, part of + * the saturation, and all of the hue of each pixel in the watermark with the corresponding pixel in + * the target image * - * Ruby usage: - * - @verbatim Image#watermark(mark) @endverbatim - * - @verbatim Image#watermark(mark, brightness) @endverbatim - * - @verbatim Image#watermark(mark, brightness, saturation) @endverbatim - * - @verbatim Image#watermark(mark, brightness, saturation, gravity) @endverbatim - * - @verbatim Image#watermark(mark, brightness, saturation, gravity, x_off) @endverbatim - * - @verbatim Image#watermark(mark, brightness, saturation, gravity, x_off, y_off) @endverbatim - * - @verbatim Image#watermark(mark, brightness, saturation, x_off) @endverbatim - * - @verbatim Image#watermark(mark, brightness, saturation, x_off, y_off) @endverbatim + * @overload watermark(mark, brightness = 1.0, saturation = 1.0, x_off = 0, y_off = 0) + * @param mark [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param brightness [Float] The fraction of the lightness component of the watermark pixels to be + * composited onto the target image. Must be a non-negative number or a string in the form + * "NN%". If lightness is a number it is interpreted as a percentage. Both 0.25 and "25%" mean + * 25%. The default is 100%. + * @param saturation [Float] The fraction of the saturation component of the watermark pixels to + * be composited onto the target image. Must be a non-negative number or a string in the form + * "NN%". If lightness is a number it is interpreted as a percentage. Both 0.25 and "25%" mean + * 25%. The default is 100%. + * @param x_off [Numeric] The offset of the watermark, measured from the left-hand side of the + * target image. + * @param y_off [Numeri] The offset of the watermark, measured from the top of the target image. * - * Notes: - * - Default brightness is 100% - * - Default saturation is 100% - * - Default x_off is 0 - * - Default y_off is 0 - * - x_off and y_off can be negative, which means measure from the - * right/bottom of the target image. + * @overload watermark(mark, brightness, saturation, gravity, x_off = 0, y_off = 0) + * @param mark [Magick::Image, Magick::ImageList] Either an imagelist or an image. If an + * imagelist, uses the current image. + * @param brightness [Float] The fraction of the lightness component of the watermark pixels to be + * composited onto the target image. Must be a non-negative number or a string in the form + * "NN%". If lightness is a number it is interpreted as a percentage. Both 0.25 and "25%" mean + * 25%. The default is 100%. + * @param saturation [Float] The fraction of the saturation component of the watermark pixels to + * be composited onto the target image. Must be a non-negative number or a string in the form + * "NN%". If lightness is a number it is interpreted as a percentage. Both 0.25 and "25%" mean + * 25%. The default is 100%. + * @param gravity [Magick::GravityType] the gravity for offset. the offsets are measured from the + * NorthWest corner by default. + * @param x_off [Numeric] The offset of the watermark, measured from the left-hand side of the + * target image. + * @param y_off [Numeri] The offset of the watermark, measured from the top of the target image. * + * @return [Magick::Image] a new image */ VALUE Image_watermark(int argc, VALUE *argv, VALUE self) { Image *image, *overlay, *new_image; @@ -15770,32 +14942,32 @@ } switch (argc) { case 3: - dst_percent = rm_percentage(argv[2],1.0) * 100.0; + dst_percent = rm_percentage(argv[2], 1.0) * 100.0; case 2: - src_percent = rm_percentage(argv[1],1.0) * 100.0; + src_percent = rm_percentage(argv[1], 1.0) * 100.0; case 1: break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc); break; } blend_geometry(geometry, sizeof(geometry), src_percent, dst_percent); - (void) CloneString(&overlay->geometry, geometry); - (void) SetImageArtifact(overlay,"compose:args", geometry); + CloneString(&overlay->geometry, geometry); + SetImageArtifact(overlay, "compose:args", geometry); new_image = rm_clone_image(image); #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) CompositeImage(new_image, overlay, ModulateCompositeOp, MagickTrue, x_offset, y_offset, exception); + CompositeImage(new_image, overlay, ModulateCompositeOp, MagickTrue, x_offset, y_offset, exception); rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #else - (void) CompositeImage(new_image, ModulateCompositeOp, overlay, x_offset, y_offset); + CompositeImage(new_image, ModulateCompositeOp, overlay, x_offset, y_offset); rm_check_image_exception(new_image, DestroyOnError); #endif RB_GC_GUARD(ovly); @@ -15803,27 +14975,17 @@ return rm_image_new(new_image); } /** - * Create a "ripple" effect in the image by shifting the pixels vertically along - * a sine wave whose amplitude and wavelength is specified by the given - * parameters. + * Create a "ripple" effect in the image by shifting the pixels vertically along a sine wave whose + * amplitude and wavelength is specified by the given parameters. * - * Ruby usage: - * - @verbatim Image#wave @endverbatim - * - @verbatim Image#wave(amplitude) @endverbatim - * - @verbatim Image#wave(amplitude, wavelength) @endverbatim - * - * Notes: - * - Default amplitude is 25.0 - * - Default wavelength is 150.0 - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image + * @overload wave(amplitude = 25.0, wavelength = 150.0) + * @param amplitude [Float] the amplitude + * @param wavelength [Float] the wave length + * @return [Magick::Image] a new image */ VALUE Image_wave(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; @@ -15849,45 +15011,34 @@ new_image = WaveImage(image, amplitude, wavelength, image->interpolate, exception); #else new_image = WaveImage(image, amplitude, wavelength, exception); #endif rm_check_exception(exception, new_image, DestroyOnError); + DestroyExceptionInfo(exception); - (void) DestroyExceptionInfo(exception); - - rm_ensure_result(new_image); - return rm_image_new(new_image); } /** - * Construct a "wet floor" reflection. + * Creates a "wet floor" reflection. The reflection is an inverted copy of the image that changes + * from partially transparent to entirely transparent. By default only the bottom third of the image + * appears in the reflection. * - * Ruby usage: - * - @verbatim Image#wet_floor @endverbatim - * - @verbatim Image#wet_floor(initial) @endverbatim - * - @verbatim Image#wet_floor(initial, rate) @endverbatim - * - * Notes: - * - Default initial is 0.5 - * - Default rate is 1.0 - * - `initial' is a number between 0 and 1, inclusive, that represents the - * initial level of transparency. Smaller numbers are less transparent than - * larger numbers. 0 is fully opaque. 1.0 is fully transparent. - * - `rate' is the rate at which the initial level of transparency changes to - * complete transparency. Larger values cause the change to occur more - * rapidly. The resulting reflection will be shorter. Smaller values cause - * the change to occur less rapidly. The resulting reflection will be - * taller. If the rate is exactly 0 then the amount of transparency doesn't - * change at all. - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see http://en.wikipedia.org/wiki/Wet_floor_effect + * @overload wet_floor(initial = 0.5, rate = 1.0) + * @param initial [Float] A value between 0.0 and 1.0 that specifies the initial percentage of + * transparency. Higher values cause the top of the reflection to be more transparent, lower + * values less transparent. The default is 0.5, which means that the top of the reflection is 50% + * transparent. + * @param rate [Float] A non-negative value that specifies how rapidly the reflection transitions + * from the initial level of transparency to entirely transparent. The default value is 1.0, which + * means that the transition occurs in 1/3 the image height. Values greater than 1.0 speed up the + * transition (the reflection will have fewer rows), values lower than 1.0 slow down the + * transition (the reflection will have more rows). A value of 0.0 means that the level of + * transparency will not change. + * @return [Magick::Image] a new image + * @see http://en.wikipedia.org/wiki/Wet_floor_effect */ VALUE Image_wet_floor(int argc, VALUE *argv, VALUE self) { Image *image, *reflection, *flip_image; @@ -15968,16 +15119,16 @@ DestroyImage(flip_image); CHECK_EXCEPTION(); #if defined(IMAGEMAGICK_7) - (void) SetImageStorageClass(reflection, DirectClass, exception); + SetImageStorageClass(reflection, DirectClass, exception); rm_check_exception(exception, reflection, DestroyOnError); - (void) SetImageAlphaChannel(reflection, ActivateAlphaChannel, exception); + SetImageAlphaChannel(reflection, ActivateAlphaChannel, exception); rm_check_exception(exception, reflection, DestroyOnError); #else - (void) SetImageStorageClass(reflection, DirectClass); + SetImageStorageClass(reflection, DirectClass); rm_check_image_exception(reflection, DestroyOnError); reflection->matte = MagickTrue; #endif @@ -16014,18 +15165,19 @@ goto error; } for (x = 0; x < (long) image->columns; x++) { - q[x] = p[x]; // Never make a pixel *less* transparent than it already is. #if defined(IMAGEMAGICK_7) + *q = *p; SetPixelAlpha(reflection, min(GetPixelAlpha(image, q), QuantumRange - (Quantum)opacity), q); p += GetPixelChannels(reflection); q += GetPixelChannels(reflection); #else + q[x] = p[x]; q[x].opacity = max(q[x].opacity, (Quantum)opacity); #endif } @@ -16034,49 +15186,45 @@ opacity += step; } - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); return rm_image_new(reflection); error: - (void) DestroyExceptionInfo(exception); - (void) DestroyImage(reflection); + DestroyExceptionInfo(exception); + DestroyImage(reflection); rb_raise(rb_eRuntimeError, "%s failed on row %lu", func, y); return(VALUE)0; } /** - * Call WhiteThresholdImage. + * Forces all pixels above the threshold into white while leaving all pixels below the threshold + * unchanged. * - * Ruby usage: - * - @verbatim Image#white_threshold(red) @endverbatim - * - @verbatim Image#white_threshold(red, green) @endverbatim - * - @verbatim Image#white_threshold(red, green, blue) @endverbatim - * - @verbatim Image#white_threshold(red, green, blue, alpha: alpha) @endverbatim - * - * @param argc number of input arguments - * @param argv array of input arguments - * @param self this object - * @return a new image - * @see threshold_image - * @see Image_black_threshold + * @overload white_threshold(red, green, blue, alpha: alpha) + * @param red [Float] the number for red channel + * @param green [Float] the number for green channel + * @param blue [Float] the number for blue channel + * @param alpha [Numeric] the number for alpha channel + * @return [Magick::Image] a new image + * @see Image#black_threshold */ VALUE Image_white_threshold(int argc, VALUE *argv, VALUE self) { return threshold_image(argc, argv, self, WhiteThresholdImage); } /** - * Copy the filename to the Info and to the Image. Add format prefix if - * necessary. This complicated code is necessary to handle filenames like the - * kind Tempfile.new produces, which have an "extension" in the form ".n", which - * confuses SetMagickInfo. So we don't use SetMagickInfo any longer. + * Copy the filename to the Info and to the Image. Add format prefix if necessary. This complicated + * code is necessary to handle filenames like the kind Tempfile.new produces, which have an + * "extension" in the form ".n", which confuses SetMagickInfo. So we don't use SetMagickInfo any + * longer. * * No Ruby usage (internal function) * * @param info the Info * @param file the file @@ -16128,13 +15276,13 @@ CHECK_EXCEPTION(); DestroyExceptionInfo(exception); if (magick_info2->magick_module && strcmp(magick_info->magick_module, magick_info2->magick_module) != 0) { - rb_raise(rb_eRuntimeError - , "filename prefix `%s' conflicts with output format `%s'" - , magick_info->name, info->magick); + rb_raise(rb_eRuntimeError, + "filename prefix `%s' conflicts with output format `%s'", + magick_info->name, info->magick); } // The filename prefix already matches the specified format. // Just copy the filename as-is. memset(info->filename, 0, sizeof(info->filename)); @@ -16146,11 +15294,11 @@ // The filename doesn't start with a format prefix. Add the format from // the image info as the filename prefix. memset(info->filename, 0, sizeof(info->filename)); - prefix_l = min(sizeof(info->filename)-1, strlen(info->magick)); + prefix_l = min(sizeof(info->filename)-1, rm_strnlen_s(info->magick, sizeof(info->magick))); memcpy(info->filename, info->magick, prefix_l); info->filename[prefix_l++] = ':'; filename_l = min(sizeof(info->filename) - prefix_l - 1, (size_t)filename_l); memcpy(info->filename+prefix_l, filename, (size_t)filename_l); @@ -16161,16 +15309,12 @@ /** * Write the image to the file. * - * Ruby usage: - * - @verbatim Image#write(filename) @endverbatim - * - * @param self this object - * @param file the filename - * @return self + * @param file [File, String] the file + * @return [Magick::Image] self */ VALUE Image_write(VALUE self, VALUE file) { Image *image; @@ -16192,50 +15336,134 @@ // Ensure file is open - raise error if not GetOpenFile(file, fptr); rb_io_check_writable(fptr); #if defined(_WIN32) add_format_prefix(info, fptr->pathv); - strcpy(image->filename, info->filename); + strlcpy(image->filename, info->filename, sizeof(image->filename)); SetImageInfoFile(info, NULL); #else SetImageInfoFile(info, rb_io_stdio_file(fptr)); memset(image->filename, 0, sizeof(image->filename)); #endif } else { add_format_prefix(info, file); - strcpy(image->filename, info->filename); + strlcpy(image->filename, info->filename, sizeof(image->filename)); SetImageInfoFile(info, NULL); } rm_sync_image_options(image, info); info->adjoin = MagickFalse; #if defined(IMAGEMAGICK_7) exception = AcquireExceptionInfo(); - (void) WriteImage(info, image, exception); - CHECK_EXCEPTION() - (void) DestroyExceptionInfo(exception); + WriteImage(info, image, exception); + CHECK_EXCEPTION(); + DestroyExceptionInfo(exception); #else - (void) WriteImage(info, image); + WriteImage(info, image); rm_check_image_exception(image, RetainOnError); #endif RB_GC_GUARD(info_obj); return self; } #if defined(IMAGEMAGICK_7) -DEF_ATTR_ACCESSORF(Image, x_resolution, resolution.x, dbl) +/** + * Get the horizontal resolution of the image. + * + * @return [Float] the resolution + */ +VALUE +Image_x_resolution(VALUE self) +{ + IMPLEMENT_ATTR_READERF(Image, x_resolution, resolution.x, dbl); +} -DEF_ATTR_ACCESSORF(Image, y_resolution, resolution.y, dbl) +/** + * Set the horizontal resolution of the image. + * + * @param val [Float] the resolution + * @return [Float] the given resolution + */ +VALUE +Image_x_resolution_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITERF(Image, x_resolution, resolution.x, dbl); +} + +/** + * Get the vertical resolution of the image. + * + * @return [Float] the resolution + */ +VALUE +Image_y_resolution(VALUE self) +{ + IMPLEMENT_ATTR_READERF(Image, y_resolution, resolution.y, dbl); +} + +/** + * Set the vertical resolution of the image. + * + * @param val [Float] the resolution + * @return [Float] the given resolution + */ +VALUE +Image_y_resolution_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITERF(Image, y_resolution, resolution.y, dbl); +} #else -DEF_ATTR_ACCESSOR(Image, x_resolution, dbl) +/** + * Get the horizontal resolution of the image. + * + * @return [Float] the resolution + */ +VALUE +Image_x_resolution(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, x_resolution, dbl); +} -DEF_ATTR_ACCESSOR(Image, y_resolution, dbl) +/** + * Set the horizontal resolution of the image. + * + * @param val [Float] the resolution + * @return [Float] the given resolution + */ +VALUE +Image_x_resolution_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, x_resolution, dbl); +} + +/** + * Get the vertical resolution of the image. + * + * @return [Float] the resolution + */ +VALUE +Image_y_resolution(VALUE self) +{ + IMPLEMENT_ATTR_READER(Image, y_resolution, dbl); +} + +/** + * Set the vertical resolution of the image. + * + * @param val [Float] the resolution + * @return [Float] the given resolution + */ +VALUE +Image_y_resolution_eq(VALUE self, VALUE val) +{ + IMPLEMENT_ATTR_WRITER(Image, y_resolution, dbl); +} #endif /** * Determine if the argument list is x, y, width, height @@ -16397,10 +15625,15 @@ break; case CenterGravity: nx = (image->columns - columns) / 2; ny = (image->rows - rows) / 2; break; +#if defined(IMAGEMAGICK_6) + case StaticGravity: + rb_raise(rb_eNotImpError, "`StaticGravity' is not supported"); + break; +#endif } x = ULONG2NUM(nx); y = ULONG2NUM(ny); break; @@ -16463,26 +15696,25 @@ new_image = (xformer)(image, &rect, exception); // An exception can occur in either the old or the new images rm_check_exception(exception, new_image, DestroyOnError); - (void) DestroyExceptionInfo(exception); + DestroyExceptionInfo(exception); #if defined(IMAGEMAGICK_6) if (rm_should_raise_exception(&image->exception, RetainExceptionRetention)) { - (void) DestroyImage(new_image); + DestroyImage(new_image); rm_check_image_exception(image, RetainOnError); } #endif - rm_ensure_result(new_image); - if (bang) { + rm_ensure_result(new_image); UPDATE_DATA_PTR(self, new_image); - (void) rm_image_destroy(image); + rm_image_destroy(image); return self; } return rm_image_new(new_image); @@ -16541,12 +15773,12 @@ * @param arg the argument */ void raise_ChannelType_error(VALUE arg) { - rb_raise(rb_eTypeError, "argument must be a ChannelType value (%s given)" - , rb_class2name(CLASS_OF(arg))); + rb_raise(rb_eTypeError, "argument must be a ChannelType value (%s given)", + rb_class2name(CLASS_OF(arg))); } /** @@ -16567,22 +15799,20 @@ trace = rb_ivar_get(Module_Magick, rm_ID_trace_proc); if (!NIL_P(trace)) { // Maybe the stack won't get extended until we need the space. char buffer[MaxTextExtent]; - int n; trace_args[0] = ID2SYM(rb_intern(which)); build_inspect_string(image, buffer, sizeof(buffer)); trace_args[1] = rb_str_new2(buffer); - n = sprintf(buffer, "%p", (void *)image); - buffer[n] = '\0'; + snprintf(buffer, sizeof(buffer), "%p", (void *)image); trace_args[2] = rb_str_new2(buffer+2); // don't use leading 0x trace_args[3] = ID2SYM(rb_frame_this_func()); - (void) rb_funcall2(trace, rm_ID_call, 4, (VALUE *)trace_args); + rb_funcall2(trace, rm_ID_call, 4, (VALUE *)trace_args); } } RB_GC_GUARD(trace); } @@ -16600,11 +15830,10 @@ rm_trace_creation_handle_exception(VALUE img, VALUE exc) { Image *image = (Image *)img; DestroyImage(image); rb_exc_raise(exc); - return Qnil; /* not reachable */ } /** * Trace image creation * @@ -16637,10 +15866,10 @@ Image *image = (Image *)img; if (img != NULL) { call_trace_proc(image, "d"); - (void) DestroyImage(image); + DestroyImage(image); } }