ext/RMagick/rmutil.c in rmagick-1.15.11 vs ext/RMagick/rmutil.c in rmagick-1.15.12

- old
+ new

@@ -1,6 +1,6 @@ -/* $Id: rmutil.c,v 1.90.2.3.2.3 2007/11/25 19:45:31 rmagick Exp $ */ +/* $Id: rmutil.c,v 1.90.2.3.2.4 2007/12/15 23:31:26 rmagick Exp $ */ /*============================================================================\ | Copyright (C) 2007 by Timothy P. Hunter | Name: rmutil.c | Author: Tim Hunter | Purpose: Utility functions for RMagick @@ -180,11 +180,38 @@ } return (int)(*s1 - *s2); } +/* + * Extern: rm_strncasecmp(s1, s2, n) + * Purpose: compare s1 and s2 ignoring case + * Returns: same as strcmp(3) +*/ +int +rm_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + { + return 0; + } + while (toupper(*s1) == toupper(*s2)) + { + if (--n == 0 || *s1 == '\0') + { + return 0; + } + s1 += 1; + s2 += 1; + } + return (int)(*s1 - *s2); +} + + + + /* * Extern: rm_check_ary_len(ary, len) * Purpose: raise exception if array too short */ void @@ -3090,9 +3117,221 @@ (void) rb_iv_set(self, "@"MAGICK_LOC, extra); return self; } + + +/* + Function: rm_get_property + Purpose: Backport GetImageProperty for pre-6.3.1 versions of ImageMagick +*/ +const char *rm_get_property(const Image *img, const char *property) +{ +#if defined(HAVE_GETIMAGEPROPERTY) + return GetImageProperty(img, property); +#else + const ImageAttribute *attr; + + attr = GetImageAttribute(img, property); + return attr ? (const char *)attr->value : NULL; +#endif +} + + +/* + Function: rm_set_property + Purpose: Backport SetImageProperty for pre-6.3.1 versions of ImageMagick +*/ +unsigned int rm_set_property(Image *image, const char *property, const char *value) +{ +#if defined(HAVE_SETIMAGEPROPERTY) + return (unsigned int) SetImageProperty(image, property, value); +#else + return SetImageAttribute(image, property, value); +#endif +} + + +/* + Function: rm_exif_by_entry + Purpose: replicate old (< 6.3.2) EXIF:* functionality using GetImageProperty + by returning the exif entries as a single string, separated by \n's. + Do this so that RMagick.rb works no matter which version of + ImageMagick is in use. + Notes: see magick/identify.c +*/ +VALUE +rm_exif_by_entry(Image *image) +{ +#if defined(HAVE_GETIMAGEPROPERTY) + const char *property, *value; + char *str; + size_t len = 0, property_l, value_l; + volatile VALUE v; + + (void) GetImageProperty(image, "exif:*"); + ResetImagePropertyIterator(image); + property = GetNextImageProperty(image); + + // Measure the exif properties and values + while (property) + { + // ignore properties that don't start with "exif:" + property_l = strlen(property); + if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0) + { + if (len > 0) + { + len += 1; // there will be a \n between property=value entries + } + len += property_l - 5; + value = GetImageProperty(image,property); + if (value) + { + // add 1 for the = between property and value + len += 1 + strlen(value); + } + } + property = GetNextImageProperty(image); + } + + if (len == 0) + { + return Qnil; + } + str = xmalloc(len); + len = 0; + + // Copy the exif properties and values into the string. + ResetImagePropertyIterator(image); + property = GetNextImageProperty(image); + + while (property) + { + property_l = strlen(property); + if (property_l > 5 && rm_strncasecmp(property, "exif:", 5) == 0) + { + if (len > 0) + { + str[len++] = '\n'; + } + memcpy(str+len, property+5, property_l-5); + len += property_l - 5; + value = GetImageProperty(image,property); + if (value) + { + value_l = strlen(value); + str[len++] = '='; + memcpy(str+len, value, value_l); + len += value_l; + } + } + property = GetNextImageProperty(image); + } + + v = rb_str_new(str, len); + xfree(str); + return v; + +#else + + const ImageAttribute *attr = GetImageAttribute(image, "EXIF:*"); + return attr ? rb_str_new2(attr->value) : Qnil; + +#endif +} + + +/* + Function: rm_exif_by_number + Purpose: replicate old (< 6.3.2) EXIF:! functionality using GetImageProperty + by returning the exif entries as a single string, separated by \n's. + Do this so that RMagick.rb works no matter which version of + ImageMagick is in use. + Notes: see magick/identify.c +*/ +VALUE +rm_exif_by_number(Image *image) +{ +#if defined(HAVE_GETIMAGEPROPERTY) + const char *property, *value; + char *str; + size_t len = 0, property_l, value_l; + volatile VALUE v; + + (void) GetImageProperty(image, "exif:!"); + ResetImagePropertyIterator(image); + property = GetNextImageProperty(image); + + // Measure the exif properties and values + while (property) + { + // ignore properties that don't start with "#" + property_l = strlen(property); + if (property_l > 1 && property[0] == '#') + { + if (len > 0) + { + len += 1; // there will be a \n between property=value entries + } + len += property_l; + value = GetImageProperty(image,property); + if (value) + { + // add 1 for the = between property and value + len += 1 + strlen(value); + } + } + property = GetNextImageProperty(image); + } + + if (len == 0) + { + return Qnil; + } + str = xmalloc(len); + len = 0; + + // Copy the exif properties and values into the string. + ResetImagePropertyIterator(image); + property = GetNextImageProperty(image); + + while (property) + { + property_l = strlen(property); + if (property_l > 1 && property[0] == '#') + { + if (len > 0) + { + str[len++] = '\n'; + } + memcpy(str+len, property, property_l); + len += property_l; + value = GetImageProperty(image,property); + if (value) + { + value_l = strlen(value); + str[len++] = '='; + memcpy(str+len, value, value_l); + len += value_l; + } + } + property = GetNextImageProperty(image); + } + + v = rb_str_new(str, len); + xfree(str); + return v; + +#else + + const ImageAttribute *attr = GetImageAttribute(image, "EXIF:!"); + return attr ? rb_str_new2(attr->value) : Qnil; + +#endif +} + /* * Extern: get_geometry * Purpose: Get the values from a Geometry object and return * them in C variables.