From 2914ecfd560f615120685e5d151dd0628d34b7b2 Mon Sep 17 00:00:00 2001 From: James Zern Date: Sat, 15 Dec 2012 19:41:03 -0800 Subject: [PATCH] cwebp/tiffdec: add TIFF metadata extraction currently the values of XMP/ICC are unused and EXIF is ignored. Change-Id: I1d8b73bde4db2768f117158f986aadbaaec45804 --- examples/cwebp.c | 2 +- examples/tiffdec.c | 62 +++++++++++++++++++++++++++++++++++++++++++--- examples/tiffdec.h | 4 ++- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/examples/cwebp.c b/examples/cwebp.c index 745380d4..507416e0 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -334,7 +334,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic, } else if (format == JPEG_) { ok = ReadJPEG(in_file, pic); } else if (format == TIFF_) { - ok = ReadTIFF(filename, pic, keep_alpha); + ok = ReadTIFF(filename, pic, keep_alpha, metadata); } } else { // If image size is specified, infer it as YUV format. diff --git a/examples/tiffdec.c b/examples/tiffdec.c index c93be49a..6528a8ae 100644 --- a/examples/tiffdec.c +++ b/examples/tiffdec.c @@ -19,9 +19,51 @@ #include #include "webp/encode.h" +#include "./metadata.h" + +static const struct { + ttag_t tag; + size_t storage_offset; +} kTIFFMetadataMap[] = { + { TIFFTAG_ICCPROFILE, METADATA_OFFSET(iccp) }, + { TIFFTAG_XMLPACKET, METADATA_OFFSET(xmp) }, + { 0, 0 }, +}; + +// Returns true on success. The caller must use MetadataFree() on 'metadata' in +// all cases. +static int ExtractMetadataFromTIFF(TIFF* const tif, Metadata* const metadata) { + int i; + uint32 exif_ifd_offset; + + for (i = 0; kTIFFMetadataMap[i].tag != 0; ++i) { + MetadataPayload* const payload = + (MetadataPayload*)((uint8_t*)metadata + + kTIFFMetadataMap[i].storage_offset); + void* tag_data; + uint32 tag_data_len; + + if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) && + !MetadataCopy((const char*)tag_data, tag_data_len, payload)) { + return 0; + } + } + + // TODO(jzern): To extract the raw EXIF directory some parsing of it would be + // necessary to determine the overall size. In addition, value offsets in + // individual directory entries may need to be updated as, depending on the + // type, they are file based. + // Exif 2.2 Section 4.6.2 Tag Structure + // TIFF Revision 6.0 Part 1 Section 2 TIFF Structure #Image File Directory + if (TIFFGetField(tif, TIFFTAG_EXIFIFD, &exif_ifd_offset)) { + fprintf(stderr, "Warning: EXIF extraction from TIFF is unsupported.\n"); + } + return 1; +} int ReadTIFF(const char* const filename, - WebPPicture* const pic, int keep_alpha) { + WebPPicture* const pic, int keep_alpha, + Metadata* const metadata) { TIFF* const tif = TIFFOpen(filename, "r"); uint32 width, height; uint32* raster; @@ -63,8 +105,18 @@ int ReadTIFF(const char* const filename, fprintf(stderr, "Error allocating TIFF RGBA memory!\n"); } - if (ok && keep_alpha == 2) { - WebPCleanupTransparentArea(pic); + if (ok) { + if (keep_alpha == 2) { + WebPCleanupTransparentArea(pic); + } + if (metadata != NULL) { + ok = ExtractMetadataFromTIFF(tif, metadata); + if (!ok) { + fprintf(stderr, "Error extracting TIFF metadata!\n"); + MetadataFree(metadata); + WebPPictureFree(pic); + } + } } TIFFClose(tif); @@ -72,10 +124,12 @@ int ReadTIFF(const char* const filename, } #else // !WEBP_HAVE_TIFF int ReadTIFF(const char* const filename, - struct WebPPicture* const pic, int keep_alpha) { + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata) { (void)filename; (void)pic; (void)keep_alpha; + (void)metadata; fprintf(stderr, "TIFF support not compiled. Please install the libtiff " "development package before building.\n"); return 0; diff --git a/examples/tiffdec.h b/examples/tiffdec.h index 1f0a7b2a..f441d5e0 100644 --- a/examples/tiffdec.h +++ b/examples/tiffdec.h @@ -14,6 +14,7 @@ extern "C" { #endif +struct Metadata; struct WebPPicture; // Reads a TIFF from 'filename', returning the decoded output in 'pic'. @@ -21,7 +22,8 @@ struct WebPPicture; // otherwise it will be RGB. // Returns true on success. int ReadTIFF(const char* const filename, - struct WebPPicture* const pic, int keep_alpha); + struct WebPPicture* const pic, int keep_alpha, + struct Metadata* const metadata); #if defined(__cplusplus) || defined(c_plusplus) } // extern "C"