/* This file is part of libextractor. Copyright (C) 2012 Christian Grothoff libextractor is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. libextractor is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with libextractor; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * @file plugins/tiff_extractor.c * @brief plugin to support TIFF files * @author Christian Grothoff */ #include "platform.h" #include "extractor.h" #include /** * Error handler for libtiff. Does nothing. * * @param module where did the error arise? * @param fmt format string * @param ap arguments for fmt */ static void error_cb (const char *module, const char *fmt, va_list ap) { /* do nothing */ } /** * Callback invoked by TIFF lib for reading. * * @param ctx the 'struct EXTRACTOR_ExtractContext' * @param data where to write data * @param size number of bytes to read * @return number of bytes read */ static tsize_t read_cb (thandle_t ctx, tdata_t data, tsize_t size) { struct EXTRACTOR_ExtractContext *ec = ctx; void *ptr; ssize_t ret; ret = ec->read (ec->cls, &ptr, size); if (ret > 0) memcpy (data, ptr, ret); return ret; } /** * Callback invoked by TIFF lib for writing. Always fails. * * @param ctx the 'struct EXTRACTOR_ExtractContext' * @param data where to write data * @param size number of bytes to read * @return -1 (error) */ static tsize_t write_cb (thandle_t ctx, tdata_t data, tsize_t size) { return -1; } /** * Callback invoked by TIFF lib for seeking. * * @param ctx the 'struct EXTRACTOR_ExtractContext' * @param offset target offset * @param whence target is relative to where * @return new offset */ static toff_t seek_cb (thandle_t ctx, toff_t offset, int whence) { struct EXTRACTOR_ExtractContext *ec = ctx; return ec->seek (ec->cls, offset, whence); } /** * Callback invoked by TIFF lib for getting the file size. * * @param ctx the 'struct EXTRACTOR_ExtractContext' * @return file size */ static toff_t size_cb (thandle_t ctx) { struct EXTRACTOR_ExtractContext *ec = ctx; return ec->get_size (ec->cls); } /** * Callback invoked by TIFF lib for closing the file. Does nothing. * * @param ctx the 'struct EXTRACTOR_ExtractContext' */ static int close_cb (thandle_t ctx) { return 0; /* success */ } /** * A mapping from TIFF Tag to extractor types. */ struct Matches { /** * TIFF Tag. */ ttag_t tag; /** * Corresponding LE type. */ enum EXTRACTOR_MetaType type; }; /** * Mapping of TIFF tags to LE types. * NULL-terminated. */ static struct Matches tmap[] = { { TIFFTAG_ARTIST, EXTRACTOR_METATYPE_ARTIST }, { TIFFTAG_COPYRIGHT, EXTRACTOR_METATYPE_COPYRIGHT }, { TIFFTAG_DATETIME, EXTRACTOR_METATYPE_CREATION_DATE }, { TIFFTAG_DOCUMENTNAME, EXTRACTOR_METATYPE_TITLE }, { TIFFTAG_HOSTCOMPUTER, EXTRACTOR_METATYPE_BUILDHOST }, { TIFFTAG_IMAGEDESCRIPTION, EXTRACTOR_METATYPE_DESCRIPTION }, { TIFFTAG_MAKE, EXTRACTOR_METATYPE_CAMERA_MAKE }, { TIFFTAG_MODEL, EXTRACTOR_METATYPE_CAMERA_MODEL }, { TIFFTAG_PAGENAME, EXTRACTOR_METATYPE_PAGE_RANGE }, { TIFFTAG_SOFTWARE, EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE }, { TIFFTAG_TARGETPRINTER, EXTRACTOR_METATYPE_TARGET_ARCHITECTURE }, { 0, 0 } }; /** * Main entry method for the 'image/tiff' extraction plugin. * * @param ec extraction context provided to the plugin */ void EXTRACTOR_tiff_extract_method (struct EXTRACTOR_ExtractContext *ec) { TIFF *tiff; unsigned int i; char *meta; char format[128]; uint32_t width; uint32_t height; TIFFSetErrorHandler (&error_cb); TIFFSetWarningHandler (&error_cb); tiff = TIFFClientOpen ("", "rm", /* read-only, no mmap */ ec, &read_cb, &write_cb, &seek_cb, &close_cb, &size_cb, NULL, NULL); if (NULL == tiff) return; for (i = 0; 0 != tmap[i].tag; i++) if ( (1 == TIFFGetField (tiff, tmap[i].tag, &meta)) && (0 != ec->proc (ec->cls, "tiff", tmap[i].type, EXTRACTOR_METAFORMAT_UTF8, "text/plain", meta, strlen (meta) + 1)) ) goto CLEANUP; if ( (1 == TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width)) && (1 == TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height)) ) { snprintf (format, sizeof (format), "%ux%u", (unsigned int) width, (unsigned int) height); if (0 != ec->proc (ec->cls, "tiff", EXTRACTOR_METATYPE_IMAGE_DIMENSIONS, EXTRACTOR_METAFORMAT_UTF8, "text/plain", format, strlen (format) + 1)) goto CLEANUP; if (0 != ec->proc (ec->cls, "tiff", EXTRACTOR_METATYPE_MIMETYPE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "image/tiff", strlen ("image/tiff") + 1)) goto CLEANUP; } CLEANUP: TIFFClose (tiff); } /* end of tiff_extractor.c */