--- exif.c-	Sun Aug 20 18:38:32 2000
+++ exif.c	Sun Aug 20 18:33:32 2000
@@ -0,0 +1,3234 @@
+/* $Id$ */
+
+/*************************************************************************
+ *                                                                       *
+ * exif.c                                                                *
+ * EXIF specific code of RenamePics                                      *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+ * exif.c and exif.h are taken from
+ * renamepics <http://wormwood.lk.etc.tu-bs.de/olympus/tools/renamepi.zip>.
+ * Originally by Denise Hallmark, it is currently
+ * maintained by Rolf Lochbuehler <rolf@together.net>
+ * and Brian Morrison <bdm@fenrir.demon.co.uk>.
+ * Their exif code was dropped into rdjpgcom by 
+ * John Heidemann <johnh@isi.edu>.
+ */
+
+
+/* 
+
+EXIF and TIFF documentation:
+
+Adobe: TIFF 6.0
+http://partners.adobe.com/asn/developer/technotes.html
+
+Thierry Bousch <bousch@topo.math.u-psud.fr>: exifdump.py
+Public domain EXIF reader written in Python
+
+ISO/DIS 12234-2: Photography - Electronic still picture
+cameras - Removable Memory Part 2: Image data format - TIFF/EP
+
+Karl Logan <Karl_Logan@hotmail.com>: Re: Display image thumbnail
+Posted 1999-01-15 in comp.lang.java.programmer
+
+Tsuro Zoh Tachibanaya: Description of EXIF File Format
+http://www.butaman.ne.jp:8000/~tsuruzoh/Computer/Digicams/exif-e.html
+
+Tawbaware: EXIFRead.exe
+Freeware EXIF reader for Windows, written in Visual Basic
+http://members.tripod.com/~tawba
+
+James D Murray: Graphics File Formats FAQs
+http://168.229.3.2/AAST/ComputerAnimation/Help_FAQs_File1.html
+
+JPEG FAQs
+http://www.cis.ohio-state.edu/hypertext/faq/usenet/jpeg-faq/part1/faq.html
+http://www.cis.ohio-state.edu/hypertext/faq/usenet/jpeg-faq/part2/faq.html
+
+The Unofficial TIFF Home Page
+http://fax.st.carnet.hr/tiff_unoficial.html
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+/* #include <sys/ea.h> */
+
+/*
+ * #include "renamepics.h"
+ * #include "denise.h"
+ */
+#include "exif.h"
+
+/* _itoa seems to be an os2-ism */
+#define _itoa(n, s, slen) snprintf(s, slen, "%d", n)
+#define _ultoa(n, s, slen) snprintf(s, slen, "%uld", n)
+#define _ltoa(n, s, slen) snprintf(s, slen, "%ld", n)
+
+
+/*************************************************************************
+ *                                                                       *
+ * isExif()                                                              *
+ * Input is start of file header (at least 12 byte long)                 *
+ *                                                                       *
+ *************************************************************************/
+int isExif ( Tbyte* start )
+  {
+
+  if( 
+    'E'  == *(start + EXIF_IdOffset)     &&
+    'x'  == *(start + EXIF_IdOffset + 1) &&
+    'i'  == *(start + EXIF_IdOffset + 2) &&
+    'f'  == *(start + EXIF_IdOffset + 3) &&
+    '\0' == *(start + EXIF_IdOffset + 4) &&
+    '\0' == *(start + EXIF_IdOffset + 5)
+    )
+    return YES;
+  else
+    return NO;
+
+  }
+
+
+/*************************************************************************
+ *                                                                       *
+ * getOrder()                                                            *
+ * Determine if EXIF/TIFF file in Intel or Motorola byte order.          *
+ * Input is start of TIFF within EXIF                                    *
+ *                                                                       *
+ *************************************************************************/
+int getOrder ( Tbyte* start )
+  {
+
+  if( TIFF_II == *((Tshort*)start) )
+    return TIFF_Intel;
+
+  else if( TIFF_MM == *((Tshort*)start) )
+    return TIFF_Motorola;
+
+  else
+    return TIFF_UnkownByteOrder;
+
+  }
+
+    
+/*************************************************************************
+ *                                                                       *
+ * getShort()                                                            *
+ * Read Tshort starting at p in specified byte order                     *
+ *                                                                       *
+ *************************************************************************/
+Tshort getShort ( Tbyte* p, int byteOrder )
+  {
+
+  switch( byteOrder )
+    {
+
+    /* Intel byte order: 3210 stored as 1032 */
+    case TIFF_Intel:
+      return *( (Tshort*)p );
+
+    /* Motorola byte order: 3210 stored as 3210 */
+    case TIFF_Motorola:
+      return (*p << 8) | *(p + 1);
+
+    otherwise:
+      printf( "*Error* Unknown byteOrder %d in getShort()\n", byteOrder );
+      exit( RET_ERROR );
+
+    }   /* end switch */
+
+  }
+
+
+/*************************************************************************
+ *                                                                       *
+ * tiffShort()                                                           *
+ * Read TtiffShort starting at p in specified byte order                 *
+ *                                                                       *
+ *************************************************************************/
+TtiffShort tiffShort ( Tbyte* p, int byteOrder )
+  {
+
+  switch( byteOrder )
+    {
+
+    /* Intel byte order: 3210 stored as 1032 */
+    case TIFF_Intel:
+      return *( (TtiffShort*)p );
+
+    /* Motorola byte order: 3210 stored as 3210 */
+    case TIFF_Motorola:
+      return (*p << 8) | *(p + 1);
+
+    otherwise:
+      printf( "*Error* Unknown byteOrder %d in tiffShort()\n", byteOrder );
+      exit( RET_ERROR );
+
+    }   /* end switch */
+
+  }
+
+
+/*************************************************************************
+ *                                                                       *
+ * tiffSShort()                                                          *
+ * Read TtiffSShort starting at p in specified byte order                *
+ *                                                                       *
+ *************************************************************************/
+TtiffSShort tiffSShort ( Tbyte* p, int byteOrder )
+  {
+
+  switch( byteOrder )
+    {
+
+    /* Intel byte order: 3210 stored as 1032 */
+    case TIFF_Intel:
+      return *( (TtiffSShort*)p );
+
+    /* Motorola byte order: 3210 stored as 3210 */
+    case TIFF_Motorola:
+      return (*p << 8) | *(p + 1);
+
+    otherwise:
+      printf( "*Error* Unknown byteOrder %d in tiffSShort()\n", byteOrder );
+      exit( RET_ERROR );
+
+    }   /* end switch */
+
+  }
+
+
+/*************************************************************************
+ *                                                                       *
+ * getLong()                                                             *
+ * Read Tlong starting at p in specified byte order                      *
+ *                                                                       *
+ *************************************************************************/
+Tlong getLong ( Tbyte* p, int byteOrder )
+  {
+
+  register Tlong x;
+
+  switch( byteOrder )
+    {
+
+    /* Intel byte order: 76543210 stored as 10325476 */
+    case TIFF_Intel:
+      return *( (Tlong*)p );
+
+    /* Motorola byte order: 76543210 stored as 76543210 */
+    case TIFF_Motorola:
+      x = *p;
+      x = (x << 8) | *(p+1);
+      x = (x << 8) | *(p+2);
+      x = (x << 8) | *(p+3);
+      return x;
+
+    otherwise:
+      printf( "*Error* Unknown byteOrder %d in getLong()\n", byteOrder );
+      exit( RET_ERROR );
+
+    }   /* end switch */
+
+  }
+
+
+/*************************************************************************
+ *                                                                       *
+ * tifflong()                                                            *
+ * Read TtiffLong starting at p in specified byte order                  *
+ *                                                                       *
+ *************************************************************************/
+TtiffLong tifflong ( Tbyte* p, int byteOrder )
+  {
+
+  register TtiffLong x;
+
+  switch( byteOrder )
+    {
+
+    /* Intel byte order: 76543210 stored as 10325476 */
+    case TIFF_Intel:
+      return *( (TtiffLong*)p );
+
+    /* Motorola byte order: 76543210 stored as 76543210 */
+    case TIFF_Motorola:
+      x = *p;
+      x = (x << 8) | *(p+1);
+      x = (x << 8) | *(p+2);
+      x = (x << 8) | *(p+3);
+      return x;
+
+    otherwise:
+      printf( "*Error* Unknown byteOrder %d in tifflong()\n", byteOrder );
+      exit( RET_ERROR );
+
+    }   /* end switch */
+
+  }
+
+
+/*************************************************************************
+ *                                                                       *
+ * tiffSLong()                                                           *
+ * Read TtiffSLong starting at p in specified byte order                 *
+ *                                                                       *
+ *************************************************************************/
+TtiffSLong tiffSLong ( Tbyte* p, int byteOrder )
+  {
+
+  register TtiffSLong x;
+
+  switch( byteOrder )
+    {
+
+    /* Intel byte order: 76543210 stored as 10325476 */
+    case TIFF_Intel:
+      return *( (TtiffSLong*)p );
+
+    /* Motorola byte order: 76543210 stored as 76543210 */
+    case TIFF_Motorola:
+      x = *p;
+      x = (x << 8) | *(p+1);
+      x = (x << 8) | *(p+2);
+      x = (x << 8) | *(p+3);
+      return x;
+
+    otherwise:
+      printf( "*Error* Unknown byteOrder %d in tiffSLong()\n", byteOrder );
+      exit( RET_ERROR );
+
+    }   /* end switch */
+
+  }
+
+
+#ifdef OS2
+/*************************************************************************
+ *                                                                       *
+ * exifPhoto()                                                           *
+ * Rename EXIF photo file, store exposure info as extended attributes    *
+ *                                                                       *
+ *************************************************************************/
+int exifPhoto ( FILE* file, char* oldName, Tbyte* start, Tbyte* end )
+  {
+
+  Tphoto photo;
+  Tbyte* p;
+  Tlong i;
+  Texif exif;
+  Tifd ifd;
+  char comment [TOTAL_LENGTH] = "";
+  char dummy [TOTAL_LENGTH] = "";
+  char newName [FILENAME_MAX+1] = "";
+  char longName [FILENAME_MAX+1] = "";
+  char extension [10];
+  char dateTime [ENTRY_LENGTH+1];
+  int rc;
+  int keepOldName;
+
+  exif.tiffOffset = EXIF_TiffOffset;
+  exif.byteOrder = getOrder( start + exif.tiffOffset );
+  exif.numIfd = EXIF_NumIfd;
+
+  strcpy( photo.type, "Type: photo" );
+
+  p = start + exif.tiffOffset + (2 * SHORT_SIZE);
+  exif.ifdOffset[1] = getLong( p, exif.byteOrder );
+
+
+  /* Read IFD 1 */
+
+  p = start + exif.tiffOffset + exif.ifdOffset[1];
+  ifd.numEntries = getShort( p, exif.byteOrder );
+
+  p += SHORT_SIZE;
+
+  *(photo.dateTime) = '\0';
+  *(photo.imageDescription) = '\0';
+  *(photo.make) = '\0';
+  *(photo.model) = '\0';
+  *(photo.resolutionUnit) = '\0';
+  *(photo.software) = '\0';
+  *(photo.xResolution) = '\0';
+  *(photo.yResolution) = '\0';
+
+  for( i = 1; i <= ifd.numEntries; i += 1 )
+    switch( getShort(p,exif.byteOrder) )
+      {
+      case TIFF_ExifSubIfdOffset:
+        p += (2 * SHORT_SIZE) + LONG_SIZE;
+        exif.subIfdOffset = getLong( p, exif.byteOrder );
+        p += LONG_SIZE;
+        break;
+      case TIFF_ImageDescription:
+        strcpy( photo.imageDescription, getImageDescription(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_Make:
+        strcpy( photo.make, getMake(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_Model:
+        strcpy( photo.model, getModel(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_ResolutionUnit:
+        strcpy( photo.resolutionUnit, getResolutionUnit(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_Software:
+        strcpy( photo.software, getSoftware(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_XResolution:
+        strcpy( photo.xResolution, getXResolution(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_YResolution:
+        strcpy( photo.yResolution, getYResolution(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      default:
+        p += IFD_ENTRY_SIZE;
+      }
+
+
+  /* Read SubIFD */
+
+  p = start + exif.tiffOffset + exif.subIfdOffset;
+  ifd.numEntries = getShort( p, exif.byteOrder );
+
+  p += SHORT_SIZE;
+
+  *(photo.dateTimeDigitized) = '\0';
+  *(photo.dateTimeOriginal) = '\0';
+  *(photo.exifImageHeight) = '\0';
+  *(photo.exifImageWidth) = '\0';
+  *(photo.exifVersion) = '\0';
+  *(photo.exposureBiasValue) = '\0';
+  *(photo.exposureTime) = '\0';
+  *(photo.fNumber) = '\0';
+  *(photo.flash) = '\0';
+  *(photo.flashPixVersion) = '\0';
+  *(photo.focalLength) = '\0';
+  *(photo.isoSpeedRatings) = '\0';
+  *(photo.lightSource) = '\0';
+  *(photo.maxApertureValue) = '\0';
+  *(photo.meteringMode) = '\0';
+
+  for( i = 1; i <= ifd.numEntries; i += 1 )
+    switch( getShort(p,exif.byteOrder) )
+      {
+      case TIFF_DateTimeDigitized:
+        strcpy( photo.dateTimeDigitized, getDateTimeDigitized(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_DateTimeOriginal:
+        strcpy( photo.dateTimeOriginal, getDateTimeOriginal(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_ExifImageHeight:
+        strcpy( photo.exifImageHeight, getExifImageHeight(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_ExifImageWidth:
+        strcpy( photo.exifImageWidth, getExifImageWidth(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_ExifVersion:
+        strcpy( photo.exifVersion, getExifVersion(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_ExposureBiasValue:
+        strcpy( photo.exposureBiasValue, getExposureBiasValue(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_ExposureTime:
+        strcpy( photo.exposureTime, getExposureTime(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_FNumber:
+        strcpy( photo.fNumber, getFNumber(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_Flash:
+        strcpy( photo.flash, getFlash(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_FlashPixVersion:
+        strcpy( photo.flashPixVersion, getFlashPixVersion(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_FocalLength:
+        strcpy( photo.focalLength, getFocalLength(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_IsoSpeedRatings:
+        strcpy( photo.isoSpeedRatings, getIsoSpeedRatings(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_LightSource:
+        strcpy( photo.lightSource, getLightSource(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_MaxApertureValue:
+        strcpy( photo.maxApertureValue, getMaxApertureValue(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      case TIFF_MeteringMode:
+        strcpy( photo.meteringMode, getMeteringMode(exif.byteOrder,start+exif.tiffOffset,p,dummy) );
+        p += IFD_ENTRY_SIZE;
+        break;
+      default:
+        p += IFD_ENTRY_SIZE;
+      }
+
+  /* Rename file, assumming 12345678.123 format of old name */
+
+  strcpy( extension, oldName + strlen(oldName) - 4 ); 
+  
+  if( 0 < strlen(photo.dateTimeDigitized) )
+    {
+    strcpy( dateTime, photo.dateTimeDigitized );
+    keepOldName = NO;
+    }
+  else if( 0 < strlen(photo.dateTimeOriginal) )
+    {
+    strcpy( dateTime, photo.dateTimeOriginal );
+    keepOldName = NO;
+    }
+  else if( 0 < strlen(photo.dateTime) )
+    {
+    strcpy( dateTime, photo.dateTime );
+    keepOldName = NO;
+    }
+  else
+    keepOldName = YES;
+
+  if( YES == keepOldName )
+    strcpy( newName, oldName );
+  else
+    {
+
+    p = strchr( dateTime, ':' );
+  
+    /* Year yyyy */
+    strncpy( newName, p + 2, 4 );
+    newName[4] = '\0';
+
+    strcat( newName, "-" );
+
+    /* Month mm */
+    strncat( newName, p + 7, 2 );
+    newName[7] = '\0';
+
+    strcat( newName, "-" );
+
+    /* Day dd */
+    strncat( newName, p + 10, 2 );
+    newName[10] = '\0';
+
+    strcat( newName, "_" );
+
+    /* Hour hh */
+    strncat( newName, p + 13, 2 );
+    newName[13] = '\0';
+
+    strcat( newName, "-" );
+
+    /* Minute mm */
+    strncat( newName, p + 16, 2 );
+    newName[16] = '\0';
+
+    strcat( newName, "-" );
+
+    /* Second ss */
+    strncat( newName, p + 19, 2 );
+    newName[19] = '\0';
+
+    strcat( newName, extension );
+
+    rc = rename( oldName, newName );
+    if( 0 != rc ) 
+      {
+      printf( "*Error* Failed to rename %s to %s: %s\n", oldName, newName, strerror(errno) );
+      return RET_ERROR;
+      }
+    
+    strcpy( longName, newName );
+    writeLongnameEa( newName, longName );
+
+    }   /* end else */
+
+
+  /* Store EAs */
+
+  strcpy( dummy, "ORIGINAL PHOTO" );
+  strcat( dummy, "\n" );
+  if( 0 < strlen(photo.dateTimeDigitized) )
+    {
+    strcat( dummy, photo.dateTimeDigitized );
+    strcat( dummy, "\n" );
+    }
+  else if( 0 < strlen(photo.dateTimeOriginal) )
+    {
+    strcat( dummy, photo.dateTimeOriginal );
+    strcat( dummy, "\n" );
+    }
+  strcat( dummy, photo.exposureBiasValue );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.exposureTime );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.fNumber );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.maxApertureValue );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.focalLength );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.flash );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.isoSpeedRatings );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.lightSource );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.meteringMode );
+  strcat( dummy, "\n" );
+  strcat( dummy, "Width x height: " );
+  strcat( dummy, photo.exifImageWidth );
+  strcat( dummy, " x " );
+  strcat( dummy, photo.exifImageHeight );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.xResolution );
+  strcat( dummy, " " );
+  strcat( dummy, photo.resolutionUnit );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.yResolution );
+  strcat( dummy, " " );
+  strcat( dummy, photo.resolutionUnit );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.make );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.model );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.software );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.exifVersion );
+  strcat( dummy, "\n" );
+  strcat( dummy, photo.flashPixVersion );
+  strcat( dummy, "\n" );
+
+  writeCommentEA( newName, dummy );       
+
+
+  return RET_OK;
+
+  }
+#endif /* OS2 */
+
+
+/*************************************************************************
+ *                                                                       *
+ * dumpExif()                                                            *
+ * Rename EXIF file and store exposure info as extended attributes       *
+ *                                                                       *
+ *************************************************************************/
+int dumpExif ( char* oldName, Tbyte* start, Tbyte* end )
+  {
+
+  Texif exif;
+  Tapp1 app1;
+  Tifd ifd;
+  Tentry entry;
+  Tlong count;
+  Tlong i, k;
+  Tbyte* p;
+  Tlong offset;
+
+  int headersize;
+  char dummy [1000] = "";
+
+  /* Read TIFF data */
+
+  exif.tiffOffset = EXIF_TiffOffset;
+  exif.byteOrder = getOrder( start + exif.tiffOffset );
+
+  /* Read EXIF data */
+
+  app1.size = getShort( start + LONG_SIZE, TIFF_Motorola );
+
+  puts( "--" );
+  puts( "(Note that all offsets are relative to start of file)" );
+  printf( "File name: %s\n", oldName );
+
+  switch( exif.byteOrder )
+    {
+    case TIFF_Intel:    puts( "  Byte order: Intel" );    break;
+    case TIFF_Motorola: puts( "  Byte order: Motorola" ); break;
+    otherwise:          puts( "  Byte order: *Unknown Entry*" );
+    };
+
+  printf( "  Size of APP1: %d byte\n", app1.size, app1.size );
+
+  /* Read regular IFDs */
+
+  p = start + exif.tiffOffset + (2 * SHORT_SIZE);
+  exif.numIfd = 0;
+  while( (offset = getLong(p,exif.byteOrder)) > 0 )
+    {
+    exif.numIfd += 1;
+    exif.ifdOffset[exif.numIfd] = offset;
+    p = start + exif.tiffOffset + exif.ifdOffset[exif.numIfd];
+    ifd.numEntries = getShort( p, exif.byteOrder );
+    printf( "IFD %d at offset %Xh = %d has %d entries\n", exif.numIfd, exif.tiffOffset + exif.ifdOffset[exif.numIfd], exif.tiffOffset + exif.ifdOffset[exif.numIfd], ifd.numEntries );
+    p += SHORT_SIZE;
+    dumpEntries( start, p, ifd.numEntries, &exif );
+    p += ifd.numEntries * ((2 * SHORT_SIZE) + (2 * LONG_SIZE));
+    }   /* end while */
+
+  /* Read Sub IFD */
+
+  p = start + exif.tiffOffset + exif.subIfdOffset;
+  ifd.numEntries = getShort( p, exif.byteOrder );
+  printf( "SubIFD at offset %Xh = %d has %d entries\n", exif.tiffOffset + exif.subIfdOffset, exif.tiffOffset + exif.subIfdOffset, ifd.numEntries );
+  p += SHORT_SIZE;
+  dumpEntries( start, p, ifd.numEntries, &exif );
+
+  /* Read EXIF Interoperability IFD */
+
+  p = start + exif.tiffOffset + exif.interoperabilityOffset;
+  ifd.numEntries = getShort( p, exif.byteOrder );
+  printf( "Interoperability IFD at offset %Xh = %d has %d entries\n", exif.tiffOffset + exif.interoperabilityOffset, exif.tiffOffset + exif.interoperabilityOffset, ifd.numEntries );
+  p += SHORT_SIZE;
+  dumpEntries( start, p, ifd.numEntries, &exif );
+
+  /* Read MakerNote IFD */
+
+  p = start + exif.tiffOffset + exif.makerNoteOffset;
+  printf( "MakerNote IFD at offset %Xh = %d has unknown data structure:\n", exif.tiffOffset + exif.makerNoteOffset, exif.tiffOffset + exif.makerNoteOffset );
+  printf( "  " );
+  for( i = 0, k = 0; i < exif.makerNoteLength; i += 1, k += 3, p += 1 )
+    printf( "%02X ", *p );
+  printf( "(hex, unknown meaning)\n" );
+
+  return RET_OK;
+
+  }   /* end dumpExif() */
+
+
+/****************************************************************
+ *                                                              *
+ * getNewSubFileType()                                          *
+ *                                                              *
+ ****************************************************************/
+char* getNewSubfileType ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSubfileType ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getImageWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getImageLength ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getBitsPerSample ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getCompression()                                             *  
+ *                                                              *
+ ****************************************************************/
+char* getCompression ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* compression )
+  {
+
+  Tlong count;
+  Tshort c;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &c );
+
+  strcpy( compression, "Compression: " );
+
+  switch( c )
+    {
+    case 1:
+      strcat( compression, "(uncompressed)" );
+      break;
+    case 2:
+      strcat( compression, "ITU-T Group-3 1-D modified Huffman RLE" );
+      break;
+    case 6:
+      strcat( compression, "JPEG" );
+      break;
+    case 32773:
+      strcat( compression, "PackBits" );
+      break;
+    default:
+      _itoa( c, dummy, 10 );
+      strcat( compression, dummy );
+      strcat( compression, " *Unknown Entry*" );
+    }
+
+  return compression;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getPhotometricInterpretation ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getThresholding ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getCellWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getCellLength ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getFillOrder ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getDocumentName ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getImageDescription()                                        *  
+ *                                                              *
+ ****************************************************************/
+char* getImageDescription ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* description )
+  {
+
+  char dummy [100];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  strcpy( description, "Created with (ImageDescription): " );
+
+  if( 0 == strlen(dummy) )
+    strcat( description, "(unspecified camera)" );
+  else
+    strcat( description, dummy );
+
+  return description;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getInteroperabilityTag1()                                    *  
+ *                                                              *
+ ****************************************************************/
+char* getInteroperabilityTag1 ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* value )
+  {
+
+  char dummy [50];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  strcpy( value, "Interoperability tag 1: " );
+
+  if( 0 == strlen(dummy) )
+    strcat( value, "(no value)" );
+  else
+    strcat( value, dummy );
+
+  return value;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getInteroperabilityTag2()                                    *  
+ *                                                              *
+ ****************************************************************/
+char* getInteroperabilityTag2 ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* value )
+  {
+
+  char dummy [50];
+  Tlong count;
+
+  getTiffUndefined( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( value, "Interoperability tag 2: " );
+  strcat( value, dummy );
+
+  return value;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getMake()                                                    *  
+ *                                                              *
+ ****************************************************************/
+char* getMake ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* make )
+  {
+
+  char dummy [200];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  strcpy( make, "Camera manufacturer (Make): " );
+
+  if( 0 == strlen(dummy) )
+    strcat( make, "(unspecified)" );
+  else
+    strcat( make, dummy );
+
+  return make;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getModel()                                                   *  
+ *                                                              *
+ ****************************************************************/
+char* getModel ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* model )
+  {
+
+  char dummy [100];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  strcpy( model, "Camera model: " );
+
+  if( 0 == strlen(dummy) )
+    strcat( model, "(unspecified)" );
+  else
+    strcat( model, dummy );
+
+  return model;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getStripOffset ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getOrientation()                                             *  
+ *                                                              *
+ ****************************************************************/
+char* getOrientation ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* orientation )
+  {
+
+  Tlong count;
+  Tshort orient;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &orient );
+
+  strcpy( orientation, "Orientation: " );
+
+  switch( orient )
+    {
+    case 1:
+      strcat( orientation, "(0,0) = top left" );
+      break;
+    case 2:
+      strcat( orientation, "(0,0) = top right" );
+      break;
+    case 3:
+      strcat( orientation, "(0,0) = bottom right" );
+      break;
+    case 4:
+      strcat( orientation, "(0,0) = bottom left" );
+      break;
+    case 5:
+      strcat( orientation, "(0,0) = left top" );
+      break;
+    case 6:
+      strcat( orientation, "(0,0) = right top" );
+      break;
+    case 7:
+      strcat( orientation, "(0,0) = right bottom" );
+      break;
+    case 8:
+      strcat( orientation, "(0,0) = left bottom" );
+      break;
+    default:
+      _itoa( orient, dummy, 10 );
+      strcat( orientation, dummy );
+      strcat( orientation, " *Unknown Entry*" );
+    }
+
+  return orientation;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSamplesPerPixel ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getRowsPerStrip ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getStripByteCounts ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getMinSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getMaxSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getXResolution()                                             *  
+ *                                                              *
+ ****************************************************************/
+char* getXResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution )
+  {
+
+  char dummy [80];
+
+  strcpy( resolution, "X resolution: " );
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcat( resolution, dummy );
+
+  return resolution;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getYResolution()                                             *  
+ *                                                              *
+ ****************************************************************/
+char* getYResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution )
+  {
+
+  char dummy [80];
+
+  strcpy( resolution, "Y resolution: " );
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcat( resolution, dummy );
+
+  return resolution;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getPlanarConfiguration ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getPageName ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getXPosition ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getYPosition ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getFreeOffsets ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getFreeByteCounts ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getGrayResponseUnit()                                        *  
+ * Note that this function returns just the unit, without any   *
+ * preceding text!                                              *
+ *                                                              *
+ ****************************************************************/
+char* getGrayResponseUnit ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getGrayResponseCurve ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getT4Options ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getT6Options ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getResolutionUnit()                                          *  
+ * Note that this function returns just the unit, without any   *
+ * preceding text!                                              *
+ *                                                              *
+ ****************************************************************/
+char* getResolutionUnit ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* unit )
+  {
+
+  Tlong count;
+  Tshort u;
+  char dummy [20];
+
+  strcpy( unit, "" );
+
+  getTiffShort( byteOrder, tiff, entry, &count, &u );
+
+  switch( u )
+    {
+    case 1:
+      strcat( unit, "pixel" );
+      break;
+    case 2:
+      strcat( unit, "pixel/in" );
+      break;
+    case 3:
+      strcat( unit, "pixel/cm" );
+      break;
+    default:
+      _itoa( u, dummy, 10 );
+      strcat( unit, "*unknown unit: " );
+      strcat( unit, dummy );
+      strcat( unit, "*" );
+    }
+
+  return unit;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getPageNumber ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTransferFunction ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getSoftware()                                                *  
+ *                                                              *
+ ****************************************************************/
+char* getSoftware ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* software )
+  {
+
+  char dummy [50];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  strcpy( software, "Software version: " );
+  strcat( software, dummy );
+
+  return software;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getDateTime()                                                *  
+ *                                                              *
+ ****************************************************************/
+char* getDateTime ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* dateTime )
+  {
+
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  dummy[4] = '-';
+  dummy[7] = '-';
+
+  strcpy( dateTime, "Date/time: " );
+  strcat( dateTime, dummy );
+
+  return dateTime;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getArtist ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getHostComputer ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getPredictor ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getWhitePoint ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getPrimaryChromaticities ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getColorMap ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getHalftoneHints ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTileWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTileLength ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTileOffsets ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTileByteCounts ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getInkSet ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getInkNames ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getNumberOfInks ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getDotRange ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTargetPrinter ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getExtraSamples ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSampleFormat ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSMinSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSMaxSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTransferRange ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegTables ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegProc ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegRestartInterval ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegLosslessPredictors ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegPointTransforms ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegQTables ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegDcTables ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getJpegAcTables ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getYCbCrCoefficients ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getYCbCrSubSampling ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getYCbCrPositioning()                                        *  
+ *                                                              *
+ ****************************************************************/
+char* getYCbCrPositioning ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* position )
+  {
+
+  Tlong count;
+  TtiffShort pos;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &pos );
+
+  strcpy( position, "Y Cb Cr positioning: " );
+
+  switch( pos )
+    {
+    case 1:
+      strcat( position, "centered" );
+      break;
+    case 2:
+      strcat( position, "cosited" );
+      break;
+    default:
+      _itoa( pos, dummy, 10 );
+      strcat( position, dummy );
+      strcat( position, " *Unknown Entry*" );
+    }
+
+  return position;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getReferenceBlackWhite ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getCfaRepeatPatternDim ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getCfaPattern ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getBatteryLevel ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getCopyright ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getExposureTime()                                            *
+ *                                                              *
+ ****************************************************************/
+char* getExposureTime ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* time )
+  {
+
+  char dummy [50];
+
+  getTiffRational2( byteOrder, tiff, entry, dummy );
+
+  strcpy( time, "Exposure time (shutter speed): " );
+  strcat( time, dummy );
+  strcat( time, " s" );
+
+  return time;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFNumber()                                                 *
+ *                                                              *
+ ****************************************************************/
+char* getFNumber ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* fstop )
+  {
+
+  char dummy [20];
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( fstop, "Aperture (FNumber): F" );
+  strcat( fstop, dummy );
+  if( NULL == strchr(fstop,'.') )
+    strcat( fstop, ".0" );
+
+  return fstop;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getIptcNaa ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getInterColorProfile ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getExposureProgram()                                         *
+ *                                                              *
+ ****************************************************************/
+char* getExposureProgram ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* prog )
+  {
+
+  TtiffShort prognum;
+  Tlong count;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &prognum );
+
+  strcpy( prog, "Exposure program: " );
+
+  switch( prognum )
+    {
+    case 1:
+      strcat( prog, "manual" );
+      break;
+    case 2:
+      strcat( prog, "normal, auto" );
+      break;
+    case 3:
+      strcat( prog, "aperture priority" );
+      break;
+    case 4:
+      strcat( prog, "shutter priority" );
+      break;
+    case 5:
+      strcat( prog, "creative, slow)" );
+      break;
+    case 6:
+      strcat( prog, "action, high-speed" );
+      break;
+    case 7:
+      strcat( prog, "portrait" );
+      break;
+    case 8:
+      strcat( prog, "landscape" );
+      break;
+    default:
+      _itoa( prognum, dummy, 10 );
+      strcat( prog, dummy );
+      strcat( prog, " *Unknown Entry*" );
+    }
+
+  return prog;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSpectralSensitivity ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getGpsInfo ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getIsoSpeedRatings()                                         *
+ *                                                              *
+ ****************************************************************/
+char* getIsoSpeedRatings ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* iso )
+  {
+
+  TtiffShort n;
+  char dummy [10];
+  Tlong count;
+
+  getTiffShort( byteOrder, tiff, entry, &count, &n );
+
+  strcpy( iso, "ISO speed rating: " );
+
+  _ltoa( (long)(n), dummy, 10 );
+
+  strcat( iso, dummy );
+
+  return iso;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getOecf ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getInterlace ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTimeZoneOffset ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSelfTimerMode ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getExifVersion()                                             *
+ *                                                              *
+ ****************************************************************/
+char* getExifVersion ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* version )
+  {
+
+  Tlong count;       /* strlen(dummy) */
+  char dummy [10];
+  Tlong i;
+
+  getTiffUndefined( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( version, "EXIF version: " );
+
+  if( 4 == count )
+    {
+    i = strlen( version );
+    if( '0' != dummy[0] )
+      version[i++]   = dummy[0];
+    version[i++] = dummy[1];
+    version[i++] = '.';
+    version[i++] = dummy[2];
+    if( '0' != dummy[3] )
+      version[i++] = dummy[3];
+    version[i] = '\0';
+    }
+  else
+    strcat( version, dummy );
+
+  return version;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getDateTimeOriginal()                                        *
+ *                                                              *
+ ****************************************************************/
+char* getDateTimeOriginal ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* dateTime )
+  {
+
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  dummy[4] = '-';
+  dummy[7] = '-';
+
+  strcpy( dateTime, "Date/time original: " );
+  strcat( dateTime, dummy );
+
+  return dateTime;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getDateTimeDigitized()                                       *
+ *                                                              *
+ ****************************************************************/
+char* getDateTimeDigitized ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* dateTime )
+  {
+
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffAscii( byteOrder, tiff, entry, dummy );
+
+  dummy[4] = '-';
+  dummy[7] = '-';
+
+  strcpy( dateTime, "Date/time digitized: " );
+  strcat( dateTime, dummy );
+
+  return dateTime;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getComponentConfiguration()                                  *
+ *                                                              *
+ ****************************************************************/
+char* getComponentConfiguration ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* config )
+  {
+
+  Tlong count;
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffUnknownFormat( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( config, "Component configuration: " );
+  strcat( config, dummy );
+
+  return config;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getCompressedBitsPerLevel()                                  *
+ *                                                              *
+ ****************************************************************/
+char* getCompressedBitsPerLevel ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* compressed )
+  {
+
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( compressed, "Compressed bits/level: " );
+  strcat( compressed, dummy );
+
+  return compressed;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getShutterSpeedValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getApertureValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getBrightnessValue ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getExposureBiasValue()                                       *
+ *                                                              *
+ ****************************************************************/
+char* getExposureBiasValue ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* bias )
+  {
+
+  char dummy [50];
+
+  getTiffSRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( bias, "Exposure bias: " );
+  strcat( bias, dummy );
+  strcat( bias, " EV" );
+
+  return bias;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getMaxApertureValue()                                        *  
+ *                                                              *
+ ****************************************************************/
+char* getMaxApertureValue ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* aperture )
+  {
+
+  char dummy [50];
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( aperture, "Max aperture: F" );
+  strcat( aperture, dummy );
+  if( NULL == strchr(aperture,'.') )
+    strcat( aperture, ".0" );
+
+  return aperture;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSubjectDistance ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getMeteringMode()                                            *  
+ *                                                              *
+ ****************************************************************/
+char* getMeteringMode ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* mode )
+  {
+
+  Tlong count;
+  Tshort m;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &m );
+
+  strcpy( mode, "Metering mode: " );
+
+  switch( m )
+    {
+    case 1:
+      strcat( mode, "average" );
+      break;
+    case 2:
+      strcat( mode, "center weighted average" );
+      break;
+    case 3:
+      strcat( mode, "spot" );
+      break;
+    case 4:
+      strcat( mode, "multi-spot" );
+      break;
+    case 5:
+      strcat( mode, "multi-segment" );
+      break;
+    default:
+      _itoa( m, dummy, 10 );
+      strcat( mode, dummy );
+      strcat( mode, " *Unknown Entry*" );
+    }
+
+  return mode;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getLightSource()                                             *
+ *                                                              *
+ ****************************************************************/
+char* getLightSource ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* balance )
+  {
+
+  TtiffShort n;
+  Tlong count;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &n );
+
+  strcpy( balance, "White balance (LightSource): " );
+
+  switch( n )
+    {
+    case 0:
+      strcat( balance, "auto" );
+      break;
+    case 1:
+      strcat( balance, "daylight" );
+      break;
+    case 2:
+      strcat( balance, "fluorescent" );
+      break;
+    case 3:
+      strcat( balance, "tungsten" );
+      break;
+    case 10:
+      strcat( balance, "flash" );
+      break;
+    default:
+      _itoa( n, dummy, 10 );
+      strcat( balance, dummy );
+      strcat( balance, " *Unknown Entry*" );
+    }
+
+  return balance;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFlash()                                                   *
+ *                                                              *
+ ****************************************************************/
+char* getFlash ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* flash )
+  {
+
+  TtiffShort n;
+  Tlong count;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &n );
+ 
+  strcpy( flash, "Flash: " );
+
+  switch( n )
+    {
+    case 0:
+      strcat( flash, "none" );
+      break;
+    case 1:
+      strcat( flash, "yes" );
+      break;
+    default:
+      _itoa( n, dummy, 10 );
+      strcat( flash, dummy );
+      strcat( flash, " *Unknown Entry*" );
+    }
+
+  return flash;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFocalLength()                                             *  
+ *                                                              *
+ ****************************************************************/
+char* getFocalLength ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* length )
+  {
+
+  char dummy [20];
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( length, "Focal length: " );
+  strcat( length, dummy );
+  strcat( length, " mm" );
+
+  return length;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getFlashEnergy ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSpatialFrequencyResponse ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getNoise ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getImageNumber ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSecurityClassification ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getImageHistory ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSubjectLocation ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getExposureIndex ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getTiffEpStandardId ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getUserComment()                                             *  
+ *                                                              *
+ ****************************************************************/
+char* getUserComment ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* comment )
+  {
+ 
+  Tlong count;
+  Tlong i;
+  char dummy [TOTAL_LENGTH];
+
+  getTiffUndefined( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( comment, "User comment: " );
+
+  if( 0 == strlen(dummy) )
+    strcat( comment, "(none)" );
+  else
+    strcat( comment, dummy );
+
+  return comment;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSubSecTime ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSubSecTimeOriginal ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSubSecTimeDigitized ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFlashPixVersion()                                         *  
+ *                                                              *
+ ****************************************************************/
+char* getFlashPixVersion ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* version )
+  {
+
+  Tlong count;
+  Tlong i;
+  char dummy [50];
+
+  getTiffUndefined( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( version, "FlashPix version: " );
+
+  if( 4 == count )
+    {
+    i = strlen( version );
+    if( '0' != dummy[0] )
+      version[i++]   = dummy[0];
+    version[i++] = dummy[1];
+    version[i++] = '.';
+    version[i++] = dummy[2];
+    if( '0' != dummy[3] )
+      version[i++] = dummy[3];
+    version[i] = '\0';
+    }
+  else
+    strcat( version, dummy );
+
+  return version;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getColorSpace()                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getColorSpace ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* color )
+  {
+
+  TtiffShort c;
+  Tlong count;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &c );
+
+  strcpy( color, "Color space: " );
+
+  switch( c )
+    {
+    case 1:
+      strcat( color, "1" );
+      break;
+    default:
+      _itoa( c, dummy, 10 );
+      strcat( color, dummy );
+      strcat( color, " *Unknown Entry*" );
+    }
+
+  return color;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getExifImageWidth()                                          *  
+ * Note that this function returns just a value, without any    *
+ * text prefixed                                                *
+ *                                                              *
+ ****************************************************************/
+char* getExifImageWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* width )
+  {
+ 
+  Tlong count;
+  TtiffLong w;
+  char dummy [20];
+
+  getTiffLong( byteOrder, tiff, entry, &count, &w );
+
+  _ultoa( w, dummy, 10 );
+
+  strcpy( width, "" );
+  strcat( width, dummy );
+  strcat( width, " pixel" );
+
+  return width;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getExifImageHeight()                                         *  
+ * Note that this function returns just a value, without any    *
+ * text prefixed                                                *
+ *                                                              *
+ ****************************************************************/
+char* getExifImageHeight ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* height )
+  {
+
+  Tlong count;
+  TtiffLong h;
+  char dummy [20];
+
+  getTiffLong( byteOrder, tiff, entry, &count, &h );
+
+  _ultoa( h, dummy, 10 );
+
+  strcpy( height, "" );
+  strcat( height, dummy );
+  strcat( height, " pixel" );
+
+  return height;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getRelatedSoundFile ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+
+  return "?";
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFocalPlaneXResolution()                                   *  
+ *                                                              *
+ ****************************************************************/
+char* getFocalPlaneXResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution )
+  {
+
+  char dummy [20];
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( resolution, "Focal plane X resolution: " );
+  strcat( resolution, dummy );
+
+  return resolution;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFocalPlaneYResolution()                                   *  
+ *                                                              *
+ ****************************************************************/
+char* getFocalPlaneYResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution )
+  {
+
+  char dummy [20];
+
+  getTiffRational( byteOrder, tiff, entry, dummy );
+
+  strcpy( resolution, "Focal plane Y resolution: " );
+  strcat( resolution, dummy );
+
+  return resolution;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFocalPlaneResolutionUnit()                                *  
+ * Note that this function returns just the unit, without any   *
+ * preceding text!                                              *
+ *                                                              *
+ ****************************************************************/
+char* getFocalPlaneResolutionUnit ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* unit )
+  {
+
+  Tlong count;
+  Tshort u;
+  char dummy [20];
+
+  getTiffShort( byteOrder, tiff, entry, &count, &u );
+
+  strcpy( unit, "" );
+
+  switch( u )
+    {
+    case 1:
+      strcat( unit, "pixel/in" );
+      break;
+    case 2:
+      strcat( unit, "pixel/m" );
+      break;
+    case 3:
+      strcat( unit, "pixel/cm" );
+      break;
+    case 4:
+      strcat( unit, "pixel/mm" );
+      break;
+    case 5:
+      strcat( unit, "pixel/æm" );
+      break;
+    default:
+      _itoa( u, dummy, 10 );
+      strcat( unit, "*unknown unit: " );
+      strcat( unit, dummy );
+      strcat( unit, "*" );
+    }
+
+  return unit;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ *                                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getSensingMethod ( int byteOrder, Tbyte* tiff, Tbyte* entry )
+  {
+  return "?";
+  }
+
+/****************************************************************
+ *                                                              *
+ * getFileSource()                                              *  
+ *                                                              *
+ ****************************************************************/
+char* getFileSource ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* source )
+  {
+
+  Tlong count;
+  Tlong i;
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffUnknownFormat( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( source, "File source: " );
+  strcat( source, dummy );
+
+  return source;
+
+  }
+
+/****************************************************************
+ *                                                              *
+ * getSceneType()                                               *  
+ *                                                              *
+ ****************************************************************/
+char* getSceneType ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* type )
+  {
+
+  Tlong count;
+  Tlong i;
+  char dummy [ENTRY_LENGTH+1];
+
+  getTiffUnknownFormat( byteOrder, tiff, entry, &count, dummy );
+
+  strcpy( type, "Scene type: " );
+  strcat( type, dummy );
+
+  return type;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffRational()                                            *
+ * Read RATIONAL number and return as float x/y                 *
+ *                                                              *
+ ****************************************************************/
+char* getTiffRational ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string )
+  {
+
+  Tbyte* p;
+  char dummy [30];
+  Tlong x, y;
+
+  p = entry + (2 * SHORT_SIZE) + LONG_SIZE;
+  p = tiff + getLong( p, byteOrder );
+
+  x = tifflong( p, byteOrder );
+
+  p += LONG_SIZE;
+
+  y = tifflong( p, byteOrder );
+
+  sprintf( string, "%g", ((float)x)/((float)y) );
+
+  return string;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffRational2()                                           *
+ * Read RATIONAL number and return as string "x/y"              *
+ *                                                              *
+ ****************************************************************/
+char* getTiffRational2 ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string )
+  {
+
+  Tbyte* p;
+  char dummy [30];
+  Tlong x, y;
+
+  p = entry + (2 * SHORT_SIZE) + LONG_SIZE;
+  p = tiff + getLong( p, byteOrder );
+  x = tifflong( p, byteOrder );
+  p += LONG_SIZE;
+  y = tifflong( p, byteOrder );
+
+  if( 0 == x )
+    {
+    strcpy( string, "0" );
+    return string;
+    }
+  else if( 0 == y % x )
+    {
+    strcpy( string, "1/" );
+    _ultoa( y / x, dummy, 10 );
+    strcat( string, dummy );
+    return string;
+    }
+  else
+    {
+    _ultoa( x, dummy, 10 );
+    strcpy( string, dummy );
+    strcat( string, "/" );
+    _ultoa( y, dummy, 10 );
+    strcat( string, dummy );
+    return string;
+    }
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffSRational()                                           *
+ * Read SRATIONAL number and return as string "x/y"             *
+ *                                                              *
+ ****************************************************************/
+char* getTiffSRational ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string )
+  {
+
+  Tbyte* p;
+  char dummy [30];
+  Tlong x, y;
+
+  p = entry + (2 * SHORT_SIZE) + LONG_SIZE;
+
+  p = tiff + getLong( p, byteOrder );
+
+#if 1
+
+  x = tiffSLong( p, byteOrder );
+
+  p += LONG_SIZE;
+
+  y = tiffSLong( p, byteOrder );
+
+  sprintf( string, "%g", ((float)x)/((float)y) );
+
+#else
+
+  _ltoa( tiffSLong(p,byteOrder), dummy, 10 );
+  strcpy( string, dummy );
+
+  strcat( string, "/" );
+
+  p += LONG_SIZE;
+
+  _ltoa( tiffSLong(p,byteOrder), dummy, 10 );
+  strcat( string, dummy );
+
+#endif
+
+  return string;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffShort()                                               *
+ * Read SHORT number                                            *
+ *                                                              *
+ ****************************************************************/
+TtiffShort* getTiffShort ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, TtiffShort* val )
+  {
+
+  Tbyte* p;
+  Tlong i;
+
+  p = entry + (2 * SHORT_SIZE);
+  *count = getLong( p, byteOrder );
+
+  p += LONG_SIZE;
+  if( *count > (LONG_SIZE / TIFF_SHORT_SIZE) )
+    p = tiff + getLong( p, byteOrder );
+
+  for( i = 0; i < *count; i += 1 )
+    {
+    val[i] = tiffShort( p, byteOrder );
+    p += TIFF_SHORT_SIZE;
+    }
+
+  return val;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffAscii()                                               *
+ * Read ASCII string                                            *
+ *                                                              *
+ ****************************************************************/
+char* getTiffAscii ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string )
+  {
+
+  Tbyte* p;
+  Tlong i;
+  Tlong count;
+
+  p = entry + (2 * SHORT_SIZE);
+  count = getShort( p, byteOrder );
+
+  p += LONG_SIZE;
+  if( count > LONG_SIZE )
+    p = tiff + getLong( p, byteOrder );
+
+  strncpy( string, p, count );
+  string[count] = '\0';
+
+  return string;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffUndefined()                                           *
+ * Read byte string of undefined format                         *
+ *                                                              *
+ ****************************************************************/
+char* getTiffUndefined ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, char* string )
+  {
+
+  Tbyte* p;
+  Tlong i;
+
+  p = entry + (2 * SHORT_SIZE);
+  *count = getShort( p, byteOrder );
+
+  p += LONG_SIZE;
+  if( *count > LONG_SIZE )
+    p = tiff + getLong( p, byteOrder );
+
+  /* Cannot use strncpy() here since it stops at the first '\0' */
+  for( i = 0; i < *count; i += 1 )
+    string[i] = p[i];
+
+  /* Last byte may not be '\0' */
+  string[*count] = '\0';
+
+  return string;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffUnknownFormat()                                       *
+ * Read byte string of unknown format                           *
+ *                                                              *
+ ****************************************************************/
+char* getTiffUnknownFormat ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, char* string )
+  {
+
+  Tbyte* p;
+  Tlong i, k;
+
+  p = entry + (2 * SHORT_SIZE);
+  *count = getShort( p, byteOrder );
+
+  p += LONG_SIZE;
+  if( *count > LONG_SIZE )
+    p = tiff + getLong( p, byteOrder );
+
+  for( i = 0, k = 0; i < *count; i += 1, k += 3, p += 1 )
+    sprintf( string + k, "%02X ", *p );
+
+  strcat( string, "(hex, unknown meaning)" );
+
+  return string;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * getTiffLong()                                                *
+ * Read LONG number                                             *
+ *                                                              *
+ ****************************************************************/
+TtiffLong* getTiffLong ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, TtiffLong* val )
+  {
+
+  Tbyte* p;
+  Tlong i;
+
+  p = entry + (2 * SHORT_SIZE);
+  *count = getLong( p, byteOrder );
+
+  p += LONG_SIZE;
+  if( *count > (LONG_SIZE / TIFF_SHORT_SIZE) )
+    p = tiff + getLong( p, byteOrder );
+
+  for( i = 0; i < *count; i += 1 )
+    {
+    val[i] = tifflong( p, byteOrder );
+    p += TIFF_LONG_SIZE;
+    }
+
+  return val;
+
+  }
+
+
+/****************************************************************
+ *                                                              *
+ * dumpEntries()                                                *
+ * Read entries in IFD                                          *
+ *                                                              *
+ ****************************************************************/
+void dumpEntries ( Tbyte* start, Tbyte* firstentry, Tlong entries, Texif* exif )
+  {
+
+  Tentry entry;
+
+  Tlong i;
+  Tbyte* p;
+
+  char dummy [1000] = "";
+
+  p = firstentry;
+
+  for( i = 1; i <= entries; i += 1 )
+    {
+
+    entry.tag = getShort( p, exif->byteOrder );
+
+    switch( entry.tag )
+      {
+
+      case TIFF_ColorSpace:
+        printf( "  %s\n", getColorSpace(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ComponentConfiguration:
+        printf( "  %s\n", getComponentConfiguration(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_CompressedBitsPerLevel:
+        printf( "  %s\n", getCompressedBitsPerLevel(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_Compression:
+        printf( "  %s\n", getCompression(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_DateTime:
+        printf( "  %s\n", getDateTime(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_DateTimeDigitized:
+        printf( "  %s\n", getDateTimeDigitized(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_DateTimeOriginal:
+        printf( "  %s\n", getDateTimeOriginal(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ExifImageHeight:
+        printf( "  EXIF image height: %s\n", getExifImageHeight(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ExifImageWidth:
+        printf( "  EXIF image width: %s\n", getExifImageWidth(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ExifInteroperabilityOffset:
+        p += (2 * SHORT_SIZE) + LONG_SIZE;
+        exif->interoperabilityOffset = getLong( p, exif->byteOrder );
+        printf( "  EXIF interoperability IFD offset: %Xh = %d (see separate listing)\n", (exif->tiffOffset) + (exif->interoperabilityOffset), (exif->tiffOffset) + (exif->interoperabilityOffset) );
+        p += LONG_SIZE;
+        break;
+
+      case TIFF_ExifSubIfdOffset:
+        p += (2 * SHORT_SIZE) + LONG_SIZE;
+        exif->subIfdOffset = getLong( p, exif->byteOrder );
+        printf( "  EXIF SubIFD offset: %Xh = %d (see separate listing)\n", (exif->tiffOffset) + (exif->subIfdOffset), (exif->tiffOffset) + (exif->subIfdOffset) );
+        p += LONG_SIZE;
+        break;
+
+      case TIFF_ExifVersion:
+        printf( "  %s\n", getExifVersion(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ExposureBiasValue:
+        printf( "  %s\n", getExposureBiasValue(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ExposureTime:
+        printf( "  %s\n", getExposureTime(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ExposureProgram:
+        printf( "  %s\n", getExposureProgram(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_FileSource:
+        printf( "  %s\n", getFileSource(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_Flash:
+        printf( "  %s\n", getFlash(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_FlashPixVersion:
+        printf( "  %s\n", getFlashPixVersion(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_FNumber:
+        printf( "  %s\n", getFNumber(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);   
+        break;
+
+      case TIFF_FocalLength:
+        printf( "  %s\n", getFocalLength(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_FocalPlaneResolutionUnit:
+        printf( "  Focal plane resolution unit: %s\n", getFocalPlaneResolutionUnit(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_FocalPlaneXResolution:
+        printf( "  %s\n", getFocalPlaneXResolution(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_FocalPlaneYResolution:
+        printf( "  %s\n", getFocalPlaneYResolution(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ImageDescription:
+        printf( "  %s\n", getImageDescription(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_InteroperabilityTag1:
+        printf( "  %s\n", getInteroperabilityTag1(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);                              
+        break;
+
+      case TIFF_InteroperabilityTag2:
+        printf( "  %s\n", getInteroperabilityTag2(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_IsoSpeedRatings:
+        printf( "  %s\n", getIsoSpeedRatings(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_JpegInterchangeFormat:
+        p += (2 * SHORT_SIZE) + LONG_SIZE;
+        exif->jpegOffset = getLong( p, exif->byteOrder );
+        printf( "  JPEG data offset (JpegInterchangeFormat): %Xh = %d\n", (exif->tiffOffset) + (exif->jpegOffset), (exif->tiffOffset) + (exif->jpegOffset) );
+        p += LONG_SIZE;
+        break;
+
+      case TIFF_JpegInterchangeFormatLength:
+        p += (2 * SHORT_SIZE) + LONG_SIZE;
+        exif->jpegLength = getLong( p, exif->byteOrder );
+        printf( "  JPEG data size (JpegInterchangeFormatLength): %d byte\n", exif->jpegLength );
+        p += LONG_SIZE;
+        break;
+
+      case TIFF_LightSource:
+        printf( "  %s\n", getLightSource(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_Make:
+        printf( "  %s\n", getMake(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_MakerNote:
+        p += (2 * SHORT_SIZE);
+        exif->makerNoteLength = getLong( p, exif->byteOrder );
+        p += LONG_SIZE;
+        exif->makerNoteOffset = getLong( p, exif->byteOrder );
+        printf( "  Maker note offset (MakerNote): %Xh = %d (see separate listing)\n", (exif->tiffOffset) + (exif->makerNoteOffset), (exif->tiffOffset) + (exif->makerNoteOffset) );
+        p += LONG_SIZE;
+        break;
+
+      case TIFF_MaxApertureValue:
+        printf( "  %s\n", getMaxApertureValue(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);                
+        break;
+
+      case TIFF_MeteringMode:
+        printf( "  %s\n", getMeteringMode(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_Model:
+        printf( "  %s\n", getModel(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_Orientation:
+        printf( "  %s\n", getOrientation(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_SceneType:
+        printf( "  %s\n", getSceneType(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_Software:
+        printf( "  %s\n", getSoftware(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_ResolutionUnit:
+        printf( "  Resolution unit: %s\n", getResolutionUnit(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_XResolution:
+        printf( "  %s\n", getXResolution(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_YResolution:
+        printf( "  %s\n", getYResolution(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_YCbCrPositioning:
+        printf( "  %s\n", getYCbCrPositioning(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      case TIFF_UserComment:
+        printf( "  %s\n", getUserComment(exif->byteOrder,start+(exif->tiffOffset),p,dummy) );
+        p += (2 * SHORT_SIZE) + (2 * LONG_SIZE);
+        break;
+
+      default:
+
+        p += SHORT_SIZE;
+        entry.type = getShort( p, exif->byteOrder );
+    
+        p += SHORT_SIZE;
+        entry.count = getLong( p, exif->byteOrder );
+    
+        p += LONG_SIZE;
+        entry.offset = getLong( p, exif->byteOrder );
+    
+        printf( 
+          "  Entry: %d  Tag: %x  Type: %x  Count: %d  Value or offset (- %d) of value: %Xh = %d\n",
+          i, entry.tag, entry.type, entry.count, exif->tiffOffset, entry.offset, entry.offset
+          );
+    
+        p += LONG_SIZE;
+
+      }   /* end switch */
+
+    }   /* end for */
+
+  return;
+
+  }
+
--- exif.h-	Sun Aug 20 18:38:32 2000
+++ exif.h	Sun Aug 20 18:28:22 2000
@@ -0,0 +1,504 @@
+#ifndef INCL_EXIF_H
+#define INCL_EXIF_H
+
+
+/* $Id$ */
+
+
+/*************************************************************************
+ *                                                                       *
+ * exif.h                                                                *
+ * Header file for EXIF specific code or RenamePics                      *
+ *                                                                       *
+ *************************************************************************/
+
+/* Return values */
+
+#define RET_OK 0
+#define RET_ERROR 1
+#define RET_HELP 2
+#define RET_INVALID_ARG 3
+
+#define NO 0
+#define YES 1
+#define EQUAL 0
+#define SUCCESS 0
+
+
+/* TIFF specifics */
+
+#define ENTRY_LENGTH                       101
+#define TOTAL_LENGTH                       10001
+
+
+/* Data types */
+
+typedef unsigned char Tbyte;
+typedef unsigned short Tshort;
+typedef unsigned long Tlong;
+
+typedef struct _Texif
+  {
+  Tshort byteOrder;
+  Tshort numIfd;
+  Tlong ifdOffset[10];
+  Tlong subIfdOffset;
+  Tlong makerNoteOffset;
+  Tlong makerNoteLength;
+  Tlong interoperabilityOffset;
+  Tlong jpegOffset;
+  Tlong jpegLength;
+  Tlong tiffOffset;
+  char version [ENTRY_LENGTH+1];
+  } Texif;
+
+
+typedef struct _Tphoto
+  {
+  char colorSpace [ENTRY_LENGTH+1];                 
+  char dateTime [ENTRY_LENGTH+1];
+  char dateTimeDigitized [ENTRY_LENGTH+1];
+  char dateTimeOriginal [ENTRY_LENGTH+1];
+  char exifImageHeight [ENTRY_LENGTH+1];
+  char exifImageWidth [ENTRY_LENGTH+1];
+  char exposureBiasValue [ENTRY_LENGTH+1];
+  char exposureTime [ENTRY_LENGTH+1];
+  char exifVersion [ENTRY_LENGTH+1];
+  char fNumber [ENTRY_LENGTH+1];
+  char flash [ENTRY_LENGTH+1];
+  char flashPixVersion [ENTRY_LENGTH+1];
+  char focalLength [ENTRY_LENGTH+1];
+  char imageDescription [ENTRY_LENGTH+1];
+  char isoSpeedRatings [ENTRY_LENGTH+1];
+  char lightSource [ENTRY_LENGTH+1];
+  char make [ENTRY_LENGTH+1];
+  char maxApertureValue [ENTRY_LENGTH+1];
+  char meteringMode [ENTRY_LENGTH+1];
+  char model [ENTRY_LENGTH+1];
+  char resolutionUnit [ENTRY_LENGTH+1];
+  char software [ENTRY_LENGTH+1];
+  char type [ENTRY_LENGTH+1];
+  char xResolution [ENTRY_LENGTH+1];
+  char yResolution [ENTRY_LENGTH+1];
+  } Tphoto;
+
+
+/* Tiff internal data types */
+
+typedef unsigned char  TtiffByte;
+typedef char           TtiffAscii;
+typedef unsigned short TtiffShort;
+typedef unsigned int   TtiffLong;
+typedef signed char    TtiffSByte;
+typedef char           TtiffUndefined;
+typedef signed short   TtiffSShort;
+typedef signed int     TtiffSLong;
+typedef float          TtiffFloat;
+typedef double         TtiffDouble;
+
+typedef struct _TtiffRational
+  {
+  TtiffLong numerator;
+  TtiffLong denominator;
+  } TtiffRational;
+
+typedef struct _TtiffSRational
+  {
+  TtiffSLong numerator;
+  TtiffSLong denominator;
+  } TtiffSRational;
+
+typedef struct _Tapp1
+  {
+  TtiffShort size;
+  } Tapp1;
+
+typedef struct _Tifd
+  {
+  TtiffShort numEntries;
+  } Tifd;
+
+typedef struct _Tentry
+  {
+  TtiffShort tag;
+  TtiffShort type;
+  TtiffLong count;
+  TtiffLong offset;
+  } Tentry;
+
+
+/* EXIF specifics */
+
+/* originally, renamepics had EXIF_JpegBufferStart == 0
+ * in rdjpgcom we make it -6 because we already handle
+ * the marker and length
+ */
+#define EXIF_JpegBufferStart		   -6
+#define EXIF_IdOffset                      (6+EXIF_JpegBufferStart) /* Offset of 'Exif\0\0' */
+#define EXIF_TiffOffset                    (12+EXIF_JpegBufferStart) /* Start of TIFF within EXIF file */
+#define EXIF_NumIfd                        2                  /* EXIF file has IFD 1 and 2 */
+
+#define EXIF_EndOfImage                    ((Tshort)0xffd9)
+#define EXIF_StartOfImage                  ((Tshort)0xffd8)
+#define EXIF_StartOfStream                 ((Tshort)0xffda)
+
+
+/* TIFF file specifics */
+
+#define LONG_SIZE                          sizeof(Tlong)       
+#define SHORT_SIZE                         sizeof(Tshort)       
+#define IFD_ENTRY_SIZE                     ((2 * SHORT_SIZE) + (2 * LONG_SIZE))
+
+
+/* TIFF specifics */
+
+#define TIFF_LONG_SIZE                     sizeof(TtiffLong)
+#define TIFF_SHORT_SIZE                    sizeof(TtiffShort)
+#define TIFF_SLONG_SIZE                    sizeof(TtiffSLong)  
+#define TIFF_SSHORT_SIZE                   sizeof(TtiffSShort)
+
+#define TIFF_UnkownByteOrder               0
+#define TIFF_Intel                         1
+#define TIFF_Motorola                      2
+
+#define TIFF_Byte                          ((Tshort)1)
+#define TIFF_Ascii                         ((Tshort)2)
+#define TIFF_Short                         ((Tshort)3)
+#define TIFF_Long                          ((Tshort)4)
+#define TIFF_Rational                      ((Tshort)5)
+#define TIFF_SByte                         ((Tshort)6)
+#define TIFF_Undefined                     ((Tshort)7)
+#define TIFF_SShort                        ((Tshort)8)
+#define TIFF_SLong                         ((Tshort)9)
+#define TIFF_SRational                     ((Tshort)10)
+#define TIFF_Float                         ((Tshort)11)
+#define TIFF_Double                        ((Tshort)12)
+
+#define TIFF_UNDEFINED                     ((Tshort)0x0)      /* Not any tag, type, or other TIFF structure */
+
+#define TIFF_42                            ((Tshort)0x002a)   /* TIFF file identifier */
+#define TIFF_II                            ((Tshort)0x4949)   /* Intel byte order: 76543210 stored as 10325476 */
+#define TIFF_MM                            ((Tshort)0x4d4d)   /* Motorola byte order: 76543210 stored as 76543210 */
+
+#define TIFF_App0                          ((Tshort)0xffe0)
+#define TIFF_App1                          ((Tshort)0xffe1)
+#define TIFF_App2                          ((Tshort)0xffe2)
+#define TIFF_App3                          ((Tshort)0xffe3)
+#define TIFF_App4                          ((Tshort)0xffe4)
+#define TIFF_App5                          ((Tshort)0xffe5)
+#define TIFF_App6                          ((Tshort)0xffe6)
+#define TIFF_App7                          ((Tshort)0xffe7)
+#define TIFF_App8                          ((Tshort)0xffe8)
+#define TIFF_App9                          ((Tshort)0xffe9)
+#define TIFF_App10                         ((Tshort)0xffea)
+#define TIFF_App11                         ((Tshort)0xffeb)
+#define TIFF_App12                         ((Tshort)0xffec)
+#define TIFF_App13                         ((Tshort)0xffed)
+#define TIFF_App14                         ((Tshort)0xffee)
+#define TIFF_App15                         ((Tshort)0xffef)
+
+#define TIFF_InteroperabilityTag1          ((Tshort)0x1)
+#define TIFF_InteroperabilityTag2          ((Tshort)0x2)
+#define TIFF_NewSubfileType                ((Tshort)0xfe)
+#define TIFF_SubfileType                   ((Tshort)0xff)
+#define TIFF_ImageWidth                    ((Tshort)0x100)
+#define TIFF_ImageLength                   ((Tshort)0x101)
+#define TIFF_BitsPerSample                 ((Tshort)0x102)
+#define TIFF_Compression                   ((Tshort)0x103)
+#define TIFF_PhotometricInterpretation     ((Tshort)0x106)
+#define TIFF_Thresholding                  ((Tshort)0x107)
+#define TIFF_CellWidth                     ((Tshort)0x108)
+#define TIFF_CellLength                    ((Tshort)0x109)
+#define TIFF_FillOrder                     ((Tshort)0x10a)
+#define TIFF_DocumentName                  ((Tshort)0x10d)
+#define TIFF_ImageDescription              ((Tshort)0x10e)
+#define TIFF_Make                          ((Tshort)0x10f)
+#define TIFF_Model                         ((Tshort)0x110)
+#define TIFF_StripOffset                   ((Tshort)0x111)
+#define TIFF_Orientation                   ((Tshort)0x112)
+#define TIFF_SamplesPerPixel               ((Tshort)0x115)
+#define TIFF_RowsPerStrip                  ((Tshort)0x116)
+#define TIFF_StripByteCounts               ((Tshort)0x117)
+#define TIFF_MinSampleValue                ((Tshort)0x118)
+#define TIFF_MaxSampleValue                ((Tshort)0x119)
+#define TIFF_XResolution                   ((Tshort)0x11a)
+#define TIFF_YResolution                   ((Tshort)0x11b)
+#define TIFF_PlanarConfiguration           ((Tshort)0x11c)
+#define TIFF_PageName                      ((Tshort)0x11d)
+#define TIFF_XPosition                     ((Tshort)0x11e)
+#define TIFF_YPosition                     ((Tshort)0x11f)
+#define TIFF_FreeOffsets                   ((Tshort)0x120)
+#define TIFF_FreeByteCounts                ((Tshort)0x121)
+#define TIFF_GrayResponseUnit              ((Tshort)0x122)
+#define TIFF_GrayResponseCurve             ((Tshort)0x123)
+#define TIFF_T4Options                     ((Tshort)0x124)
+#define TIFF_T6Options                     ((Tshort)0x125)
+#define TIFF_ResolutionUnit                ((Tshort)0x128)
+#define TIFF_PageNumber                    ((Tshort)0x129)
+#define TIFF_TransferFunction              ((Tshort)0x12d)
+#define TIFF_Software                      ((Tshort)0x131)
+#define TIFF_DateTime                      ((Tshort)0x132)
+#define TIFF_Artist                        ((Tshort)0x13b)
+#define TIFF_HostComputer                  ((Tshort)0x13c)
+#define TIFF_Predictor                     ((Tshort)0x13d)
+#define TIFF_WhitePoint                    ((Tshort)0x13e)
+#define TIFF_PrimaryChromaticities         ((Tshort)0x13f)
+#define TIFF_ColorMap                      ((Tshort)0x140)
+#define TIFF_HalftoneHints                 ((Tshort)0x141)
+#define TIFF_TileWidth                     ((Tshort)0x142)
+#define TIFF_TileLength                    ((Tshort)0x143)
+#define TIFF_TileOffsets                   ((Tshort)0x144)
+#define TIFF_TileByteCounts                ((Tshort)0x145)
+#define TIFF_InkSet                        ((Tshort)0x14c)
+#define TIFF_InkNames                      ((Tshort)0x14d)
+#define TIFF_NumberOfInks                  ((Tshort)0x14e)
+#define TIFF_DotRange                      ((Tshort)0x150)
+#define TIFF_TargetPrinter                 ((Tshort)0x151)
+#define TIFF_ExtraSamples                  ((Tshort)0x152)
+#define TIFF_SampleFormat                  ((Tshort)0x153)
+#define TIFF_SMinSampleValue               ((Tshort)0x154)
+#define TIFF_SMaxSampleValue               ((Tshort)0x155)
+#define TIFF_TransferRange                 ((Tshort)0x156)
+#define TIFF_JpegTables                    ((Tshort)0x15b)
+#define TIFF_JpegProc                      ((Tshort)0x200)
+#define TIFF_JpegInterchangeFormat         ((Tshort)0x201)
+#define TIFF_JpegInterchangeFormatLength   ((Tshort)0x202)
+#define TIFF_JpegRestartInterval           ((Tshort)0x203)
+#define TIFF_JpegLosslessPredictors        ((Tshort)0x205)
+#define TIFF_JpegPointTransforms           ((Tshort)0x206)
+#define TIFF_JpegQTables                   ((Tshort)0x207)
+#define TIFF_JpegDcTables                  ((Tshort)0x208)
+#define TIFF_JpegAcTables                  ((Tshort)0x209)
+#define TIFF_YCbCrCoefficients             ((Tshort)0x211)
+#define TIFF_YCbCrSubSampling              ((Tshort)0x212)
+#define TIFF_YCbCrPositioning              ((Tshort)0x213)
+#define TIFF_ReferenceBlackWhite           ((Tshort)0x214)
+#define TIFF_CfaRepeatPatternDim           ((Tshort)0x828d)
+#define TIFF_CfaPattern                    ((Tshort)0x828e)
+#define TIFF_BatteryLevel                  ((Tshort)0x828f)
+#define TIFF_Copyright                     ((Tshort)0x8298)
+#define TIFF_ExposureTime                  ((Tshort)0x829a)
+#define TIFF_FNumber                       ((Tshort)0x829d)
+#define TIFF_IptcNaa                       ((Tshort)0x83bb)
+#define TIFF_ExifSubIfdOffset              ((Tshort)0x8769)   /* Offset to EXIF SubIFD */
+#define TIFF_InterColorProfile             ((Tshort)0x8773)
+#define TIFF_ExposureProgram               ((Tshort)0x8822)
+#define TIFF_SpectralSensitivity           ((Tshort)0x8824)
+#define TIFF_GpsInfo                       ((Tshort)0x8825)
+#define TIFF_IsoSpeedRatings               ((Tshort)0x8827)
+#define TIFF_Oecf                          ((Tshort)0x8828)
+#define TIFF_Interlace                     ((Tshort)0x8829)
+#define TIFF_TimeZoneOffset                ((Tshort)0x882a)
+#define TIFF_SelfTimerMode                 ((Tshort)0x882b)
+#define TIFF_ExifVersion                   ((Tshort)0x9000)
+#define TIFF_DateTimeOriginal              ((Tshort)0x9003)
+#define TIFF_DateTimeDigitized             ((Tshort)0x9004)
+#define TIFF_ComponentConfiguration        ((Tshort)0x9101)
+#define TIFF_CompressedBitsPerLevel        ((Tshort)0x9102)   /* CompressedBitsPerPixel */
+#define TIFF_ShutterSpeedValue             ((Tshort)0x9201)
+#define TIFF_ApertureValue                 ((Tshort)0x9202)
+#define TIFF_BrightnessValue               ((Tshort)0x9203)
+#define TIFF_ExposureBiasValue             ((Tshort)0x9204)
+#define TIFF_MaxApertureValue              ((Tshort)0x9205)
+#define TIFF_SubjectDistance               ((Tshort)0x9206)
+#define TIFF_MeteringMode                  ((Tshort)0x9207)
+#define TIFF_LightSource                   ((Tshort)0x9208)
+#define TIFF_Flash                         ((Tshort)0x9209)
+#define TIFF_FocalLength                   ((Tshort)0x920a)
+#define TIFF_FlashEnergy                   ((Tshort)0x920b)
+#define TIFF_SpatialFrequencyResponse      ((Tshort)0x920c)
+#define TIFF_Noise                         ((Tshort)0x920d)
+#define TIFF_ImageNumber                   ((Tshort)0x9211)
+#define TIFF_SecurityClassification        ((Tshort)0x9212)
+#define TIFF_ImageHistory                  ((Tshort)0x9213)
+#define TIFF_SubjectLocation               ((Tshort)0x9214)
+#define TIFF_ExposureIndex                 ((Tshort)0x9215)
+#define TIFF_TiffEpStandardId              ((Tshort)0x9216)
+#define TIFF_MakerNote                     ((Tshort)0x927c)
+#define TIFF_UserComment                   ((Tshort)0x9286)
+#define TIFF_SubSecTime                    ((Tshort)0x9290)
+#define TIFF_SubSecTimeOriginal            ((Tshort)0x9291)
+#define TIFF_SubSecTimeDigitized           ((Tshort)0x9292)
+#define TIFF_FlashPixVersion               ((Tshort)0xa000)
+#define TIFF_ColorSpace                    ((Tshort)0xa001)
+#define TIFF_ExifImageWidth                ((Tshort)0xa002)
+#define TIFF_ExifImageHeight               ((Tshort)0xa003)
+#define TIFF_RelatedSoundFile              ((Tshort)0xa004)
+#define TIFF_ExifInteroperabilityOffset    ((Tshort)0xa005)
+/*
+#define TIFF_FlashEnergy                   ((Tshort)0xa20b)
+#define TIFF_SpatialFrequencyResponse      ((Tshort)0xa20c)
+*/
+#define TIFF_FocalPlaneXResolution         ((Tshort)0xa20e)
+#define TIFF_FocalPlaneYResolution         ((Tshort)0xa20f)
+#define TIFF_FocalPlaneResolutionUnit      ((Tshort)0xa210)
+/*
+#define TIFF_SubjectLocation               ((Tshort)0xa214)
+#define TIFF_ExposureIndex                 ((Tshort)0xa215)
+*/
+#define TIFF_SensingMethod                 ((Tshort)0xa217)
+#define TIFF_FileSource                    ((Tshort)0xa300)
+#define TIFF_SceneType                     ((Tshort)0xa301)
+/*
+#define TIFF_CfaPattern                    ((Tshort)0xa302)
+*/
+
+
+/* Functions */
+
+void dumpEntries ( Tbyte* start, Tbyte* firstentry, Tlong entries, Texif* exif );
+int getOrder ( Tbyte* start );
+int isExif ( Tbyte* start );
+
+int dumpExif ( char* oldName, Tbyte* start, Tbyte* end );
+int exifPhoto ( FILE* file, char* oldName, Tbyte* start, Tbyte* end );
+
+char*       getTiffAscii         ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string );
+TtiffLong*  getTiffLong          ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, TtiffLong* val );
+char*       getTiffRational      ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string );
+char*       getTiffRational2     ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string );
+TtiffShort* getTiffShort         ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, TtiffShort* val );
+char*       getTiffSRational     ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* string );
+char*       getTiffUndefined     ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, char* string );
+char*       getTiffUnknownFormat ( int byteOrder, Tbyte* tiff, Tbyte* entry, Tlong* count, char* string );
+
+Tlong       getLong    ( Tbyte* p, int byteOrder );
+Tshort      getShort   ( Tbyte* p, int byteOrder );
+TtiffLong   tifflong   ( Tbyte* p, int byteOrder );
+TtiffShort  tiffShort  ( Tbyte* p, int byteOrder );
+TtiffSLong  tiffSLong  ( Tbyte* p, int byteOrder );
+TtiffSShort tiffSShort ( Tbyte* p, int byteOrder );
+
+char* getApertureValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getArtist ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getBatteryLevel ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getBitsPerSample ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getBrightnessValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getCellLength ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getCellWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getCfaPattern ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getCfaRepeatPatternDim ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getColorMap ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getColorSpace ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* color );
+char* getComponentConfiguration ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* config );
+char* getCompressedBitsPerLevel ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* compressed );
+char* getCompression ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* compression );
+char* getCopyright ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getDateTime ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* dateTime );
+char* getDateTimeDigitized ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* dateTime );
+char* getDateTimeOriginal ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* dateTime );
+char* getDocumentName ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getDotRange ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getExifImageHeight ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* height );
+char* getExifImageWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* width );
+char* getExifVersion ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* version );
+char* getExposureBiasValue ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* bias );
+char* getExposureIndex ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getExposureProgram ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* prog );
+char* getExposureTime ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* time );
+char* getExtraSamples ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getFNumber ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* fstop );
+char* getFileSource ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* source );
+char* getFillOrder ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getFlash ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* flash );
+char* getFlashEnergy ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getFlashPixVersion ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* version );
+char* getFocalLength ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* length );
+char* getFocalPlaneResolutionUnit ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* unit );
+char* getFocalPlaneXResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution );
+char* getFocalPlaneYResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution );
+char* getFreeByteCounts ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getFreeOffsets ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getGpsInfo ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getGrayResponseCurve ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getGrayResponseUnit ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getHalftoneHints ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getHostComputer ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getImageDescription ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* description );
+char* getImageHistory ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getImageLength ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getImageNumber ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getImageWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getInkNames ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getInkSet ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getInterColorProfile ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getInterlace ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getInteroperabilityTag1 ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* value );
+char* getInteroperabilityTag2 ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* value );
+char* getIptcNaa ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getIsoSpeedRatings ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* iso );
+char* getJpegAcTables ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegDcTables ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegLosslessPredictors ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegPointTransforms ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegProc ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegQTables ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegRestartInterval ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getJpegTables ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getLightSource ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* balance );
+char* getMake ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* make );
+char* getMaxApertureValue ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* aperture );
+char* getMaxSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getMeteringMode ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* mode );
+char* getMinSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getModel ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* model );
+char* getNewSubfileType ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getNoise ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getNumberOfInks ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getOecf ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getOrientation ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* orientation );
+char* getPageName ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getPageNumber ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getPhotometricInterpretation ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getPlanarConfiguration ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getPredictor ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getPrimaryChromaticities ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getReferenceBlackWhite ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getRelatedSoundFile ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getResolutionUnit ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* unit );
+char* getRowsPerStrip ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSMaxSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSMinSampleValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSampleFormat ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSamplesPerPixel ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSceneType ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* type );
+char* getSecurityClassification ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSelfTimerMode ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSensingMethod ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getShutterSpeedValue ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSoftware ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* software );
+char* getSpatialFrequencyResponse ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSpectralSensitivity ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getStripByteCounts ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getStripOffset ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSubSecTime ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSubSecTimeDigitized ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSubSecTimeOriginal ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSubfileType ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSubjectDistance ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getSubjectLocation ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getT4Options ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getT6Options ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTargetPrinter ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getThresholding ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTiffEpStandardId ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTileByteCounts ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTileLength ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTileOffsets ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTileWidth ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTimeZoneOffset ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTransferFunction ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getTransferRange ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getUserComment ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* comment );
+char* getWhitePoint ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getXPosition ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getXResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution );
+char* getYCbCrCoefficients ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getYCbCrPositioning ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* position );
+char* getYCbCrSubSampling ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getYPosition ( int byteOrder, Tbyte* tiff, Tbyte* entry );
+char* getYResolution ( int byteOrder, Tbyte* tiff, Tbyte* entry, char* resolution );
+
+
+#endif
+
--- makefile.cfg-	Sat Mar 21 11:08:57 1998
+++ makefile.cfg	Sun Aug 20 18:14:54 2000
@@ -84,7 +84,7 @@
 # memmgr back ends: compile only one of these into a working library
 SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c
 # source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom
-APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \
+APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c exif.c wrjpgcom.c cdjpeg.c \
         rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \
         rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c
 SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES)
@@ -182,8 +182,8 @@
 jpegtran: $(TROBJECTS) libjpeg.$(A)
 	$(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.$(A) $(LDLIBS)
 
-rdjpgcom: rdjpgcom.$(O)
-	$(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.$(O) $(LDLIBS)
+rdjpgcom: rdjpgcom.$(O) exif.$(O)
+	$(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.$(O) exif.$(O) $(LDLIBS)
 
 wrjpgcom: wrjpgcom.$(O)
 	$(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.$(O) $(LDLIBS)
--- rdjpgcom.c-	Sat Oct 11 15:41:04 1997
+++ rdjpgcom.c	Sun Aug 20 18:25:34 2000
@@ -120,6 +120,7 @@
 #define M_EOI   0xD9		/* End Of Image (end of datastream) */
 #define M_SOS   0xDA		/* Start Of Scan (begins compressed data) */
 #define M_APP0	0xE0		/* Application-specific marker, type N */
+#define M_APP1	0xE1
 #define M_APP12	0xEC		/* (we don't bother to list all 16 APPn's) */
 #define M_COM   0xFE		/* COMment */
 
@@ -210,6 +211,42 @@
   }
 }
 
+/*
+ * APP1 w/exif
+ */
+static void
+process_APP1(int verbose)
+{
+	typedef unsigned char Tbyte;
+	extern int isExif ( Tbyte* start );
+	extern int dumpExif ( char* oldName, Tbyte* start, Tbyte* end );
+	unsigned int length;
+	char *buf = NULL;
+	char *p;
+
+	/* Get the marker parameter length count */
+	length = read_2_bytes();
+	/* Length includes itself, so must be at least 2 */
+	if (length < 2)
+		ERREXIT("Erroneous JPEG marker length");
+	length -= 2;
+	/* get the whole record */
+	buf = malloc(length);
+	if (!buf)
+		ERREXIT("Cannot allocate space for APP1 buffer.");
+	/* lame read loop... */
+	for (p = buf; length; length--)
+		*p++ = read_1_byte();
+
+	if (!isExif(buf)) {
+		if (verbose)
+			printf("APP1 record but not Exif format.\n");
+		return;
+	};
+	dumpExif("file", buf, p - 1);
+}
+
+
 
 /*
  * Process a COM marker.
@@ -332,6 +369,8 @@
   /* Scan miscellaneous markers until we reach SOS. */
   for (;;) {
     marker = next_marker();
+    if (verbose > 1)
+	    printf("marker: %x\n", marker);
     switch (marker) {
       /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
        * treated as SOFn.  C4 in particular is actually DHT.
@@ -365,6 +404,12 @@
       process_COM();
       break;
 
+    case M_APP1:
+	    /* handle Exif format entries */
+	    if (verbose)
+		    process_APP1(verbose);
+	    else skip_variable();
+	    break;
     case M_APP12:
       /* Some digital camera makers put useful textual information into
        * APP12 markers, so we print those out too when in -verbose mode.
