I wrote:
> Hi,
> 
> the attached patch adds the functionality to extract GPS information 
> from images.

Oops, GMANE ate it. Here it is again, inline.

--- ImageMagick-6.4.4.orig/magick/property.c    2008-10-10 07:26:57.000000000 
+0600
+++ ImageMagick-6.4.4/magick/property.c 2008-11-15 15:43:53.000000000 +0500
@@ -722,6 +722,7 @@
  #define EXIF_FMT_SINGLE  11
  #define EXIF_FMT_DOUBLE  12
  #define TAG_EXIF_OFFSET  0x8769
+#define TAG_GPS_OFFSET  0x8825
  #define TAG_INTEROP_OFFSET  0xa005

    typedef struct _DirectoryInfo
@@ -731,11 +732,14 @@

      unsigned long
        entry;
+
+    unsigned long
+      tag_offset;
    } DirectoryInfo;

    typedef struct _TagInfo
    {
-    unsigned short
+    unsigned long
        tag;

      const char
@@ -982,6 +986,37 @@
        {  0xa40c, "exif:SubjectDistanceRange" },
        {  0xa420, "exif:ImageUniqueID" },
        {  0xc4a5, "exif:PrintImageMatching" },
+      { 0x10000, "exif:GPSVersionID" },
+      { 0x10001, "exif:GPSLatitudeRef" },
+      { 0x10002, "exif:GPSLatitude" },
+      { 0x10003, "exif:GPSLongitudeRef" },
+      { 0x10004, "exif:GPSLongitude" },
+      { 0x10005, "exif:GPSAltitudeRef" },
+      { 0x10006, "exif:GPSAltitude" },
+      { 0x10007, "exif:GPSTimeStamp" },
+      { 0x10008, "exif:GPSSatellites" },
+      { 0x10009, "exif:GPSStatus" },
+      { 0x1000a, "exif:GPSMeasureMode" },
+      { 0x1000b, "exif:GPSDop" },
+      { 0x1000c, "exif:GPSSpeedRef" },
+      { 0x1000d, "exif:GPSSpeed" },
+      { 0x1000e, "exif:GPSTrackRef" },
+      { 0x1000f, "exif:GPSTrack" },
+      { 0x10010, "exif:GPSImgDirectionRef" },
+      { 0x10011, "exif:GPSImgDirection" },
+      { 0x10012, "exif:GPSMapDatum" },
+      { 0x10013, "exif:GPSDestLatitudeRef" },
+      { 0x10014, "exif:GPSDestLatitude" },
+      { 0x10015, "exif:GPSDestLongitudeRef" },
+      { 0x10016, "exif:GPSDestLongitude" },
+      { 0x10017, "exif:GPSDestBearingRef" },
+      { 0x10018, "exif:GPSDestBearing" },
+      { 0x10019, "exif:GPSDestDistanceRef" },
+      { 0x1001a, "exif:GPSDestDistance" },
+      { 0x1001b, "exif:GPSProcessingMethod" },
+      { 0x1001c, "exif:GPSAreaInformation" },
+      { 0x1001d, "exif:GPSDateStamp" },
+      { 0x1001e, "exif:GPSDifferential" },
        {  0x0000, NULL}
      };

@@ -1019,6 +1054,7 @@
    unsigned long
      entry,
      number_entries,
+    tag_offset,
      tag;

    /*
@@ -1051,6 +1087,7 @@
        break;
      }
      case '#':
+    case '@':
      {
        int
          c;
@@ -1061,7 +1098,7 @@
        /*
          Check for a hex based tag specification first.
        */
-      tag=0;
+      tag=(*(property+5) == '@') ? 1 : 0;
        property+=6;
        n=strlen(property);
        if (n != 4)
@@ -1153,6 +1190,7 @@
    directory=exif+offset;
    level=0;
    entry=0;
