diff -Naur org/apache/tika/parser/image/ImageMetadataExtractor.java org/apache/tika/parser/image/ImageMetadataExtractor.java
--- org/apache/tika/parser/image/ImageMetadataExtractor.java	2012-07-10 12:01:58.000000000 +0200
+++ org/apache/tika/parser/image/ImageMetadataExtractor.java	2012-09-21 14:43:57.346650852 +0200
@@ -37,6 +37,7 @@
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.xml.sax.SAXException;
 
+import com.drew.imaging.jpeg.JpegMetadataReader;
 import com.drew.imaging.jpeg.JpegProcessingException;
 import com.drew.imaging.jpeg.JpegSegmentReader;
 import com.drew.imaging.tiff.TiffMetadataReader;
@@ -46,8 +47,10 @@
 import com.drew.metadata.MetadataException;
 import com.drew.metadata.MetadataReader;
 import com.drew.metadata.Tag;
-import com.drew.metadata.exif.ExifDirectory;
+import com.drew.metadata.exif.ExifIFD0Directory;
 import com.drew.metadata.exif.ExifReader;
+import com.drew.metadata.exif.ExifSubIFDDirectory;
+import com.drew.metadata.exif.ExifThumbnailDirectory;
 import com.drew.metadata.exif.GpsDirectory;
 import com.drew.metadata.iptc.IptcDirectory;
 import com.drew.metadata.iptc.IptcReader;
