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.