+  tag_offset=0;
    do
    {
      /*
@@ -1163,6 +1201,7 @@
          level--;
          directory=directory_stack[level].directory;
          entry=directory_stack[level].entry;
+        tag_offset=directory_stack[level].tag_offset;
        }
      /*
        Determine how many entries there are in the current IFD.
@@ -1184,7 +1223,7 @@
          format;

        q=(unsigned char *) (directory+2+(12*entry));
-      tag_value=(long) ReadPropertyShort(endian,q);
+      tag_value=(long) ReadPropertyShort(endian,q) + tag_offset;
        format=(unsigned long) ReadPropertyShort(endian,q+2);
        if (format >= (sizeof(tag_bytes)/sizeof(*tag_bytes)))
          break;
@@ -1211,74 +1250,99 @@
              buffer[MaxTextExtent],
              *value;

+#define FORMAT_MULTIPLE_VALUES(size, format, arg) \
+    long component; \
+    size_t used_space; \
+    unsigned char *p1; \
+    used_space=0; \
+    p1=p; \
+    for (component = 0; component < components; component++) \
+       { \
+          used_space+=FormatMagickString(buffer+used_space, \
+             MaxTextExtent-used_space,format", ",arg); \
+          if (used_space >= MaxTextExtent - 1) \
+             used_space=MaxTextExtent-1; \
+          p1+=size; \
+       } \
+    buffer[used_space-2]='\0'; \
+    value=AcquireString(buffer);
+
+#define FORMAT_MULTIPLE_FRACTIONS(size, format, arg1, arg2) \
+    long component; \
+    size_t used_space; \
+    unsigned char *p1; \
+    used_space=0; \
+    p1=p; \
+    for (component = 0; component < components; component++) \
+       { \
+          used_space+=FormatMagickString(buffer+used_space, \
+             MaxTextExtent-used_space,format", ",arg1, arg2); \
+          if (used_space >= MaxTextExtent - 1) \
+             used_space=MaxTextExtent-1; \
+          p1+=size; \
+       } \
+    buffer[used_space-2]='\0'; \
+    value=AcquireString(buffer);
+
            switch (format)
            {
+            case EXIF_FMT_BYTE:
+            case EXIF_FMT_UNDEFINED:
+            {
+              FORMAT_MULTIPLE_VALUES(1, "%lu",
+                 (unsigned long) (*(unsigned char *) p1));
+              break;
+            }
              case EXIF_FMT_SBYTE:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%ld",
-                (long) (*(char *) p));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(1, "%ld", (long) (*(signed char *) p1));
                break;
              }
              case EXIF_FMT_SSHORT:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%hd",
-                ReadPropertyShort(endian,p));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(2, "%hd", ReadPropertyShort(endian,p1));
                break;
              }
              case EXIF_FMT_USHORT:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%hu",
-                ReadPropertyShort(endian,p));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(2, "%hu", ReadPropertyShort(endian,p1));
                break;
              }
              case EXIF_FMT_ULONG:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%lu",
-                ReadPropertyLong(endian,p));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(4, "%lu", ReadPropertyLong(endian,p1));
                break;
              }
              case EXIF_FMT_SLONG:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%ld",
-                ReadPropertyLong(endian,p));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(4, "%ld", ReadPropertyLong(endian,p1));
                break;
              }
              case EXIF_FMT_URATIONAL:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%ld/%ld",
-                ReadPropertyLong(endian,p),ReadPropertyLong(endian,p+4));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_FRACTIONS(8, "%ld/%ld",
+                 ReadPropertyLong(endian,p1),ReadPropertyLong(endian,p1+4));
                break;
              }
              case EXIF_FMT_SRATIONAL:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%ld/%ld",
-                ReadPropertyLong(endian,p),ReadPropertyLong(endian,p+4));
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_FRACTIONS(8, "%ld/%ld",
+                 ReadPropertyLong(endian,p1),ReadPropertyLong(endian,p1+4));
                break;
              }
              case EXIF_FMT_SINGLE:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%f",
-                (double) *(float *) p);
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(4, "%f", (double) *(float *) p1);
                break;
              }
              case EXIF_FMT_DOUBLE:
              {
-              (void) FormatMagickString(buffer,MaxTextExtent,"%f",
-                *(double *) p);
-              value=AcquireString(buffer);
+              FORMAT_MULTIPLE_VALUES(8, "%f", *(double *) p1);
                break;
              }
+#undef FORMAT_MULTIPLE_VALUES
+#undef FORMAT_MULTIPLE_FRACTIONS
              default:
-            case EXIF_FMT_UNDEFINED:
-            case EXIF_FMT_BYTE:
              case EXIF_FMT_STRING:
              {
                value=(char *) NULL;
@@ -1337,8 +1401,14 @@
                  }
                  case 2:
                  {
-                  (void) FormatMagickString(key,MaxTextExtent,"#%04lx",
-                    tag_value);
+                  if (tag_value < 0x10000)
+                      (void) FormatMagickString(key,MaxTextExtent,"#%04lx",
+                        tag_value);
+                  else if (tag_value < 0x20000)
+                      (void) FormatMagickString(key,MaxTextExtent,"@%04lx",
+                        tag_value & 0xffff);
+                  else
+                      (void) FormatMagickString(key,MaxTextExtent,"bug");
                    break;
                  }
                }
@@ -1349,7 +1419,9 @@
                value=DestroyString(value);
              }
          }
-        if ((tag_value == TAG_EXIF_OFFSET) || (tag_value == 
TAG_INTEROP_OFFSET))
+        if ((tag_value == TAG_EXIF_OFFSET)
+         || (tag_value == TAG_INTEROP_OFFSET)
+         || (tag_value == TAG_GPS_OFFSET))
            {
              size_t
                offset;
@@ -1357,11 +1429,16 @@
              offset=(size_t) ReadPropertyLong(endian,p);
              if ((offset < length) && (level < (MaxDirectoryStack-2)))
                {
+                unsigned long tag_offset1=(tag_value == TAG_GPS_OFFSET) ?
+                   0x10000 : 0;
+
                  directory_stack[level].directory=directory;
                  entry++;
                  directory_stack[level].entry=entry;
+                directory_stack[level].tag_offset=tag_offset;
                  level++;
                  directory_stack[level].directory=exif+offset;
+                directory_stack[level].tag_offset=tag_offset1;
                  directory_stack[level].entry=0;
                  level++;
                  if ((directory+2+(12*number_entries)) > (exif+length))
@@ -1373,6 +1450,7 @@
                    {
                      directory_stack[level].directory=exif+offset;
                      directory_stack[level].entry=0;
+                    directory_stack[level].tag_offset=tag_offset1;
                      level++;
                    }
                }

_______________________________________________
Magick-developers mailing list
Magick-developers@imagemagick.org
http://studio.imagemagick.org/mailman/listinfo/magick-developers

Reply via email to