ext/RMagick/rmutil.c in rmagick-2.2.2 vs ext/RMagick/rmutil.c in rmagick-2.3.0

- old
+ new

@@ -1,6 +1,6 @@ -/* $Id: rmutil.c,v 1.146 2008/01/20 17:29:42 rmagick Exp $ */ +/* $Id: rmutil.c,v 1.153 2008/03/29 15:19:15 rmagick Exp $ */ /*============================================================================\ | Copyright (C) 2008 by Timothy P. Hunter | Name: rmutil.c | Author: Tim Hunter | Purpose: Utility functions for RMagick @@ -16,10 +16,11 @@ static VALUE Enum_type_values(VALUE); static VALUE Enum_type_inspect(VALUE); static void handle_exception(ExceptionInfo *, Image *, ErrorRetention); static VALUE Pixel_from_MagickPixelPacket(MagickPixelPacket *); +#define ENUMERATORS_CLASS_VAR "@@enumerators" /* Extern: magick_safe_malloc, magick_malloc, magick_free, magick_realloc Purpose: ImageMagick versions of standard memory routines. Notes: use when managing memory that ImageMagick may have @@ -227,11 +228,11 @@ } /* Extern: rm_str2cstr(str, &len); - Purpose: Supply our own version of the "obsolete" rm_str2cstr. + Purpose: Supply our own version of the "obsolete" rb_str2cstr. */ char * rm_str2cstr(VALUE str, long *len) { StringValue(str); @@ -567,32 +568,53 @@ } return Pixel_from_PixelPacket(&pp); } + /* - Method: Magick::Pixel#to_color(compliance=Magick::???Compliance, - matte=False - depth=QuantumDepth) + Static: rm_set_magick_pixel_packet + Purpose: Convert a PixelPacket to a MagickPixelPacket + Notes: Same code as the private function SetMagickPixelPacket + in ImageMagick. +*/ +static void rm_set_magick_pixel_packet(Pixel *pixel, IndexPacket *index, MagickPixelPacket *pp) +{ + pp->red = (MagickRealType) pixel->red; + pp->green = (MagickRealType) pixel->green; + pp->blue = (MagickRealType) pixel->blue; + pp->opacity = (MagickRealType) (pp->matte ? pixel->opacity : OpaqueOpacity); + pp->index = (MagickRealType) ((pp->colorspace == CMYKColorspace) && (index ? *index : 0)); +} + + + +/* + Method: Magick::Pixel#to_color(compliance=AllCompliance, matte=false, + depth=QuantumDepth, hex=false) Purpose: return the color name corresponding to the pixel values Notes: the conversion respects the value of the 'opacity' field in the Pixel. */ VALUE Pixel_to_color(int argc, VALUE *argv, VALUE self) { Info *info; Image *image; Pixel *pixel; + MagickPixelPacket mpp; + MagickBooleanType hex = MagickFalse; char name[MaxTextExtent]; ExceptionInfo exception; ComplianceType compliance = AllCompliance; unsigned int matte = MagickFalse; unsigned int depth = QuantumDepth; switch (argc) { + case 4: + hex = RTEST(argv[3]); case 3: depth = NUM2UINT(argv[2]); // Ensure depth is appropriate for the way xMagick was compiled. switch (depth) @@ -624,22 +646,26 @@ info = CloneImageInfo(NULL); image = AllocateImage(info); image->depth = depth; image->matte = matte; (void) DestroyImageInfo(info); + + GetMagickPixelPacket(image, &mpp); + rm_set_magick_pixel_packet(pixel, NULL, &mpp); + GetExceptionInfo(&exception); - (void) QueryColorname(image, pixel, compliance, name, &exception); + (void) QueryMagickColorname(image, &mpp, compliance, hex, name, &exception); (void) DestroyImage(image); CHECK_EXCEPTION() (void) DestroyExceptionInfo(&exception); // Always return a string, even if it's "" return rb_str_new2(name); } /* - Method: Pixel#to_HSL + Method: Pixel#to_HSL *** DEPRECATED *** Purpose: Converts an RGB pixel to the array [hue, saturation, luminosity]. */ VALUE Pixel_to_HSL(VALUE self) @@ -648,10 +674,11 @@ double hue, saturation, luminosity; volatile VALUE hsl; Data_Get_Struct(self, Pixel, pixel); #if defined(HAVE_CONVERTRGBTOHSL) + rb_warning("Pixel#to_HSL is deprecated; use to_hsla"); ConvertRGBToHSL(pixel->red, pixel->green, pixel->blue, &hue, &saturation, &luminosity); #else TransformHSL(pixel->red, pixel->green, pixel->blue, &hue, &saturation, &luminosity); #endif @@ -660,11 +687,11 @@ return hsl; } /* - Method: Pixel.from_HSL + Method: Pixel.from_HSL *** DEPRECATED *** Purpose: Constructs an RGB pixel from the array [hue, saturation, luminosity]. */ VALUE Pixel_from_HSL(VALUE class, VALUE hsl) @@ -684,20 +711,134 @@ hue = NUM2DBL(rb_ary_entry(hsl, 0)); saturation = NUM2DBL(rb_ary_entry(hsl, 1)); luminosity = NUM2DBL(rb_ary_entry(hsl, 2)); #if defined(HAVE_CONVERTHSLTORGB) + rb_warning("Pixel#from_HSL is deprecated; use from_hsla"); ConvertHSLToRGB(hue, saturation, luminosity, &rgb.red, &rgb.green, &rgb.blue); #else HSLTransform(hue, saturation, luminosity, &rgb.red, &rgb.green, &rgb.blue); #endif return Pixel_from_PixelPacket(&rgb); } + + /* + Method: Pixel#from_hsla(hue, saturation, lightness, alpha=1) + Purpose: Replace brain-dead from_HSL, above. + Notes: 0 <= hue < 360, 0 <= saturation <= 1, 0 <= lightness <= 1 + 0 <= alpha <= 1 (0 is transparent, 1 is opaque) +*/ +VALUE +Pixel_from_hsla(int argc, VALUE *argv, VALUE class) +{ + double h, s, l, a = 1.0; + MagickPixelPacket pp; + ExceptionInfo exception; + char name[50]; + MagickBooleanType alpha = MagickFalse; + + class = class; // defeat "unused parameter" message. + + switch (argc) + { + case 4: + a = NUM2DBL(argv[3]); + alpha = MagickTrue; + case 3: + l = NUM2DBL(argv[2]); + s = NUM2DBL(argv[1]); + h = NUM2DBL(argv[0]); + break; + default: + rb_raise(rb_eArgError, "wrong number of arguments (%d for 3 or 4)", argc); + break; + } + + if (alpha && (a < 0.0 || a > 1.0)) + { + rb_raise(rb_eRangeError, "alpha %g out of range [0.0, 1.0]", a); + } + if (l < 0.0 || l > 100.0) + { + rb_raise(rb_eRangeError, "lightness %g out of range [0.0, 100.0]", l); + } + if (s < 0.0 || s > 100.0) + { + rb_raise(rb_eRangeError, "saturation %g out of range [0.0, 100.0]", s); + } + if (h < 0.0 || h >= 360.0) + { + rb_raise(rb_eRangeError, "hue %g out of range [0.0, 360.0)", h); + } + + memset(name, 0, sizeof(name)); + if (alpha) + { + sprintf(name, "hsla(%-2.1f,%-2.1f,%-2.1f,%-2.1f)", h, s, l, a); + } + else + { + sprintf(name, "hsl(%-2.1f,%-2.1f,%-2.1f)", h, s, l); + } + + GetExceptionInfo(&exception); + + (void) QueryMagickColor(name, &pp, &exception); + CHECK_EXCEPTION() + + (void) DestroyExceptionInfo(&exception); + + return Pixel_from_MagickPixelPacket(&pp); +} + + +/* + Method: Pixel#to_hsla() + Purpose: Replace brain-dead to_HSL, above. + Notes: Returns [hue, saturation, lightness, alpha] in the same ranges as from_hsla() +*/ +VALUE +Pixel_to_hsla(VALUE self) +{ + double hue, sat, lum, alpha; + Pixel *pixel; + volatile VALUE hsla; + + Data_Get_Struct(self, Pixel, pixel); + +#if defined(HAVE_CONVERTRGBTOHSL) + ConvertRGBToHSL(pixel->red, pixel->green, pixel->blue, &hue, &sat, &lum); +#else + TransformHSL(pixel->red, pixel->green, pixel->blue, &hue, &sat, &lum); +#endif + hue *= 360.0; + sat *= 100.0; + lum *= 100.0; + + if (pixel->opacity == OpaqueOpacity) + { + alpha = 1.0; + } + else if (pixel->opacity == TransparentOpacity) + { + alpha = 0.0; + } + else + { + alpha = ROUND_TO_QUANTUM(QuantumRange - (pixel->opacity / QuantumRange)); + } + + hsla = rb_ary_new3(4, rb_float_new(hue), rb_float_new(sat), rb_float_new(lum), rb_float_new(alpha)); + return hsla; +} + + +/* Method: Pixel#eql? Purpose: For use with Hash */ VALUE Pixel_eql_q(VALUE self, VALUE other) @@ -1393,10 +1534,19 @@ switch (ct) { ENUM_TO_NAME(UndefinedCompression) ENUM_TO_NAME(NoCompression) ENUM_TO_NAME(BZipCompression) +#if defined(HAVE_ENUM_DXT1COMPRESSION) + ENUM_TO_NAME(DXT1Compression) +#endif +#if defined(HAVE_ENUM_DXT3COMPRESSION) + ENUM_TO_NAME(DXT3Compression) +#endif +#if defined(HAVE_ENUM_DXT5COMPRESSION) + ENUM_TO_NAME(DXT5Compression) +#endif ENUM_TO_NAME(FaxCompression) ENUM_TO_NAME(Group4Compression) ENUM_TO_NAME(JPEGCompression) ENUM_TO_NAME(JPEG2000Compression) ENUM_TO_NAME(LosslessJPEGCompression) @@ -2625,11 +2775,11 @@ { VALUE argv[2]; argv[0] = sym; argv[1] = val; - return rb_class_new_instance(2, argv, class); + return rb_obj_freeze(rb_class_new_instance(2, argv, class)); } /* Extern: Enum_alloc (1.8) Purpose: Enum class alloc function @@ -2638,11 +2788,11 @@ { MagickEnum *magick_enum; volatile VALUE enumr; enumr = Data_Make_Struct(class, MagickEnum, NULL, NULL, magick_enum); - OBJ_FREEZE(enumr); + rb_obj_freeze(enumr); return enumr; } /* @@ -2747,20 +2897,16 @@ super_argv[0] = sym; super_argv[1] = val; (void) rb_call_super(2, (VALUE *)super_argv); - if (rb_cvar_defined(CLASS_OF(self), rm_ID_enumerators) != Qtrue) + if (rb_cvar_defined(CLASS_OF(self), rb_intern(ENUMERATORS_CLASS_VAR)) != Qtrue) { -#if defined(HAVE_NEW_RB_CVAR_SET) - rb_cvar_set(CLASS_OF(self), rm_ID_enumerators, rb_ary_new()); -#else - rb_cvar_set(CLASS_OF(self), rm_ID_enumerators, rb_ary_new(), 0); -#endif + rb_cv_set(CLASS_OF(self), ENUMERATORS_CLASS_VAR, rb_ary_new()); } - enumerators = rb_cvar_get(CLASS_OF(self), rm_ID_enumerators); + enumerators = rb_cv_get(CLASS_OF(self), ENUMERATORS_CLASS_VAR); (void) rb_ary_push(enumerators, self); return self; } @@ -2790,11 +2936,11 @@ { volatile VALUE enumerators, copy; volatile VALUE rv; int x; - enumerators = rb_cvar_get(class, rm_ID_enumerators); + enumerators = rb_cv_get(class, ENUMERATORS_CLASS_VAR); if (rb_block_given_p()) { for (x = 0; x < RARRAY_LEN(enumerators); x++) { @@ -2807,11 +2953,11 @@ copy = rb_ary_new2(RARRAY_LEN(enumerators)); for (x = 0; x < RARRAY_LEN(enumerators); x++) { (void) rb_ary_push(copy, rb_ary_entry(enumerators, x)); } - OBJ_FREEZE(copy); + rb_obj_freeze(copy); rv = copy; } return rv; } @@ -2938,36 +3084,33 @@ void rm_write_temp_image(Image *image, char *tmpnam) { #if defined(HAVE_SETIMAGEREGISTRY) +#define TMPNAM_CLASS_VAR "@@_tmpnam_" + MagickBooleanType okay; ExceptionInfo exception; volatile VALUE id_value; int id; GetExceptionInfo(&exception); // 'id' is always the value of its previous use - if (rb_cvar_defined(Module_Magick, rm_ID__tmpnam_) == Qtrue) + if (rb_cvar_defined(Module_Magick, rb_intern(TMPNAM_CLASS_VAR)) == Qtrue) { - id_value = rb_cvar_get(Module_Magick, rm_ID__tmpnam_); + id_value = rb_cv_get(Module_Magick, TMPNAM_CLASS_VAR); id = FIX2INT(id_value); } else { id = 0; - rb_define_class_variable(Module_Magick, "@@__tmpnam__", INT2FIX(id)); + rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id)); } id += 1; -#if defined(HAVE_NEW_RB_CVAR_SET) - rb_cvar_set(Module_Magick, rm_ID__tmpnam_, INT2FIX(id)); -#else - rb_cvar_set(Module_Magick, rm_ID__tmpnam_, INT2FIX(id), 0); -#endif - + rb_cv_set(Module_Magick, TMPNAM_CLASS_VAR, INT2FIX(id)); sprintf(tmpnam, "mpri:%d", id); // Omit "mpri:" from filename to form the key okay = SetImageRegistry(ImageRegistryType, tmpnam+5, image, &exception); CHECK_EXCEPTION()