/ext/exif/exif.c
C | 4203 lines | 3366 code | 343 blank | 494 comment | 470 complexity | a8ff9db064d3d6c8d395bc765427f815 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Rasmus Lerdorf <rasmus@php.net> |
- | Marcus Boerger <helly@php.net> |
- +----------------------------------------------------------------------+
- */
- /* $Id: exif.c 308362 2011-02-15 14:02:26Z pajoye $ */
- /* ToDos
- *
- * See if example images from http://www.exif.org have illegal
- * thumbnail sizes or if code is corrupt.
- * Create/Update exif headers.
- * Create/Remove/Update image thumbnails.
- */
- /* Security
- *
- * At current time i do not see any security problems but a potential
- * attacker could generate an image with recursive ifd pointers...(Marcus)
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include "php.h"
- #include "ext/standard/file.h"
- #ifdef HAVE_STDINT_H
- # include <stdint.h>
- #endif
- #ifdef HAVE_INTTYPES_H
- # include <inttypes.h>
- #endif
- #ifdef PHP_WIN32
- # include "win32/php_stdint.h"
- #endif
- #if HAVE_EXIF
- /* When EXIF_DEBUG is defined the module generates a lot of debug messages
- * that help understanding what is going on. This can and should be used
- * while extending the module as it shows if you are at the right position.
- * You are always considered to have a copy of TIFF6.0 and EXIF2.10 standard.
- */
- #undef EXIF_DEBUG
- #ifdef EXIF_DEBUG
- #define EXIFERR_DC , const char *_file, size_t _line TSRMLS_DC
- #define EXIFERR_CC , __FILE__, __LINE__ TSRMLS_CC
- #else
- #define EXIFERR_DC TSRMLS_DC
- #define EXIFERR_CC TSRMLS_CC
- #endif
- #undef EXIF_JPEG2000
- #include "php_exif.h"
- #include <math.h>
- #include "php_ini.h"
- #include "ext/standard/php_string.h"
- #include "ext/standard/php_image.h"
- #include "ext/standard/info.h"
- #if defined(PHP_WIN32) || (HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING))
- #define EXIF_USE_MBSTRING 1
- #else
- #define EXIF_USE_MBSTRING 0
- #endif
- #if EXIF_USE_MBSTRING
- #include "ext/mbstring/mbstring.h"
- #endif
- /* needed for ssize_t definition */
- #include <sys/types.h>
- typedef unsigned char uchar;
- #ifndef safe_emalloc
- # define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
- #endif
- #ifndef safe_erealloc
- # define safe_erealloc(p,a,b,c) erealloc(p, (a)*(b)+(c))
- #endif
- #ifndef TRUE
- # define TRUE 1
- # define FALSE 0
- #endif
- #ifndef max
- # define max(a,b) ((a)>(b) ? (a) : (b))
- #endif
- #define EFREE_IF(ptr) if (ptr) efree(ptr)
- #define MAX_IFD_NESTING_LEVEL 100
- /* {{{ arginfo */
- ZEND_BEGIN_ARG_INFO(arginfo_exif_tagname, 0)
- ZEND_ARG_INFO(0, index)
- ZEND_END_ARG_INFO()
- ZEND_BEGIN_ARG_INFO_EX(arginfo_exif_read_data, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, sections_needed)
- ZEND_ARG_INFO(0, sub_arrays)
- ZEND_ARG_INFO(0, read_thumbnail)
- ZEND_END_ARG_INFO()
- ZEND_BEGIN_ARG_INFO_EX(arginfo_exif_thumbnail, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(1, width)
- ZEND_ARG_INFO(1, height)
- ZEND_ARG_INFO(1, imagetype)
- ZEND_END_ARG_INFO()
- ZEND_BEGIN_ARG_INFO(arginfo_exif_imagetype, 0)
- ZEND_ARG_INFO(0, imagefile)
- ZEND_END_ARG_INFO()
- /* }}} */
- /* {{{ exif_functions[]
- */
- const zend_function_entry exif_functions[] = {
- PHP_FE(exif_read_data, arginfo_exif_read_data)
- PHP_FALIAS(read_exif_data, exif_read_data, arginfo_exif_read_data)
- PHP_FE(exif_tagname, arginfo_exif_tagname)
- PHP_FE(exif_thumbnail, arginfo_exif_thumbnail)
- PHP_FE(exif_imagetype, arginfo_exif_imagetype)
- {NULL, NULL, NULL}
- };
- /* }}} */
- #define EXIF_VERSION "1.4 $Id: exif.c 308362 2011-02-15 14:02:26Z pajoye $"
- /* {{{ PHP_MINFO_FUNCTION
- */
- PHP_MINFO_FUNCTION(exif)
- {
- php_info_print_table_start();
- php_info_print_table_row(2, "EXIF Support", "enabled");
- php_info_print_table_row(2, "EXIF Version", EXIF_VERSION);
- php_info_print_table_row(2, "Supported EXIF Version", "0220");
- php_info_print_table_row(2, "Supported filetypes", "JPEG,TIFF");
- php_info_print_table_end();
- DISPLAY_INI_ENTRIES();
- }
- /* }}} */
- ZEND_BEGIN_MODULE_GLOBALS(exif)
- char * encode_unicode;
- char * decode_unicode_be;
- char * decode_unicode_le;
- char * encode_jis;
- char * decode_jis_be;
- char * decode_jis_le;
- ZEND_END_MODULE_GLOBALS(exif)
- ZEND_DECLARE_MODULE_GLOBALS(exif)
- #ifdef ZTS
- #define EXIF_G(v) TSRMG(exif_globals_id, zend_exif_globals *, v)
- #else
- #define EXIF_G(v) (exif_globals.v)
- #endif
-
- /* {{{ PHP_INI
- */
- ZEND_INI_MH(OnUpdateEncode)
- {
- #if EXIF_USE_MBSTRING
- if (new_value && strlen(new_value) && !php_mb_check_encoding_list(new_value TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
- return FAILURE;
- }
- #endif
- return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
- }
- ZEND_INI_MH(OnUpdateDecode)
- {
- #if EXIF_USE_MBSTRING
- if (!php_mb_check_encoding_list(new_value TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
- return FAILURE;
- }
- #endif
- return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
- }
- PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("exif.encode_unicode", "ISO-8859-15", PHP_INI_ALL, OnUpdateEncode, encode_unicode, zend_exif_globals, exif_globals)
- STD_PHP_INI_ENTRY("exif.decode_unicode_motorola", "UCS-2BE", PHP_INI_ALL, OnUpdateDecode, decode_unicode_be, zend_exif_globals, exif_globals)
- STD_PHP_INI_ENTRY("exif.decode_unicode_intel", "UCS-2LE", PHP_INI_ALL, OnUpdateDecode, decode_unicode_le, zend_exif_globals, exif_globals)
- STD_PHP_INI_ENTRY("exif.encode_jis", "", PHP_INI_ALL, OnUpdateEncode, encode_jis, zend_exif_globals, exif_globals)
- STD_PHP_INI_ENTRY("exif.decode_jis_motorola", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_be, zend_exif_globals, exif_globals)
- STD_PHP_INI_ENTRY("exif.decode_jis_intel", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_le, zend_exif_globals, exif_globals)
- PHP_INI_END()
- /* }}} */
-
- /* {{{ PHP_GINIT_FUNCTION
- */
- static PHP_GINIT_FUNCTION(exif)
- {
- exif_globals->encode_unicode = NULL;
- exif_globals->decode_unicode_be = NULL;
- exif_globals->decode_unicode_le = NULL;
- exif_globals->encode_jis = NULL;
- exif_globals->decode_jis_be = NULL;
- exif_globals->decode_jis_le = NULL;
- }
- /* }}} */
- /* {{{ PHP_MINIT_FUNCTION(exif)
- Get the size of an image as 4-element array */
- PHP_MINIT_FUNCTION(exif)
- {
- REGISTER_INI_ENTRIES();
- REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", EXIF_USE_MBSTRING, CONST_CS | CONST_PERSISTENT);
- return SUCCESS;
- }
- /* }}} */
- /* {{{ PHP_MSHUTDOWN_FUNCTION
- */
- PHP_MSHUTDOWN_FUNCTION(exif)
- {
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
- }
- /* }}} */
- /* {{{ exif dependencies */
- static const zend_module_dep exif_module_deps[] = {
- ZEND_MOD_REQUIRED("standard")
- #if EXIF_USE_MBSTRING
- ZEND_MOD_REQUIRED("mbstring")
- #endif
- {NULL, NULL, NULL}
- };
- /* }}} */
- /* {{{ exif_module_entry
- */
- zend_module_entry exif_module_entry = {
- STANDARD_MODULE_HEADER_EX, NULL,
- exif_module_deps,
- "exif",
- exif_functions,
- PHP_MINIT(exif),
- PHP_MSHUTDOWN(exif),
- NULL, NULL,
- PHP_MINFO(exif),
- #if ZEND_MODULE_API_NO >= 20010901
- EXIF_VERSION,
- #endif
- #if ZEND_MODULE_API_NO >= 20060613
- PHP_MODULE_GLOBALS(exif),
- PHP_GINIT(exif),
- NULL,
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
- #else
- STANDARD_MODULE_PROPERTIES
- #endif
- };
- /* }}} */
- #ifdef COMPILE_DL_EXIF
- ZEND_GET_MODULE(exif)
- #endif
- /* {{{ php_strnlen
- * get length of string if buffer if less than buffer size or buffer size */
- static size_t php_strnlen(char* str, size_t maxlen) {
- size_t len = 0;
- if (str && maxlen && *str) {
- do {
- len++;
- } while (--maxlen && *(++str));
- }
- return len;
- }
- /* }}} */
- /* {{{ error messages
- */
- static const char * EXIF_ERROR_FILEEOF = "Unexpected end of file reached";
- static const char * EXIF_ERROR_CORRUPT = "File structure corrupted";
- static const char * EXIF_ERROR_THUMBEOF = "Thumbnail goes IFD boundary or end of file reached";
- static const char * EXIF_ERROR_FSREALLOC = "Illegal reallocating of undefined file section";
- #define EXIF_ERRLOG_FILEEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FILEEOF);
- #define EXIF_ERRLOG_CORRUPT(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_CORRUPT);
- #define EXIF_ERRLOG_THUMBEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_THUMBEOF);
- #define EXIF_ERRLOG_FSREALLOC(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FSREALLOC);
- /* }}} */
- /* {{{ format description defines
- Describes format descriptor
- */
- static int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 1};
- #define NUM_FORMATS 13
- #define TAG_FMT_BYTE 1
- #define TAG_FMT_STRING 2
- #define TAG_FMT_USHORT 3
- #define TAG_FMT_ULONG 4
- #define TAG_FMT_URATIONAL 5
- #define TAG_FMT_SBYTE 6
- #define TAG_FMT_UNDEFINED 7
- #define TAG_FMT_SSHORT 8
- #define TAG_FMT_SLONG 9
- #define TAG_FMT_SRATIONAL 10
- #define TAG_FMT_SINGLE 11
- #define TAG_FMT_DOUBLE 12
- #define TAG_FMT_IFD 13
- #ifdef EXIF_DEBUG
- static char *exif_get_tagformat(int format)
- {
- switch(format) {
- case TAG_FMT_BYTE: return "BYTE";
- case TAG_FMT_STRING: return "STRING";
- case TAG_FMT_USHORT: return "USHORT";
- case TAG_FMT_ULONG: return "ULONG";
- case TAG_FMT_URATIONAL: return "URATIONAL";
- case TAG_FMT_SBYTE: return "SBYTE";
- case TAG_FMT_UNDEFINED: return "UNDEFINED";
- case TAG_FMT_SSHORT: return "SSHORT";
- case TAG_FMT_SLONG: return "SLONG";
- case TAG_FMT_SRATIONAL: return "SRATIONAL";
- case TAG_FMT_SINGLE: return "SINGLE";
- case TAG_FMT_DOUBLE: return "DOUBLE";
- case TAG_FMT_IFD: return "IFD";
- }
- return "*Illegal";
- }
- #endif
- /* Describes tag values */
- #define TAG_GPS_VERSION_ID 0x0000
- #define TAG_GPS_LATITUDE_REF 0x0001
- #define TAG_GPS_LATITUDE 0x0002
- #define TAG_GPS_LONGITUDE_REF 0x0003
- #define TAG_GPS_LONGITUDE 0x0004
- #define TAG_GPS_ALTITUDE_REF 0x0005
- #define TAG_GPS_ALTITUDE 0x0006
- #define TAG_GPS_TIME_STAMP 0x0007
- #define TAG_GPS_SATELLITES 0x0008
- #define TAG_GPS_STATUS 0x0009
- #define TAG_GPS_MEASURE_MODE 0x000A
- #define TAG_GPS_DOP 0x000B
- #define TAG_GPS_SPEED_REF 0x000C
- #define TAG_GPS_SPEED 0x000D
- #define TAG_GPS_TRACK_REF 0x000E
- #define TAG_GPS_TRACK 0x000F
- #define TAG_GPS_IMG_DIRECTION_REF 0x0010
- #define TAG_GPS_IMG_DIRECTION 0x0011
- #define TAG_GPS_MAP_DATUM 0x0012
- #define TAG_GPS_DEST_LATITUDE_REF 0x0013
- #define TAG_GPS_DEST_LATITUDE 0x0014
- #define TAG_GPS_DEST_LONGITUDE_REF 0x0015
- #define TAG_GPS_DEST_LONGITUDE 0x0016
- #define TAG_GPS_DEST_BEARING_REF 0x0017
- #define TAG_GPS_DEST_BEARING 0x0018
- #define TAG_GPS_DEST_DISTANCE_REF 0x0019
- #define TAG_GPS_DEST_DISTANCE 0x001A
- #define TAG_GPS_PROCESSING_METHOD 0x001B
- #define TAG_GPS_AREA_INFORMATION 0x001C
- #define TAG_GPS_DATE_STAMP 0x001D
- #define TAG_GPS_DIFFERENTIAL 0x001E
- #define TAG_TIFF_COMMENT 0x00FE /* SHOUDLNT HAPPEN */
- #define TAG_NEW_SUBFILE 0x00FE /* New version of subfile tag */
- #define TAG_SUBFILE_TYPE 0x00FF /* Old version of subfile tag */
- #define TAG_IMAGEWIDTH 0x0100
- #define TAG_IMAGEHEIGHT 0x0101
- #define TAG_BITS_PER_SAMPLE 0x0102
- #define TAG_COMPRESSION 0x0103
- #define TAG_PHOTOMETRIC_INTERPRETATION 0x0106
- #define TAG_TRESHHOLDING 0x0107
- #define TAG_CELL_WIDTH 0x0108
- #define TAG_CELL_HEIGHT 0x0109
- #define TAG_FILL_ORDER 0x010A
- #define TAG_DOCUMENT_NAME 0x010D
- #define TAG_IMAGE_DESCRIPTION 0x010E
- #define TAG_MAKE 0x010F
- #define TAG_MODEL 0x0110
- #define TAG_STRIP_OFFSETS 0x0111
- #define TAG_ORIENTATION 0x0112
- #define TAG_SAMPLES_PER_PIXEL 0x0115
- #define TAG_ROWS_PER_STRIP 0x0116
- #define TAG_STRIP_BYTE_COUNTS 0x0117
- #define TAG_MIN_SAMPPLE_VALUE 0x0118
- #define TAG_MAX_SAMPLE_VALUE 0x0119
- #define TAG_X_RESOLUTION 0x011A
- #define TAG_Y_RESOLUTION 0x011B
- #define TAG_PLANAR_CONFIGURATION 0x011C
- #define TAG_PAGE_NAME 0x011D
- #define TAG_X_POSITION 0x011E
- #define TAG_Y_POSITION 0x011F
- #define TAG_FREE_OFFSETS 0x0120
- #define TAG_FREE_BYTE_COUNTS 0x0121
- #define TAG_GRAY_RESPONSE_UNIT 0x0122
- #define TAG_GRAY_RESPONSE_CURVE 0x0123
- #define TAG_RESOLUTION_UNIT 0x0128
- #define TAG_PAGE_NUMBER 0x0129
- #define TAG_TRANSFER_FUNCTION 0x012D
- #define TAG_SOFTWARE 0x0131
- #define TAG_DATETIME 0x0132
- #define TAG_ARTIST 0x013B
- #define TAG_HOST_COMPUTER 0x013C
- #define TAG_PREDICTOR 0x013D
- #define TAG_WHITE_POINT 0x013E
- #define TAG_PRIMARY_CHROMATICITIES 0x013F
- #define TAG_COLOR_MAP 0x0140
- #define TAG_HALFTONE_HINTS 0x0141
- #define TAG_TILE_WIDTH 0x0142
- #define TAG_TILE_LENGTH 0x0143
- #define TAG_TILE_OFFSETS 0x0144
- #define TAG_TILE_BYTE_COUNTS 0x0145
- #define TAG_SUB_IFD 0x014A
- #define TAG_INK_SETMPUTER 0x014C
- #define TAG_INK_NAMES 0x014D
- #define TAG_NUMBER_OF_INKS 0x014E
- #define TAG_DOT_RANGE 0x0150
- #define TAG_TARGET_PRINTER 0x0151
- #define TAG_EXTRA_SAMPLE 0x0152
- #define TAG_SAMPLE_FORMAT 0x0153
- #define TAG_S_MIN_SAMPLE_VALUE 0x0154
- #define TAG_S_MAX_SAMPLE_VALUE 0x0155
- #define TAG_TRANSFER_RANGE 0x0156
- #define TAG_JPEG_TABLES 0x015B
- #define TAG_JPEG_PROC 0x0200
- #define TAG_JPEG_INTERCHANGE_FORMAT 0x0201
- #define TAG_JPEG_INTERCHANGE_FORMAT_LEN 0x0202
- #define TAG_JPEG_RESTART_INTERVAL 0x0203
- #define TAG_JPEG_LOSSLESS_PREDICTOR 0x0205
- #define TAG_JPEG_POINT_TRANSFORMS 0x0206
- #define TAG_JPEG_Q_TABLES 0x0207
- #define TAG_JPEG_DC_TABLES 0x0208
- #define TAG_JPEG_AC_TABLES 0x0209
- #define TAG_YCC_COEFFICIENTS 0x0211
- #define TAG_YCC_SUB_SAMPLING 0x0212
- #define TAG_YCC_POSITIONING 0x0213
- #define TAG_REFERENCE_BLACK_WHITE 0x0214
- /* 0x0301 - 0x0302 */
- /* 0x0320 */
- /* 0x0343 */
- /* 0x5001 - 0x501B */
- /* 0x5021 - 0x503B */
- /* 0x5090 - 0x5091 */
- /* 0x5100 - 0x5101 */
- /* 0x5110 - 0x5113 */
- /* 0x80E3 - 0x80E6 */
- /* 0x828d - 0x828F */
- #define TAG_COPYRIGHT 0x8298
- #define TAG_EXPOSURETIME 0x829A
- #define TAG_FNUMBER 0x829D
- #define TAG_EXIF_IFD_POINTER 0x8769
- #define TAG_ICC_PROFILE 0x8773
- #define TAG_EXPOSURE_PROGRAM 0x8822
- #define TAG_SPECTRAL_SENSITY 0x8824
- #define TAG_GPS_IFD_POINTER 0x8825
- #define TAG_ISOSPEED 0x8827
- #define TAG_OPTOELECTRIC_CONVERSION_F 0x8828
- /* 0x8829 - 0x882b */
- #define TAG_EXIFVERSION 0x9000
- #define TAG_DATE_TIME_ORIGINAL 0x9003
- #define TAG_DATE_TIME_DIGITIZED 0x9004
- #define TAG_COMPONENT_CONFIG 0x9101
- #define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102
- #define TAG_SHUTTERSPEED 0x9201
- #define TAG_APERTURE 0x9202
- #define TAG_BRIGHTNESS_VALUE 0x9203
- #define TAG_EXPOSURE_BIAS_VALUE 0x9204
- #define TAG_MAX_APERTURE 0x9205
- #define TAG_SUBJECT_DISTANCE 0x9206
- #define TAG_METRIC_MODULE 0x9207
- #define TAG_LIGHT_SOURCE 0x9208
- #define TAG_FLASH 0x9209
- #define TAG_FOCAL_LENGTH 0x920A
- /* 0x920B - 0x920D */
- /* 0x9211 - 0x9216 */
- #define TAG_SUBJECT_AREA 0x9214
- #define TAG_MAKER_NOTE 0x927C
- #define TAG_USERCOMMENT 0x9286
- #define TAG_SUB_SEC_TIME 0x9290
- #define TAG_SUB_SEC_TIME_ORIGINAL 0x9291
- #define TAG_SUB_SEC_TIME_DIGITIZED 0x9292
- /* 0x923F */
- /* 0x935C */
- #define TAG_XP_TITLE 0x9C9B
- #define TAG_XP_COMMENTS 0x9C9C
- #define TAG_XP_AUTHOR 0x9C9D
- #define TAG_XP_KEYWORDS 0x9C9E
- #define TAG_XP_SUBJECT 0x9C9F
- #define TAG_FLASH_PIX_VERSION 0xA000
- #define TAG_COLOR_SPACE 0xA001
- #define TAG_COMP_IMAGE_WIDTH 0xA002 /* compressed images only */
- #define TAG_COMP_IMAGE_HEIGHT 0xA003
- #define TAG_RELATED_SOUND_FILE 0xA004
- #define TAG_INTEROP_IFD_POINTER 0xA005 /* IFD pointer */
- #define TAG_FLASH_ENERGY 0xA20B
- #define TAG_SPATIAL_FREQUENCY_RESPONSE 0xA20C
- #define TAG_FOCALPLANE_X_RES 0xA20E
- #define TAG_FOCALPLANE_Y_RES 0xA20F
- #define TAG_FOCALPLANE_RESOLUTION_UNIT 0xA210
- #define TAG_SUBJECT_LOCATION 0xA214
- #define TAG_EXPOSURE_INDEX 0xA215
- #define TAG_SENSING_METHOD 0xA217
- #define TAG_FILE_SOURCE 0xA300
- #define TAG_SCENE_TYPE 0xA301
- #define TAG_CFA_PATTERN 0xA302
- #define TAG_CUSTOM_RENDERED 0xA401
- #define TAG_EXPOSURE_MODE 0xA402
- #define TAG_WHITE_BALANCE 0xA403
- #define TAG_DIGITAL_ZOOM_RATIO 0xA404
- #define TAG_FOCAL_LENGTH_IN_35_MM_FILM 0xA405
- #define TAG_SCENE_CAPTURE_TYPE 0xA406
- #define TAG_GAIN_CONTROL 0xA407
- #define TAG_CONTRAST 0xA408
- #define TAG_SATURATION 0xA409
- #define TAG_SHARPNESS 0xA40A
- #define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B
- #define TAG_SUBJECT_DISTANCE_RANGE 0xA40C
- #define TAG_IMAGE_UNIQUE_ID 0xA420
- /* Olympus specific tags */
- #define TAG_OLYMPUS_SPECIALMODE 0x0200
- #define TAG_OLYMPUS_JPEGQUAL 0x0201
- #define TAG_OLYMPUS_MACRO 0x0202
- #define TAG_OLYMPUS_DIGIZOOM 0x0204
- #define TAG_OLYMPUS_SOFTWARERELEASE 0x0207
- #define TAG_OLYMPUS_PICTINFO 0x0208
- #define TAG_OLYMPUS_CAMERAID 0x0209
- /* end Olympus specific tags */
- /* Internal */
- #define TAG_NONE -1 /* note that -1 <> 0xFFFF */
- #define TAG_COMPUTED_VALUE -2
- #define TAG_END_OF_LIST 0xFFFD
- /* Values for TAG_PHOTOMETRIC_INTERPRETATION */
- #define PMI_BLACK_IS_ZERO 0
- #define PMI_WHITE_IS_ZERO 1
- #define PMI_RGB 2
- #define PMI_PALETTE_COLOR 3
- #define PMI_TRANSPARENCY_MASK 4
- #define PMI_SEPARATED 5
- #define PMI_YCBCR 6
- #define PMI_CIELAB 8
- /* }}} */
- /* {{{ TabTable[]
- */
- typedef const struct {
- unsigned short Tag;
- char *Desc;
- } tag_info_type;
- typedef tag_info_type tag_info_array[];
- typedef tag_info_type *tag_table_type;
- #define TAG_TABLE_END \
- {TAG_NONE, "No tag value"},\
- {TAG_COMPUTED_VALUE, "Computed value"},\
- {TAG_END_OF_LIST, ""} /* Important for exif_get_tagname() IF value != "" function result is != false */
- static tag_info_array tag_table_IFD = {
- { 0x000B, "ACDComment"},
- { 0x00FE, "NewSubFile"}, /* better name it 'ImageType' ? */
- { 0x00FF, "SubFile"},
- { 0x0100, "ImageWidth"},
- { 0x0101, "ImageLength"},
- { 0x0102, "BitsPerSample"},
- { 0x0103, "Compression"},
- { 0x0106, "PhotometricInterpretation"},
- { 0x010A, "FillOrder"},
- { 0x010D, "DocumentName"},
- { 0x010E, "ImageDescription"},
- { 0x010F, "Make"},
- { 0x0110, "Model"},
- { 0x0111, "StripOffsets"},
- { 0x0112, "Orientation"},
- { 0x0115, "SamplesPerPixel"},
- { 0x0116, "RowsPerStrip"},
- { 0x0117, "StripByteCounts"},
- { 0x0118, "MinSampleValue"},
- { 0x0119, "MaxSampleValue"},
- { 0x011A, "XResolution"},
- { 0x011B, "YResolution"},
- { 0x011C, "PlanarConfiguration"},
- { 0x011D, "PageName"},
- { 0x011E, "XPosition"},
- { 0x011F, "YPosition"},
- { 0x0120, "FreeOffsets"},
- { 0x0121, "FreeByteCounts"},
- { 0x0122, "GrayResponseUnit"},
- { 0x0123, "GrayResponseCurve"},
- { 0x0124, "T4Options"},
- { 0x0125, "T6Options"},
- { 0x0128, "ResolutionUnit"},
- { 0x0129, "PageNumber"},
- { 0x012D, "TransferFunction"},
- { 0x0131, "Software"},
- { 0x0132, "DateTime"},
- { 0x013B, "Artist"},
- { 0x013C, "HostComputer"},
- { 0x013D, "Predictor"},
- { 0x013E, "WhitePoint"},
- { 0x013F, "PrimaryChromaticities"},
- { 0x0140, "ColorMap"},
- { 0x0141, "HalfToneHints"},
- { 0x0142, "TileWidth"},
- { 0x0143, "TileLength"},
- { 0x0144, "TileOffsets"},
- { 0x0145, "TileByteCounts"},
- { 0x014A, "SubIFD"},
- { 0x014C, "InkSet"},
- { 0x014D, "InkNames"},
- { 0x014E, "NumberOfInks"},
- { 0x0150, "DotRange"},
- { 0x0151, "TargetPrinter"},
- { 0x0152, "ExtraSample"},
- { 0x0153, "SampleFormat"},
- { 0x0154, "SMinSampleValue"},
- { 0x0155, "SMaxSampleValue"},
- { 0x0156, "TransferRange"},
- { 0x0157, "ClipPath"},
- { 0x0158, "XClipPathUnits"},
- { 0x0159, "YClipPathUnits"},
- { 0x015A, "Indexed"},
- { 0x015B, "JPEGTables"},
- { 0x015F, "OPIProxy"},
- { 0x0200, "JPEGProc"},
- { 0x0201, "JPEGInterchangeFormat"},
- { 0x0202, "JPEGInterchangeFormatLength"},
- { 0x0203, "JPEGRestartInterval"},
- { 0x0205, "JPEGLosslessPredictors"},
- { 0x0206, "JPEGPointTransforms"},
- { 0x0207, "JPEGQTables"},
- { 0x0208, "JPEGDCTables"},
- { 0x0209, "JPEGACTables"},
- { 0x0211, "YCbCrCoefficients"},
- { 0x0212, "YCbCrSubSampling"},
- { 0x0213, "YCbCrPositioning"},
- { 0x0214, "ReferenceBlackWhite"},
- { 0x02BC, "ExtensibleMetadataPlatform"}, /* XAP: Extensible Authoring Publishing, obsoleted by XMP: Extensible Metadata Platform */
- { 0x0301, "Gamma"},
- { 0x0302, "ICCProfileDescriptor"},
- { 0x0303, "SRGBRenderingIntent"},
- { 0x0320, "ImageTitle"},
- { 0x5001, "ResolutionXUnit"},
- { 0x5002, "ResolutionYUnit"},
- { 0x5003, "ResolutionXLengthUnit"},
- { 0x5004, "ResolutionYLengthUnit"},
- { 0x5005, "PrintFlags"},
- { 0x5006, "PrintFlagsVersion"},
- { 0x5007, "PrintFlagsCrop"},
- { 0x5008, "PrintFlagsBleedWidth"},
- { 0x5009, "PrintFlagsBleedWidthScale"},
- { 0x500A, "HalftoneLPI"},
- { 0x500B, "HalftoneLPIUnit"},
- { 0x500C, "HalftoneDegree"},
- { 0x500D, "HalftoneShape"},
- { 0x500E, "HalftoneMisc"},
- { 0x500F, "HalftoneScreen"},
- { 0x5010, "JPEGQuality"},
- { 0x5011, "GridSize"},
- { 0x5012, "ThumbnailFormat"},
- { 0x5013, "ThumbnailWidth"},
- { 0x5014, "ThumbnailHeight"},
- { 0x5015, "ThumbnailColorDepth"},
- { 0x5016, "ThumbnailPlanes"},
- { 0x5017, "ThumbnailRawBytes"},
- { 0x5018, "ThumbnailSize"},
- { 0x5019, "ThumbnailCompressedSize"},
- { 0x501A, "ColorTransferFunction"},
- { 0x501B, "ThumbnailData"},
- { 0x5020, "ThumbnailImageWidth"},
- { 0x5021, "ThumbnailImageHeight"},
- { 0x5022, "ThumbnailBitsPerSample"},
- { 0x5023, "ThumbnailCompression"},
- { 0x5024, "ThumbnailPhotometricInterp"},
- { 0x5025, "ThumbnailImageDescription"},
- { 0x5026, "ThumbnailEquipMake"},
- { 0x5027, "ThumbnailEquipModel"},
- { 0x5028, "ThumbnailStripOffsets"},
- { 0x5029, "ThumbnailOrientation"},
- { 0x502A, "ThumbnailSamplesPerPixel"},
- { 0x502B, "ThumbnailRowsPerStrip"},
- { 0x502C, "ThumbnailStripBytesCount"},
- { 0x502D, "ThumbnailResolutionX"},
- { 0x502E, "ThumbnailResolutionY"},
- { 0x502F, "ThumbnailPlanarConfig"},
- { 0x5030, "ThumbnailResolutionUnit"},
- { 0x5031, "ThumbnailTransferFunction"},
- { 0x5032, "ThumbnailSoftwareUsed"},
- { 0x5033, "ThumbnailDateTime"},
- { 0x5034, "ThumbnailArtist"},
- { 0x5035, "ThumbnailWhitePoint"},
- { 0x5036, "ThumbnailPrimaryChromaticities"},
- { 0x5037, "ThumbnailYCbCrCoefficients"},
- { 0x5038, "ThumbnailYCbCrSubsampling"},
- { 0x5039, "ThumbnailYCbCrPositioning"},
- { 0x503A, "ThumbnailRefBlackWhite"},
- { 0x503B, "ThumbnailCopyRight"},
- { 0x5090, "LuminanceTable"},
- { 0x5091, "ChrominanceTable"},
- { 0x5100, "FrameDelay"},
- { 0x5101, "LoopCount"},
- { 0x5110, "PixelUnit"},
- { 0x5111, "PixelPerUnitX"},
- { 0x5112, "PixelPerUnitY"},
- { 0x5113, "PaletteHistogram"},
- { 0x1000, "RelatedImageFileFormat"},
- { 0x800D, "ImageID"},
- { 0x80E3, "Matteing"}, /* obsoleted by ExtraSamples */
- { 0x80E4, "DataType"}, /* obsoleted by SampleFormat */
- { 0x80E5, "ImageDepth"},
- { 0x80E6, "TileDepth"},
- { 0x828D, "CFARepeatPatternDim"},
- { 0x828E, "CFAPattern"},
- { 0x828F, "BatteryLevel"},
- { 0x8298, "Copyright"},
- { 0x829A, "ExposureTime"},
- { 0x829D, "FNumber"},
- { 0x83BB, "IPTC/NAA"},
- { 0x84E3, "IT8RasterPadding"},
- { 0x84E5, "IT8ColorTable"},
- { 0x8649, "ImageResourceInformation"}, /* PhotoShop */
- { 0x8769, "Exif_IFD_Pointer"},
- { 0x8773, "ICC_Profile"},
- { 0x8822, "ExposureProgram"},
- { 0x8824, "SpectralSensity"},
- { 0x8828, "OECF"},
- { 0x8825, "GPS_IFD_Pointer"},
- { 0x8827, "ISOSpeedRatings"},
- { 0x8828, "OECF"},
- { 0x9000, "ExifVersion"},
- { 0x9003, "DateTimeOriginal"},
- { 0x9004, "DateTimeDigitized"},
- { 0x9101, "ComponentsConfiguration"},
- { 0x9102, "CompressedBitsPerPixel"},
- { 0x9201, "ShutterSpeedValue"},
- { 0x9202, "ApertureValue"},
- { 0x9203, "BrightnessValue"},
- { 0x9204, "ExposureBiasValue"},
- { 0x9205, "MaxApertureValue"},
- { 0x9206, "SubjectDistance"},
- { 0x9207, "MeteringMode"},
- { 0x9208, "LightSource"},
- { 0x9209, "Flash"},
- { 0x920A, "FocalLength"},
- { 0x920B, "FlashEnergy"}, /* 0xA20B in JPEG */
- { 0x920C, "SpatialFrequencyResponse"}, /* 0xA20C - - */
- { 0x920D, "Noise"},
- { 0x920E, "FocalPlaneXResolution"}, /* 0xA20E - - */
- { 0x920F, "FocalPlaneYResolution"}, /* 0xA20F - - */
- { 0x9210, "FocalPlaneResolutionUnit"}, /* 0xA210 - - */
- { 0x9211, "ImageNumber"},
- { 0x9212, "SecurityClassification"},
- { 0x9213, "ImageHistory"},
- { 0x9214, "SubjectLocation"}, /* 0xA214 - - */
- { 0x9215, "ExposureIndex"}, /* 0xA215 - - */
- { 0x9216, "TIFF/EPStandardID"},
- { 0x9217, "SensingMethod"}, /* 0xA217 - - */
- { 0x923F, "StoNits"},
- { 0x927C, "MakerNote"},
- { 0x9286, "UserComment"},
- { 0x9290, "SubSecTime"},
- { 0x9291, "SubSecTimeOriginal"},
- { 0x9292, "SubSecTimeDigitized"},
- { 0x935C, "ImageSourceData"}, /* "Adobe Photoshop Document Data Block": 8BIM... */
- { 0x9c9b, "Title" }, /* Win XP specific, Unicode */
- { 0x9c9c, "Comments" }, /* Win XP specific, Unicode */
- { 0x9c9d, "Author" }, /* Win XP specific, Unicode */
- { 0x9c9e, "Keywords" }, /* Win XP specific, Unicode */
- { 0x9c9f, "Subject" }, /* Win XP specific, Unicode, not to be confused with SubjectDistance and SubjectLocation */
- { 0xA000, "FlashPixVersion"},
- { 0xA001, "ColorSpace"},
- { 0xA002, "ExifImageWidth"},
- { 0xA003, "ExifImageLength"},
- { 0xA004, "RelatedSoundFile"},
- { 0xA005, "InteroperabilityOffset"},
- { 0xA20B, "FlashEnergy"}, /* 0x920B in TIFF/EP */
- { 0xA20C, "SpatialFrequencyResponse"}, /* 0x920C - - */
- { 0xA20D, "Noise"},
- { 0xA20E, "FocalPlaneXResolution"}, /* 0x920E - - */
- { 0xA20F, "FocalPlaneYResolution"}, /* 0x920F - - */
- { 0xA210, "FocalPlaneResolutionUnit"}, /* 0x9210 - - */
- { 0xA211, "ImageNumber"},
- { 0xA212, "SecurityClassification"},
- { 0xA213, "ImageHistory"},
- { 0xA214, "SubjectLocation"}, /* 0x9214 - - */
- { 0xA215, "ExposureIndex"}, /* 0x9215 - - */
- { 0xA216, "TIFF/EPStandardID"},
- { 0xA217, "SensingMethod"}, /* 0x9217 - - */
- { 0xA300, "FileSource"},
- { 0xA301, "SceneType"},
- { 0xA302, "CFAPattern"},
- { 0xA401, "CustomRendered"},
- { 0xA402, "ExposureMode"},
- { 0xA403, "WhiteBalance"},
- { 0xA404, "DigitalZoomRatio"},
- { 0xA405, "FocalLengthIn35mmFilm"},
- { 0xA406, "SceneCaptureType"},
- { 0xA407, "GainControl"},
- { 0xA408, "Contrast"},
- { 0xA409, "Saturation"},
- { 0xA40A, "Sharpness"},
- { 0xA40B, "DeviceSettingDescription"},
- { 0xA40C, "SubjectDistanceRange"},
- { 0xA420, "ImageUniqueID"},
- TAG_TABLE_END
- } ;
- static tag_info_array tag_table_GPS = {
- { 0x0000, "GPSVersion"},
- { 0x0001, "GPSLatitudeRef"},
- { 0x0002, "GPSLatitude"},
- { 0x0003, "GPSLongitudeRef"},
- { 0x0004, "GPSLongitude"},
- { 0x0005, "GPSAltitudeRef"},
- { 0x0006, "GPSAltitude"},
- { 0x0007, "GPSTimeStamp"},
- { 0x0008, "GPSSatellites"},
- { 0x0009, "GPSStatus"},
- { 0x000A, "GPSMeasureMode"},
- { 0x000B, "GPSDOP"},
- { 0x000C, "GPSSpeedRef"},
- { 0x000D, "GPSSpeed"},
- { 0x000E, "GPSTrackRef"},
- { 0x000F, "GPSTrack"},
- { 0x0010, "GPSImgDirectionRef"},
- { 0x0011, "GPSImgDirection"},
- { 0x0012, "GPSMapDatum"},
- { 0x0013, "GPSDestLatitudeRef"},
- { 0x0014, "GPSDestLatitude"},
- { 0x0015, "GPSDestLongitudeRef"},
- { 0x0016, "GPSDestLongitude"},
- { 0x0017, "GPSDestBearingRef"},
- { 0x0018, "GPSDestBearing"},
- { 0x0019, "GPSDestDistanceRef"},
- { 0x001A, "GPSDestDistance"},
- { 0x001B, "GPSProcessingMode"},
- { 0x001C, "GPSAreaInformation"},
- { 0x001D, "GPSDateStamp"},
- { 0x001E, "GPSDifferential"},
- TAG_TABLE_END
- };
- static tag_info_array tag_table_IOP = {
- { 0x0001, "InterOperabilityIndex"}, /* should be 'R98' or 'THM' */
- { 0x0002, "InterOperabilityVersion"},
- { 0x1000, "RelatedFileFormat"},
- { 0x1001, "RelatedImageWidth"},
- { 0x1002, "RelatedImageHeight"},
- TAG_TABLE_END
- };
- static tag_info_array tag_table_VND_CANON = {
- { 0x0001, "ModeArray"}, /* guess */
- { 0x0004, "ImageInfo"}, /* guess */
- { 0x0006, "ImageType"},
- { 0x0007, "FirmwareVersion"},
- { 0x0008, "ImageNumber"},
- { 0x0009, "OwnerName"},
- { 0x000C, "Camera"},
- { 0x000F, "CustomFunctions"},
- TAG_TABLE_END
- };
- static tag_info_array tag_table_VND_CASIO = {
- { 0x0001, "RecordingMode"},
- { 0x0002, "Quality"},
- { 0x0003, "FocusingMode"},
- { 0x0004, "FlashMode"},
- { 0x0005, "FlashIntensity"},
- { 0x0006, "ObjectDistance"},
- { 0x0007, "WhiteBalance"},
- { 0x000A, "DigitalZoom"},
- { 0x000B, "Sharpness"},
- { 0x000C, "Contrast"},
- { 0x000D, "Saturation"},
- { 0x0014, "CCDSensitivity"},
- TAG_TABLE_END
- };
- static tag_info_array tag_table_VND_FUJI = {
- { 0x0000, "Version"},
- { 0x1000, "Quality"},
- { 0x1001, "Sharpness"},
- { 0x1002, "WhiteBalance"},
- { 0x1003, "Color"},
- { 0x1004, "Tone"},
- { 0x1010, "FlashMode"},
- { 0x1011, "FlashStrength"},
- { 0x1020, "Macro"},
- { 0x1021, "FocusMode"},
- { 0x1030, "SlowSync"},
- { 0x1031, "PictureMode"},
- { 0x1100, "ContTake"},
- { 0x1300, "BlurWarning"},
- { 0x1301, "FocusWarning"},
- { 0x1302, "AEWarning "},
- TAG_TABLE_END
- };
- static tag_info_array tag_table_VND_NIKON = {
- { 0x0003, "Quality"},
- { 0x0004, "ColorMode"},
- { 0x0005, "ImageAdjustment"},
- { 0x0006, "CCDSensitivity"},
- { 0x0007, "WhiteBalance"},
- { 0x0008, "Focus"},
- { 0x000a, "DigitalZoom"},
- { 0x000b, "Converter"},
- TAG_TABLE_END
- };
-
- static tag_info_array tag_table_VND_NIKON_990 = {
- { 0x0001, "Version"},
- { 0x0002, "ISOSetting"},
- { 0x0003, "ColorMode"},
- { 0x0004, "Quality"},
- { 0x0005, "WhiteBalance"},
- { 0x0006, "ImageSharpening"},
- { 0x0007, "FocusMode"},
- { 0x0008, "FlashSetting"},
- { 0x000F, "ISOSelection"},
- { 0x0080, "ImageAdjustment"},
- { 0x0082, "AuxiliaryLens"},
- { 0x0085, "ManualFocusDistance"},
- { 0x0086, "DigitalZoom"},
- { 0x0088, "AFFocusPosition"},
- { 0x0010, "DataDump"},
- TAG_TABLE_END
- };
-
- static tag_info_array tag_table_VND_OLYMPUS = {
- { 0x0200, "SpecialMode"},
- { 0x0201, "JPEGQuality"},
- { 0x0202, "Macro"},
- { 0x0204, "DigitalZoom"},
- { 0x0207, "SoftwareRelease"},
- { 0x0208, "PictureInfo"},
- { 0x0209, "CameraId"},
- { 0x0F00, "DataDump"},
- TAG_TABLE_END
- };
- typedef enum mn_byte_order_t {
- MN_ORDER_INTEL = 0,
- MN_ORDER_MOTOROLA = 1,
- MN_ORDER_NORMAL
- } mn_byte_order_t;
- typedef enum mn_offset_mode_t {
- MN_OFFSET_NORMAL,
- MN_OFFSET_MAKER,
- MN_OFFSET_GUESS
- } mn_offset_mode_t;
- typedef struct {
- tag_table_type tag_table;
- char * make;
- char * model;
- char * id_string;
- int id_string_len;
- int offset;
- mn_byte_order_t byte_order;
- mn_offset_mode_t offset_mode;
- } maker_note_type;
- static const maker_note_type maker_note_array[] = {
- { tag_table_VND_CANON, "Canon", NULL, NULL, 0, 0, MN_ORDER_INTEL, MN_OFFSET_GUESS},
- /* { tag_table_VND_CANON, "Canon", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},*/
- { tag_table_VND_CASIO, "CASIO", NULL, NULL, 0, 0, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
- { tag_table_VND_FUJI, "FUJIFILM", NULL, "FUJIFILM\x0C\x00\x00\x00", 12, 12, MN_ORDER_INTEL, MN_OFFSET_MAKER},
- { tag_table_VND_NIKON, "NIKON", NULL, "Nikon\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
- { tag_table_VND_NIKON_990, "NIKON", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
- { tag_table_VND_OLYMPUS, "OLYMPUS OPTICAL CO.,LTD", NULL, "OLYMP\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
- };
- /* }}} */
- /* {{{ exif_get_tagname
- Get headername for tag_num or NULL if not defined */
- static char * exif_get_tagname(int tag_num, char *ret, int len, tag_table_type tag_table TSRMLS_DC)
- {
- int i, t;
- char tmp[32];
- for (i = 0; (t = tag_table[i].Tag) != TAG_END_OF_LIST; i++) {
- if (t == tag_num) {
- if (ret && len) {
- strlcpy(ret, tag_table[i].Desc, abs(len));
- if (len < 0) {
- memset(ret + strlen(ret), ' ', -len - strlen(ret) - 1);
- ret[-len - 1] = '\0';
- }
- return ret;
- }
- return tag_table[i].Desc;
- }
- }
- if (ret && len) {
- snprintf(tmp, sizeof(tmp), "UndefinedTag:0x%04X", tag_num);
- strlcpy(ret, tmp, abs(len));
- if (len < 0) {
- memset(ret + strlen(ret), ' ', -len - strlen(ret) - 1);
- ret[-len - 1] = '\0';
- }
- return ret;
- }
- return "";
- }
- /* }}} */
- /* {{{ exif_char_dump
- * Do not use! This is a debug function... */
- #ifdef EXIF_DEBUG
- static unsigned char* exif_char_dump(unsigned char * addr, int len, int offset)
- {
- static unsigned char buf[4096+1];
- static unsigned char tmp[20];
- int c, i, p=0, n = 5+31;
- p += slprintf(buf+p, sizeof(buf)-p, "\nDump Len: %08X (%d)", len, len);
- if (len) {
- for(i=0; i<len+15 && p+n<=sizeof(buf); i++) {
- if (i%16==0) {
- p += slprintf(buf+p, sizeof(buf)-p, "\n%08X: ", i+offset);
- }
- if (i<len) {
- c = *addr++;
- p += slprintf(buf+p, sizeof(buf)-p, "%02X ", c);
- tmp[i%16] = c>=32 ? c : '.';
- tmp[(i%16)+1] = '\0';
- } else {
- p += slprintf(buf+p, sizeof(buf)-p, " ");
- }
- if (i%16==15) {
- p += slprintf(buf+p, sizeof(buf)-p, " %s", tmp);
- if (i>=len) {
- break;
- }
- }
- }
- }
- buf[sizeof(buf)-1] = '\0';
- return buf;
- }
- #endif
- /* }}} */
- /* {{{ php_jpg_get16
- Get 16 bits motorola order (always) for jpeg header stuff.
- */
- static int php_jpg_get16(void *value)
- {
- return (((uchar *)value)[0] << 8) | ((uchar *)value)[1];
- }
- /* }}} */
- /* {{{ php_ifd_get16u
- * Convert a 16 bit unsigned value from file's native byte order */
- static int php_ifd_get16u(void *value, int motorola_intel)
- {
- if (motorola_intel) {
- return (((uchar *)value)[0] << 8) | ((uchar *)value)[1];
- } else {
- return (((uchar *)value)[1] << 8) | ((uchar *)value)[0];
- }
- }
- /* }}} */
- /* {{{ php_ifd_get16s
- * Convert a 16 bit signed value from file's native byte order */
- static signed short php_ifd_get16s(void *value, int motorola_intel)
- {
- return (signed short)php_ifd_get16u(value, motorola_intel);
- }
- /* }}} */
- /* {{{ php_ifd_get32s
- * Convert a 32 bit signed value from file's native byte order */
- static int php_ifd_get32s(void *value, int motorola_intel)
- {
- if (motorola_intel) {
- return (((char *)value)[0] << 24)
- | (((uchar *)value)[1] << 16)
- | (((uchar *)value)[2] << 8 )
- | (((uchar *)value)[3] );
- } else {
- return (((char *)value)[3] << 24)
- | (((uchar *)value)[2] << 16)
- | (((uchar *)value)[1] << 8 )
- | (((uchar *)value)[0] );
- }
- }
- /* }}} */
- /* {{{ php_ifd_get32u
- * Write 32 bit unsigned value to data */
- static unsigned php_ifd_get32u(void *value, int motorola_intel)
- {
- return (unsigned)php_ifd_get32s(value, motorola_intel) & 0xffffffff;
- }
- /* }}} */
- /* {{{ php_ifd_set16u
- * Write 16 bit unsigned value to data */
- static void php_ifd_set16u(char *data, unsigned int value, int motorola_intel)
- {
- if (motorola_intel) {
- data[0] = (value & 0xFF00) >> 8;
- data[1] = (value & 0x00FF);
- } else {
- data[1] = (value & 0xFF00) >> 8;
- data[0] = (value & 0x00FF);
- }
- }
- /* }}} */
- /* {{{ php_ifd_set32u
- * Convert a 32 bit unsigned value from file's native byte order */
- static void php_ifd_set32u(char *data, size_t value, int motorola_intel)
- {
- if (motorola_intel) {
- data[0] = (value & 0xFF000000) >> 24;
- data[1] = (value & 0x00FF0000) >> 16;
- data[2] = (value & 0x0000FF00) >> 8;
- data[3] = (value & 0x000000FF);
- } else {
- data[3] = (value & 0xFF000000) >> 24;
- data[2] = (value & 0x00FF0000) >> 16;
- data[1] = (value & 0x0000FF00) >> 8;
- data[0] = (value & 0x000000FF);
- }
- }
- /* }}} */
- #ifdef EXIF_DEBUG
- char * exif_dump_data(int *dump_free, int format, int components, int length, int motorola_intel, char *value_ptr TSRMLS_DC) /* {{{ */
- {
- char *dump;
- int len;
- *dump_free = 0;
- if (format == TAG_FMT_STRING) {
- return value_ptr ? value_ptr : "<no data>";
- }
- if (format == TAG_FMT_UNDEFINED) {
- return "<undefined>\n";
- }
- if (format == TAG_FMT_IFD) {
- return "";
- }
- if (format == TAG_FMT_SINGLE || format == TAG_FMT_DOUBLE) {
- return "<not implemented>";
- }
- *dump_free = 1;
- if (components > 1) {
- len = spprintf(&dump, 0, "(%d,%d) {", components, length);
- } else {
- len = spprintf(&dump, 0, "{");
- }
- while(components > 0) {
- switch(format) {
- case TAG_FMT_BYTE:
- case TAG_FMT_UNDEFINED:
- case TAG_FMT_STRING:
- case TAG_FMT_SBYTE:
- dump = erealloc(dump, len + 4 + 1);
- snprintf(dump + len, 4 + 1, "0x%02X", *value_ptr);
- len += 4;
- value_ptr++;
- break;
- case TAG_FMT_USHORT:
- case TAG_FMT_SSHORT:
- dump = erealloc(dump, len + 6 + 1);
- snprintf(dump + len, 6 + 1, "0x%04X", php_ifd_get16s(value_ptr, motorola_intel));
- len += 6;
- value_ptr += 2;
- break;
- case TAG_FMT_ULONG:
- case TAG_FMT_SLONG:
- dump = erealloc(dump, len + 6 + 1);
- snprintf(dump + len, 6 + 1, "0x%04X", php_ifd_get32s(value_ptr, motorola_intel));
- len += 6;
- value_ptr += 4;
- break;
- case TAG_FMT_URATIONAL:
- case TAG_FMT_SRATIONAL:
- dump = erealloc(dump, len + 13 + 1);
- snprintf(dump + len, 13 + 1, "0x%04X/0x%04X", php_ifd_get32s(value_ptr, motorola_intel), php_ifd_get32s(value_ptr+4, motorola_intel));
- len += 13;
- value_ptr += 8;
- break;
- }
- if (components > 0) {
- dump = erealloc(dump, len + 2 + 1);
- snprintf(dump + len, 2 + 1, ", ");
- len += 2;
- components--;
- } else{
- break;
- }
- }
- dump = erealloc(dump, len + 1 + 1);
- snprintf(dump + len, 1 + 1, "}");
- return dump;
- }
- /* }}} */
- #endif
- /* {{{ exif_convert_any_format
- * Evaluate number, be it int, rational, or float from directory. */
- static double exif_convert_any_format(void *value, int format, int motorola_intel TSRMLS_DC)
- {
- int s_den;
- unsigned u_den;
- switch(format) {
- case TAG_FMT_SBYTE: return *(signed char *)value;
- case TAG_FMT_BYTE: return *(uchar *)value;
- case TAG_FMT_USHORT: return php_ifd_get16u(value, motorola_intel);
- case TAG_FMT_ULONG: return php_ifd_get32u(value, motorola_intel);
- case TAG_FMT_URATIONAL:
- u_den = php_ifd_get32u(4+(char *)value, motorola_intel);
- if (u_den == 0) {
- return 0;
- } else {
- return (double)php_ifd_get32u(value, motorola_intel) / u_den;
- }
- case TAG_FMT_SRATIONAL:
- s_den = php_ifd_get32s(4+(char *)value, motorola_intel);
- if (s_den == 0) {
- return 0;
- } else {
- return (double)php_ifd_get32s(value, motorola_intel) / s_den;
- }
- case TAG_FMT_SSHORT: return (signed short)php_ifd_get16u(value, motorola_intel);
- case TAG_FMT_SLONG: return php_ifd_get32s(value, motorola_intel);
- /* Not sure if this is correct (never seen float used in Exif format) */
- case TAG_FMT_SINGLE:
- #ifdef EXIF_DEBUG
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type single");
- #endif
- return (double)*(float *)value;
- case TAG_FMT_DOUBLE:
- #ifdef EXIF_DEBUG
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type double");
- #endif
- return *(double *)value;
- }
- return 0;
- }
- /* }}} */
- /* {{{ exif_convert_any_to_int
- * Evaluate number, be it int, rational, or float from directory. */
- static size_t exif_convert_any_to_int(void *value, int format, int motorola_intel TSRMLS_DC)
- {
- int s_den;
- unsigned u_den;
- switch(format) {
- case TAG_FMT_SBYTE: return *(signed char *)value;
- case TAG_FMT_BYTE: return *(uchar *)value;
- case TAG_FMT_USHORT: return php_ifd_get16u(value, motorola_intel);
- case TAG_FMT_ULONG: return php_ifd_get32u(value, motorola_intel);
- case TAG_FMT_URATIONAL:
- u_den = php_ifd_get32u(4+(char *)value, motorola_intel);
- if (u_den == 0) {
- return 0;
- } else {
- return php_ifd_get32u(value, motorola_intel) / u_den;
- }
- case TAG_FMT_SRATIONAL:
- s_den = php_ifd_get32s(4+(char *)value, motorola_intel);
- if (s_den == 0) {
- return 0;
- } else {
- return php_ifd_get32s(value, motorola_intel) / s_den;
- }
- case TAG_FMT_SSHORT: return php_ifd_get16u(value, motorola_intel);
- case TAG_FMT_SLONG: return php_ifd_get32s(value, motorola_intel);
- /* Not sure if this is correct (never seen float used in Exif format) */
- case TAG_FMT_SINGLE:
- #ifdef EXIF_DEBUG
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type single");
- #endif
- return (size_t)*(float *)value;
- case TAG_FMT_DOUBLE:
- #ifdef EXIF_DEBUG
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type double");
- #endif
- return (size_t)*(double *)value;
- }
- return 0;
- }
- /* }}} */
- /* {{{ struct image_info_value, image_info_list
- */
- #ifndef WORD
- #define WORD unsigned short
- #endif
- #ifndef DWORD
- #define DWORD unsigned int
- #endif
- typedef struct {
- int num;
- int den;
- } signed_rational;
- typedef struct {
- unsigned int num;
- unsigned int den;
- } unsigned_rational;
- typedef union _image_info_value {
- char *s;
- unsigned u;
- int i;
- float f;
- double d;
- signed_rational sr;
- unsigned_rational ur;
- union _image_info_value *list;
- } image_info_value;
- typedef struct {
- WORD tag;
- WORD format;
- DWORD length;
- DWORD dummy; /* value ptr of tiff directory entry */
- char *name;
- image_info_value value;
- } image_info_data;
- typedef struct {
- int count;
- image_info_data *list;
- } image_info_list;
- /* }}} */
- /* {{{ exif_get_sectionname
- Returns the name of a section
- */
- #define SECTION_FILE 0
- #define SECTION_COMPUTED 1
- #define SECTION_ANY_TAG 2
- #define SECTION_IFD0 3
- #define SECTION_THUMBNAIL 4
- #define SECTION_COMMENT 5
- #define SECTION_APP0 6
- #define SECTION_EXIF 7
- #define SECTION_FPIX 8
- #define SECTION_GPS 9
- #define SECTION_INTEROP 10
- #define SECTION_APP12 11
- #define SECTION_WINXP 12
- #define SECTION_MAKERNOTE 13
- #define SECTION_COUNT 14
- #define FOUND_FILE (1<<SECTION_FILE)
- #define FOUND_COMPUTED (1<<SECTION_COMPUTED)
- #define FOUND_ANY_TAG (1<<SECTION_ANY_TAG)
- #define FOUND_IFD0 (1<<SECTION_IFD0)
- #define FOUND_THUMBNAIL (1<<SECTION_THUMBNAIL)
- #define FOUND_COMMENT (1<<SECTION_COMMENT)
- #define FOUND_APP0 (1<<SECTION_APP0)
- #define FOUND_EXIF (1<<SECTION_EXIF)
- #define FOUND_FPIX (1<<SECTION_FPIX)
- #define FOUND_GPS (1<<SECTION_GPS)
- #define FOUND_INTEROP (1<<SECTION_INTEROP)
- #define FOUND_APP12 (1<<SECTION_APP12)
- #define FOUND_WINXP (1<<SECTION_WINXP)
- #define FOUND_MAKERNOTE (1<<SECTION_MAKERNOTE)
- static char *exif_get_sectionname(int section)
- {
- switch(section) {
- case SECTION_FILE: return "FILE";
- case SECTION_COMPUTED: return "COMPUTED";
- case SECTION_ANY_TAG: return "ANY_TAG";
- case SECTION_IFD0: return "IFD0";
- case SECTION_THUMBNAIL: return "THUMBNAIL";
- case SECTION_COMMENT: return "COMMENT";
- case SECTION_APP0: return "APP0";
- case SECTION_EXIF: return "EXIF";
- case SECTION_FPIX: return "FPIX";
- case SECTION_GPS: return "GPS";
- case SECTION_INTEROP: return "INTEROP";
- case SECTION_APP12: return "APP12";
- case SECTION_WINXP: return "WINXP";
- case SECTION_MAKERNOTE: return "MAKERNOTE";
- }
- return "";
- }
- static tag_table_type exif_get_tag_table(int section)
- {
- switch(section) {
- case SECTION_FILE: return &tag_table_IFD[0];
- case SECTION_COMPUTED: return &tag_table_IFD[0];
- case SECTION_ANY_TAG: return &tag_table_IFD[0];
- case SECTION_IFD0: return &tag_table_IFD[0];
- case SECTION_THUMBNAIL: return &tag_table_IFD[0];
- case SECTION_COMMENT: return &tag_table_IFD[0];
- case SECTION_APP0: return &tag_table_IFD[0];
- case SECTION_EXIF: return &tag_table_IFD[0];
- case SECTION_FPIX: return &tag_table_IFD[0];
- case SECTION_GPS: return &tag_table_GPS[0];
- case SECTION_INTEROP: return &tag_table_IOP[0];
- case SECTION_APP12: return &tag_table_IFD[0];
- case SECTION_WINXP: return &tag_table_IFD[0];
- }
- return &tag_table_IFD[0];
- }
- /* }}} */
- /* {{{ exif_get_sectionlist
- Return list of sectionnames specified by sectionlist. Return value must be freed
- */
- static char *exif_get_sectionlist(int sectionlist TSRMLS_DC)
- {
- int i, len, ml = 0;
- char *sections;
- for(i=0; i<SECTION_COUNT; i++) {
- ml += strlen(exif_get_sectionname(i))+2;
- }
- sections = safe_emalloc(ml, 1, 1);
- sections[0] = '\0';
- len = 0;
- for(i=0; i<SECTION_COUNT; i++) {
- if (sectionlist&(1<<i)) {
- snprintf(sections+len, ml-len, "%s, ", exif_get_sectionname(i));
- len = strlen(sections);
- }
- }
- if (len>2)
- sections[len-2] = '\0';
- return sections;
- }
- /* }}} */
- /* {{{ struct image_info_type
- This structure stores Exif header image elements in a simple manner
- Used to store camera data as extracted from the various ways that it can be
- stored in a nexif header
- */
- typedef struct {
- int type;
- size_t size;
- uchar *data;
- } file_section;
- typedef struct {
- int count;
- file_section *list;
- } file_section_list;
- typedef struct {
- image_filetype filetype;
- size_t width, height;
- size_t size;
- size_t offset;
- char *data;
- } thumbnail_data;
- typedef struct {
- char *value;
- size_t size;
- int tag;
- } xp_field_type;
- typedef struct {
- int count;
- xp_field_type *list;
- } xp_field_list;
- /* This structure is used to store a section of a Jpeg file. */
- typedef struct {
- php_stream *infile;
- char *FileName;
- time_t FileDateTime;
- size_t FileSize;
- image_filetype FileType;
- int Height, Width;
- int IsColor;
- char *make;
- char *model;
- float ApertureFNumber;
- float ExposureTime;
- double FocalplaneUnits;
- float CCDWidth;
- double FocalplaneXRes;
- size_t ExifImageWidth;
- float FocalLength;
- float Distance;
- int motorola_intel; /* 1 Motorola; 0 Intel */
- char *UserComment;
- int UserCommentLength;
- char *UserCommentEncoding;
- char *encode_unicode;
- char *decode_unicode_be;
- char *decode_unicode_le;
- char *encode_jis;
- char *decode_jis_be;
- char *decode_jis_le;
- char *Copyright;/* EXIF standard defines Copyright as "<Photographer> [ '\0' <Editor> ] ['\0']" */
- char *CopyrightPhotographer;
- char *CopyrightEditor;
- xp_field_list xp_fields;
- thumbnail_data Thumbnail;
- /* other */
- int sections_found; /* FOUND_<marker> */
- image_info_list info_list[SECTION_COUNT];
- /* for parsing */
- int read_thumbnail;
- int read_all;
- int ifd_nesting_level;
- /* internal */
- file_section_list file;
- } image_info_type;
- /* }}} */
- /* {{{ exif_error_docref */
- static void exif_error_docref(const char *docref EXIFERR_DC, const image_info_type *ImageInfo, int type, const char *format, ...)
- {
- va_list args;
-
- va_start(args, format);
- #ifdef EXIF_DEBUG
- {
- char *buf;
- spprintf(&buf, 0, "%s(%d): %s", _file, _line, format);
- php_verror(docref, ImageInfo->FileName?ImageInfo->FileName:"", type, buf, args TSRMLS_CC);
- efree(buf);
- }
- #else
- php_verror(docref, ImageInfo->FileName?ImageInfo->FileName:"", type, format, args TSRMLS_CC);
- #en…
Large files files are truncated, but you can click here to view the full file