@@ -111,19 +114,12 @@
             JpegSegmentReader reader, byte marker,
             Class<? extends MetadataReader> klass) {
         try {
-            Constructor<? extends MetadataReader> constructor =
-                    klass.getConstructor(byte[].class);
 
-            int n = reader.getSegmentCount(marker);
-            for (int i = 0; i < n; i++) {
-                byte[] segment = reader.readSegment(marker, i);
-
-                com.drew.metadata.Metadata metadata =
-                        new com.drew.metadata.Metadata();
-                constructor.newInstance(segment).extract(metadata);
 
-                handle(metadata);
-            }
+            com.drew.metadata.Metadata metadata = JpegMetadataReader.extractMetadataFromJpegSegmentReader(reader.getSegmentData());
+                    new com.drew.metadata.Metadata();
+
+            handle(metadata);
         } catch (Exception e) {
             // Unable to read this kind of metadata, so skip
         }
@@ -133,11 +129,9 @@
             throws IOException, SAXException, TikaException {
         try {
             com.drew.metadata.Metadata tiffMetadata =
-                TiffMetadataReader.readMetadata(stream);
+                TiffMetadataReader.readMetadata(stream, false);
 
             handle(tiffMetadata);
-        } catch (TiffProcessingException e) {
-            throw new TikaException("Can't read TIFF metadata", e);
         } catch (MetadataException e) {
             throw new TikaException("Can't read TIFF metadata", e);
         }
@@ -151,7 +145,7 @@
     @SuppressWarnings("unchecked")
     protected void handle(com.drew.metadata.Metadata metadataExtractor) 
             throws MetadataException {
-        handle(metadataExtractor.getDirectoryIterator());
+        handle(metadataExtractor.getDirectories().iterator());
     }
 
     /**
@@ -198,7 +192,7 @@
         }
         public void handle(Directory directory, Metadata metadata)
                 throws MetadataException {
-            Iterator<?> tags = directory.getTagIterator();
+            Iterator<?> tags = directory.getTags().iterator();
             while (tags.hasNext()) {
                 Tag tag = (Tag) tags.next();
                 metadata.set(tag.getTagName(), tag.getDescription());
@@ -217,23 +211,18 @@
         }
         public void handle(Directory directory, Metadata metadata)
                 throws MetadataException {
-            Iterator<?> tags = directory.getTagIterator();
+            Iterator<?> tags = directory.getTags().iterator();
             while (tags.hasNext()) {
                 Tag tag = (Tag) tags.next();
                 String name = tag.getTagName();
                 if (!MetadataFields.isMetadataField(name)) {
-                   try {
-                      String value = tag.getDescription().trim();
-                      if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
-                          value = Boolean.TRUE.toString();
-                      } else if (Boolean.FALSE.toString().equalsIgnoreCase(value)) {
-                          value = Boolean.FALSE.toString();
-                      }
-                      metadata.set(name, value);
-                   } catch(MetadataException e) {
-                      // Either something's corrupt, or it's a JPEG tag
-                      //  that the library doesn't know about. Skip it
+                   String value = tag.getDescription().trim();
+                   if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
+                       value = Boolean.TRUE.toString();
+                   } else if (Boolean.FALSE.toString().equalsIgnoreCase(value)) {
+                       value = Boolean.FALSE.toString();
                    }
+                   metadata.set(name, value);
                 }
             }
         }
@@ -245,22 +234,22 @@
     static class DimensionsHandler implements DirectoryHandler {
         private final Pattern LEADING_NUMBERS = Pattern.compile("(\\d+)\\s*.*");
         public boolean supports(Class<? extends Directory> directoryType) {
-            return directoryType == JpegDirectory.class || directoryType == ExifDirectory.class;
+            return directoryType == JpegDirectory.class || directoryType == ExifThumbnailDirectory.class;
         }
         public void handle(Directory directory, Metadata metadata) throws MetadataException {
             // The test TIFF has width and height stored as follows according to exiv2
             //Exif.Image.ImageWidth                        Short       1  100
             //Exif.Image.ImageLength                       Short       1  75
             // and the values are found in "Thumbnail Image Width" (and Height) from Metadata Extractor
-            set(directory, metadata, ExifDirectory.TAG_THUMBNAIL_IMAGE_WIDTH, Metadata.IMAGE_WIDTH);
+            set(directory, metadata, ExifThumbnailDirectory.TAG_THUMBNAIL_IMAGE_WIDTH, Metadata.IMAGE_WIDTH);
             set(directory, metadata, JpegDirectory.TAG_JPEG_IMAGE_WIDTH, Metadata.IMAGE_WIDTH);
-            set(directory, metadata, ExifDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT, Metadata.IMAGE_LENGTH);
+            set(directory, metadata, ExifThumbnailDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT, Metadata.IMAGE_LENGTH);
             set(directory, metadata, JpegDirectory.TAG_JPEG_IMAGE_HEIGHT, Metadata.IMAGE_LENGTH);
             // Bits per sample, two methods of extracting, exif overrides jpeg
             set(directory, metadata, JpegDirectory.TAG_JPEG_DATA_PRECISION, Metadata.BITS_PER_SAMPLE);
-            set(directory, metadata, ExifDirectory.TAG_BITS_PER_SAMPLE, Metadata.BITS_PER_SAMPLE);
+            set(directory, metadata, ExifThumbnailDirectory.TAG_BITS_PER_SAMPLE, Metadata.BITS_PER_SAMPLE);
             // Straightforward
-            set(directory, metadata, ExifDirectory.TAG_SAMPLES_PER_PIXEL, Metadata.SAMPLES_PER_PIXEL);
+            set(directory, metadata, ExifThumbnailDirectory.TAG_SAMPLES_PER_PIXEL, Metadata.SAMPLES_PER_PIXEL);
         }
         private void set(Directory directory, Metadata metadata, int extractTag, Property metadataField) {
             if (directory.containsTag(extractTag)) {
@@ -286,7 +275,7 @@
     static class ExifHandler implements DirectoryHandler {
         private static final SimpleDateFormat DATE_UNSPECIFIED_TZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
         public boolean supports(Class<? extends Directory> directoryType) {
-            return directoryType == ExifDirectory.class;
+            return directoryType == ExifIFD0Directory.class || directoryType == ExifSubIFDDirectory.class;
         }
         public void handle(Directory directory, Metadata metadata) {
             try {
@@ -303,8 +292,8 @@
          */
         public void handleCommentTags(Directory directory, Metadata metadata) {
             if (metadata.get(TikaCoreProperties.DESCRIPTION) == null &&
-                    directory.containsTag(ExifDirectory.TAG_IMAGE_DESCRIPTION)) {
-                metadata.set(TikaCoreProperties.DESCRIPTION, directory.getString(ExifDirectory.TAG_IMAGE_DESCRIPTION));
+                    directory.containsTag(ExifIFD0Directory.TAG_IMAGE_DESCRIPTION)) {
+                metadata.set(TikaCoreProperties.DESCRIPTION, directory.getString(ExifIFD0Directory.TAG_IMAGE_DESCRIPTION));
             }
         }
         /**
@@ -312,22 +301,18 @@
          *  TIFF image metadata namespace.
          */       
         public void handlePhotoTags(Directory directory, Metadata metadata) {
-            if(directory.containsTag(ExifDirectory.TAG_EXPOSURE_TIME)) {
-               Object exposure = directory.getObject(ExifDirectory.TAG_EXPOSURE_TIME);
+            if(directory.containsTag(ExifSubIFDDirectory.TAG_EXPOSURE_TIME)) {
+               Object exposure = directory.getObject(ExifSubIFDDirectory.TAG_EXPOSURE_TIME);
                if(exposure instanceof Rational) {
                   metadata.set(Metadata.EXPOSURE_TIME, ((Rational)exposure).doubleValue());
                } else {
-                  metadata.set(Metadata.EXPOSURE_TIME, directory.getString(ExifDirectory.TAG_EXPOSURE_TIME));
+                  metadata.set(Metadata.EXPOSURE_TIME, directory.getString(ExifSubIFDDirectory.TAG_EXPOSURE_TIME));
                }
             }
             
-            if(directory.containsTag(ExifDirectory.TAG_FLASH)) {
+            if(directory.containsTag(ExifSubIFDDirectory.TAG_FLASH)) {
                String flash = "";
-               try {
-                  flash = directory.getDescription(ExifDirectory.TAG_FLASH);
-               } catch (MetadataException e) {
-                  // ignore
-               }
+               flash = directory.getDescription(ExifSubIFDDirectory.TAG_FLASH);
                if(flash.indexOf("Flash fired") > -1) {
                   metadata.set(Metadata.FLASH_FIRED, Boolean.TRUE.toString());
                }
@@ -339,70 +324,66 @@
                }
             }
 
-            if(directory.containsTag(ExifDirectory.TAG_FNUMBER)) {
-               Object fnumber = directory.getObject(ExifDirectory.TAG_FNUMBER);
+            if(directory.containsTag(ExifSubIFDDirectory.TAG_FNUMBER)) {
+               Object fnumber = directory.getObject(ExifSubIFDDirectory.TAG_FNUMBER);
                if(fnumber instanceof Rational) {
                   metadata.set(Metadata.F_NUMBER, ((Rational)fnumber).doubleValue());
                } else {
-                  metadata.set(Metadata.F_NUMBER, directory.getString(ExifDirectory.TAG_FNUMBER));
+                  metadata.set(Metadata.F_NUMBER, directory.getString(ExifSubIFDDirectory.TAG_FNUMBER));
                }
             }
             
-            if(directory.containsTag(ExifDirectory.TAG_FOCAL_LENGTH)) {
-               Object length = directory.getObject(ExifDirectory.TAG_FOCAL_LENGTH);
+            if(directory.containsTag(ExifSubIFDDirectory.TAG_FOCAL_LENGTH)) {
+               Object length = directory.getObject(ExifSubIFDDirectory.TAG_FOCAL_LENGTH);
                if(length instanceof Rational) {
                   metadata.set(Metadata.FOCAL_LENGTH, ((Rational)length).doubleValue());
                } else {
-                  metadata.set(Metadata.FOCAL_LENGTH, directory.getString(ExifDirectory.TAG_FOCAL_LENGTH));
+                  metadata.set(Metadata.FOCAL_LENGTH, directory.getString(ExifSubIFDDirectory.TAG_FOCAL_LENGTH));
                }
             }
             
-            if(directory.containsTag(ExifDirectory.TAG_ISO_EQUIVALENT)) {
-               metadata.set(Metadata.ISO_SPEED_RATINGS, directory.getString(ExifDirectory.TAG_ISO_EQUIVALENT));
+            if(directory.containsTag(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT)) {
+               metadata.set(Metadata.ISO_SPEED_RATINGS, directory.getString(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT));
             }
           
-            if(directory.containsTag(ExifDirectory.TAG_MAKE)) {
-               metadata.set(Metadata.EQUIPMENT_MAKE, directory.getString(ExifDirectory.TAG_MAKE));
+            if(directory.containsTag(ExifIFD0Directory.TAG_MAKE)) {
+               metadata.set(Metadata.EQUIPMENT_MAKE, directory.getString(ExifIFD0Directory.TAG_MAKE));
             }
-            if(directory.containsTag(ExifDirectory.TAG_MODEL)) {
-               metadata.set(Metadata.EQUIPMENT_MODEL, directory.getString(ExifDirectory.TAG_MODEL));
+            if(directory.containsTag(ExifIFD0Directory.TAG_MODEL)) {
+               metadata.set(Metadata.EQUIPMENT_MODEL, directory.getString(ExifIFD0Directory.TAG_MODEL));
             }
           
-            if(directory.containsTag(ExifDirectory.TAG_ORIENTATION)) {
-               Object length = directory.getObject(ExifDirectory.TAG_ORIENTATION);
+            if(directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+               Object length = directory.getObject(ExifIFD0Directory.TAG_ORIENTATION);
                if(length instanceof Integer) {
                   metadata.set(Metadata.ORIENTATION, Integer.toString( ((Integer)length).intValue() ));
                } else {
-                  metadata.set(Metadata.ORIENTATION, directory.getString(ExifDirectory.TAG_ORIENTATION));
+                  metadata.set(Metadata.ORIENTATION, directory.getString(ExifIFD0Directory.TAG_ORIENTATION));
                }
             }
             
-            if(directory.containsTag(ExifDirectory.TAG_SOFTWARE)) {
-               metadata.set(Metadata.SOFTWARE, directory.getString(ExifDirectory.TAG_SOFTWARE));
+            if(directory.containsTag(ExifIFD0Directory.TAG_SOFTWARE)) {
+               metadata.set(Metadata.SOFTWARE, directory.getString(ExifIFD0Directory.TAG_SOFTWARE));
             }
             
-            if(directory.containsTag(ExifDirectory.TAG_X_RESOLUTION)) {
-               Object resolution = directory.getObject(ExifDirectory.TAG_X_RESOLUTION);
+            if(directory.containsTag(ExifIFD0Directory.TAG_X_RESOLUTION)) {
+               Object resolution = directory.getObject(ExifIFD0Directory.TAG_X_RESOLUTION);
                if(resolution instanceof Rational) {
                   metadata.set(Metadata.RESOLUTION_HORIZONTAL, ((Rational)resolution).doubleValue());
                } else {
-                  metadata.set(Metadata.RESOLUTION_HORIZONTAL, directory.getString(ExifDirectory.TAG_X_RESOLUTION));
+                  metadata.set(Metadata.RESOLUTION_HORIZONTAL, directory.getString(ExifIFD0Directory.TAG_X_RESOLUTION));
                }
             }
-            if(directory.containsTag(ExifDirectory.TAG_Y_RESOLUTION)) {
-               Object resolution = directory.getObject(ExifDirectory.TAG_Y_RESOLUTION);
+            if(directory.containsTag(ExifIFD0Directory.TAG_Y_RESOLUTION)) {
+               Object resolution = directory.getObject(ExifIFD0Directory.TAG_Y_RESOLUTION);
                if(resolution instanceof Rational) {
                   metadata.set(Metadata.RESOLUTION_VERTICAL, ((Rational)resolution).doubleValue());
                } else {
-                  metadata.set(Metadata.RESOLUTION_VERTICAL, directory.getString(ExifDirectory.TAG_Y_RESOLUTION));
+                  metadata.set(Metadata.RESOLUTION_VERTICAL, directory.getString(ExifIFD0Directory.TAG_Y_RESOLUTION));
                }
             }
-            if(directory.containsTag(ExifDirectory.TAG_RESOLUTION_UNIT)) {
-               try {
-                  metadata.set(Metadata.RESOLUTION_UNIT, directory.getDescription(ExifDirectory.TAG_RESOLUTION_UNIT));
-               } catch (MetadataException e) {
-                  // ignore
-               }
+            if(directory.containsTag(ExifIFD0Directory.TAG_RESOLUTION_UNIT)) {
+               metadata.set(Metadata.RESOLUTION_UNIT, directory.getDescription(ExifIFD0Directory.TAG_RESOLUTION_UNIT));
             }
         }
         /**
@@ -412,16 +393,16 @@
                 throws MetadataException {
             // Date/Time Original overrides value from ExifDirectory.TAG_DATETIME
             Date original = null;
-            if (directory.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
-                original = directory.getDate(ExifDirectory.TAG_DATETIME_ORIGINAL);
+            if (directory.containsTag(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL)) {
+                original = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
                 // Unless we have GPS time we don't know the time zone so date must be set
                 // as ISO 8601 datetime without timezone suffix (no Z or +/-)
                 String datetimeNoTimeZone = DATE_UNSPECIFIED_TZ.format(original); // Same time zone as Metadata Extractor uses
                 metadata.set(TikaCoreProperties.CREATED, datetimeNoTimeZone);
                 metadata.set(Metadata.ORIGINAL_DATE, datetimeNoTimeZone);
             }
-            if (directory.containsTag(ExifDirectory.TAG_DATETIME)) {
-                Date datetime = directory.getDate(ExifDirectory.TAG_DATETIME);
+            if (directory.containsTag(ExifIFD0Directory.TAG_DATETIME)) {
+                Date datetime = directory.getDate(ExifIFD0Directory.TAG_DATETIME);
                 String datetimeNoTimeZone = DATE_UNSPECIFIED_TZ.format(datetime);
                 metadata.set(TikaCoreProperties.MODIFIED, datetimeNoTimeZone);
                 // If Date/Time Original does not exist this might be creation date
