PageRenderTime 61ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 2ms

/ext/exif/exif.c

http://github.com/infusion/PHP
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

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2011 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Rasmus Lerdorf <rasmus@php.net> |
  16. | Marcus Boerger <helly@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id: exif.c 308362 2011-02-15 14:02:26Z pajoye $ */
  20. /* ToDos
  21. *
  22. * See if example images from http://www.exif.org have illegal
  23. * thumbnail sizes or if code is corrupt.
  24. * Create/Update exif headers.
  25. * Create/Remove/Update image thumbnails.
  26. */
  27. /* Security
  28. *
  29. * At current time i do not see any security problems but a potential
  30. * attacker could generate an image with recursive ifd pointers...(Marcus)
  31. */
  32. #ifdef HAVE_CONFIG_H
  33. #include "config.h"
  34. #endif
  35. #include "php.h"
  36. #include "ext/standard/file.h"
  37. #ifdef HAVE_STDINT_H
  38. # include <stdint.h>
  39. #endif
  40. #ifdef HAVE_INTTYPES_H
  41. # include <inttypes.h>
  42. #endif
  43. #ifdef PHP_WIN32
  44. # include "win32/php_stdint.h"
  45. #endif
  46. #if HAVE_EXIF
  47. /* When EXIF_DEBUG is defined the module generates a lot of debug messages
  48. * that help understanding what is going on. This can and should be used
  49. * while extending the module as it shows if you are at the right position.
  50. * You are always considered to have a copy of TIFF6.0 and EXIF2.10 standard.
  51. */
  52. #undef EXIF_DEBUG
  53. #ifdef EXIF_DEBUG
  54. #define EXIFERR_DC , const char *_file, size_t _line TSRMLS_DC
  55. #define EXIFERR_CC , __FILE__, __LINE__ TSRMLS_CC
  56. #else
  57. #define EXIFERR_DC TSRMLS_DC
  58. #define EXIFERR_CC TSRMLS_CC
  59. #endif
  60. #undef EXIF_JPEG2000
  61. #include "php_exif.h"
  62. #include <math.h>
  63. #include "php_ini.h"
  64. #include "ext/standard/php_string.h"
  65. #include "ext/standard/php_image.h"
  66. #include "ext/standard/info.h"
  67. #if defined(PHP_WIN32) || (HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING))
  68. #define EXIF_USE_MBSTRING 1
  69. #else
  70. #define EXIF_USE_MBSTRING 0
  71. #endif
  72. #if EXIF_USE_MBSTRING
  73. #include "ext/mbstring/mbstring.h"
  74. #endif
  75. /* needed for ssize_t definition */
  76. #include <sys/types.h>
  77. typedef unsigned char uchar;
  78. #ifndef safe_emalloc
  79. # define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
  80. #endif
  81. #ifndef safe_erealloc
  82. # define safe_erealloc(p,a,b,c) erealloc(p, (a)*(b)+(c))
  83. #endif
  84. #ifndef TRUE
  85. # define TRUE 1
  86. # define FALSE 0
  87. #endif
  88. #ifndef max
  89. # define max(a,b) ((a)>(b) ? (a) : (b))
  90. #endif
  91. #define EFREE_IF(ptr) if (ptr) efree(ptr)
  92. #define MAX_IFD_NESTING_LEVEL 100
  93. /* {{{ arginfo */
  94. ZEND_BEGIN_ARG_INFO(arginfo_exif_tagname, 0)
  95. ZEND_ARG_INFO(0, index)
  96. ZEND_END_ARG_INFO()
  97. ZEND_BEGIN_ARG_INFO_EX(arginfo_exif_read_data, 0, 0, 1)
  98. ZEND_ARG_INFO(0, filename)
  99. ZEND_ARG_INFO(0, sections_needed)
  100. ZEND_ARG_INFO(0, sub_arrays)
  101. ZEND_ARG_INFO(0, read_thumbnail)
  102. ZEND_END_ARG_INFO()
  103. ZEND_BEGIN_ARG_INFO_EX(arginfo_exif_thumbnail, 0, 0, 1)
  104. ZEND_ARG_INFO(0, filename)
  105. ZEND_ARG_INFO(1, width)
  106. ZEND_ARG_INFO(1, height)
  107. ZEND_ARG_INFO(1, imagetype)
  108. ZEND_END_ARG_INFO()
  109. ZEND_BEGIN_ARG_INFO(arginfo_exif_imagetype, 0)
  110. ZEND_ARG_INFO(0, imagefile)
  111. ZEND_END_ARG_INFO()
  112. /* }}} */
  113. /* {{{ exif_functions[]
  114. */
  115. const zend_function_entry exif_functions[] = {
  116. PHP_FE(exif_read_data, arginfo_exif_read_data)
  117. PHP_FALIAS(read_exif_data, exif_read_data, arginfo_exif_read_data)
  118. PHP_FE(exif_tagname, arginfo_exif_tagname)
  119. PHP_FE(exif_thumbnail, arginfo_exif_thumbnail)
  120. PHP_FE(exif_imagetype, arginfo_exif_imagetype)
  121. {NULL, NULL, NULL}
  122. };
  123. /* }}} */
  124. #define EXIF_VERSION "1.4 $Id: exif.c 308362 2011-02-15 14:02:26Z pajoye $"
  125. /* {{{ PHP_MINFO_FUNCTION
  126. */
  127. PHP_MINFO_FUNCTION(exif)
  128. {
  129. php_info_print_table_start();
  130. php_info_print_table_row(2, "EXIF Support", "enabled");
  131. php_info_print_table_row(2, "EXIF Version", EXIF_VERSION);
  132. php_info_print_table_row(2, "Supported EXIF Version", "0220");
  133. php_info_print_table_row(2, "Supported filetypes", "JPEG,TIFF");
  134. php_info_print_table_end();
  135. DISPLAY_INI_ENTRIES();
  136. }
  137. /* }}} */
  138. ZEND_BEGIN_MODULE_GLOBALS(exif)
  139. char * encode_unicode;
  140. char * decode_unicode_be;
  141. char * decode_unicode_le;
  142. char * encode_jis;
  143. char * decode_jis_be;
  144. char * decode_jis_le;
  145. ZEND_END_MODULE_GLOBALS(exif)
  146. ZEND_DECLARE_MODULE_GLOBALS(exif)
  147. #ifdef ZTS
  148. #define EXIF_G(v) TSRMG(exif_globals_id, zend_exif_globals *, v)
  149. #else
  150. #define EXIF_G(v) (exif_globals.v)
  151. #endif
  152. /* {{{ PHP_INI
  153. */
  154. ZEND_INI_MH(OnUpdateEncode)
  155. {
  156. #if EXIF_USE_MBSTRING
  157. if (new_value && strlen(new_value) && !php_mb_check_encoding_list(new_value TSRMLS_CC)) {
  158. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
  159. return FAILURE;
  160. }
  161. #endif
  162. return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
  163. }
  164. ZEND_INI_MH(OnUpdateDecode)
  165. {
  166. #if EXIF_USE_MBSTRING
  167. if (!php_mb_check_encoding_list(new_value TSRMLS_CC)) {
  168. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
  169. return FAILURE;
  170. }
  171. #endif
  172. return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
  173. }
  174. PHP_INI_BEGIN()
  175. STD_PHP_INI_ENTRY("exif.encode_unicode", "ISO-8859-15", PHP_INI_ALL, OnUpdateEncode, encode_unicode, zend_exif_globals, exif_globals)
  176. STD_PHP_INI_ENTRY("exif.decode_unicode_motorola", "UCS-2BE", PHP_INI_ALL, OnUpdateDecode, decode_unicode_be, zend_exif_globals, exif_globals)
  177. STD_PHP_INI_ENTRY("exif.decode_unicode_intel", "UCS-2LE", PHP_INI_ALL, OnUpdateDecode, decode_unicode_le, zend_exif_globals, exif_globals)
  178. STD_PHP_INI_ENTRY("exif.encode_jis", "", PHP_INI_ALL, OnUpdateEncode, encode_jis, zend_exif_globals, exif_globals)
  179. STD_PHP_INI_ENTRY("exif.decode_jis_motorola", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_be, zend_exif_globals, exif_globals)
  180. STD_PHP_INI_ENTRY("exif.decode_jis_intel", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_le, zend_exif_globals, exif_globals)
  181. PHP_INI_END()
  182. /* }}} */
  183. /* {{{ PHP_GINIT_FUNCTION
  184. */
  185. static PHP_GINIT_FUNCTION(exif)
  186. {
  187. exif_globals->encode_unicode = NULL;
  188. exif_globals->decode_unicode_be = NULL;
  189. exif_globals->decode_unicode_le = NULL;
  190. exif_globals->encode_jis = NULL;
  191. exif_globals->decode_jis_be = NULL;
  192. exif_globals->decode_jis_le = NULL;
  193. }
  194. /* }}} */
  195. /* {{{ PHP_MINIT_FUNCTION(exif)
  196. Get the size of an image as 4-element array */
  197. PHP_MINIT_FUNCTION(exif)
  198. {
  199. REGISTER_INI_ENTRIES();
  200. REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", EXIF_USE_MBSTRING, CONST_CS | CONST_PERSISTENT);
  201. return SUCCESS;
  202. }
  203. /* }}} */
  204. /* {{{ PHP_MSHUTDOWN_FUNCTION
  205. */
  206. PHP_MSHUTDOWN_FUNCTION(exif)
  207. {
  208. UNREGISTER_INI_ENTRIES();
  209. return SUCCESS;
  210. }
  211. /* }}} */
  212. /* {{{ exif dependencies */
  213. static const zend_module_dep exif_module_deps[] = {
  214. ZEND_MOD_REQUIRED("standard")
  215. #if EXIF_USE_MBSTRING
  216. ZEND_MOD_REQUIRED("mbstring")
  217. #endif
  218. {NULL, NULL, NULL}
  219. };
  220. /* }}} */
  221. /* {{{ exif_module_entry
  222. */
  223. zend_module_entry exif_module_entry = {
  224. STANDARD_MODULE_HEADER_EX, NULL,
  225. exif_module_deps,
  226. "exif",
  227. exif_functions,
  228. PHP_MINIT(exif),
  229. PHP_MSHUTDOWN(exif),
  230. NULL, NULL,
  231. PHP_MINFO(exif),
  232. #if ZEND_MODULE_API_NO >= 20010901
  233. EXIF_VERSION,
  234. #endif
  235. #if ZEND_MODULE_API_NO >= 20060613
  236. PHP_MODULE_GLOBALS(exif),
  237. PHP_GINIT(exif),
  238. NULL,
  239. NULL,
  240. STANDARD_MODULE_PROPERTIES_EX
  241. #else
  242. STANDARD_MODULE_PROPERTIES
  243. #endif
  244. };
  245. /* }}} */
  246. #ifdef COMPILE_DL_EXIF
  247. ZEND_GET_MODULE(exif)
  248. #endif
  249. /* {{{ php_strnlen
  250. * get length of string if buffer if less than buffer size or buffer size */
  251. static size_t php_strnlen(char* str, size_t maxlen) {
  252. size_t len = 0;
  253. if (str && maxlen && *str) {
  254. do {
  255. len++;
  256. } while (--maxlen && *(++str));
  257. }
  258. return len;
  259. }
  260. /* }}} */
  261. /* {{{ error messages
  262. */
  263. static const char * EXIF_ERROR_FILEEOF = "Unexpected end of file reached";
  264. static const char * EXIF_ERROR_CORRUPT = "File structure corrupted";
  265. static const char * EXIF_ERROR_THUMBEOF = "Thumbnail goes IFD boundary or end of file reached";
  266. static const char * EXIF_ERROR_FSREALLOC = "Illegal reallocating of undefined file section";
  267. #define EXIF_ERRLOG_FILEEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FILEEOF);
  268. #define EXIF_ERRLOG_CORRUPT(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_CORRUPT);
  269. #define EXIF_ERRLOG_THUMBEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_THUMBEOF);
  270. #define EXIF_ERRLOG_FSREALLOC(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FSREALLOC);
  271. /* }}} */
  272. /* {{{ format description defines
  273. Describes format descriptor
  274. */
  275. static int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 1};
  276. #define NUM_FORMATS 13
  277. #define TAG_FMT_BYTE 1
  278. #define TAG_FMT_STRING 2
  279. #define TAG_FMT_USHORT 3
  280. #define TAG_FMT_ULONG 4
  281. #define TAG_FMT_URATIONAL 5
  282. #define TAG_FMT_SBYTE 6
  283. #define TAG_FMT_UNDEFINED 7
  284. #define TAG_FMT_SSHORT 8
  285. #define TAG_FMT_SLONG 9
  286. #define TAG_FMT_SRATIONAL 10
  287. #define TAG_FMT_SINGLE 11
  288. #define TAG_FMT_DOUBLE 12
  289. #define TAG_FMT_IFD 13
  290. #ifdef EXIF_DEBUG
  291. static char *exif_get_tagformat(int format)
  292. {
  293. switch(format) {
  294. case TAG_FMT_BYTE: return "BYTE";
  295. case TAG_FMT_STRING: return "STRING";
  296. case TAG_FMT_USHORT: return "USHORT";
  297. case TAG_FMT_ULONG: return "ULONG";
  298. case TAG_FMT_URATIONAL: return "URATIONAL";
  299. case TAG_FMT_SBYTE: return "SBYTE";
  300. case TAG_FMT_UNDEFINED: return "UNDEFINED";
  301. case TAG_FMT_SSHORT: return "SSHORT";
  302. case TAG_FMT_SLONG: return "SLONG";
  303. case TAG_FMT_SRATIONAL: return "SRATIONAL";
  304. case TAG_FMT_SINGLE: return "SINGLE";
  305. case TAG_FMT_DOUBLE: return "DOUBLE";
  306. case TAG_FMT_IFD: return "IFD";
  307. }
  308. return "*Illegal";
  309. }
  310. #endif
  311. /* Describes tag values */
  312. #define TAG_GPS_VERSION_ID 0x0000
  313. #define TAG_GPS_LATITUDE_REF 0x0001
  314. #define TAG_GPS_LATITUDE 0x0002
  315. #define TAG_GPS_LONGITUDE_REF 0x0003
  316. #define TAG_GPS_LONGITUDE 0x0004
  317. #define TAG_GPS_ALTITUDE_REF 0x0005
  318. #define TAG_GPS_ALTITUDE 0x0006
  319. #define TAG_GPS_TIME_STAMP 0x0007
  320. #define TAG_GPS_SATELLITES 0x0008
  321. #define TAG_GPS_STATUS 0x0009
  322. #define TAG_GPS_MEASURE_MODE 0x000A
  323. #define TAG_GPS_DOP 0x000B
  324. #define TAG_GPS_SPEED_REF 0x000C
  325. #define TAG_GPS_SPEED 0x000D
  326. #define TAG_GPS_TRACK_REF 0x000E
  327. #define TAG_GPS_TRACK 0x000F
  328. #define TAG_GPS_IMG_DIRECTION_REF 0x0010
  329. #define TAG_GPS_IMG_DIRECTION 0x0011
  330. #define TAG_GPS_MAP_DATUM 0x0012
  331. #define TAG_GPS_DEST_LATITUDE_REF 0x0013
  332. #define TAG_GPS_DEST_LATITUDE 0x0014
  333. #define TAG_GPS_DEST_LONGITUDE_REF 0x0015
  334. #define TAG_GPS_DEST_LONGITUDE 0x0016
  335. #define TAG_GPS_DEST_BEARING_REF 0x0017
  336. #define TAG_GPS_DEST_BEARING 0x0018
  337. #define TAG_GPS_DEST_DISTANCE_REF 0x0019
  338. #define TAG_GPS_DEST_DISTANCE 0x001A
  339. #define TAG_GPS_PROCESSING_METHOD 0x001B
  340. #define TAG_GPS_AREA_INFORMATION 0x001C
  341. #define TAG_GPS_DATE_STAMP 0x001D
  342. #define TAG_GPS_DIFFERENTIAL 0x001E
  343. #define TAG_TIFF_COMMENT 0x00FE /* SHOUDLNT HAPPEN */
  344. #define TAG_NEW_SUBFILE 0x00FE /* New version of subfile tag */
  345. #define TAG_SUBFILE_TYPE 0x00FF /* Old version of subfile tag */
  346. #define TAG_IMAGEWIDTH 0x0100
  347. #define TAG_IMAGEHEIGHT 0x0101
  348. #define TAG_BITS_PER_SAMPLE 0x0102
  349. #define TAG_COMPRESSION 0x0103
  350. #define TAG_PHOTOMETRIC_INTERPRETATION 0x0106
  351. #define TAG_TRESHHOLDING 0x0107
  352. #define TAG_CELL_WIDTH 0x0108
  353. #define TAG_CELL_HEIGHT 0x0109
  354. #define TAG_FILL_ORDER 0x010A
  355. #define TAG_DOCUMENT_NAME 0x010D
  356. #define TAG_IMAGE_DESCRIPTION 0x010E
  357. #define TAG_MAKE 0x010F
  358. #define TAG_MODEL 0x0110
  359. #define TAG_STRIP_OFFSETS 0x0111
  360. #define TAG_ORIENTATION 0x0112
  361. #define TAG_SAMPLES_PER_PIXEL 0x0115
  362. #define TAG_ROWS_PER_STRIP 0x0116
  363. #define TAG_STRIP_BYTE_COUNTS 0x0117
  364. #define TAG_MIN_SAMPPLE_VALUE 0x0118
  365. #define TAG_MAX_SAMPLE_VALUE 0x0119
  366. #define TAG_X_RESOLUTION 0x011A
  367. #define TAG_Y_RESOLUTION 0x011B
  368. #define TAG_PLANAR_CONFIGURATION 0x011C
  369. #define TAG_PAGE_NAME 0x011D
  370. #define TAG_X_POSITION 0x011E
  371. #define TAG_Y_POSITION 0x011F
  372. #define TAG_FREE_OFFSETS 0x0120
  373. #define TAG_FREE_BYTE_COUNTS 0x0121
  374. #define TAG_GRAY_RESPONSE_UNIT 0x0122
  375. #define TAG_GRAY_RESPONSE_CURVE 0x0123
  376. #define TAG_RESOLUTION_UNIT 0x0128
  377. #define TAG_PAGE_NUMBER 0x0129
  378. #define TAG_TRANSFER_FUNCTION 0x012D
  379. #define TAG_SOFTWARE 0x0131
  380. #define TAG_DATETIME 0x0132
  381. #define TAG_ARTIST 0x013B
  382. #define TAG_HOST_COMPUTER 0x013C
  383. #define TAG_PREDICTOR 0x013D
  384. #define TAG_WHITE_POINT 0x013E
  385. #define TAG_PRIMARY_CHROMATICITIES 0x013F
  386. #define TAG_COLOR_MAP 0x0140
  387. #define TAG_HALFTONE_HINTS 0x0141
  388. #define TAG_TILE_WIDTH 0x0142
  389. #define TAG_TILE_LENGTH 0x0143
  390. #define TAG_TILE_OFFSETS 0x0144
  391. #define TAG_TILE_BYTE_COUNTS 0x0145
  392. #define TAG_SUB_IFD 0x014A
  393. #define TAG_INK_SETMPUTER 0x014C
  394. #define TAG_INK_NAMES 0x014D
  395. #define TAG_NUMBER_OF_INKS 0x014E
  396. #define TAG_DOT_RANGE 0x0150
  397. #define TAG_TARGET_PRINTER 0x0151
  398. #define TAG_EXTRA_SAMPLE 0x0152
  399. #define TAG_SAMPLE_FORMAT 0x0153
  400. #define TAG_S_MIN_SAMPLE_VALUE 0x0154
  401. #define TAG_S_MAX_SAMPLE_VALUE 0x0155
  402. #define TAG_TRANSFER_RANGE 0x0156
  403. #define TAG_JPEG_TABLES 0x015B
  404. #define TAG_JPEG_PROC 0x0200
  405. #define TAG_JPEG_INTERCHANGE_FORMAT 0x0201
  406. #define TAG_JPEG_INTERCHANGE_FORMAT_LEN 0x0202
  407. #define TAG_JPEG_RESTART_INTERVAL 0x0203
  408. #define TAG_JPEG_LOSSLESS_PREDICTOR 0x0205
  409. #define TAG_JPEG_POINT_TRANSFORMS 0x0206
  410. #define TAG_JPEG_Q_TABLES 0x0207
  411. #define TAG_JPEG_DC_TABLES 0x0208
  412. #define TAG_JPEG_AC_TABLES 0x0209
  413. #define TAG_YCC_COEFFICIENTS 0x0211
  414. #define TAG_YCC_SUB_SAMPLING 0x0212
  415. #define TAG_YCC_POSITIONING 0x0213
  416. #define TAG_REFERENCE_BLACK_WHITE 0x0214
  417. /* 0x0301 - 0x0302 */
  418. /* 0x0320 */
  419. /* 0x0343 */
  420. /* 0x5001 - 0x501B */
  421. /* 0x5021 - 0x503B */
  422. /* 0x5090 - 0x5091 */
  423. /* 0x5100 - 0x5101 */
  424. /* 0x5110 - 0x5113 */
  425. /* 0x80E3 - 0x80E6 */
  426. /* 0x828d - 0x828F */
  427. #define TAG_COPYRIGHT 0x8298
  428. #define TAG_EXPOSURETIME 0x829A
  429. #define TAG_FNUMBER 0x829D
  430. #define TAG_EXIF_IFD_POINTER 0x8769
  431. #define TAG_ICC_PROFILE 0x8773
  432. #define TAG_EXPOSURE_PROGRAM 0x8822
  433. #define TAG_SPECTRAL_SENSITY 0x8824
  434. #define TAG_GPS_IFD_POINTER 0x8825
  435. #define TAG_ISOSPEED 0x8827
  436. #define TAG_OPTOELECTRIC_CONVERSION_F 0x8828
  437. /* 0x8829 - 0x882b */
  438. #define TAG_EXIFVERSION 0x9000
  439. #define TAG_DATE_TIME_ORIGINAL 0x9003
  440. #define TAG_DATE_TIME_DIGITIZED 0x9004
  441. #define TAG_COMPONENT_CONFIG 0x9101
  442. #define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102
  443. #define TAG_SHUTTERSPEED 0x9201
  444. #define TAG_APERTURE 0x9202
  445. #define TAG_BRIGHTNESS_VALUE 0x9203
  446. #define TAG_EXPOSURE_BIAS_VALUE 0x9204
  447. #define TAG_MAX_APERTURE 0x9205
  448. #define TAG_SUBJECT_DISTANCE 0x9206
  449. #define TAG_METRIC_MODULE 0x9207
  450. #define TAG_LIGHT_SOURCE 0x9208
  451. #define TAG_FLASH 0x9209
  452. #define TAG_FOCAL_LENGTH 0x920A
  453. /* 0x920B - 0x920D */
  454. /* 0x9211 - 0x9216 */
  455. #define TAG_SUBJECT_AREA 0x9214
  456. #define TAG_MAKER_NOTE 0x927C
  457. #define TAG_USERCOMMENT 0x9286
  458. #define TAG_SUB_SEC_TIME 0x9290
  459. #define TAG_SUB_SEC_TIME_ORIGINAL 0x9291
  460. #define TAG_SUB_SEC_TIME_DIGITIZED 0x9292
  461. /* 0x923F */
  462. /* 0x935C */
  463. #define TAG_XP_TITLE 0x9C9B
  464. #define TAG_XP_COMMENTS 0x9C9C
  465. #define TAG_XP_AUTHOR 0x9C9D
  466. #define TAG_XP_KEYWORDS 0x9C9E
  467. #define TAG_XP_SUBJECT 0x9C9F
  468. #define TAG_FLASH_PIX_VERSION 0xA000
  469. #define TAG_COLOR_SPACE 0xA001
  470. #define TAG_COMP_IMAGE_WIDTH 0xA002 /* compressed images only */
  471. #define TAG_COMP_IMAGE_HEIGHT 0xA003
  472. #define TAG_RELATED_SOUND_FILE 0xA004
  473. #define TAG_INTEROP_IFD_POINTER 0xA005 /* IFD pointer */
  474. #define TAG_FLASH_ENERGY 0xA20B
  475. #define TAG_SPATIAL_FREQUENCY_RESPONSE 0xA20C
  476. #define TAG_FOCALPLANE_X_RES 0xA20E
  477. #define TAG_FOCALPLANE_Y_RES 0xA20F
  478. #define TAG_FOCALPLANE_RESOLUTION_UNIT 0xA210
  479. #define TAG_SUBJECT_LOCATION 0xA214
  480. #define TAG_EXPOSURE_INDEX 0xA215
  481. #define TAG_SENSING_METHOD 0xA217
  482. #define TAG_FILE_SOURCE 0xA300
  483. #define TAG_SCENE_TYPE 0xA301
  484. #define TAG_CFA_PATTERN 0xA302
  485. #define TAG_CUSTOM_RENDERED 0xA401
  486. #define TAG_EXPOSURE_MODE 0xA402
  487. #define TAG_WHITE_BALANCE 0xA403
  488. #define TAG_DIGITAL_ZOOM_RATIO 0xA404
  489. #define TAG_FOCAL_LENGTH_IN_35_MM_FILM 0xA405
  490. #define TAG_SCENE_CAPTURE_TYPE 0xA406
  491. #define TAG_GAIN_CONTROL 0xA407
  492. #define TAG_CONTRAST 0xA408
  493. #define TAG_SATURATION 0xA409
  494. #define TAG_SHARPNESS 0xA40A
  495. #define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B
  496. #define TAG_SUBJECT_DISTANCE_RANGE 0xA40C
  497. #define TAG_IMAGE_UNIQUE_ID 0xA420
  498. /* Olympus specific tags */
  499. #define TAG_OLYMPUS_SPECIALMODE 0x0200
  500. #define TAG_OLYMPUS_JPEGQUAL 0x0201
  501. #define TAG_OLYMPUS_MACRO 0x0202
  502. #define TAG_OLYMPUS_DIGIZOOM 0x0204
  503. #define TAG_OLYMPUS_SOFTWARERELEASE 0x0207
  504. #define TAG_OLYMPUS_PICTINFO 0x0208
  505. #define TAG_OLYMPUS_CAMERAID 0x0209
  506. /* end Olympus specific tags */
  507. /* Internal */
  508. #define TAG_NONE -1 /* note that -1 <> 0xFFFF */
  509. #define TAG_COMPUTED_VALUE -2
  510. #define TAG_END_OF_LIST 0xFFFD
  511. /* Values for TAG_PHOTOMETRIC_INTERPRETATION */
  512. #define PMI_BLACK_IS_ZERO 0
  513. #define PMI_WHITE_IS_ZERO 1
  514. #define PMI_RGB 2
  515. #define PMI_PALETTE_COLOR 3
  516. #define PMI_TRANSPARENCY_MASK 4
  517. #define PMI_SEPARATED 5
  518. #define PMI_YCBCR 6
  519. #define PMI_CIELAB 8
  520. /* }}} */
  521. /* {{{ TabTable[]
  522. */
  523. typedef const struct {
  524. unsigned short Tag;
  525. char *Desc;
  526. } tag_info_type;
  527. typedef tag_info_type tag_info_array[];
  528. typedef tag_info_type *tag_table_type;
  529. #define TAG_TABLE_END \
  530. {TAG_NONE, "No tag value"},\
  531. {TAG_COMPUTED_VALUE, "Computed value"},\
  532. {TAG_END_OF_LIST, ""} /* Important for exif_get_tagname() IF value != "" function result is != false */
  533. static tag_info_array tag_table_IFD = {
  534. { 0x000B, "ACDComment"},
  535. { 0x00FE, "NewSubFile"}, /* better name it 'ImageType' ? */
  536. { 0x00FF, "SubFile"},
  537. { 0x0100, "ImageWidth"},
  538. { 0x0101, "ImageLength"},
  539. { 0x0102, "BitsPerSample"},
  540. { 0x0103, "Compression"},
  541. { 0x0106, "PhotometricInterpretation"},
  542. { 0x010A, "FillOrder"},
  543. { 0x010D, "DocumentName"},
  544. { 0x010E, "ImageDescription"},
  545. { 0x010F, "Make"},
  546. { 0x0110, "Model"},
  547. { 0x0111, "StripOffsets"},
  548. { 0x0112, "Orientation"},
  549. { 0x0115, "SamplesPerPixel"},
  550. { 0x0116, "RowsPerStrip"},
  551. { 0x0117, "StripByteCounts"},
  552. { 0x0118, "MinSampleValue"},
  553. { 0x0119, "MaxSampleValue"},
  554. { 0x011A, "XResolution"},
  555. { 0x011B, "YResolution"},
  556. { 0x011C, "PlanarConfiguration"},
  557. { 0x011D, "PageName"},
  558. { 0x011E, "XPosition"},
  559. { 0x011F, "YPosition"},
  560. { 0x0120, "FreeOffsets"},
  561. { 0x0121, "FreeByteCounts"},
  562. { 0x0122, "GrayResponseUnit"},
  563. { 0x0123, "GrayResponseCurve"},
  564. { 0x0124, "T4Options"},
  565. { 0x0125, "T6Options"},
  566. { 0x0128, "ResolutionUnit"},
  567. { 0x0129, "PageNumber"},
  568. { 0x012D, "TransferFunction"},
  569. { 0x0131, "Software"},
  570. { 0x0132, "DateTime"},
  571. { 0x013B, "Artist"},
  572. { 0x013C, "HostComputer"},
  573. { 0x013D, "Predictor"},
  574. { 0x013E, "WhitePoint"},
  575. { 0x013F, "PrimaryChromaticities"},
  576. { 0x0140, "ColorMap"},
  577. { 0x0141, "HalfToneHints"},
  578. { 0x0142, "TileWidth"},
  579. { 0x0143, "TileLength"},
  580. { 0x0144, "TileOffsets"},
  581. { 0x0145, "TileByteCounts"},
  582. { 0x014A, "SubIFD"},
  583. { 0x014C, "InkSet"},
  584. { 0x014D, "InkNames"},
  585. { 0x014E, "NumberOfInks"},
  586. { 0x0150, "DotRange"},
  587. { 0x0151, "TargetPrinter"},
  588. { 0x0152, "ExtraSample"},
  589. { 0x0153, "SampleFormat"},
  590. { 0x0154, "SMinSampleValue"},
  591. { 0x0155, "SMaxSampleValue"},
  592. { 0x0156, "TransferRange"},
  593. { 0x0157, "ClipPath"},
  594. { 0x0158, "XClipPathUnits"},
  595. { 0x0159, "YClipPathUnits"},
  596. { 0x015A, "Indexed"},
  597. { 0x015B, "JPEGTables"},
  598. { 0x015F, "OPIProxy"},
  599. { 0x0200, "JPEGProc"},
  600. { 0x0201, "JPEGInterchangeFormat"},
  601. { 0x0202, "JPEGInterchangeFormatLength"},
  602. { 0x0203, "JPEGRestartInterval"},
  603. { 0x0205, "JPEGLosslessPredictors"},
  604. { 0x0206, "JPEGPointTransforms"},
  605. { 0x0207, "JPEGQTables"},
  606. { 0x0208, "JPEGDCTables"},
  607. { 0x0209, "JPEGACTables"},
  608. { 0x0211, "YCbCrCoefficients"},
  609. { 0x0212, "YCbCrSubSampling"},
  610. { 0x0213, "YCbCrPositioning"},
  611. { 0x0214, "ReferenceBlackWhite"},
  612. { 0x02BC, "ExtensibleMetadataPlatform"}, /* XAP: Extensible Authoring Publishing, obsoleted by XMP: Extensible Metadata Platform */
  613. { 0x0301, "Gamma"},
  614. { 0x0302, "ICCProfileDescriptor"},
  615. { 0x0303, "SRGBRenderingIntent"},
  616. { 0x0320, "ImageTitle"},
  617. { 0x5001, "ResolutionXUnit"},
  618. { 0x5002, "ResolutionYUnit"},
  619. { 0x5003, "ResolutionXLengthUnit"},
  620. { 0x5004, "ResolutionYLengthUnit"},
  621. { 0x5005, "PrintFlags"},
  622. { 0x5006, "PrintFlagsVersion"},
  623. { 0x5007, "PrintFlagsCrop"},
  624. { 0x5008, "PrintFlagsBleedWidth"},
  625. { 0x5009, "PrintFlagsBleedWidthScale"},
  626. { 0x500A, "HalftoneLPI"},
  627. { 0x500B, "HalftoneLPIUnit"},
  628. { 0x500C, "HalftoneDegree"},
  629. { 0x500D, "HalftoneShape"},
  630. { 0x500E, "HalftoneMisc"},
  631. { 0x500F, "HalftoneScreen"},
  632. { 0x5010, "JPEGQuality"},
  633. { 0x5011, "GridSize"},
  634. { 0x5012, "ThumbnailFormat"},
  635. { 0x5013, "ThumbnailWidth"},
  636. { 0x5014, "ThumbnailHeight"},
  637. { 0x5015, "ThumbnailColorDepth"},
  638. { 0x5016, "ThumbnailPlanes"},
  639. { 0x5017, "ThumbnailRawBytes"},
  640. { 0x5018, "ThumbnailSize"},
  641. { 0x5019, "ThumbnailCompressedSize"},
  642. { 0x501A, "ColorTransferFunction"},
  643. { 0x501B, "ThumbnailData"},
  644. { 0x5020, "ThumbnailImageWidth"},
  645. { 0x5021, "ThumbnailImageHeight"},
  646. { 0x5022, "ThumbnailBitsPerSample"},
  647. { 0x5023, "ThumbnailCompression"},
  648. { 0x5024, "ThumbnailPhotometricInterp"},
  649. { 0x5025, "ThumbnailImageDescription"},
  650. { 0x5026, "ThumbnailEquipMake"},
  651. { 0x5027, "ThumbnailEquipModel"},
  652. { 0x5028, "ThumbnailStripOffsets"},
  653. { 0x5029, "ThumbnailOrientation"},
  654. { 0x502A, "ThumbnailSamplesPerPixel"},
  655. { 0x502B, "ThumbnailRowsPerStrip"},
  656. { 0x502C, "ThumbnailStripBytesCount"},
  657. { 0x502D, "ThumbnailResolutionX"},
  658. { 0x502E, "ThumbnailResolutionY"},
  659. { 0x502F, "ThumbnailPlanarConfig"},
  660. { 0x5030, "ThumbnailResolutionUnit"},
  661. { 0x5031, "ThumbnailTransferFunction"},
  662. { 0x5032, "ThumbnailSoftwareUsed"},
  663. { 0x5033, "ThumbnailDateTime"},
  664. { 0x5034, "ThumbnailArtist"},
  665. { 0x5035, "ThumbnailWhitePoint"},
  666. { 0x5036, "ThumbnailPrimaryChromaticities"},
  667. { 0x5037, "ThumbnailYCbCrCoefficients"},
  668. { 0x5038, "ThumbnailYCbCrSubsampling"},
  669. { 0x5039, "ThumbnailYCbCrPositioning"},
  670. { 0x503A, "ThumbnailRefBlackWhite"},
  671. { 0x503B, "ThumbnailCopyRight"},
  672. { 0x5090, "LuminanceTable"},
  673. { 0x5091, "ChrominanceTable"},
  674. { 0x5100, "FrameDelay"},
  675. { 0x5101, "LoopCount"},
  676. { 0x5110, "PixelUnit"},
  677. { 0x5111, "PixelPerUnitX"},
  678. { 0x5112, "PixelPerUnitY"},
  679. { 0x5113, "PaletteHistogram"},
  680. { 0x1000, "RelatedImageFileFormat"},
  681. { 0x800D, "ImageID"},
  682. { 0x80E3, "Matteing"}, /* obsoleted by ExtraSamples */
  683. { 0x80E4, "DataType"}, /* obsoleted by SampleFormat */
  684. { 0x80E5, "ImageDepth"},
  685. { 0x80E6, "TileDepth"},
  686. { 0x828D, "CFARepeatPatternDim"},
  687. { 0x828E, "CFAPattern"},
  688. { 0x828F, "BatteryLevel"},
  689. { 0x8298, "Copyright"},
  690. { 0x829A, "ExposureTime"},
  691. { 0x829D, "FNumber"},
  692. { 0x83BB, "IPTC/NAA"},
  693. { 0x84E3, "IT8RasterPadding"},
  694. { 0x84E5, "IT8ColorTable"},
  695. { 0x8649, "ImageResourceInformation"}, /* PhotoShop */
  696. { 0x8769, "Exif_IFD_Pointer"},
  697. { 0x8773, "ICC_Profile"},
  698. { 0x8822, "ExposureProgram"},
  699. { 0x8824, "SpectralSensity"},
  700. { 0x8828, "OECF"},
  701. { 0x8825, "GPS_IFD_Pointer"},
  702. { 0x8827, "ISOSpeedRatings"},
  703. { 0x8828, "OECF"},
  704. { 0x9000, "ExifVersion"},
  705. { 0x9003, "DateTimeOriginal"},
  706. { 0x9004, "DateTimeDigitized"},
  707. { 0x9101, "ComponentsConfiguration"},
  708. { 0x9102, "CompressedBitsPerPixel"},
  709. { 0x9201, "ShutterSpeedValue"},
  710. { 0x9202, "ApertureValue"},
  711. { 0x9203, "BrightnessValue"},
  712. { 0x9204, "ExposureBiasValue"},
  713. { 0x9205, "MaxApertureValue"},
  714. { 0x9206, "SubjectDistance"},
  715. { 0x9207, "MeteringMode"},
  716. { 0x9208, "LightSource"},
  717. { 0x9209, "Flash"},
  718. { 0x920A, "FocalLength"},
  719. { 0x920B, "FlashEnergy"}, /* 0xA20B in JPEG */
  720. { 0x920C, "SpatialFrequencyResponse"}, /* 0xA20C - - */
  721. { 0x920D, "Noise"},
  722. { 0x920E, "FocalPlaneXResolution"}, /* 0xA20E - - */
  723. { 0x920F, "FocalPlaneYResolution"}, /* 0xA20F - - */
  724. { 0x9210, "FocalPlaneResolutionUnit"}, /* 0xA210 - - */
  725. { 0x9211, "ImageNumber"},
  726. { 0x9212, "SecurityClassification"},
  727. { 0x9213, "ImageHistory"},
  728. { 0x9214, "SubjectLocation"}, /* 0xA214 - - */
  729. { 0x9215, "ExposureIndex"}, /* 0xA215 - - */
  730. { 0x9216, "TIFF/EPStandardID"},
  731. { 0x9217, "SensingMethod"}, /* 0xA217 - - */
  732. { 0x923F, "StoNits"},
  733. { 0x927C, "MakerNote"},
  734. { 0x9286, "UserComment"},
  735. { 0x9290, "SubSecTime"},
  736. { 0x9291, "SubSecTimeOriginal"},
  737. { 0x9292, "SubSecTimeDigitized"},
  738. { 0x935C, "ImageSourceData"}, /* "Adobe Photoshop Document Data Block": 8BIM... */
  739. { 0x9c9b, "Title" }, /* Win XP specific, Unicode */
  740. { 0x9c9c, "Comments" }, /* Win XP specific, Unicode */
  741. { 0x9c9d, "Author" }, /* Win XP specific, Unicode */
  742. { 0x9c9e, "Keywords" }, /* Win XP specific, Unicode */
  743. { 0x9c9f, "Subject" }, /* Win XP specific, Unicode, not to be confused with SubjectDistance and SubjectLocation */
  744. { 0xA000, "FlashPixVersion"},
  745. { 0xA001, "ColorSpace"},
  746. { 0xA002, "ExifImageWidth"},
  747. { 0xA003, "ExifImageLength"},
  748. { 0xA004, "RelatedSoundFile"},
  749. { 0xA005, "InteroperabilityOffset"},
  750. { 0xA20B, "FlashEnergy"}, /* 0x920B in TIFF/EP */
  751. { 0xA20C, "SpatialFrequencyResponse"}, /* 0x920C - - */
  752. { 0xA20D, "Noise"},
  753. { 0xA20E, "FocalPlaneXResolution"}, /* 0x920E - - */
  754. { 0xA20F, "FocalPlaneYResolution"}, /* 0x920F - - */
  755. { 0xA210, "FocalPlaneResolutionUnit"}, /* 0x9210 - - */
  756. { 0xA211, "ImageNumber"},
  757. { 0xA212, "SecurityClassification"},
  758. { 0xA213, "ImageHistory"},
  759. { 0xA214, "SubjectLocation"}, /* 0x9214 - - */
  760. { 0xA215, "ExposureIndex"}, /* 0x9215 - - */
  761. { 0xA216, "TIFF/EPStandardID"},
  762. { 0xA217, "SensingMethod"}, /* 0x9217 - - */
  763. { 0xA300, "FileSource"},
  764. { 0xA301, "SceneType"},
  765. { 0xA302, "CFAPattern"},
  766. { 0xA401, "CustomRendered"},
  767. { 0xA402, "ExposureMode"},
  768. { 0xA403, "WhiteBalance"},
  769. { 0xA404, "DigitalZoomRatio"},
  770. { 0xA405, "FocalLengthIn35mmFilm"},
  771. { 0xA406, "SceneCaptureType"},
  772. { 0xA407, "GainControl"},
  773. { 0xA408, "Contrast"},
  774. { 0xA409, "Saturation"},
  775. { 0xA40A, "Sharpness"},
  776. { 0xA40B, "DeviceSettingDescription"},
  777. { 0xA40C, "SubjectDistanceRange"},
  778. { 0xA420, "ImageUniqueID"},
  779. TAG_TABLE_END
  780. } ;
  781. static tag_info_array tag_table_GPS = {
  782. { 0x0000, "GPSVersion"},
  783. { 0x0001, "GPSLatitudeRef"},
  784. { 0x0002, "GPSLatitude"},
  785. { 0x0003, "GPSLongitudeRef"},
  786. { 0x0004, "GPSLongitude"},
  787. { 0x0005, "GPSAltitudeRef"},
  788. { 0x0006, "GPSAltitude"},
  789. { 0x0007, "GPSTimeStamp"},
  790. { 0x0008, "GPSSatellites"},
  791. { 0x0009, "GPSStatus"},
  792. { 0x000A, "GPSMeasureMode"},
  793. { 0x000B, "GPSDOP"},
  794. { 0x000C, "GPSSpeedRef"},
  795. { 0x000D, "GPSSpeed"},
  796. { 0x000E, "GPSTrackRef"},
  797. { 0x000F, "GPSTrack"},
  798. { 0x0010, "GPSImgDirectionRef"},
  799. { 0x0011, "GPSImgDirection"},
  800. { 0x0012, "GPSMapDatum"},
  801. { 0x0013, "GPSDestLatitudeRef"},
  802. { 0x0014, "GPSDestLatitude"},
  803. { 0x0015, "GPSDestLongitudeRef"},
  804. { 0x0016, "GPSDestLongitude"},
  805. { 0x0017, "GPSDestBearingRef"},
  806. { 0x0018, "GPSDestBearing"},
  807. { 0x0019, "GPSDestDistanceRef"},
  808. { 0x001A, "GPSDestDistance"},
  809. { 0x001B, "GPSProcessingMode"},
  810. { 0x001C, "GPSAreaInformation"},
  811. { 0x001D, "GPSDateStamp"},
  812. { 0x001E, "GPSDifferential"},
  813. TAG_TABLE_END
  814. };
  815. static tag_info_array tag_table_IOP = {
  816. { 0x0001, "InterOperabilityIndex"}, /* should be 'R98' or 'THM' */
  817. { 0x0002, "InterOperabilityVersion"},
  818. { 0x1000, "RelatedFileFormat"},
  819. { 0x1001, "RelatedImageWidth"},
  820. { 0x1002, "RelatedImageHeight"},
  821. TAG_TABLE_END
  822. };
  823. static tag_info_array tag_table_VND_CANON = {
  824. { 0x0001, "ModeArray"}, /* guess */
  825. { 0x0004, "ImageInfo"}, /* guess */
  826. { 0x0006, "ImageType"},
  827. { 0x0007, "FirmwareVersion"},
  828. { 0x0008, "ImageNumber"},
  829. { 0x0009, "OwnerName"},
  830. { 0x000C, "Camera"},
  831. { 0x000F, "CustomFunctions"},
  832. TAG_TABLE_END
  833. };
  834. static tag_info_array tag_table_VND_CASIO = {
  835. { 0x0001, "RecordingMode"},
  836. { 0x0002, "Quality"},
  837. { 0x0003, "FocusingMode"},
  838. { 0x0004, "FlashMode"},
  839. { 0x0005, "FlashIntensity"},
  840. { 0x0006, "ObjectDistance"},
  841. { 0x0007, "WhiteBalance"},
  842. { 0x000A, "DigitalZoom"},
  843. { 0x000B, "Sharpness"},
  844. { 0x000C, "Contrast"},
  845. { 0x000D, "Saturation"},
  846. { 0x0014, "CCDSensitivity"},
  847. TAG_TABLE_END
  848. };
  849. static tag_info_array tag_table_VND_FUJI = {
  850. { 0x0000, "Version"},
  851. { 0x1000, "Quality"},
  852. { 0x1001, "Sharpness"},
  853. { 0x1002, "WhiteBalance"},
  854. { 0x1003, "Color"},
  855. { 0x1004, "Tone"},
  856. { 0x1010, "FlashMode"},
  857. { 0x1011, "FlashStrength"},
  858. { 0x1020, "Macro"},
  859. { 0x1021, "FocusMode"},
  860. { 0x1030, "SlowSync"},
  861. { 0x1031, "PictureMode"},
  862. { 0x1100, "ContTake"},
  863. { 0x1300, "BlurWarning"},
  864. { 0x1301, "FocusWarning"},
  865. { 0x1302, "AEWarning "},
  866. TAG_TABLE_END
  867. };
  868. static tag_info_array tag_table_VND_NIKON = {
  869. { 0x0003, "Quality"},
  870. { 0x0004, "ColorMode"},
  871. { 0x0005, "ImageAdjustment"},
  872. { 0x0006, "CCDSensitivity"},
  873. { 0x0007, "WhiteBalance"},
  874. { 0x0008, "Focus"},
  875. { 0x000a, "DigitalZoom"},
  876. { 0x000b, "Converter"},
  877. TAG_TABLE_END
  878. };
  879. static tag_info_array tag_table_VND_NIKON_990 = {
  880. { 0x0001, "Version"},
  881. { 0x0002, "ISOSetting"},
  882. { 0x0003, "ColorMode"},
  883. { 0x0004, "Quality"},
  884. { 0x0005, "WhiteBalance"},
  885. { 0x0006, "ImageSharpening"},
  886. { 0x0007, "FocusMode"},
  887. { 0x0008, "FlashSetting"},
  888. { 0x000F, "ISOSelection"},
  889. { 0x0080, "ImageAdjustment"},
  890. { 0x0082, "AuxiliaryLens"},
  891. { 0x0085, "ManualFocusDistance"},
  892. { 0x0086, "DigitalZoom"},
  893. { 0x0088, "AFFocusPosition"},
  894. { 0x0010, "DataDump"},
  895. TAG_TABLE_END
  896. };
  897. static tag_info_array tag_table_VND_OLYMPUS = {
  898. { 0x0200, "SpecialMode"},
  899. { 0x0201, "JPEGQuality"},
  900. { 0x0202, "Macro"},
  901. { 0x0204, "DigitalZoom"},
  902. { 0x0207, "SoftwareRelease"},
  903. { 0x0208, "PictureInfo"},
  904. { 0x0209, "CameraId"},
  905. { 0x0F00, "DataDump"},
  906. TAG_TABLE_END
  907. };
  908. typedef enum mn_byte_order_t {
  909. MN_ORDER_INTEL = 0,
  910. MN_ORDER_MOTOROLA = 1,
  911. MN_ORDER_NORMAL
  912. } mn_byte_order_t;
  913. typedef enum mn_offset_mode_t {
  914. MN_OFFSET_NORMAL,
  915. MN_OFFSET_MAKER,
  916. MN_OFFSET_GUESS
  917. } mn_offset_mode_t;
  918. typedef struct {
  919. tag_table_type tag_table;
  920. char * make;
  921. char * model;
  922. char * id_string;
  923. int id_string_len;
  924. int offset;
  925. mn_byte_order_t byte_order;
  926. mn_offset_mode_t offset_mode;
  927. } maker_note_type;
  928. static const maker_note_type maker_note_array[] = {
  929. { tag_table_VND_CANON, "Canon", NULL, NULL, 0, 0, MN_ORDER_INTEL, MN_OFFSET_GUESS},
  930. /* { tag_table_VND_CANON, "Canon", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},*/
  931. { tag_table_VND_CASIO, "CASIO", NULL, NULL, 0, 0, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
  932. { tag_table_VND_FUJI, "FUJIFILM", NULL, "FUJIFILM\x0C\x00\x00\x00", 12, 12, MN_ORDER_INTEL, MN_OFFSET_MAKER},
  933. { tag_table_VND_NIKON, "NIKON", NULL, "Nikon\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  934. { tag_table_VND_NIKON_990, "NIKON", NULL, NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  935. { tag_table_VND_OLYMPUS, "OLYMPUS OPTICAL CO.,LTD", NULL, "OLYMP\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  936. };
  937. /* }}} */
  938. /* {{{ exif_get_tagname
  939. Get headername for tag_num or NULL if not defined */
  940. static char * exif_get_tagname(int tag_num, char *ret, int len, tag_table_type tag_table TSRMLS_DC)
  941. {
  942. int i, t;
  943. char tmp[32];
  944. for (i = 0; (t = tag_table[i].Tag) != TAG_END_OF_LIST; i++) {
  945. if (t == tag_num) {
  946. if (ret && len) {
  947. strlcpy(ret, tag_table[i].Desc, abs(len));
  948. if (len < 0) {
  949. memset(ret + strlen(ret), ' ', -len - strlen(ret) - 1);
  950. ret[-len - 1] = '\0';
  951. }
  952. return ret;
  953. }
  954. return tag_table[i].Desc;
  955. }
  956. }
  957. if (ret && len) {
  958. snprintf(tmp, sizeof(tmp), "UndefinedTag:0x%04X", tag_num);
  959. strlcpy(ret, tmp, abs(len));
  960. if (len < 0) {
  961. memset(ret + strlen(ret), ' ', -len - strlen(ret) - 1);
  962. ret[-len - 1] = '\0';
  963. }
  964. return ret;
  965. }
  966. return "";
  967. }
  968. /* }}} */
  969. /* {{{ exif_char_dump
  970. * Do not use! This is a debug function... */
  971. #ifdef EXIF_DEBUG
  972. static unsigned char* exif_char_dump(unsigned char * addr, int len, int offset)
  973. {
  974. static unsigned char buf[4096+1];
  975. static unsigned char tmp[20];
  976. int c, i, p=0, n = 5+31;
  977. p += slprintf(buf+p, sizeof(buf)-p, "\nDump Len: %08X (%d)", len, len);
  978. if (len) {
  979. for(i=0; i<len+15 && p+n<=sizeof(buf); i++) {
  980. if (i%16==0) {
  981. p += slprintf(buf+p, sizeof(buf)-p, "\n%08X: ", i+offset);
  982. }
  983. if (i<len) {
  984. c = *addr++;
  985. p += slprintf(buf+p, sizeof(buf)-p, "%02X ", c);
  986. tmp[i%16] = c>=32 ? c : '.';
  987. tmp[(i%16)+1] = '\0';
  988. } else {
  989. p += slprintf(buf+p, sizeof(buf)-p, " ");
  990. }
  991. if (i%16==15) {
  992. p += slprintf(buf+p, sizeof(buf)-p, " %s", tmp);
  993. if (i>=len) {
  994. break;
  995. }
  996. }
  997. }
  998. }
  999. buf[sizeof(buf)-1] = '\0';
  1000. return buf;
  1001. }
  1002. #endif
  1003. /* }}} */
  1004. /* {{{ php_jpg_get16
  1005. Get 16 bits motorola order (always) for jpeg header stuff.
  1006. */
  1007. static int php_jpg_get16(void *value)
  1008. {
  1009. return (((uchar *)value)[0] << 8) | ((uchar *)value)[1];
  1010. }
  1011. /* }}} */
  1012. /* {{{ php_ifd_get16u
  1013. * Convert a 16 bit unsigned value from file's native byte order */
  1014. static int php_ifd_get16u(void *value, int motorola_intel)
  1015. {
  1016. if (motorola_intel) {
  1017. return (((uchar *)value)[0] << 8) | ((uchar *)value)[1];
  1018. } else {
  1019. return (((uchar *)value)[1] << 8) | ((uchar *)value)[0];
  1020. }
  1021. }
  1022. /* }}} */
  1023. /* {{{ php_ifd_get16s
  1024. * Convert a 16 bit signed value from file's native byte order */
  1025. static signed short php_ifd_get16s(void *value, int motorola_intel)
  1026. {
  1027. return (signed short)php_ifd_get16u(value, motorola_intel);
  1028. }
  1029. /* }}} */
  1030. /* {{{ php_ifd_get32s
  1031. * Convert a 32 bit signed value from file's native byte order */
  1032. static int php_ifd_get32s(void *value, int motorola_intel)
  1033. {
  1034. if (motorola_intel) {
  1035. return (((char *)value)[0] << 24)
  1036. | (((uchar *)value)[1] << 16)
  1037. | (((uchar *)value)[2] << 8 )
  1038. | (((uchar *)value)[3] );
  1039. } else {
  1040. return (((char *)value)[3] << 24)
  1041. | (((uchar *)value)[2] << 16)
  1042. | (((uchar *)value)[1] << 8 )
  1043. | (((uchar *)value)[0] );
  1044. }
  1045. }
  1046. /* }}} */
  1047. /* {{{ php_ifd_get32u
  1048. * Write 32 bit unsigned value to data */
  1049. static unsigned php_ifd_get32u(void *value, int motorola_intel)
  1050. {
  1051. return (unsigned)php_ifd_get32s(value, motorola_intel) & 0xffffffff;
  1052. }
  1053. /* }}} */
  1054. /* {{{ php_ifd_set16u
  1055. * Write 16 bit unsigned value to data */
  1056. static void php_ifd_set16u(char *data, unsigned int value, int motorola_intel)
  1057. {
  1058. if (motorola_intel) {
  1059. data[0] = (value & 0xFF00) >> 8;
  1060. data[1] = (value & 0x00FF);
  1061. } else {
  1062. data[1] = (value & 0xFF00) >> 8;
  1063. data[0] = (value & 0x00FF);
  1064. }
  1065. }
  1066. /* }}} */
  1067. /* {{{ php_ifd_set32u
  1068. * Convert a 32 bit unsigned value from file's native byte order */
  1069. static void php_ifd_set32u(char *data, size_t value, int motorola_intel)
  1070. {
  1071. if (motorola_intel) {
  1072. data[0] = (value & 0xFF000000) >> 24;
  1073. data[1] = (value & 0x00FF0000) >> 16;
  1074. data[2] = (value & 0x0000FF00) >> 8;
  1075. data[3] = (value & 0x000000FF);
  1076. } else {
  1077. data[3] = (value & 0xFF000000) >> 24;
  1078. data[2] = (value & 0x00FF0000) >> 16;
  1079. data[1] = (value & 0x0000FF00) >> 8;
  1080. data[0] = (value & 0x000000FF);
  1081. }
  1082. }
  1083. /* }}} */
  1084. #ifdef EXIF_DEBUG
  1085. char * exif_dump_data(int *dump_free, int format, int components, int length, int motorola_intel, char *value_ptr TSRMLS_DC) /* {{{ */
  1086. {
  1087. char *dump;
  1088. int len;
  1089. *dump_free = 0;
  1090. if (format == TAG_FMT_STRING) {
  1091. return value_ptr ? value_ptr : "<no data>";
  1092. }
  1093. if (format == TAG_FMT_UNDEFINED) {
  1094. return "<undefined>\n";
  1095. }
  1096. if (format == TAG_FMT_IFD) {
  1097. return "";
  1098. }
  1099. if (format == TAG_FMT_SINGLE || format == TAG_FMT_DOUBLE) {
  1100. return "<not implemented>";
  1101. }
  1102. *dump_free = 1;
  1103. if (components > 1) {
  1104. len = spprintf(&dump, 0, "(%d,%d) {", components, length);
  1105. } else {
  1106. len = spprintf(&dump, 0, "{");
  1107. }
  1108. while(components > 0) {
  1109. switch(format) {
  1110. case TAG_FMT_BYTE:
  1111. case TAG_FMT_UNDEFINED:
  1112. case TAG_FMT_STRING:
  1113. case TAG_FMT_SBYTE:
  1114. dump = erealloc(dump, len + 4 + 1);
  1115. snprintf(dump + len, 4 + 1, "0x%02X", *value_ptr);
  1116. len += 4;
  1117. value_ptr++;
  1118. break;
  1119. case TAG_FMT_USHORT:
  1120. case TAG_FMT_SSHORT:
  1121. dump = erealloc(dump, len + 6 + 1);
  1122. snprintf(dump + len, 6 + 1, "0x%04X", php_ifd_get16s(value_ptr, motorola_intel));
  1123. len += 6;
  1124. value_ptr += 2;
  1125. break;
  1126. case TAG_FMT_ULONG:
  1127. case TAG_FMT_SLONG:
  1128. dump = erealloc(dump, len + 6 + 1);
  1129. snprintf(dump + len, 6 + 1, "0x%04X", php_ifd_get32s(value_ptr, motorola_intel));
  1130. len += 6;
  1131. value_ptr += 4;
  1132. break;
  1133. case TAG_FMT_URATIONAL:
  1134. case TAG_FMT_SRATIONAL:
  1135. dump = erealloc(dump, len + 13 + 1);
  1136. snprintf(dump + len, 13 + 1, "0x%04X/0x%04X", php_ifd_get32s(value_ptr, motorola_intel), php_ifd_get32s(value_ptr+4, motorola_intel));
  1137. len += 13;
  1138. value_ptr += 8;
  1139. break;
  1140. }
  1141. if (components > 0) {
  1142. dump = erealloc(dump, len + 2 + 1);
  1143. snprintf(dump + len, 2 + 1, ", ");
  1144. len += 2;
  1145. components--;
  1146. } else{
  1147. break;
  1148. }
  1149. }
  1150. dump = erealloc(dump, len + 1 + 1);
  1151. snprintf(dump + len, 1 + 1, "}");
  1152. return dump;
  1153. }
  1154. /* }}} */
  1155. #endif
  1156. /* {{{ exif_convert_any_format
  1157. * Evaluate number, be it int, rational, or float from directory. */
  1158. static double exif_convert_any_format(void *value, int format, int motorola_intel TSRMLS_DC)
  1159. {
  1160. int s_den;
  1161. unsigned u_den;
  1162. switch(format) {
  1163. case TAG_FMT_SBYTE: return *(signed char *)value;
  1164. case TAG_FMT_BYTE: return *(uchar *)value;
  1165. case TAG_FMT_USHORT: return php_ifd_get16u(value, motorola_intel);
  1166. case TAG_FMT_ULONG: return php_ifd_get32u(value, motorola_intel);
  1167. case TAG_FMT_URATIONAL:
  1168. u_den = php_ifd_get32u(4+(char *)value, motorola_intel);
  1169. if (u_den == 0) {
  1170. return 0;
  1171. } else {
  1172. return (double)php_ifd_get32u(value, motorola_intel) / u_den;
  1173. }
  1174. case TAG_FMT_SRATIONAL:
  1175. s_den = php_ifd_get32s(4+(char *)value, motorola_intel);
  1176. if (s_den == 0) {
  1177. return 0;
  1178. } else {
  1179. return (double)php_ifd_get32s(value, motorola_intel) / s_den;
  1180. }
  1181. case TAG_FMT_SSHORT: return (signed short)php_ifd_get16u(value, motorola_intel);
  1182. case TAG_FMT_SLONG: return php_ifd_get32s(value, motorola_intel);
  1183. /* Not sure if this is correct (never seen float used in Exif format) */
  1184. case TAG_FMT_SINGLE:
  1185. #ifdef EXIF_DEBUG
  1186. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type single");
  1187. #endif
  1188. return (double)*(float *)value;
  1189. case TAG_FMT_DOUBLE:
  1190. #ifdef EXIF_DEBUG
  1191. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type double");
  1192. #endif
  1193. return *(double *)value;
  1194. }
  1195. return 0;
  1196. }
  1197. /* }}} */
  1198. /* {{{ exif_convert_any_to_int
  1199. * Evaluate number, be it int, rational, or float from directory. */
  1200. static size_t exif_convert_any_to_int(void *value, int format, int motorola_intel TSRMLS_DC)
  1201. {
  1202. int s_den;
  1203. unsigned u_den;
  1204. switch(format) {
  1205. case TAG_FMT_SBYTE: return *(signed char *)value;
  1206. case TAG_FMT_BYTE: return *(uchar *)value;
  1207. case TAG_FMT_USHORT: return php_ifd_get16u(value, motorola_intel);
  1208. case TAG_FMT_ULONG: return php_ifd_get32u(value, motorola_intel);
  1209. case TAG_FMT_URATIONAL:
  1210. u_den = php_ifd_get32u(4+(char *)value, motorola_intel);
  1211. if (u_den == 0) {
  1212. return 0;
  1213. } else {
  1214. return php_ifd_get32u(value, motorola_intel) / u_den;
  1215. }
  1216. case TAG_FMT_SRATIONAL:
  1217. s_den = php_ifd_get32s(4+(char *)value, motorola_intel);
  1218. if (s_den == 0) {
  1219. return 0;
  1220. } else {
  1221. return php_ifd_get32s(value, motorola_intel) / s_den;
  1222. }
  1223. case TAG_FMT_SSHORT: return php_ifd_get16u(value, motorola_intel);
  1224. case TAG_FMT_SLONG: return php_ifd_get32s(value, motorola_intel);
  1225. /* Not sure if this is correct (never seen float used in Exif format) */
  1226. case TAG_FMT_SINGLE:
  1227. #ifdef EXIF_DEBUG
  1228. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type single");
  1229. #endif
  1230. return (size_t)*(float *)value;
  1231. case TAG_FMT_DOUBLE:
  1232. #ifdef EXIF_DEBUG
  1233. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found value of type double");
  1234. #endif
  1235. return (size_t)*(double *)value;
  1236. }
  1237. return 0;
  1238. }
  1239. /* }}} */
  1240. /* {{{ struct image_info_value, image_info_list
  1241. */
  1242. #ifndef WORD
  1243. #define WORD unsigned short
  1244. #endif
  1245. #ifndef DWORD
  1246. #define DWORD unsigned int
  1247. #endif
  1248. typedef struct {
  1249. int num;
  1250. int den;
  1251. } signed_rational;
  1252. typedef struct {
  1253. unsigned int num;
  1254. unsigned int den;
  1255. } unsigned_rational;
  1256. typedef union _image_info_value {
  1257. char *s;
  1258. unsigned u;
  1259. int i;
  1260. float f;
  1261. double d;
  1262. signed_rational sr;
  1263. unsigned_rational ur;
  1264. union _image_info_value *list;
  1265. } image_info_value;
  1266. typedef struct {
  1267. WORD tag;
  1268. WORD format;
  1269. DWORD length;
  1270. DWORD dummy; /* value ptr of tiff directory entry */
  1271. char *name;
  1272. image_info_value value;
  1273. } image_info_data;
  1274. typedef struct {
  1275. int count;
  1276. image_info_data *list;
  1277. } image_info_list;
  1278. /* }}} */
  1279. /* {{{ exif_get_sectionname
  1280. Returns the name of a section
  1281. */
  1282. #define SECTION_FILE 0
  1283. #define SECTION_COMPUTED 1
  1284. #define SECTION_ANY_TAG 2
  1285. #define SECTION_IFD0 3
  1286. #define SECTION_THUMBNAIL 4
  1287. #define SECTION_COMMENT 5
  1288. #define SECTION_APP0 6
  1289. #define SECTION_EXIF 7
  1290. #define SECTION_FPIX 8
  1291. #define SECTION_GPS 9
  1292. #define SECTION_INTEROP 10
  1293. #define SECTION_APP12 11
  1294. #define SECTION_WINXP 12
  1295. #define SECTION_MAKERNOTE 13
  1296. #define SECTION_COUNT 14
  1297. #define FOUND_FILE (1<<SECTION_FILE)
  1298. #define FOUND_COMPUTED (1<<SECTION_COMPUTED)
  1299. #define FOUND_ANY_TAG (1<<SECTION_ANY_TAG)
  1300. #define FOUND_IFD0 (1<<SECTION_IFD0)
  1301. #define FOUND_THUMBNAIL (1<<SECTION_THUMBNAIL)
  1302. #define FOUND_COMMENT (1<<SECTION_COMMENT)
  1303. #define FOUND_APP0 (1<<SECTION_APP0)
  1304. #define FOUND_EXIF (1<<SECTION_EXIF)
  1305. #define FOUND_FPIX (1<<SECTION_FPIX)
  1306. #define FOUND_GPS (1<<SECTION_GPS)
  1307. #define FOUND_INTEROP (1<<SECTION_INTEROP)
  1308. #define FOUND_APP12 (1<<SECTION_APP12)
  1309. #define FOUND_WINXP (1<<SECTION_WINXP)
  1310. #define FOUND_MAKERNOTE (1<<SECTION_MAKERNOTE)
  1311. static char *exif_get_sectionname(int section)
  1312. {
  1313. switch(section) {
  1314. case SECTION_FILE: return "FILE";
  1315. case SECTION_COMPUTED: return "COMPUTED";
  1316. case SECTION_ANY_TAG: return "ANY_TAG";
  1317. case SECTION_IFD0: return "IFD0";
  1318. case SECTION_THUMBNAIL: return "THUMBNAIL";
  1319. case SECTION_COMMENT: return "COMMENT";
  1320. case SECTION_APP0: return "APP0";
  1321. case SECTION_EXIF: return "EXIF";
  1322. case SECTION_FPIX: return "FPIX";
  1323. case SECTION_GPS: return "GPS";
  1324. case SECTION_INTEROP: return "INTEROP";
  1325. case SECTION_APP12: return "APP12";
  1326. case SECTION_WINXP: return "WINXP";
  1327. case SECTION_MAKERNOTE: return "MAKERNOTE";
  1328. }
  1329. return "";
  1330. }
  1331. static tag_table_type exif_get_tag_table(int section)
  1332. {
  1333. switch(section) {
  1334. case SECTION_FILE: return &tag_table_IFD[0];
  1335. case SECTION_COMPUTED: return &tag_table_IFD[0];
  1336. case SECTION_ANY_TAG: return &tag_table_IFD[0];
  1337. case SECTION_IFD0: return &tag_table_IFD[0];
  1338. case SECTION_THUMBNAIL: return &tag_table_IFD[0];
  1339. case SECTION_COMMENT: return &tag_table_IFD[0];
  1340. case SECTION_APP0: return &tag_table_IFD[0];
  1341. case SECTION_EXIF: return &tag_table_IFD[0];
  1342. case SECTION_FPIX: return &tag_table_IFD[0];
  1343. case SECTION_GPS: return &tag_table_GPS[0];
  1344. case SECTION_INTEROP: return &tag_table_IOP[0];
  1345. case SECTION_APP12: return &tag_table_IFD[0];
  1346. case SECTION_WINXP: return &tag_table_IFD[0];
  1347. }
  1348. return &tag_table_IFD[0];
  1349. }
  1350. /* }}} */
  1351. /* {{{ exif_get_sectionlist
  1352. Return list of sectionnames specified by sectionlist. Return value must be freed
  1353. */
  1354. static char *exif_get_sectionlist(int sectionlist TSRMLS_DC)
  1355. {
  1356. int i, len, ml = 0;
  1357. char *sections;
  1358. for(i=0; i<SECTION_COUNT; i++) {
  1359. ml += strlen(exif_get_sectionname(i))+2;
  1360. }
  1361. sections = safe_emalloc(ml, 1, 1);
  1362. sections[0] = '\0';
  1363. len = 0;
  1364. for(i=0; i<SECTION_COUNT; i++) {
  1365. if (sectionlist&(1<<i)) {
  1366. snprintf(sections+len, ml-len, "%s, ", exif_get_sectionname(i));
  1367. len = strlen(sections);
  1368. }
  1369. }
  1370. if (len>2)
  1371. sections[len-2] = '\0';
  1372. return sections;
  1373. }
  1374. /* }}} */
  1375. /* {{{ struct image_info_type
  1376. This structure stores Exif header image elements in a simple manner
  1377. Used to store camera data as extracted from the various ways that it can be
  1378. stored in a nexif header
  1379. */
  1380. typedef struct {
  1381. int type;
  1382. size_t size;
  1383. uchar *data;
  1384. } file_section;
  1385. typedef struct {
  1386. int count;
  1387. file_section *list;
  1388. } file_section_list;
  1389. typedef struct {
  1390. image_filetype filetype;
  1391. size_t width, height;
  1392. size_t size;
  1393. size_t offset;
  1394. char *data;
  1395. } thumbnail_data;
  1396. typedef struct {
  1397. char *value;
  1398. size_t size;
  1399. int tag;
  1400. } xp_field_type;
  1401. typedef struct {
  1402. int count;
  1403. xp_field_type *list;
  1404. } xp_field_list;
  1405. /* This structure is used to store a section of a Jpeg file. */
  1406. typedef struct {
  1407. php_stream *infile;
  1408. char *FileName;
  1409. time_t FileDateTime;
  1410. size_t FileSize;
  1411. image_filetype FileType;
  1412. int Height, Width;
  1413. int IsColor;
  1414. char *make;
  1415. char *model;
  1416. float ApertureFNumber;
  1417. float ExposureTime;
  1418. double FocalplaneUnits;
  1419. float CCDWidth;
  1420. double FocalplaneXRes;
  1421. size_t ExifImageWidth;
  1422. float FocalLength;
  1423. float Distance;
  1424. int motorola_intel; /* 1 Motorola; 0 Intel */
  1425. char *UserComment;
  1426. int UserCommentLength;
  1427. char *UserCommentEncoding;
  1428. char *encode_unicode;
  1429. char *decode_unicode_be;
  1430. char *decode_unicode_le;
  1431. char *encode_jis;
  1432. char *decode_jis_be;
  1433. char *decode_jis_le;
  1434. char *Copyright;/* EXIF standard defines Copyright as "<Photographer> [ '\0' <Editor> ] ['\0']" */
  1435. char *CopyrightPhotographer;
  1436. char *CopyrightEditor;
  1437. xp_field_list xp_fields;
  1438. thumbnail_data Thumbnail;
  1439. /* other */
  1440. int sections_found; /* FOUND_<marker> */
  1441. image_info_list info_list[SECTION_COUNT];
  1442. /* for parsing */
  1443. int read_thumbnail;
  1444. int read_all;
  1445. int ifd_nesting_level;
  1446. /* internal */
  1447. file_section_list file;
  1448. } image_info_type;
  1449. /* }}} */
  1450. /* {{{ exif_error_docref */
  1451. static void exif_error_docref(const char *docref EXIFERR_DC, const image_info_type *ImageInfo, int type, const char *format, ...)
  1452. {
  1453. va_list args;
  1454. va_start(args, format);
  1455. #ifdef EXIF_DEBUG
  1456. {
  1457. char *buf;
  1458. spprintf(&buf, 0, "%s(%d): %s", _file, _line, format);
  1459. php_verror(docref, ImageInfo->FileName?ImageInfo->FileName:"", type, buf, args TSRMLS_CC);
  1460. efree(buf);
  1461. }
  1462. #else
  1463. php_verror(docref, ImageInfo->FileName?ImageInfo->FileName:"", type, format, args TSRMLS_CC);
  1464. #en

Large files files are truncated, but you can click here to view the full file