ext/RMagick/rmimage.c in rmagick-2.3.0 vs ext/RMagick/rmimage.c in rmagick-2.4.0

- old
+ new

@@ -1,6 +1,6 @@ -/* $Id: rmimage.c,v 1.288 2008/03/23 15:15:46 rmagick Exp $ */ +/* $Id: rmimage.c,v 1.295 2008/06/02 22:47:37 rmagick Exp $ */ /*============================================================================\ | Copyright (C) 2008 by Timothy P. Hunter | Name: rmimage.c | Author: Tim Hunter | Purpose: Image class method definitions for RMagick @@ -24,11 +24,11 @@ static VALUE rotate(int, int, VALUE *, VALUE); 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 *, char *); +static void call_trace_proc(Image *, const char *); static const char *BlackPointCompensationKey = "PROFILE:black-point-compensation"; @@ -144,20 +144,20 @@ return adaptive_channel_method(argc, argv, self, AdaptiveBlurImageChannel); } /* - Method: Image#adaptive_resize(scale) + Method: Image#adaptive_resize(scale_val) Image#adaptive_resize(cols, rows) Purpose: Call AdaptiveResizeImage */ VALUE Image_adaptive_resize(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; unsigned long rows, columns; - double scale, drows, dcols; + double scale_val, drows, dcols; ExceptionInfo exception; image = rm_check_destroyed(self); switch (argc) @@ -165,17 +165,17 @@ case 2: rows = NUM2ULONG(argv[1]); columns = NUM2ULONG(argv[0]); break; case 1: - scale = NUM2DBL(argv[0]); - if (scale < 0.0) + scale_val = NUM2DBL(argv[0]); + if (scale_val < 0.0) { - rb_raise(rb_eArgError, "invalid scale value (%g given)", scale); + rb_raise(rb_eArgError, "invalid scale_val value (%g given)", scale_val); } - drows = scale * image->rows + 0.5; - dcols = scale * image->columns + 0.5; + drows = scale_val * image->rows + 0.5; + dcols = scale_val * image->columns + 0.5; if (drows > (double)ULONG_MAX || dcols > (double)ULONG_MAX) { rb_raise(rb_eRangeError, "resized image too big"); } rows = (unsigned long) drows; @@ -358,12 +358,19 @@ info = CloneImageInfo(NULL); if (!info) { rb_raise(rb_eNoMemError, "not enough memory to continue"); } - info->client_data= (void *)GetImageProfile(image,"8bim"); - +#if defined(HAVE_ST_PROFILE) + profile = GetImageProfile(image, "iptc"); + if (profile) + { + info->profile = (void *)CloneStringInfo(profile); + } +#else + info->client_data = GetImageProfile(image, "8bim"); +#endif strncpy(info->filename, profile_filename, min((size_t)profile_filename_l, sizeof(info->filename))); info->filename[MaxTextExtent-1] = '\0'; GetExceptionInfo(&exception); profile_image = ReadImage(info, &exception); @@ -377,11 +384,12 @@ while (profile_name) { profile = GetImageProfile(profile_image, profile_name); if (profile) { - (void)ProfileImage(image, profile_name, profile->datum, (unsigned long)profile->length, MagickFalse); + (void)ProfileImage(image, profile_name, GetStringInfoDatum(profile) + , GetStringInfoLength(profile), MagickFalse); if (image->exception.severity >= ErrorException) { break; } } @@ -600,17 +608,17 @@ Image#[:key] = attr Purpose: Update or add image attribute "key" Returns: self Notes: Specify attr=nil to remove the key from the list. - SetImageAttribute normally APPENDS the new value + 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 - SetImageAttribute returns "False" for many reasons, + SetImageProperty returns "False" for many reasons, some legitimate. */ VALUE Image_aset(VALUE self, VALUE key_arg, VALUE attr_arg) { @@ -640,20 +648,20 @@ } break; } - // Delete existing value. SetImageAttribute returns False if + // Delete existing value. SetImageProperty returns False if // the attribute doesn't exist - we don't care. (void) rm_set_property(image, key, NULL); // Set new value if (attr) { okay = rm_set_property(image, key, attr); if (!okay) { - rb_warning("SetImageAttribute failed (probably out of memory)"); + rb_warning("SetImageProperty failed (probably out of memory)"); } } return self; } @@ -922,11 +930,11 @@ */ VALUE Image_black_point_compensation_eq(VALUE self, VALUE arg) { Image *image; - char *value; + const char *value; image = rm_check_frozen(self); (void) rm_set_property(image, BlackPointCompensationKey, NULL); value = RTEST(arg) ? "true" : "false"; (void) rm_set_property(image, BlackPointCompensationKey, value); @@ -958,11 +966,11 @@ Image *image, Image *mark, long *x_offset, long *y_offset) { - MagickEnum *magick_enum; + MagickEnum *m_enum; GravityType gravity; VALUE_TO_ENUM(grav, gravity, GravityType); switch (gravity) @@ -997,12 +1005,12 @@ case NorthEastGravity: case NorthGravity: // Don't let these run into the default case break; default: - Data_Get_Struct(grav, MagickEnum, magick_enum); - rb_warning("gravity type `%s' has no effect", rb_id2name(magick_enum->id)); + Data_Get_Struct(grav, MagickEnum, m_enum); + rb_warning("gravity type `%s' has no effect", rb_id2name(m_enum->id)); break; } } @@ -2065,11 +2073,36 @@ } draw_info->fill = fill; new_image = rm_clone_image(image); +#if defined(HAVE_FLOODFILLPAINTIMAGE) + { + MagickPixelPacket target_mpp; + MagickBooleanType invert; + + GetMagickPixelPacket(new_image, &target_mpp); + if (fill_method == FillToBorderMethod) + { + invert = MagickTrue; + target_mpp.red = (MagickRealType) image->border_color.red; + target_mpp.green = (MagickRealType) image->border_color.green; + target_mpp.blue = (MagickRealType) image->border_color.blue; + } + else + { + invert = MagickFalse; + target_mpp.red = (MagickRealType) target.red; + target_mpp.green = (MagickRealType) target.green; + target_mpp.blue = (MagickRealType) target.blue; + } + + (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &target_mpp, x, y, invert); + } +#else (void) ColorFloodfillImage(new_image, draw_info, target, x, y, (PaintMethod)fill_method); +#endif // No need to check for error (void) DestroyDrawInfo(draw_info); return rm_image_new(new_image); } @@ -2139,23 +2172,23 @@ */ VALUE Image_colormap(int argc, VALUE *argv, VALUE self) { Image *image; - unsigned long index; + unsigned long idx; PixelPacket color, new_color; image = rm_check_destroyed(self); // We can handle either 1 or 2 arguments. Nothing else. if (argc == 0 || argc > 2) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 2)", argc); } - index = NUM2ULONG(argv[0]); - if (index > QuantumRange) + idx = NUM2ULONG(argv[0]); + if (idx > QuantumRange) { rb_raise(rb_eIndexError, "index out of range"); } // If this is a simple "get" operation, ensure the image has a colormap. @@ -2165,15 +2198,15 @@ { rb_raise(rb_eIndexError, "image does not contain a colormap"); } // Validate the index - if (index > image->colors-1) + if (idx > image->colors-1) { rb_raise(rb_eIndexError, "index out of range"); } - return PixelPacket_to_Color_Name(image, &image->colormap[index]); + return PixelPacket_to_Color_Name(image, &image->colormap[idx]); } // This is a "set" operation. Things are different. rb_check_frozen(self); @@ -2181,37 +2214,37 @@ // Replace with new color? The arg can be either a color name or // a Magick::Pixel. Color_to_PixelPacket(&new_color, argv[1]); // Handle no colormap or current colormap too small. - if (!image->colormap || index > image->colors-1) + if (!image->colormap || idx > image->colors-1) { PixelPacket black; unsigned long i; memset(&black, 0, sizeof(black)); if (!image->colormap) { - image->colormap = (PixelPacket *)magick_safe_malloc((index+1), sizeof(PixelPacket)); + image->colormap = (PixelPacket *)magick_safe_malloc((idx+1), sizeof(PixelPacket)); image->colors = 0; } else { - image->colormap = (PixelPacket *)magick_safe_realloc(image->colormap, (index+1), sizeof(PixelPacket)); + image->colormap = (PixelPacket *)magick_safe_realloc(image->colormap, (idx+1), sizeof(PixelPacket)); } - for (i = image->colors; i < index; i++) + for (i = image->colors; i < idx; i++) { image->colormap[i] = black; } - image->colors = index+1; + image->colors = idx+1; } // Save the current color so we can return it. Set the new color. - color = image->colormap[index]; - image->colormap[index] = new_color; + color = image->colormap[idx]; + image->colormap[idx] = new_color; return PixelPacket_to_Color_Name(image, &color); } DEF_ATTR_READER(Image, colors, ulong) @@ -2437,11 +2470,11 @@ { Image *image, *new_image; Image *comp_image; CompositeOperator operator = UndefinedCompositeOp; GravityType gravity; - MagickEnum *magick_enum; + MagickEnum *m_enum; volatile VALUE comp; signed long x_offset = 0; signed long y_offset = 0; image = rm_check_destroyed(self); @@ -2555,12 +2588,12 @@ case NorthEastGravity: case NorthGravity: // Don't let these run into the default case break; default: - Data_Get_Struct(argv[1], MagickEnum, magick_enum); - rb_warning("gravity type `%s' has no effect", rb_id2name(magick_enum->id)); + Data_Get_Struct(argv[1], MagickEnum, m_enum); + rb_warning("gravity type `%s' has no effect", rb_id2name(m_enum->id)); break; } break; } @@ -2611,19 +2644,19 @@ Image_composite_affine( VALUE self, VALUE source, VALUE affine_matrix) { - Image *image, *composite, *new_image; + Image *image, *composite_image, *new_image; AffineMatrix affine; image = rm_check_destroyed(self); - composite = rm_check_destroyed(source); + composite_image = rm_check_destroyed(source); new_image = rm_clone_image(image); AffineMatrix_to_AffineMatrix(&affine, affine_matrix); - (void) DrawAffineImage(new_image, composite, &affine); + (void) DrawAffineImage(new_image, composite_image, &affine); rm_check_image_exception(new_image, DestroyOnError); return rm_image_new(new_image); } @@ -2728,15 +2761,15 @@ volatile VALUE pixel, pixel0; unsigned long width, height; long x, npixels; char *map; long map_l; - union + volatile union { - volatile double *f; - volatile Quantum *i; - volatile void *v; + double *f; + Quantum *i; + void *v; } pixels; volatile VALUE pixel_class; StorageType stg_type; class = class; // Suppress "never referenced" message from icc @@ -2765,17 +2798,17 @@ // 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); if (rb_obj_is_kind_of(pixel0, rb_cFloat) == Qtrue) { - pixels.f = ALLOC_N(volatile double, npixels); + pixels.f = ALLOC_N(double, npixels); stg_type = DoublePixel; pixel_class = rb_cFloat; } else if (rb_obj_is_kind_of(pixel0, rb_cInteger) == Qtrue) { - pixels.i = ALLOC_N(volatile Quantum, npixels); + pixels.i = ALLOC_N(Quantum, npixels); stg_type = QuantumPixel; pixel_class = rb_cInteger; } else { @@ -2822,12 +2855,12 @@ rm_check_image_exception(image, DestroyOnError); (void) SetImageBackgroundColor(image); rm_check_image_exception(image, DestroyOnError); - (void) ImportImagePixels(image, 0, 0, width, height, map, stg_type, (void *)pixels.v); - xfree((void *)pixels.v); + (void) ImportImagePixels(image, 0, 0, width, height, map, stg_type, (const void *)pixels.v); + xfree(pixels.v); rm_check_image_exception(image, DestroyOnError); (void) DestroyExceptionInfo(&exception); DestroyConstitute(); @@ -2967,11 +3000,11 @@ VALUE self, VALUE order_arg, VALUE kernel_arg) { Image *image, *new_image; - volatile double *kernel; + double *kernel; unsigned int x, order; ExceptionInfo exception; image = rm_check_destroyed(self); @@ -2980,20 +3013,20 @@ kernel_arg = rb_Array(kernel_arg); rm_check_ary_len(kernel_arg, (long)(order*order)); // Convert the kernel array argument to an array of doubles - kernel = (volatile double *)ALLOC_N(double, order*order); + kernel = (double *)ALLOC_N(double, order*order); for (x = 0; x < order*order; x++) { kernel[x] = NUM2DBL(rb_ary_entry(kernel_arg, (long)x)); } GetExceptionInfo(&exception); - new_image = ConvolveImage(image, order, (double *)kernel, &exception); - xfree((double *)kernel); + new_image = ConvolveImage((const Image *)image, order, (double *)kernel, &exception); + xfree((void *)kernel); rm_check_exception(&exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(&exception); rm_ensure_result(new_image); @@ -3011,11 +3044,11 @@ int argc, VALUE *argv, VALUE self) { Image *image, *new_image; - volatile double *kernel; + double *kernel; volatile VALUE ary; unsigned int x, order; ChannelType channels; ExceptionInfo exception; @@ -3046,12 +3079,12 @@ kernel[x] = NUM2DBL(rb_ary_entry(ary, (long)x)); } GetExceptionInfo(&exception); - new_image = ConvolveImageChannel(image, channels, order, (double *)kernel, &exception); - xfree((double *)kernel); + new_image = ConvolveImageChannel(image, channels, order, kernel, &exception); + xfree((void *)kernel); rm_check_exception(&exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(&exception); rm_ensure_result(new_image); @@ -3457,15 +3490,15 @@ StorageType stg_type = QuantumPixel; char *map; long mapL; MagickBooleanType okay; ExceptionInfo exception; - union + volatile union { - volatile Quantum *i; - volatile double *f; - volatile void *v; + Quantum *i; + double *f; + void *v; } pixels; (void) rm_check_destroyed(self); if (argc < 5 || argc > 6) @@ -3577,22 +3610,22 @@ /* Method: Image#dissolve(overlay, src_percent, dst_percent, x_offset=0, y_offset=0) Image#dissolve(overlay, src_percent, dst_percent, gravity, x_offset=0, y_offset=0) - Purpose: Corresponds to the composite -dissolve operation + Purpose: Corresponds to the composite_image -dissolve operation Notes: `percent' can be a number or a string in the form "NN%" The "default" value of dst_percent is -1.0, which tells blend_geometry to leave it out of the geometry string. */ VALUE Image_dissolve(int argc, VALUE *argv, VALUE self) { Image *image, *overlay; double src_percent, dst_percent = -1.0; long x_offset = 0L, y_offset = 0L; - volatile VALUE composite, ovly; + volatile VALUE composite_image, ovly; image = rm_check_destroyed(self); if (argc < 1) { @@ -3619,14 +3652,14 @@ default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 to 6)", argc); break; } - composite = 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); - return composite; + return composite_image; } /* * Method: Image#distort(type, points, bestfit=false) @@ -4172,12 +4205,12 @@ Image *image; long x_off = 0L, y_off = 0L; unsigned long cols, rows; long n, npixels; unsigned int okay; - char *map = "RGB"; - volatile Quantum *pixels; + const char *map = "RGB"; + Quantum *pixels; volatile VALUE ary; ExceptionInfo exception; image = rm_check_destroyed(self); @@ -4221,11 +4254,11 @@ GetExceptionInfo(&exception); okay = ExportImagePixels(image, x_off, y_off, cols, rows, map, QuantumPixel, (void *)pixels, &exception); if (!okay) { - xfree((unsigned int *)pixels); + xfree((void *)pixels); CHECK_EXCEPTION() // Should never get here... rm_magick_error("ExportImagePixels failed with no explanation.", NULL); } @@ -4236,11 +4269,11 @@ for (n = 0; n < npixels; n++) { (void) rb_ary_push(ary, QUANTUM2NUM(pixels[n])); } - xfree((unsigned int *)pixels); + xfree((void *)pixels); return ary; } @@ -4322,11 +4355,11 @@ long x_off = 0L, y_off = 0L; unsigned long cols, rows; unsigned long npixels; size_t sz; unsigned int okay; - char *map = "RGB"; + const char *map = "RGB"; StorageType type = CharPixel; volatile VALUE string; char *str; ExceptionInfo exception; @@ -4825,11 +4858,11 @@ VALUE Image_gamma_correct(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; double red_gamma, green_gamma, blue_gamma; - char gamma[50]; + char gamma_arg[50]; image = rm_check_destroyed(self); switch (argc) { case 1: @@ -4857,15 +4890,15 @@ default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 3)", argc); break; } - sprintf(gamma, "%f,%f,%f", red_gamma, green_gamma, blue_gamma); + sprintf(gamma_arg, "%f,%f,%f", red_gamma, green_gamma, blue_gamma); new_image = rm_clone_image(image); - (void) GammaImage(new_image, gamma); + (void) GammaImage(new_image, gamma_arg); rm_check_image_exception(new_image, DestroyOnError); return rm_image_new(new_image); } @@ -4974,11 +5007,11 @@ VALUE y_arg, VALUE cols_arg, VALUE rows_arg) { Image *image; - PixelPacket *pixels; + const PixelPacket *pixels; ExceptionInfo exception; long x, y; unsigned long columns, rows; long size, n; VALUE pixel_ary; @@ -4996,11 +5029,11 @@ } // 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. GetExceptionInfo(&exception); - pixels = (PixelPacket *)AcquireImagePixels(image, x, y, columns, rows, &exception); + pixels = AcquireImagePixels(image, x, y, columns, rows, &exception); CHECK_EXCEPTION() (void) DestroyExceptionInfo(&exception); // If the function failed, return a 0-length array. @@ -5118,13 +5151,13 @@ long buffer_l; char *map; volatile VALUE pixel_arg, pixel_ary; StorageType stg_type = CharPixel; size_t type_sz, map_l; - volatile Quantum *pixels = NULL; - volatile double *fpixels = NULL; - volatile void *buffer; + Quantum *pixels = NULL; + double *fpixels = NULL; + void *buffer; unsigned int okay; image = rm_check_frozen(self); switch (argc) @@ -5243,11 +5276,11 @@ stg_type = QuantumPixel; } } - okay = ImportImagePixels(image, x_off, y_off, cols, rows, map, stg_type, (const void *)buffer); + okay = ImportImagePixels(image, x_off, y_off, cols, rows, map, stg_type, buffer); // Free pixel array before checking for errors. if (pixels) { xfree((void *)pixels); @@ -5270,11 +5303,11 @@ /* Method: Image#inspect Purpose: Overrides Object#inspect - returns a string description of the image. Returns: the string - Notes: this is essentially the DescribeImage except the description is + Notes: this is essentially the IdentifyImage except the description is built in a char buffer instead of being written to a file. */ static void build_inspect_string(Image *image, char *buffer, size_t len) { unsigned long quantum_depth; @@ -5361,23 +5394,23 @@ // Print bit depth quantum_depth = GetImageQuantumDepth(image, MagickTrue); x += sprintf(buffer+x, "%lu-bit", quantum_depth); // Print blob info if appropriate. - if (SizeBlob(image) != 0) + if (GetBlobSize(image) != 0) { - if (SizeBlob(image) >= (1 << 24)) + if (GetBlobSize(image) >= (1 << 24)) { - x += sprintf(buffer+x, " %lumb", (unsigned long) (SizeBlob(image)/1024/1024)); + x += sprintf(buffer+x, " %lumb", (unsigned long) (GetBlobSize(image)/1024/1024)); } - else if (SizeBlob(image) >= 1024) + else if (GetBlobSize(image) >= 1024) { - x += sprintf(buffer+x, " %lukb", (unsigned long) (SizeBlob(image)/1024)); + x += sprintf(buffer+x, " %lukb", (unsigned long) (GetBlobSize(image)/1024)); } else { - x += sprintf(buffer+x, " %lub", (unsigned long) SizeBlob(image)); + x += sprintf(buffer+x, " %lub", (unsigned long) GetBlobSize(image)); } } assert(x < (int)(len-1)); buffer[x] = '\0'; @@ -5482,11 +5515,11 @@ */ VALUE Image_level2(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; - double black_point = 0.0, gamma = 1.0, white_point = (double)QuantumRange; + double black_point = 0.0, gamma_val = 1.0, white_point = (double)QuantumRange; char level[50]; image = rm_check_destroyed(self); switch (argc) { @@ -5501,20 +5534,20 @@ white_point = NUM2DBL(argv[1]); break; case 3: black_point = NUM2DBL(argv[0]); white_point = NUM2DBL(argv[1]); - gamma = NUM2DBL(argv[2]); + gamma_val = NUM2DBL(argv[2]); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 to 3)", argc); break; } new_image = rm_clone_image(image); - sprintf(level, "%gx%g+%g", black_point, white_point, gamma); + sprintf(level, "%gx%g+%g", black_point, white_point, gamma_val); (void) LevelImage(new_image, level); rm_check_image_exception(new_image, DestroyOnError); return rm_image_new(new_image); } @@ -5526,11 +5559,11 @@ */ VALUE Image_level_channel(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; - double black_point = 0.0, gamma = 1.0, white_point = (double)QuantumRange; + double black_point = 0.0, gamma_val = 1.0, white_point = (double)QuantumRange; ChannelType channel; image = rm_check_destroyed(self); switch (argc) { @@ -5545,22 +5578,22 @@ white_point = NUM2DBL(argv[2]); break; case 4: black_point = NUM2DBL(argv[1]); white_point = NUM2DBL(argv[2]); - gamma = NUM2DBL(argv[3]); + gamma_val = NUM2DBL(argv[3]); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 to 4)", argc); break; } VALUE_TO_ENUM(argv[0], channel, ChannelType); new_image = rm_clone_image(image); - (void) LevelImageChannel(new_image, channel, black_point, white_point, gamma); + (void) LevelImageChannel(new_image, channel, black_point, white_point, gamma_val); rm_check_image_exception(new_image, DestroyOnError); return rm_image_new(new_image); } @@ -6007,38 +6040,38 @@ Color_to_PixelPacket(&image->matte_color, color); return self; } /* - Method: Image#matte_flood_fill(color, opacity, x, y, method) + Method: Image#matte_flood_fill(color, opacity, x, y, method_obj) Purpose: Call MatteFloodFillImage */ VALUE Image_matte_flood_fill( VALUE self, VALUE color, VALUE opacity, VALUE x_obj, VALUE y_obj, - VALUE method) + VALUE method_obj) { Image *image, *new_image; PixelPacket target; Quantum op; long x, y; - PaintMethod pm; + PaintMethod method; image = rm_check_destroyed(self); Color_to_PixelPacket(&target, color); op = APP2QUANTUM(opacity); - VALUE_TO_ENUM(method, pm, PaintMethod); - if (!(pm == FloodfillMethod || pm == FillToBorderMethod)) + VALUE_TO_ENUM(method_obj, method, PaintMethod); + if (!(method == FloodfillMethod || method == FillToBorderMethod)) { - rb_raise(rb_eArgError, "paint method must be FloodfillMethod or " - "FillToBorderMethod (%d given)", pm); + rb_raise(rb_eArgError, "paint method_obj must be FloodfillMethod or " + "FillToBorderMethod (%d given)", method); } x = NUM2LONG(x_obj); y = NUM2LONG(y_obj); if ((unsigned long)x > image->columns || (unsigned long)y > image->rows) { @@ -6047,11 +6080,44 @@ } new_image = rm_clone_image(image); - (void) MatteFloodfillImage(new_image, target, op, x, y, pm); +#if defined(HAVE_FLOODFILLPAINTIMAGE) + { + DrawInfo *draw_info; + MagickPixelPacket target_mpp; + MagickBooleanType invert; + + // FloodfillPaintImage looks for the opacity in the DrawInfo.fill field. + draw_info = CloneDrawInfo(NULL, NULL); + if (!draw_info) + { + rb_raise(rb_eNoMemError, "not enough memory to continue"); + } + draw_info->fill.opacity = op; + + if (method == FillToBorderMethod) + { + invert = MagickTrue; + target_mpp.red = (MagickRealType) image->border_color.red; + target_mpp.green = (MagickRealType) image->border_color.green; + target_mpp.blue = (MagickRealType) image->border_color.blue; + } + else + { + invert = MagickFalse; + target_mpp.red = (MagickRealType) target.red; + target_mpp.green = (MagickRealType) target.green; + target_mpp.blue = (MagickRealType) target.blue; + } + + (void) FloodfillPaintImage(new_image, OpacityChannel, draw_info, &target_mpp, x, y, invert); + } +#else + (void) MatteFloodfillImage(new_image, target, op, x, y, method); +#endif rm_check_image_exception(new_image, DestroyOnError); return rm_image_new(new_image); } @@ -6427,13 +6493,13 @@ // NOW store a real image in the image object. UPDATE_DATA_PTR(self, image); SetImageExtent(image, cols, rows); - // If the caller did not supply a fill argument, call SetImage to fill the - // image using the background color. The background color can be set by - // specifying it when creating the Info parm block. + // 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) { (void) SetImageBackgroundColor(image); } // fillobj.fill(self) @@ -6851,11 +6917,11 @@ // Use fuzz value from caller keep = new_image->fuzz; new_image->fuzz = fuzz; - okay = TransparentPaintImage(new_image, &color, opacity, invert); + okay = TransparentPaintImage(new_image, (const MagickPixelPacket *)&color, opacity, invert); new_image->fuzz = keep; // Is it possible for TransparentPaintImage to silently fail? rm_check_image_exception(new_image, DestroyOnError); if (!okay) @@ -7757,11 +7823,11 @@ */ static VALUE resize(int bang, int argc, VALUE *argv, VALUE self) { Image *image, *new_image; - double scale; + double scale_arg; FilterTypes filter; unsigned long rows, columns; double blur, drows, dcols; ExceptionInfo exception; @@ -7786,17 +7852,17 @@ { rb_raise(rb_eArgError, "invalid result dimension (%lu, %lu given)", columns, rows); } break; case 1: - scale = NUM2DBL(argv[0]); - if (scale < 0.0) + scale_arg = NUM2DBL(argv[0]); + if (scale_arg < 0.0) { - rb_raise(rb_eArgError, "invalid scale value (%g given)", scale); + rb_raise(rb_eArgError, "invalid scale_arg value (%g given)", scale_arg); } - drows = scale * image->rows + 0.5; - dcols = scale * image->columns + 0.5; + drows = scale_arg * image->rows + 0.5; + dcols = scale_arg * image->columns + 0.5; if (drows > (double)ULONG_MAX || dcols > (double)ULONG_MAX) { rb_raise(rb_eRangeError, "resized image too big"); } rows = (unsigned long) drows; @@ -7991,11 +8057,11 @@ static VALUE scale(int bang, int argc, VALUE *argv, VALUE self, scaler_t scaler) { Image *image, *new_image; unsigned long columns, rows; - double scale, drows, dcols; + double scale_arg, drows, dcols; ExceptionInfo exception; Data_Get_Struct(self, Image, image); switch (argc) @@ -8007,17 +8073,17 @@ { rb_raise(rb_eArgError, "invalid result dimension (%lu, %lu given)", columns, rows); } break; case 1: - scale = NUM2DBL(argv[0]); - if (scale <= 0) + scale_arg = NUM2DBL(argv[0]); + if (scale_arg <= 0) { - rb_raise(rb_eArgError, "invalid scale value (%g given)", scale); + rb_raise(rb_eArgError, "invalid scale value (%g given)", scale_arg); } - drows = scale * image->rows + 0.5; - dcols = scale * image->columns + 0.5; + drows = scale_arg * image->rows + 0.5; + dcols = scale_arg * image->columns + 0.5; if (drows > (double)ULONG_MAX || dcols > (double)ULONG_MAX) { rb_raise(rb_eRangeError, "resized image too big"); } rows = (unsigned long) drows; @@ -8721,18 +8787,18 @@ */ VALUE Image_spread(int argc, VALUE *argv, VALUE self) { Image *image, *new_image; - unsigned int radius = 3; + double radius = 3.0; ExceptionInfo exception; image = rm_check_destroyed(self); switch (argc) { case 1: - radius = NUM2UINT(argv[0]); + radius = NUM2DBL(argv[0]); case 0: break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc); break; @@ -9057,20 +9123,38 @@ } draw_info->fill_pattern = rm_clone_image(texture_image); new_image = rm_clone_image(image); - // Hack: By-pass bug in ColorFloodfillImage that tests - // the fill color even though the fill color isn't used. + +#if defined(HAVE_FLOODFILLPAINTIMAGE) + { + MagickPixelPacket color_mpp; + MagickBooleanType invert; + + GetMagickPixelPacket(new_image, &color_mpp); if (method == FillToBorderMethod) { - draw_info->fill.red = ROUND_TO_QUANTUM(color.red + new_image->fuzz + 1); - draw_info->fill.green = color.green; - draw_info->fill.blue = color.blue; + invert = MagickTrue; + color_mpp.red = (MagickRealType) image->border_color.red; + color_mpp.green = (MagickRealType) image->border_color.green; + color_mpp.blue = (MagickRealType) image->border_color.blue; } + else + { + invert = MagickFalse; + color_mpp.red = (MagickRealType) color.red; + color_mpp.green = (MagickRealType) color.green; + color_mpp.blue = (MagickRealType) color.blue; + } + (void) FloodfillPaintImage(new_image, DefaultChannels, draw_info, &color_mpp, x, y, invert); + } + +#else (void) ColorFloodfillImage(new_image, draw_info, color, x, y, method); +#endif (void) DestroyDrawInfo(draw_info); rm_check_image_exception(new_image, DestroyOnError); @@ -9162,11 +9246,11 @@ static VALUE thumbnail(int bang, int argc, VALUE *argv, VALUE self) { Image *image, *new_image; unsigned long columns, rows; - double scale, drows, dcols; + double scale_arg, drows, dcols; ExceptionInfo exception; Data_Get_Struct(self, Image, image); switch (argc) @@ -9178,17 +9262,17 @@ { rb_raise(rb_eArgError, "invalid result dimension (%lu, %lu given)", columns, rows); } break; case 1: - scale = NUM2DBL(argv[0]); - if (scale < 0.0) + scale_arg = NUM2DBL(argv[0]); + if (scale_arg < 0.0) { - rb_raise(rb_eArgError, "invalid scale value (%g given)", scale); + rb_raise(rb_eArgError, "invalid scale value (%g given)", scale_arg); } - drows = scale * image->rows + 0.5; - dcols = scale * image->columns + 0.5; + drows = scale_arg * image->rows + 0.5; + dcols = scale_arg * image->columns + 0.5; if (drows > (double)ULONG_MAX || dcols > (double)ULONG_MAX) { rb_raise(rb_eRangeError, "resized image too big"); } rows = (unsigned long) drows; @@ -9448,11 +9532,11 @@ } /* Method: Image#transparent(color-name<, opacity>) Image#transparent(pixel<, opacity>) - Purpose: Call TransparentImage + Purpose: Call TransparentPaintImage Notes: Can use Magick::OpaqueOpacity or Magick::TransparentOpacity, or any value >= 0 && <= QuantumRange. The default is Magick::TransparentOpacity. Use Image#fuzz= to define the tolerance level. */ @@ -9571,11 +9655,10 @@ static VALUE trimmer(int bang, int argc, VALUE *argv, VALUE self) { Image *image, *new_image; - RectangleInfo geometry; ExceptionInfo exception; int reset_page = 0; switch (argc) { @@ -9589,15 +9672,11 @@ } Data_Get_Struct(self, Image, image); GetExceptionInfo(&exception); - - geometry = GetImageBoundingBox(image, &exception); - CHECK_EXCEPTION() - - new_image = CropImage(image, &geometry, &exception); + new_image = TrimImage(image, &exception); rm_check_exception(&exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(&exception); rm_ensure_result(new_image); @@ -9656,12 +9735,12 @@ return gravity; } /* - Method: Image#image_type - Purpose: Call GetImageType to get the image type + Method: Image#image_type, image_type= + Purpose: Call GetImageType/SetImageType to get/set the image type */ VALUE Image_image_type(VALUE self) { Image *image; ImageType type; @@ -9676,10 +9755,22 @@ return ImageType_new(type); } +VALUE Image_image_type_eq(VALUE self, VALUE image_type) +{ + Image *image; + ImageType type; + + image = rm_check_frozen(self); + VALUE_TO_ENUM(image_type, type, ImageType); + SetImageType(image, type); + return image_type; +} + + /* Method: Image#unique_colors Purpose: Call UniqueImageColors */ VALUE @@ -10070,17 +10161,18 @@ */ VALUE Image_wet_floor(int argc, VALUE *argv, VALUE self) { Image *image, *reflection, *flip_image; - PixelPacket *p, *q; + const PixelPacket *p; + PixelPacket *q; RectangleInfo geometry; long x, y, max_rows; double initial = 0.5; double rate = 1.0; double opacity, step; - char *func; + const char *func; MagickBooleanType okay; ExceptionInfo exception; image = rm_check_destroyed(self); switch (argc) @@ -10149,11 +10241,11 @@ if (opacity > TransparentOpacity) { opacity = TransparentOpacity; } - p = (PixelPacket *)AcquireImagePixels(reflection, 0, y, image->columns, 1, &exception); + p = AcquireImagePixels(reflection, 0, y, image->columns, 1, &exception); rm_check_exception(&exception, reflection, RetainOnError); q = SetImagePixels(reflection, 0, y, image->columns, 1); rm_check_image_exception(reflection, DestroyOnError); if (!q) @@ -10294,11 +10386,11 @@ volatile VALUE x, y, width, height; unsigned long nx = 0, ny = 0; unsigned long columns, rows; int reset_page = 0; GravityType gravity; - MagickEnum *magick_enum; + MagickEnum *m_enum; Image *image; VALUE cropped; // Check for a "reset page" trailing argument. if (argc >= 1) @@ -10365,12 +10457,12 @@ case NorthEastGravity: case NorthGravity: // Don't let these run into the default case break; default: - Data_Get_Struct(argv[0], MagickEnum, magick_enum); - rb_warning("gravity type `%s' has no effect", rb_id2name(magick_enum->id)); + Data_Get_Struct(argv[0], MagickEnum, m_enum); + rb_warning("gravity type `%s' has no effect", rb_id2name(m_enum->id)); break; } x = ULONG2NUM(nx); y = ULONG2NUM(ny); @@ -10573,13 +10665,13 @@ /* Static: call_trace_proc Purpose: If Magick.trace_proc is not nil, build an argument list and call the proc. */ -static void call_trace_proc(Image *image, char *which) +static void call_trace_proc(Image *image, const char *which) { volatile VALUE trace; - volatile VALUE trace_args[4]; + VALUE trace_args[4]; if (rb_ivar_defined(Module_Magick, rm_ID_trace_proc) == Qtrue) { trace = rb_ivar_get(Module_Magick, rm_ID_trace_proc); if (!NIL_P(trace))