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()