Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support extracting thumbnail data #149

Open
guigri opened this issue Feb 20, 2016 · 7 comments
Open

Support extracting thumbnail data #149

guigri opened this issue Feb 20, 2016 · 7 comments
Milestone

Comments

@guigri
Copy link

guigri commented Feb 20, 2016

Dear Drew,

it is possible to extract thumbnail images from a Canon EOS 450D raw image file (CR2) using an old version 2.6.2 of metadata-extractor:

Metadata localMetadata = ImageMetadataReader.readMetadata(new File("<path to CR2 file>"));
ExifThumbnailDirectory myExifThumbnailDirectory;
myExifThumbnailDirectory = localMetadata.getDirectory(ExifThumbnailDirectory.class);
myExifThumbnailDirectory.hasThumbnailData(); // ---> returns true

Apparently, this does not work any more with version 2.8.1 of metadata-extractor.

Metadata localMetadata = ImageMetadataReader.readMetadata(new File("<path to CR2 file>"));
ExifThumbnailDirectory myExifThumbnailDirectory;
myExifThumbnailDirectory = localMetadata.getFirstDirectoryOfType(ExifThumbnailDirectory.class);
myExifThumbnailDirectory.hasThumbnailData(); // ---> returns false !!!

myExifThumbnailDirectory.getString(ExifThumbnailDirectory.TAG_THUMBNAIL_COMPRESSION));
does work on the same file (returns 6), for example.

Do I make any mistake?

I can provide an example image file if necessary.

Thank you.

Best wishes,
Guido

@guigri guigri changed the title Can not extract thumbnail image from Cannon raw file (CR 2) using version 2.8.1 Can not extract thumbnail image from Canon raw file (CR 2) using version 2.8.1 Feb 20, 2016
@kwhopper
Copy link
Collaborator

CR2 is read using TiffMetadataReader, which ends up using ExifTiffHandler. For some reason, the second argument to the ExifTiffHandler constructor (storeThumbnailBytes) is explictly set to false. ExifReader also uses ExifTiffHandler, but has a property (StoreThumbnailBytes) that is passed through.

Drew will have to comment. Perhaps TiffMetadataReader does this on purpose, or was accidentally not completed. If it was accidental, it is easily fixed.

@drewnoakes
Copy link
Owner

@kwhopper is correct.

If you know you're decoding a TIFF file (i.e. CR2) then you could just use
the TiffMetadataReader class directly and pass 'true' for
storeThumbnailBytes.

I'm happy for the default to be changed. I expect most users don't use
thumbnail images so it seems wasteful to allocate them in the default case.
Perhaps a better idea is to allow this setting to be passed in (optionally)
to ImageMetadataReader and propagated to sub-readers that support thumbnail
extraction.

On 17 March 2016 at 21:52, kwhopper [email protected] wrote:

CR2 is read using TiffMetadataReader, which ends up using ExifTiffHandler.
For some reason, the second argument to the ExifTiffHandler constructor
(storeThumbnailBytes) is explictly set to false. ExifReader also uses
ExifTiffHandler, but has a property (StoreThumbnailBytes) that is passed
through.

Drew will have to comment. Perhaps TiffMetadataReader does this on
purpose, or was accidentally not completed. If it was accidental, it is
easily fixed.


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
#149 (comment)

@drewnoakes
Copy link
Owner

Given your sample code, would it be suitable to have code such as this?

File file = new File("<path to CR2 file>");
Metadata meta = ImageMetadataReader.readMetadata(file);
ExifThumbnailDirectory dir = meta.getDirectory(ExifThumbnailDirectory.class);
if (dir.hasThumbnail()) {
    byte[] thumbnailData = dir.getThumbnail(file); // pass 'file' again (or a seekable stream)
    // use bytes
}

If you're working with files, this should be fine. However if you were consuming data from a non-seekable stream (maybe over a network) then it wouldn't be suitable. However I expect it'd cover the majority of use cases and be simple to implement.

@guigri
Copy link
Author

guigri commented May 14, 2016

...thanks guys for your comments.

@drew: I am working with files and your code is suitable. There is no getDirectory(...) method in Metadata today, so I guess your code is a suggestion for changing the library?

I have no idea about how many people do need to access thumbnails and whether it is worth to introduce a specific handling. However, a clean approach to handle this is probably kwhoppers suggestion to pass some kind of flag "considerThumbnailData" through the methods. In this case classes ImageMetaDataReader, Metadata and TiffMetadataReader might have alternative methods readMetadata(...) with an additional boolean parameter, for example.

@sschloen
Copy link

This thumbnail extraction from CR2 files feature is one of the main reasons we are using this library and we are eager to see this fixed. Your suggestion above which you state you expect would cover the majority of cases and be simple to implement would certainly work for us. We've had to revert to 2.6.2. in the meantime. Thanks!

@drewnoakes drewnoakes added this to the 2.10 milestone Mar 31, 2017
@drewnoakes drewnoakes changed the title Can not extract thumbnail image from Canon raw file (CR 2) using version 2.8.1 Support extracting thumbnail data Mar 31, 2017
@drewnoakes drewnoakes modified the milestones: 2.10, 2.11 Mar 31, 2017
@haumacher
Copy link

haumacher commented Aug 13, 2019

The second thing I tried with this library is getting the thumbnail data and cannot find a solution. It is perfectly OK not to store the thumbnail data in the metadata, offset and lenth are great. Unfortunately, the following does not work - as I understand, because the offset is not (or not always) the offest from the beginning of the file:

File file = ...;
Metadata metadata = ImageMetadataReader.readMetadata(file);

ExifThumbnailDirectory tn = metadata.getFirstDirectoryOfType(ExifThumbnailDirectory.class);
long offset = tn.getLong(ExifThumbnailDirectory.TAG_THUMBNAIL_OFFSET);
int length = tn.getInt(ExifThumbnailDirectory.TAG_THUMBNAIL_LENGTH);
try (RandomAccessFile handle = new RandomAccessFile(file, "r")) {
   handle.seek(offset);
   byte[] buffer = new byte[length];
   handle.readFully(buffer);

   try (FileOutputStream out = new FileOutputStream(new File("tn.jpg"))) {
      out.write(buffer);
   }
}

How do I compute the correct offset?

@haumacher
Copy link

There is a workaround that dynamically patches the library to store thumbnail data in the ExifThumbnailDirectory as explained in #276 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants