PageRenderTime 107ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 1ms

/ext/exif/exif.c

https://github.com/php/php-src
C | 4804 lines | 3983 code | 389 blank | 432 comment | 564 complexity | c6641b2c4ae9d4be75a227b413f22d28 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1

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

  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Rasmus Lerdorf <rasmus@php.net> |
  14. | Marcus Boerger <helly@php.net> |
  15. +----------------------------------------------------------------------+
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "php.h"
  21. #include "ext/standard/file.h"
  22. /* When EXIF_DEBUG is defined the module generates a lot of debug messages
  23. * that help understanding what is going on. This can and should be used
  24. * while extending the module as it shows if you are at the right position.
  25. * You are always considered to have a copy of TIFF6.0 and EXIF2.10 standard.
  26. */
  27. #undef EXIF_DEBUG
  28. #ifdef EXIF_DEBUG
  29. #define EXIFERR_DC , const char *_file, size_t _line
  30. #define EXIFERR_CC , __FILE__, __LINE__
  31. #else
  32. #define EXIFERR_DC
  33. #define EXIFERR_CC
  34. #endif
  35. #include "php_exif.h"
  36. #include "exif_arginfo.h"
  37. #include <math.h>
  38. #include "php_ini.h"
  39. #include "ext/standard/php_string.h"
  40. #include "ext/standard/php_image.h"
  41. #include "ext/standard/info.h"
  42. /* needed for ssize_t definition */
  43. #include <sys/types.h>
  44. #ifdef __SANITIZE_ADDRESS__
  45. # include <sanitizer/asan_interface.h>
  46. #endif
  47. typedef unsigned char uchar;
  48. #ifndef max
  49. # define max(a,b) ((a)>(b) ? (a) : (b))
  50. #endif
  51. #define EFREE_IF(ptr) if (ptr) efree(ptr)
  52. #define MAX_IFD_NESTING_LEVEL 10
  53. #define MAX_IFD_TAGS 1000
  54. /* {{{ PHP_MINFO_FUNCTION */
  55. PHP_MINFO_FUNCTION(exif)
  56. {
  57. php_info_print_table_start();
  58. php_info_print_table_row(2, "EXIF Support", "enabled");
  59. php_info_print_table_row(2, "Supported EXIF Version", "0220");
  60. php_info_print_table_row(2, "Supported filetypes", "JPEG, TIFF");
  61. if (zend_hash_str_exists(&module_registry, "mbstring", sizeof("mbstring")-1)) {
  62. php_info_print_table_row(2, "Multibyte decoding support using mbstring", "enabled");
  63. } else {
  64. php_info_print_table_row(2, "Multibyte decoding support using mbstring", "disabled");
  65. }
  66. php_info_print_table_row(2, "Extended EXIF tag formats", "Canon, Casio, Fujifilm, Nikon, Olympus, Samsung, Panasonic, DJI, Sony, Pentax, Minolta, Sigma, Foveon, Kyocera, Ricoh, AGFA, Epson");
  67. php_info_print_table_end();
  68. DISPLAY_INI_ENTRIES();
  69. }
  70. /* }}} */
  71. ZEND_BEGIN_MODULE_GLOBALS(exif)
  72. char * encode_unicode;
  73. char * decode_unicode_be;
  74. char * decode_unicode_le;
  75. char * encode_jis;
  76. char * decode_jis_be;
  77. char * decode_jis_le;
  78. HashTable *tag_table_cache;
  79. ZEND_END_MODULE_GLOBALS(exif)
  80. ZEND_DECLARE_MODULE_GLOBALS(exif)
  81. #define EXIF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(exif, v)
  82. #if defined(ZTS) && defined(COMPILE_DL_EXIF)
  83. ZEND_TSRMLS_CACHE_DEFINE()
  84. #endif
  85. /* {{{ PHP_INI */
  86. ZEND_INI_MH(OnUpdateEncode)
  87. {
  88. if (new_value && ZSTR_LEN(new_value)) {
  89. const zend_encoding **return_list;
  90. size_t return_size;
  91. if (FAILURE == zend_multibyte_parse_encoding_list(ZSTR_VAL(new_value), ZSTR_LEN(new_value),
  92. &return_list, &return_size, 0)) {
  93. php_error_docref(NULL, E_WARNING, "Illegal encoding ignored: '%s'", ZSTR_VAL(new_value));
  94. return FAILURE;
  95. }
  96. pefree((void *) return_list, 0);
  97. }
  98. return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
  99. }
  100. ZEND_INI_MH(OnUpdateDecode)
  101. {
  102. if (new_value) {
  103. const zend_encoding **return_list;
  104. size_t return_size;
  105. if (FAILURE == zend_multibyte_parse_encoding_list(ZSTR_VAL(new_value), ZSTR_LEN(new_value),
  106. &return_list, &return_size, 0)) {
  107. php_error_docref(NULL, E_WARNING, "Illegal encoding ignored: '%s'", ZSTR_VAL(new_value));
  108. return FAILURE;
  109. }
  110. pefree((void *) return_list, 0);
  111. }
  112. return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
  113. }
  114. PHP_INI_BEGIN()
  115. STD_PHP_INI_ENTRY("exif.encode_unicode", "ISO-8859-15", PHP_INI_ALL, OnUpdateEncode, encode_unicode, zend_exif_globals, exif_globals)
  116. STD_PHP_INI_ENTRY("exif.decode_unicode_motorola", "UCS-2BE", PHP_INI_ALL, OnUpdateDecode, decode_unicode_be, zend_exif_globals, exif_globals)
  117. STD_PHP_INI_ENTRY("exif.decode_unicode_intel", "UCS-2LE", PHP_INI_ALL, OnUpdateDecode, decode_unicode_le, zend_exif_globals, exif_globals)
  118. STD_PHP_INI_ENTRY("exif.encode_jis", "", PHP_INI_ALL, OnUpdateEncode, encode_jis, zend_exif_globals, exif_globals)
  119. STD_PHP_INI_ENTRY("exif.decode_jis_motorola", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_be, zend_exif_globals, exif_globals)
  120. STD_PHP_INI_ENTRY("exif.decode_jis_intel", "JIS", PHP_INI_ALL, OnUpdateDecode, decode_jis_le, zend_exif_globals, exif_globals)
  121. PHP_INI_END()
  122. /* }}} */
  123. /* {{{ PHP_GINIT_FUNCTION */
  124. static PHP_GINIT_FUNCTION(exif)
  125. {
  126. #if defined(COMPILE_DL_EXIF) && defined(ZTS)
  127. ZEND_TSRMLS_CACHE_UPDATE();
  128. #endif
  129. exif_globals->encode_unicode = NULL;
  130. exif_globals->decode_unicode_be = NULL;
  131. exif_globals->decode_unicode_le = NULL;
  132. exif_globals->encode_jis = NULL;
  133. exif_globals->decode_jis_be = NULL;
  134. exif_globals->decode_jis_le = NULL;
  135. exif_globals->tag_table_cache = NULL;
  136. }
  137. /* }}} */
  138. /* {{{ PHP_MINIT_FUNCTION(exif) */
  139. PHP_MINIT_FUNCTION(exif)
  140. {
  141. REGISTER_INI_ENTRIES();
  142. if (zend_hash_str_exists(&module_registry, "mbstring", sizeof("mbstring")-1)) {
  143. REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 1, CONST_CS | CONST_PERSISTENT);
  144. } else {
  145. REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 0, CONST_CS | CONST_PERSISTENT);
  146. }
  147. return SUCCESS;
  148. }
  149. /* }}} */
  150. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  151. PHP_MSHUTDOWN_FUNCTION(exif)
  152. {
  153. UNREGISTER_INI_ENTRIES();
  154. if (EXIF_G(tag_table_cache)) {
  155. zend_hash_destroy(EXIF_G(tag_table_cache));
  156. free(EXIF_G(tag_table_cache));
  157. }
  158. return SUCCESS;
  159. }
  160. /* }}} */
  161. /* {{{ exif dependencies */
  162. static const zend_module_dep exif_module_deps[] = {
  163. ZEND_MOD_REQUIRED("standard")
  164. ZEND_MOD_OPTIONAL("mbstring")
  165. ZEND_MOD_END
  166. };
  167. /* }}} */
  168. /* {{{ exif_module_entry */
  169. zend_module_entry exif_module_entry = {
  170. STANDARD_MODULE_HEADER_EX, NULL,
  171. exif_module_deps,
  172. "exif",
  173. ext_functions,
  174. PHP_MINIT(exif),
  175. PHP_MSHUTDOWN(exif),
  176. NULL, NULL,
  177. PHP_MINFO(exif),
  178. PHP_EXIF_VERSION,
  179. PHP_MODULE_GLOBALS(exif),
  180. PHP_GINIT(exif),
  181. NULL,
  182. NULL,
  183. STANDARD_MODULE_PROPERTIES_EX
  184. };
  185. /* }}} */
  186. #ifdef COMPILE_DL_EXIF
  187. ZEND_GET_MODULE(exif)
  188. #endif
  189. /* {{{ php_strnlen
  190. * get length of string if buffer if less than buffer size or buffer size */
  191. static size_t php_strnlen(char* str, size_t maxlen) {
  192. size_t len = 0;
  193. if (str && maxlen && *str) {
  194. do {
  195. len++;
  196. } while (--maxlen && *(++str));
  197. }
  198. return len;
  199. }
  200. /* }}} */
  201. /* {{{ error messages */
  202. static const char * EXIF_ERROR_FILEEOF = "Unexpected end of file reached";
  203. static const char * EXIF_ERROR_CORRUPT = "File structure corrupted";
  204. static const char * EXIF_ERROR_THUMBEOF = "Thumbnail goes IFD boundary or end of file reached";
  205. static const char * EXIF_ERROR_FSREALLOC = "Illegal reallocating of undefined file section";
  206. #define EXIF_ERRLOG_FILEEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FILEEOF);
  207. #define EXIF_ERRLOG_CORRUPT(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_CORRUPT);
  208. #define EXIF_ERRLOG_THUMBEOF(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_THUMBEOF);
  209. #define EXIF_ERRLOG_FSREALLOC(ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FSREALLOC);
  210. /* }}} */
  211. /* {{{ format description defines
  212. Describes format descriptor
  213. */
  214. static int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 1};
  215. #define NUM_FORMATS 13
  216. #define TAG_FMT_BYTE 1
  217. #define TAG_FMT_STRING 2
  218. #define TAG_FMT_USHORT 3
  219. #define TAG_FMT_ULONG 4
  220. #define TAG_FMT_URATIONAL 5
  221. #define TAG_FMT_SBYTE 6
  222. #define TAG_FMT_UNDEFINED 7
  223. #define TAG_FMT_SSHORT 8
  224. #define TAG_FMT_SLONG 9
  225. #define TAG_FMT_SRATIONAL 10
  226. #define TAG_FMT_SINGLE 11
  227. #define TAG_FMT_DOUBLE 12
  228. #define TAG_FMT_IFD 13
  229. #ifdef EXIF_DEBUG
  230. static char *exif_get_tagformat(int format)
  231. {
  232. switch(format) {
  233. case TAG_FMT_BYTE: return "BYTE";
  234. case TAG_FMT_STRING: return "STRING";
  235. case TAG_FMT_USHORT: return "USHORT";
  236. case TAG_FMT_ULONG: return "ULONG";
  237. case TAG_FMT_URATIONAL: return "URATIONAL";
  238. case TAG_FMT_SBYTE: return "SBYTE";
  239. case TAG_FMT_UNDEFINED: return "UNDEFINED";
  240. case TAG_FMT_SSHORT: return "SSHORT";
  241. case TAG_FMT_SLONG: return "SLONG";
  242. case TAG_FMT_SRATIONAL: return "SRATIONAL";
  243. case TAG_FMT_SINGLE: return "SINGLE";
  244. case TAG_FMT_DOUBLE: return "DOUBLE";
  245. case TAG_FMT_IFD: return "IFD";
  246. }
  247. return "*Illegal";
  248. }
  249. #endif
  250. /* Describes tag values */
  251. #define TAG_GPS_VERSION_ID 0x0000
  252. #define TAG_GPS_LATITUDE_REF 0x0001
  253. #define TAG_GPS_LATITUDE 0x0002
  254. #define TAG_GPS_LONGITUDE_REF 0x0003
  255. #define TAG_GPS_LONGITUDE 0x0004
  256. #define TAG_GPS_ALTITUDE_REF 0x0005
  257. #define TAG_GPS_ALTITUDE 0x0006
  258. #define TAG_GPS_TIME_STAMP 0x0007
  259. #define TAG_GPS_SATELLITES 0x0008
  260. #define TAG_GPS_STATUS 0x0009
  261. #define TAG_GPS_MEASURE_MODE 0x000A
  262. #define TAG_GPS_DOP 0x000B
  263. #define TAG_GPS_SPEED_REF 0x000C
  264. #define TAG_GPS_SPEED 0x000D
  265. #define TAG_GPS_TRACK_REF 0x000E
  266. #define TAG_GPS_TRACK 0x000F
  267. #define TAG_GPS_IMG_DIRECTION_REF 0x0010
  268. #define TAG_GPS_IMG_DIRECTION 0x0011
  269. #define TAG_GPS_MAP_DATUM 0x0012
  270. #define TAG_GPS_DEST_LATITUDE_REF 0x0013
  271. #define TAG_GPS_DEST_LATITUDE 0x0014
  272. #define TAG_GPS_DEST_LONGITUDE_REF 0x0015
  273. #define TAG_GPS_DEST_LONGITUDE 0x0016
  274. #define TAG_GPS_DEST_BEARING_REF 0x0017
  275. #define TAG_GPS_DEST_BEARING 0x0018
  276. #define TAG_GPS_DEST_DISTANCE_REF 0x0019
  277. #define TAG_GPS_DEST_DISTANCE 0x001A
  278. #define TAG_GPS_PROCESSING_METHOD 0x001B
  279. #define TAG_GPS_AREA_INFORMATION 0x001C
  280. #define TAG_GPS_DATE_STAMP 0x001D
  281. #define TAG_GPS_DIFFERENTIAL 0x001E
  282. #define TAG_TIFF_COMMENT 0x00FE /* SHOULDN'T HAPPEN */
  283. #define TAG_NEW_SUBFILE 0x00FE /* New version of subfile tag */
  284. #define TAG_SUBFILE_TYPE 0x00FF /* Old version of subfile tag */
  285. #define TAG_IMAGEWIDTH 0x0100
  286. #define TAG_IMAGEHEIGHT 0x0101
  287. #define TAG_BITS_PER_SAMPLE 0x0102
  288. #define TAG_COMPRESSION 0x0103
  289. #define TAG_PHOTOMETRIC_INTERPRETATION 0x0106
  290. #define TAG_TRESHHOLDING 0x0107
  291. #define TAG_CELL_WIDTH 0x0108
  292. #define TAG_CELL_HEIGHT 0x0109
  293. #define TAG_FILL_ORDER 0x010A
  294. #define TAG_DOCUMENT_NAME 0x010D
  295. #define TAG_IMAGE_DESCRIPTION 0x010E
  296. #define TAG_MAKE 0x010F
  297. #define TAG_MODEL 0x0110
  298. #define TAG_STRIP_OFFSETS 0x0111
  299. #define TAG_ORIENTATION 0x0112
  300. #define TAG_SAMPLES_PER_PIXEL 0x0115
  301. #define TAG_ROWS_PER_STRIP 0x0116
  302. #define TAG_STRIP_BYTE_COUNTS 0x0117
  303. #define TAG_MIN_SAMPPLE_VALUE 0x0118
  304. #define TAG_MAX_SAMPLE_VALUE 0x0119
  305. #define TAG_X_RESOLUTION 0x011A
  306. #define TAG_Y_RESOLUTION 0x011B
  307. #define TAG_PLANAR_CONFIGURATION 0x011C
  308. #define TAG_PAGE_NAME 0x011D
  309. #define TAG_X_POSITION 0x011E
  310. #define TAG_Y_POSITION 0x011F
  311. #define TAG_FREE_OFFSETS 0x0120
  312. #define TAG_FREE_BYTE_COUNTS 0x0121
  313. #define TAG_GRAY_RESPONSE_UNIT 0x0122
  314. #define TAG_GRAY_RESPONSE_CURVE 0x0123
  315. #define TAG_RESOLUTION_UNIT 0x0128
  316. #define TAG_PAGE_NUMBER 0x0129
  317. #define TAG_TRANSFER_FUNCTION 0x012D
  318. #define TAG_SOFTWARE 0x0131
  319. #define TAG_DATETIME 0x0132
  320. #define TAG_ARTIST 0x013B
  321. #define TAG_HOST_COMPUTER 0x013C
  322. #define TAG_PREDICTOR 0x013D
  323. #define TAG_WHITE_POINT 0x013E
  324. #define TAG_PRIMARY_CHROMATICITIES 0x013F
  325. #define TAG_COLOR_MAP 0x0140
  326. #define TAG_HALFTONE_HINTS 0x0141
  327. #define TAG_TILE_WIDTH 0x0142
  328. #define TAG_TILE_LENGTH 0x0143
  329. #define TAG_TILE_OFFSETS 0x0144
  330. #define TAG_TILE_BYTE_COUNTS 0x0145
  331. #define TAG_SUB_IFD 0x014A
  332. #define TAG_INK_SETMPUTER 0x014C
  333. #define TAG_INK_NAMES 0x014D
  334. #define TAG_NUMBER_OF_INKS 0x014E
  335. #define TAG_DOT_RANGE 0x0150
  336. #define TAG_TARGET_PRINTER 0x0151
  337. #define TAG_EXTRA_SAMPLE 0x0152
  338. #define TAG_SAMPLE_FORMAT 0x0153
  339. #define TAG_S_MIN_SAMPLE_VALUE 0x0154
  340. #define TAG_S_MAX_SAMPLE_VALUE 0x0155
  341. #define TAG_TRANSFER_RANGE 0x0156
  342. #define TAG_JPEG_TABLES 0x015B
  343. #define TAG_JPEG_PROC 0x0200
  344. #define TAG_JPEG_INTERCHANGE_FORMAT 0x0201
  345. #define TAG_JPEG_INTERCHANGE_FORMAT_LEN 0x0202
  346. #define TAG_JPEG_RESTART_INTERVAL 0x0203
  347. #define TAG_JPEG_LOSSLESS_PREDICTOR 0x0205
  348. #define TAG_JPEG_POINT_TRANSFORMS 0x0206
  349. #define TAG_JPEG_Q_TABLES 0x0207
  350. #define TAG_JPEG_DC_TABLES 0x0208
  351. #define TAG_JPEG_AC_TABLES 0x0209
  352. #define TAG_YCC_COEFFICIENTS 0x0211
  353. #define TAG_YCC_SUB_SAMPLING 0x0212
  354. #define TAG_YCC_POSITIONING 0x0213
  355. #define TAG_REFERENCE_BLACK_WHITE 0x0214
  356. /* 0x0301 - 0x0302 */
  357. /* 0x0320 */
  358. /* 0x0343 */
  359. /* 0x5001 - 0x501B */
  360. /* 0x5021 - 0x503B */
  361. /* 0x5090 - 0x5091 */
  362. /* 0x5100 - 0x5101 */
  363. /* 0x5110 - 0x5113 */
  364. /* 0x80E3 - 0x80E6 */
  365. /* 0x828d - 0x828F */
  366. #define TAG_COPYRIGHT 0x8298
  367. #define TAG_EXPOSURETIME 0x829A
  368. #define TAG_FNUMBER 0x829D
  369. #define TAG_EXIF_IFD_POINTER 0x8769
  370. #define TAG_ICC_PROFILE 0x8773
  371. #define TAG_EXPOSURE_PROGRAM 0x8822
  372. #define TAG_SPECTRAL_SENSITY 0x8824
  373. #define TAG_GPS_IFD_POINTER 0x8825
  374. #define TAG_ISOSPEED 0x8827
  375. #define TAG_OPTOELECTRIC_CONVERSION_F 0x8828
  376. /* 0x8829 - 0x882b */
  377. #define TAG_EXIFVERSION 0x9000
  378. #define TAG_DATE_TIME_ORIGINAL 0x9003
  379. #define TAG_DATE_TIME_DIGITIZED 0x9004
  380. #define TAG_COMPONENT_CONFIG 0x9101
  381. #define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102
  382. #define TAG_SHUTTERSPEED 0x9201
  383. #define TAG_APERTURE 0x9202
  384. #define TAG_BRIGHTNESS_VALUE 0x9203
  385. #define TAG_EXPOSURE_BIAS_VALUE 0x9204
  386. #define TAG_MAX_APERTURE 0x9205
  387. #define TAG_SUBJECT_DISTANCE 0x9206
  388. #define TAG_METRIC_MODULE 0x9207
  389. #define TAG_LIGHT_SOURCE 0x9208
  390. #define TAG_FLASH 0x9209
  391. #define TAG_FOCAL_LENGTH 0x920A
  392. /* 0x920B - 0x920D */
  393. /* 0x9211 - 0x9216 */
  394. #define TAG_SUBJECT_AREA 0x9214
  395. #define TAG_MAKER_NOTE 0x927C
  396. #define TAG_USERCOMMENT 0x9286
  397. #define TAG_SUB_SEC_TIME 0x9290
  398. #define TAG_SUB_SEC_TIME_ORIGINAL 0x9291
  399. #define TAG_SUB_SEC_TIME_DIGITIZED 0x9292
  400. /* 0x923F */
  401. /* 0x935C */
  402. #define TAG_XP_TITLE 0x9C9B
  403. #define TAG_XP_COMMENTS 0x9C9C
  404. #define TAG_XP_AUTHOR 0x9C9D
  405. #define TAG_XP_KEYWORDS 0x9C9E
  406. #define TAG_XP_SUBJECT 0x9C9F
  407. #define TAG_FLASH_PIX_VERSION 0xA000
  408. #define TAG_COLOR_SPACE 0xA001
  409. #define TAG_COMP_IMAGE_WIDTH 0xA002 /* compressed images only */
  410. #define TAG_COMP_IMAGE_HEIGHT 0xA003
  411. #define TAG_RELATED_SOUND_FILE 0xA004
  412. #define TAG_INTEROP_IFD_POINTER 0xA005 /* IFD pointer */
  413. #define TAG_FLASH_ENERGY 0xA20B
  414. #define TAG_SPATIAL_FREQUENCY_RESPONSE 0xA20C
  415. #define TAG_FOCALPLANE_X_RES 0xA20E
  416. #define TAG_FOCALPLANE_Y_RES 0xA20F
  417. #define TAG_FOCALPLANE_RESOLUTION_UNIT 0xA210
  418. #define TAG_SUBJECT_LOCATION 0xA214
  419. #define TAG_EXPOSURE_INDEX 0xA215
  420. #define TAG_SENSING_METHOD 0xA217
  421. #define TAG_FILE_SOURCE 0xA300
  422. #define TAG_SCENE_TYPE 0xA301
  423. #define TAG_CFA_PATTERN 0xA302
  424. #define TAG_CUSTOM_RENDERED 0xA401
  425. #define TAG_EXPOSURE_MODE 0xA402
  426. #define TAG_WHITE_BALANCE 0xA403
  427. #define TAG_DIGITAL_ZOOM_RATIO 0xA404
  428. #define TAG_FOCAL_LENGTH_IN_35_MM_FILM 0xA405
  429. #define TAG_SCENE_CAPTURE_TYPE 0xA406
  430. #define TAG_GAIN_CONTROL 0xA407
  431. #define TAG_CONTRAST 0xA408
  432. #define TAG_SATURATION 0xA409
  433. #define TAG_SHARPNESS 0xA40A
  434. #define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B
  435. #define TAG_SUBJECT_DISTANCE_RANGE 0xA40C
  436. #define TAG_IMAGE_UNIQUE_ID 0xA420
  437. /* Olympus specific tags */
  438. #define TAG_OLYMPUS_SPECIALMODE 0x0200
  439. #define TAG_OLYMPUS_JPEGQUAL 0x0201
  440. #define TAG_OLYMPUS_MACRO 0x0202
  441. #define TAG_OLYMPUS_DIGIZOOM 0x0204
  442. #define TAG_OLYMPUS_SOFTWARERELEASE 0x0207
  443. #define TAG_OLYMPUS_PICTINFO 0x0208
  444. #define TAG_OLYMPUS_CAMERAID 0x0209
  445. /* end Olympus specific tags */
  446. /* Internal */
  447. #define TAG_NONE -1 /* note that -1 <> 0xFFFF */
  448. #define TAG_COMPUTED_VALUE -2
  449. #define TAG_END_OF_LIST 0xFFFD
  450. /* Values for TAG_PHOTOMETRIC_INTERPRETATION */
  451. #define PMI_BLACK_IS_ZERO 0
  452. #define PMI_WHITE_IS_ZERO 1
  453. #define PMI_RGB 2
  454. #define PMI_PALETTE_COLOR 3
  455. #define PMI_TRANSPARENCY_MASK 4
  456. #define PMI_SEPARATED 5
  457. #define PMI_YCBCR 6
  458. #define PMI_CIELAB 8
  459. /* }}} */
  460. /* {{{ TabTable[] */
  461. typedef const struct {
  462. unsigned short Tag;
  463. char *Desc;
  464. } tag_info_type;
  465. typedef tag_info_type tag_info_array[];
  466. typedef tag_info_type *tag_table_type;
  467. #define TAG_TABLE_END \
  468. {TAG_NONE, "No tag value"},\
  469. {TAG_COMPUTED_VALUE, "Computed value"},\
  470. {TAG_END_OF_LIST, ""} /* Important for exif_get_tagname() IF value != "" function result is != false */
  471. static tag_info_array tag_table_IFD = {
  472. { 0x000B, "ACDComment"},
  473. { 0x00FE, "NewSubFile"}, /* better name it 'ImageType' ? */
  474. { 0x00FF, "SubFile"},
  475. { 0x0100, "ImageWidth"},
  476. { 0x0101, "ImageLength"},
  477. { 0x0102, "BitsPerSample"},
  478. { 0x0103, "Compression"},
  479. { 0x0106, "PhotometricInterpretation"},
  480. { 0x010A, "FillOrder"},
  481. { 0x010D, "DocumentName"},
  482. { 0x010E, "ImageDescription"},
  483. { 0x010F, "Make"},
  484. { 0x0110, "Model"},
  485. { 0x0111, "StripOffsets"},
  486. { 0x0112, "Orientation"},
  487. { 0x0115, "SamplesPerPixel"},
  488. { 0x0116, "RowsPerStrip"},
  489. { 0x0117, "StripByteCounts"},
  490. { 0x0118, "MinSampleValue"},
  491. { 0x0119, "MaxSampleValue"},
  492. { 0x011A, "XResolution"},
  493. { 0x011B, "YResolution"},
  494. { 0x011C, "PlanarConfiguration"},
  495. { 0x011D, "PageName"},
  496. { 0x011E, "XPosition"},
  497. { 0x011F, "YPosition"},
  498. { 0x0120, "FreeOffsets"},
  499. { 0x0121, "FreeByteCounts"},
  500. { 0x0122, "GrayResponseUnit"},
  501. { 0x0123, "GrayResponseCurve"},
  502. { 0x0124, "T4Options"},
  503. { 0x0125, "T6Options"},
  504. { 0x0128, "ResolutionUnit"},
  505. { 0x0129, "PageNumber"},
  506. { 0x012D, "TransferFunction"},
  507. { 0x0131, "Software"},
  508. { 0x0132, "DateTime"},
  509. { 0x013B, "Artist"},
  510. { 0x013C, "HostComputer"},
  511. { 0x013D, "Predictor"},
  512. { 0x013E, "WhitePoint"},
  513. { 0x013F, "PrimaryChromaticities"},
  514. { 0x0140, "ColorMap"},
  515. { 0x0141, "HalfToneHints"},
  516. { 0x0142, "TileWidth"},
  517. { 0x0143, "TileLength"},
  518. { 0x0144, "TileOffsets"},
  519. { 0x0145, "TileByteCounts"},
  520. { 0x014A, "SubIFD"},
  521. { 0x014C, "InkSet"},
  522. { 0x014D, "InkNames"},
  523. { 0x014E, "NumberOfInks"},
  524. { 0x0150, "DotRange"},
  525. { 0x0151, "TargetPrinter"},
  526. { 0x0152, "ExtraSample"},
  527. { 0x0153, "SampleFormat"},
  528. { 0x0154, "SMinSampleValue"},
  529. { 0x0155, "SMaxSampleValue"},
  530. { 0x0156, "TransferRange"},
  531. { 0x0157, "ClipPath"},
  532. { 0x0158, "XClipPathUnits"},
  533. { 0x0159, "YClipPathUnits"},
  534. { 0x015A, "Indexed"},
  535. { 0x015B, "JPEGTables"},
  536. { 0x015F, "OPIProxy"},
  537. { 0x0200, "JPEGProc"},
  538. { 0x0201, "JPEGInterchangeFormat"},
  539. { 0x0202, "JPEGInterchangeFormatLength"},
  540. { 0x0203, "JPEGRestartInterval"},
  541. { 0x0205, "JPEGLosslessPredictors"},
  542. { 0x0206, "JPEGPointTransforms"},
  543. { 0x0207, "JPEGQTables"},
  544. { 0x0208, "JPEGDCTables"},
  545. { 0x0209, "JPEGACTables"},
  546. { 0x0211, "YCbCrCoefficients"},
  547. { 0x0212, "YCbCrSubSampling"},
  548. { 0x0213, "YCbCrPositioning"},
  549. { 0x0214, "ReferenceBlackWhite"},
  550. { 0x02BC, "ExtensibleMetadataPlatform"}, /* XAP: Extensible Authoring Publishing, obsoleted by XMP: Extensible Metadata Platform */
  551. { 0x0301, "Gamma"},
  552. { 0x0302, "ICCProfileDescriptor"},
  553. { 0x0303, "SRGBRenderingIntent"},
  554. { 0x0320, "ImageTitle"},
  555. { 0x5001, "ResolutionXUnit"},
  556. { 0x5002, "ResolutionYUnit"},
  557. { 0x5003, "ResolutionXLengthUnit"},
  558. { 0x5004, "ResolutionYLengthUnit"},
  559. { 0x5005, "PrintFlags"},
  560. { 0x5006, "PrintFlagsVersion"},
  561. { 0x5007, "PrintFlagsCrop"},
  562. { 0x5008, "PrintFlagsBleedWidth"},
  563. { 0x5009, "PrintFlagsBleedWidthScale"},
  564. { 0x500A, "HalftoneLPI"},
  565. { 0x500B, "HalftoneLPIUnit"},
  566. { 0x500C, "HalftoneDegree"},
  567. { 0x500D, "HalftoneShape"},
  568. { 0x500E, "HalftoneMisc"},
  569. { 0x500F, "HalftoneScreen"},
  570. { 0x5010, "JPEGQuality"},
  571. { 0x5011, "GridSize"},
  572. { 0x5012, "ThumbnailFormat"},
  573. { 0x5013, "ThumbnailWidth"},
  574. { 0x5014, "ThumbnailHeight"},
  575. { 0x5015, "ThumbnailColorDepth"},
  576. { 0x5016, "ThumbnailPlanes"},
  577. { 0x5017, "ThumbnailRawBytes"},
  578. { 0x5018, "ThumbnailSize"},
  579. { 0x5019, "ThumbnailCompressedSize"},
  580. { 0x501A, "ColorTransferFunction"},
  581. { 0x501B, "ThumbnailData"},
  582. { 0x5020, "ThumbnailImageWidth"},
  583. { 0x5021, "ThumbnailImageHeight"},
  584. { 0x5022, "ThumbnailBitsPerSample"},
  585. { 0x5023, "ThumbnailCompression"},
  586. { 0x5024, "ThumbnailPhotometricInterp"},
  587. { 0x5025, "ThumbnailImageDescription"},
  588. { 0x5026, "ThumbnailEquipMake"},
  589. { 0x5027, "ThumbnailEquipModel"},
  590. { 0x5028, "ThumbnailStripOffsets"},
  591. { 0x5029, "ThumbnailOrientation"},
  592. { 0x502A, "ThumbnailSamplesPerPixel"},
  593. { 0x502B, "ThumbnailRowsPerStrip"},
  594. { 0x502C, "ThumbnailStripBytesCount"},
  595. { 0x502D, "ThumbnailResolutionX"},
  596. { 0x502E, "ThumbnailResolutionY"},
  597. { 0x502F, "ThumbnailPlanarConfig"},
  598. { 0x5030, "ThumbnailResolutionUnit"},
  599. { 0x5031, "ThumbnailTransferFunction"},
  600. { 0x5032, "ThumbnailSoftwareUsed"},
  601. { 0x5033, "ThumbnailDateTime"},
  602. { 0x5034, "ThumbnailArtist"},
  603. { 0x5035, "ThumbnailWhitePoint"},
  604. { 0x5036, "ThumbnailPrimaryChromaticities"},
  605. { 0x5037, "ThumbnailYCbCrCoefficients"},
  606. { 0x5038, "ThumbnailYCbCrSubsampling"},
  607. { 0x5039, "ThumbnailYCbCrPositioning"},
  608. { 0x503A, "ThumbnailRefBlackWhite"},
  609. { 0x503B, "ThumbnailCopyRight"},
  610. { 0x5090, "LuminanceTable"},
  611. { 0x5091, "ChrominanceTable"},
  612. { 0x5100, "FrameDelay"},
  613. { 0x5101, "LoopCount"},
  614. { 0x5110, "PixelUnit"},
  615. { 0x5111, "PixelPerUnitX"},
  616. { 0x5112, "PixelPerUnitY"},
  617. { 0x5113, "PaletteHistogram"},
  618. { 0x1000, "RelatedImageFileFormat"},
  619. { 0x800D, "ImageID"},
  620. { 0x80E3, "Matteing"}, /* obsoleted by ExtraSamples */
  621. { 0x80E4, "DataType"}, /* obsoleted by SampleFormat */
  622. { 0x80E5, "ImageDepth"},
  623. { 0x80E6, "TileDepth"},
  624. { 0x828D, "CFARepeatPatternDim"},
  625. { 0x828E, "CFAPattern"},
  626. { 0x828F, "BatteryLevel"},
  627. { 0x8298, "Copyright"},
  628. { 0x829A, "ExposureTime"},
  629. { 0x829D, "FNumber"},
  630. { 0x83BB, "IPTC/NAA"},
  631. { 0x84E3, "IT8RasterPadding"},
  632. { 0x84E5, "IT8ColorTable"},
  633. { 0x8649, "ImageResourceInformation"}, /* PhotoShop */
  634. { 0x8769, "Exif_IFD_Pointer"},
  635. { 0x8773, "ICC_Profile"},
  636. { 0x8822, "ExposureProgram"},
  637. { 0x8824, "SpectralSensity"},
  638. { 0x8825, "GPS_IFD_Pointer"},
  639. { 0x8827, "ISOSpeedRatings"},
  640. { 0x8828, "OECF"},
  641. { 0x9000, "ExifVersion"},
  642. { 0x9003, "DateTimeOriginal"},
  643. { 0x9004, "DateTimeDigitized"},
  644. { 0x9101, "ComponentsConfiguration"},
  645. { 0x9102, "CompressedBitsPerPixel"},
  646. { 0x9201, "ShutterSpeedValue"},
  647. { 0x9202, "ApertureValue"},
  648. { 0x9203, "BrightnessValue"},
  649. { 0x9204, "ExposureBiasValue"},
  650. { 0x9205, "MaxApertureValue"},
  651. { 0x9206, "SubjectDistance"},
  652. { 0x9207, "MeteringMode"},
  653. { 0x9208, "LightSource"},
  654. { 0x9209, "Flash"},
  655. { 0x920A, "FocalLength"},
  656. { 0x920B, "FlashEnergy"}, /* 0xA20B in JPEG */
  657. { 0x920C, "SpatialFrequencyResponse"}, /* 0xA20C - - */
  658. { 0x920D, "Noise"},
  659. { 0x920E, "FocalPlaneXResolution"}, /* 0xA20E - - */
  660. { 0x920F, "FocalPlaneYResolution"}, /* 0xA20F - - */
  661. { 0x9210, "FocalPlaneResolutionUnit"}, /* 0xA210 - - */
  662. { 0x9211, "ImageNumber"},
  663. { 0x9212, "SecurityClassification"},
  664. { 0x9213, "ImageHistory"},
  665. { 0x9214, "SubjectLocation"}, /* 0xA214 - - */
  666. { 0x9215, "ExposureIndex"}, /* 0xA215 - - */
  667. { 0x9216, "TIFF/EPStandardID"},
  668. { 0x9217, "SensingMethod"}, /* 0xA217 - - */
  669. { 0x923F, "StoNits"},
  670. { 0x927C, "MakerNote"},
  671. { 0x9286, "UserComment"},
  672. { 0x9290, "SubSecTime"},
  673. { 0x9291, "SubSecTimeOriginal"},
  674. { 0x9292, "SubSecTimeDigitized"},
  675. { 0x935C, "ImageSourceData"}, /* "Adobe Photoshop Document Data Block": 8BIM... */
  676. { 0x9c9b, "Title" }, /* Win XP specific, Unicode */
  677. { 0x9c9c, "Comments" }, /* Win XP specific, Unicode */
  678. { 0x9c9d, "Author" }, /* Win XP specific, Unicode */
  679. { 0x9c9e, "Keywords" }, /* Win XP specific, Unicode */
  680. { 0x9c9f, "Subject" }, /* Win XP specific, Unicode, not to be confused with SubjectDistance and SubjectLocation */
  681. { 0xA000, "FlashPixVersion"},
  682. { 0xA001, "ColorSpace"},
  683. { 0xA002, "ExifImageWidth"},
  684. { 0xA003, "ExifImageLength"},
  685. { 0xA004, "RelatedSoundFile"},
  686. { 0xA005, "InteroperabilityOffset"},
  687. { 0xA20B, "FlashEnergy"}, /* 0x920B in TIFF/EP */
  688. { 0xA20C, "SpatialFrequencyResponse"}, /* 0x920C - - */
  689. { 0xA20D, "Noise"},
  690. { 0xA20E, "FocalPlaneXResolution"}, /* 0x920E - - */
  691. { 0xA20F, "FocalPlaneYResolution"}, /* 0x920F - - */
  692. { 0xA210, "FocalPlaneResolutionUnit"}, /* 0x9210 - - */
  693. { 0xA211, "ImageNumber"},
  694. { 0xA212, "SecurityClassification"},
  695. { 0xA213, "ImageHistory"},
  696. { 0xA214, "SubjectLocation"}, /* 0x9214 - - */
  697. { 0xA215, "ExposureIndex"}, /* 0x9215 - - */
  698. { 0xA216, "TIFF/EPStandardID"},
  699. { 0xA217, "SensingMethod"}, /* 0x9217 - - */
  700. { 0xA300, "FileSource"},
  701. { 0xA301, "SceneType"},
  702. { 0xA302, "CFAPattern"},
  703. { 0xA401, "CustomRendered"},
  704. { 0xA402, "ExposureMode"},
  705. { 0xA403, "WhiteBalance"},
  706. { 0xA404, "DigitalZoomRatio"},
  707. { 0xA405, "FocalLengthIn35mmFilm"},
  708. { 0xA406, "SceneCaptureType"},
  709. { 0xA407, "GainControl"},
  710. { 0xA408, "Contrast"},
  711. { 0xA409, "Saturation"},
  712. { 0xA40A, "Sharpness"},
  713. { 0xA40B, "DeviceSettingDescription"},
  714. { 0xA40C, "SubjectDistanceRange"},
  715. { 0xA420, "ImageUniqueID"},
  716. TAG_TABLE_END
  717. } ;
  718. static tag_info_array tag_table_GPS = {
  719. { 0x0000, "GPSVersion"},
  720. { 0x0001, "GPSLatitudeRef"},
  721. { 0x0002, "GPSLatitude"},
  722. { 0x0003, "GPSLongitudeRef"},
  723. { 0x0004, "GPSLongitude"},
  724. { 0x0005, "GPSAltitudeRef"},
  725. { 0x0006, "GPSAltitude"},
  726. { 0x0007, "GPSTimeStamp"},
  727. { 0x0008, "GPSSatellites"},
  728. { 0x0009, "GPSStatus"},
  729. { 0x000A, "GPSMeasureMode"},
  730. { 0x000B, "GPSDOP"},
  731. { 0x000C, "GPSSpeedRef"},
  732. { 0x000D, "GPSSpeed"},
  733. { 0x000E, "GPSTrackRef"},
  734. { 0x000F, "GPSTrack"},
  735. { 0x0010, "GPSImgDirectionRef"},
  736. { 0x0011, "GPSImgDirection"},
  737. { 0x0012, "GPSMapDatum"},
  738. { 0x0013, "GPSDestLatitudeRef"},
  739. { 0x0014, "GPSDestLatitude"},
  740. { 0x0015, "GPSDestLongitudeRef"},
  741. { 0x0016, "GPSDestLongitude"},
  742. { 0x0017, "GPSDestBearingRef"},
  743. { 0x0018, "GPSDestBearing"},
  744. { 0x0019, "GPSDestDistanceRef"},
  745. { 0x001A, "GPSDestDistance"},
  746. { 0x001B, "GPSProcessingMode"},
  747. { 0x001C, "GPSAreaInformation"},
  748. { 0x001D, "GPSDateStamp"},
  749. { 0x001E, "GPSDifferential"},
  750. TAG_TABLE_END
  751. };
  752. static tag_info_array tag_table_IOP = {
  753. { 0x0001, "InterOperabilityIndex"}, /* should be 'R98' or 'THM' */
  754. { 0x0002, "InterOperabilityVersion"},
  755. { 0x1000, "RelatedFileFormat"},
  756. { 0x1001, "RelatedImageWidth"},
  757. { 0x1002, "RelatedImageHeight"},
  758. TAG_TABLE_END
  759. };
  760. static tag_info_array tag_table_VND_CANON = {
  761. { 0x0001, "ModeArray"}, /* guess */
  762. { 0x0004, "ImageInfo"}, /* guess */
  763. { 0x0006, "ImageType"},
  764. { 0x0007, "FirmwareVersion"},
  765. { 0x0008, "ImageNumber"},
  766. { 0x0009, "OwnerName"},
  767. { 0x000C, "Camera"},
  768. { 0x000F, "CustomFunctions"},
  769. TAG_TABLE_END
  770. };
  771. static tag_info_array tag_table_VND_CASIO = {
  772. { 0x0001, "RecordingMode"},
  773. { 0x0002, "Quality"},
  774. { 0x0003, "FocusingMode"},
  775. { 0x0004, "FlashMode"},
  776. { 0x0005, "FlashIntensity"},
  777. { 0x0006, "ObjectDistance"},
  778. { 0x0007, "WhiteBalance"},
  779. { 0x000A, "DigitalZoom"},
  780. { 0x000B, "Sharpness"},
  781. { 0x000C, "Contrast"},
  782. { 0x000D, "Saturation"},
  783. { 0x0014, "CCDSensitivity"},
  784. TAG_TABLE_END
  785. };
  786. static tag_info_array tag_table_VND_FUJI = {
  787. { 0x0000, "Version"},
  788. { 0x1000, "Quality"},
  789. { 0x1001, "Sharpness"},
  790. { 0x1002, "WhiteBalance"},
  791. { 0x1003, "Color"},
  792. { 0x1004, "Tone"},
  793. { 0x1010, "FlashMode"},
  794. { 0x1011, "FlashStrength"},
  795. { 0x1020, "Macro"},
  796. { 0x1021, "FocusMode"},
  797. { 0x1030, "SlowSync"},
  798. { 0x1031, "PictureMode"},
  799. { 0x1100, "ContTake"},
  800. { 0x1300, "BlurWarning"},
  801. { 0x1301, "FocusWarning"},
  802. { 0x1302, "AEWarning "},
  803. TAG_TABLE_END
  804. };
  805. static tag_info_array tag_table_VND_NIKON = {
  806. { 0x0003, "Quality"},
  807. { 0x0004, "ColorMode"},
  808. { 0x0005, "ImageAdjustment"},
  809. { 0x0006, "CCDSensitivity"},
  810. { 0x0007, "WhiteBalance"},
  811. { 0x0008, "Focus"},
  812. { 0x000a, "DigitalZoom"},
  813. { 0x000b, "Converter"},
  814. TAG_TABLE_END
  815. };
  816. static tag_info_array tag_table_VND_NIKON_990 = {
  817. { 0x0001, "Version"},
  818. { 0x0002, "ISOSetting"},
  819. { 0x0003, "ColorMode"},
  820. { 0x0004, "Quality"},
  821. { 0x0005, "WhiteBalance"},
  822. { 0x0006, "ImageSharpening"},
  823. { 0x0007, "FocusMode"},
  824. { 0x0008, "FlashSetting"},
  825. { 0x000F, "ISOSelection"},
  826. { 0x0080, "ImageAdjustment"},
  827. { 0x0082, "AuxiliaryLens"},
  828. { 0x0085, "ManualFocusDistance"},
  829. { 0x0086, "DigitalZoom"},
  830. { 0x0088, "AFFocusPosition"},
  831. { 0x0010, "DataDump"},
  832. TAG_TABLE_END
  833. };
  834. static tag_info_array tag_table_VND_OLYMPUS = {
  835. { 0x0200, "SpecialMode"},
  836. { 0x0201, "JPEGQuality"},
  837. { 0x0202, "Macro"},
  838. { 0x0204, "DigitalZoom"},
  839. { 0x0207, "SoftwareRelease"},
  840. { 0x0208, "PictureInfo"},
  841. { 0x0209, "CameraId"},
  842. { 0x0F00, "DataDump"},
  843. TAG_TABLE_END
  844. };
  845. static tag_info_array tag_table_VND_SAMSUNG = {
  846. { 0x0001, "Version"},
  847. { 0x0021, "PictureWizard"},
  848. { 0x0030, "LocalLocationName"},
  849. { 0x0031, "LocationName"},
  850. { 0x0035, "Preview"},
  851. { 0x0043, "CameraTemperature"},
  852. { 0xa001, "FirmwareName"},
  853. { 0xa003, "LensType"},
  854. { 0xa004, "LensFirmware"},
  855. { 0xa010, "SensorAreas"},
  856. { 0xa011, "ColorSpace"},
  857. { 0xa012, "SmartRange"},
  858. { 0xa013, "ExposureBiasValue"},
  859. { 0xa014, "ISO"},
  860. { 0xa018, "ExposureTime"},
  861. { 0xa019, "FNumber"},
  862. { 0xa01a, "FocalLengthIn35mmFormat"},
  863. { 0xa020, "EncryptionKey"},
  864. { 0xa021, "WB_RGGBLevelsUncorrected"},
  865. { 0xa022, "WB_RGGBLevelsAuto"},
  866. { 0xa023, "WB_RGGBLevelsIlluminator1"},
  867. { 0xa024, "WB_RGGBLevelsIlluminator2"},
  868. { 0xa028, "WB_RGGBLevelsBlack"},
  869. { 0xa030, "ColorMatrix"},
  870. { 0xa031, "ColorMatrixSRGB"},
  871. { 0xa032, "ColorMatrixAdobeRGB"},
  872. { 0xa040, "ToneCurve1"},
  873. { 0xa041, "ToneCurve2"},
  874. { 0xa042, "ToneCurve3"},
  875. { 0xa043, "ToneCurve4"},
  876. TAG_TABLE_END
  877. };
  878. static tag_info_array tag_table_VND_PANASONIC = {
  879. { 0x0001, "Quality"},
  880. { 0x0002, "FirmwareVersion"},
  881. { 0x0003, "WhiteBalance"},
  882. { 0x0007, "FocusMode"},
  883. { 0x000f, "AFMode"},
  884. { 0x001a, "ImageStabilization"},
  885. { 0x001c, "Macro"},
  886. { 0x001f, "ShootingMode"},
  887. { 0x0020, "Audio"},
  888. { 0x0021, "DataDump"},
  889. { 0x0023, "WhiteBalanceBias"},
  890. { 0x0024, "FlashBias"},
  891. { 0x0025, "InternalSerialNumber"},
  892. { 0x0026, "ExifVersion"},
  893. { 0x0028, "ColorEffect"},
  894. { 0x0029, "TimeSincePowerOn"},
  895. { 0x002a, "BurstMode"},
  896. { 0x002b, "SequenceNumber"},
  897. { 0x002c, "Contrast"},
  898. { 0x002d, "NoiseReduction"},
  899. { 0x002e, "SelfTimer"},
  900. { 0x0030, "Rotation"},
  901. { 0x0031, "AFAssistLamp"},
  902. { 0x0032, "ColorMode"},
  903. { 0x0033, "BabyAge1"},
  904. { 0x0034, "OpticalZoomMode"},
  905. { 0x0035, "ConversionLens"},
  906. { 0x0036, "TravelDay"},
  907. { 0x0039, "Contrast"},
  908. { 0x003a, "WorldTimeLocation"},
  909. { 0x003b, "TextStamp1"},
  910. { 0x003c, "ProgramISO"},
  911. { 0x003d, "AdvancedSceneType"},
  912. { 0x003e, "TextStamp2"},
  913. { 0x003f, "FacesDetected"},
  914. { 0x0040, "Saturation"},
  915. { 0x0041, "Sharpness"},
  916. { 0x0042, "FilmMode"},
  917. { 0x0044, "ColorTempKelvin"},
  918. { 0x0045, "BracketSettings"},
  919. { 0x0046, "WBAdjustAB"},
  920. { 0x0047, "WBAdjustGM"},
  921. { 0x0048, "FlashCurtain"},
  922. { 0x0049, "LongShutterNoiseReduction"},
  923. { 0x004b, "ImageWidth"},
  924. { 0x004c, "ImageHeight"},
  925. { 0x004d, "AFPointPosition"},
  926. { 0x004e, "FaceDetInfo"},
  927. { 0x0051, "LensType"},
  928. { 0x0052, "LensSerialNumber"},
  929. { 0x0053, "AccessoryType"},
  930. { 0x0054, "AccessorySerialNumber"},
  931. { 0x0059, "Transform1"},
  932. { 0x005d, "IntelligentExposure"},
  933. { 0x0060, "LensFirmwareVersion"},
  934. { 0x0061, "FaceRecInfo"},
  935. { 0x0062, "FlashWarning"},
  936. { 0x0065, "Title"},
  937. { 0x0066, "BabyName"},
  938. { 0x0067, "Location"},
  939. { 0x0069, "Country"},
  940. { 0x006b, "State"},
  941. { 0x006d, "City"},
  942. { 0x006f, "Landmark"},
  943. { 0x0070, "IntelligentResolution"},
  944. { 0x0077, "BurstSheed"},
  945. { 0x0079, "IntelligentDRange"},
  946. { 0x007c, "ClearRetouch"},
  947. { 0x0080, "City2"},
  948. { 0x0086, "ManometerPressure"},
  949. { 0x0089, "PhotoStyle"},
  950. { 0x008a, "ShadingCompensation"},
  951. { 0x008c, "AccelerometerZ"},
  952. { 0x008d, "AccelerometerX"},
  953. { 0x008e, "AccelerometerY"},
  954. { 0x008f, "CameraOrientation"},
  955. { 0x0090, "RollAngle"},
  956. { 0x0091, "PitchAngle"},
  957. { 0x0093, "SweepPanoramaDirection"},
  958. { 0x0094, "PanoramaFieldOfView"},
  959. { 0x0096, "TimerRecording"},
  960. { 0x009d, "InternalNDFilter"},
  961. { 0x009e, "HDR"},
  962. { 0x009f, "ShutterType"},
  963. { 0x00a3, "ClearRetouchValue"},
  964. { 0x00ab, "TouchAE"},
  965. { 0x0e00, "PrintIM"},
  966. { 0x8000, "MakerNoteVersion"},
  967. { 0x8001, "SceneMode"},
  968. { 0x8004, "WBRedLevel"},
  969. { 0x8005, "WBGreenLevel"},
  970. { 0x8006, "WBBlueLevel"},
  971. { 0x8007, "FlashFired"},
  972. { 0x8008, "TextStamp3"},
  973. { 0x8009, "TextStamp4"},
  974. { 0x8010, "BabyAge2"},
  975. { 0x8012, "Transform2"},
  976. TAG_TABLE_END
  977. };
  978. static tag_info_array tag_table_VND_DJI = {
  979. { 0x0001, "Make"},
  980. { 0x0003, "SpeedX"},
  981. { 0x0004, "SpeedY"},
  982. { 0x0005, "SpeedZ"},
  983. { 0x0006, "Pitch"},
  984. { 0x0007, "Yaw"},
  985. { 0x0008, "Roll"},
  986. { 0x0009, "CameraPitch"},
  987. { 0x000a, "CameraYaw"},
  988. { 0x000b, "CameraRoll"},
  989. TAG_TABLE_END
  990. };
  991. static tag_info_array tag_table_VND_SONY = {
  992. { 0x0102, "Quality"},
  993. { 0x0104, "FlashExposureComp"},
  994. { 0x0105, "Teleconverter"},
  995. { 0x0112, "WhiteBalanceFineTune"},
  996. { 0x0114, "CameraSettings"},
  997. { 0x0115, "WhiteBalance"},
  998. { 0x0116, "ExtraInfo"},
  999. { 0x0e00, "PrintIM"},
  1000. { 0x1000, "MultiBurstMode"},
  1001. { 0x1001, "MultiBurstImageWidth"},
  1002. { 0x1002, "MultiBurstImageHeight"},
  1003. { 0x1003, "Panorama"},
  1004. { 0x2001, "PreviewImage"},
  1005. { 0x2002, "Rating"},
  1006. { 0x2004, "Contrast"},
  1007. { 0x2005, "Saturation"},
  1008. { 0x2006, "Sharpness"},
  1009. { 0x2007, "Brightness"},
  1010. { 0x2008, "LongExposureNoiseReduction"},
  1011. { 0x2009, "HighISONoiseReduction"},
  1012. { 0x200a, "AutoHDR"},
  1013. { 0x3000, "ShotInfo"},
  1014. { 0xb000, "FileFormat"},
  1015. { 0xb001, "SonyModelID"},
  1016. { 0xb020, "ColorReproduction"},
  1017. { 0xb021, "ColorTemperature"},
  1018. { 0xb022, "ColorCompensationFilter"},
  1019. { 0xb023, "SceneMode"},
  1020. { 0xb024, "ZoneMatching"},
  1021. { 0xb025, "DynamicRangeOptimizer"},
  1022. { 0xb026, "ImageStabilization"},
  1023. { 0xb027, "LensID"},
  1024. { 0xb028, "MinoltaMakerNote"},
  1025. { 0xb029, "ColorMode"},
  1026. { 0xb02b, "FullImageSize"},
  1027. { 0xb02c, "PreviewImageSize"},
  1028. { 0xb040, "Macro"},
  1029. { 0xb041, "ExposureMode"},
  1030. { 0xb042, "FocusMode"},
  1031. { 0xb043, "AFMode"},
  1032. { 0xb044, "AFIlluminator"},
  1033. { 0xb047, "JPEGQuality"},
  1034. { 0xb048, "FlashLevel"},
  1035. { 0xb049, "ReleaseMode"},
  1036. { 0xb04a, "SequenceNumber"},
  1037. { 0xb04b, "AntiBlur"},
  1038. { 0xb04e, "FocusMode"},
  1039. { 0xb04f, "DynamicRangeOptimizer"},
  1040. { 0xb050, "HighISONoiseReduction2"},
  1041. { 0xb052, "IntelligentAuto"},
  1042. { 0xb054, "WhiteBalance2"},
  1043. TAG_TABLE_END
  1044. };
  1045. static tag_info_array tag_table_VND_PENTAX = {
  1046. { 0x0000, "Version"},
  1047. { 0x0001, "Mode"},
  1048. { 0x0002, "PreviewResolution"},
  1049. { 0x0003, "PreviewLength"},
  1050. { 0x0004, "PreviewOffset"},
  1051. { 0x0005, "ModelID"},
  1052. { 0x0006, "Date"},
  1053. { 0x0007, "Time"},
  1054. { 0x0008, "Quality"},
  1055. { 0x0009, "Size"},
  1056. { 0x000c, "Flash"},
  1057. { 0x000d, "Focus"},
  1058. { 0x000e, "AFPoint"},
  1059. { 0x000f, "AFPointInFocus"},
  1060. { 0x0012, "ExposureTime"},
  1061. { 0x0013, "FNumber"},
  1062. { 0x0014, "ISO"},
  1063. { 0x0016, "ExposureCompensation"},
  1064. { 0x0017, "MeteringMode"},
  1065. { 0x0018, "AutoBracketing"},
  1066. { 0x0019, "WhiteBalance"},
  1067. { 0x001a, "WhiteBalanceMode"},
  1068. { 0x001b, "BlueBalance"},
  1069. { 0x001c, "RedBalance"},
  1070. { 0x001d, "FocalLength"},
  1071. { 0x001e, "DigitalZoom"},
  1072. { 0x001f, "Saturation"},
  1073. { 0x0020, "Contrast"},
  1074. { 0x0021, "Sharpness"},
  1075. { 0x0022, "Location"},
  1076. { 0x0023, "Hometown"},
  1077. { 0x0024, "Destination"},
  1078. { 0x0025, "HometownDST"},
  1079. { 0x0026, "DestinationDST"},
  1080. { 0x0027, "DSPFirmwareVersion"},
  1081. { 0x0028, "CPUFirmwareVersion"},
  1082. { 0x0029, "FrameNumber"},
  1083. { 0x002d, "EffectiveLV"},
  1084. { 0x0032, "ImageProcessing"},
  1085. { 0x0033, "PictureMode"},
  1086. { 0x0034, "DriveMode"},
  1087. { 0x0037, "ColorSpace"},
  1088. { 0x0038, "ImageAreaOffset"},
  1089. { 0x0039, "RawImageSize"},
  1090. { 0x003e, "PreviewImageBorders"},
  1091. { 0x003f, "LensType"},
  1092. { 0x0040, "SensitivityAdjust"},
  1093. { 0x0041, "DigitalFilter"},
  1094. { 0x0047, "Temperature"},
  1095. { 0x0048, "AELock"},
  1096. { 0x0049, "NoiseReduction"},
  1097. { 0x004d, "FlashExposureCompensation"},
  1098. { 0x004f, "ImageTone"},
  1099. { 0x0050, "ColorTemperature"},
  1100. { 0x005c, "ShakeReduction"},
  1101. { 0x005d, "ShutterCount"},
  1102. { 0x0069, "DynamicRangeExpansion"},
  1103. { 0x0071, "HighISONoiseReduction"},
  1104. { 0x0072, "AFAdjustment"},
  1105. { 0x0200, "BlackPoint"},
  1106. { 0x0201, "WhitePoint"},
  1107. { 0x0205, "ShotInfo"},
  1108. { 0x0206, "AEInfo"},
  1109. { 0x0207, "LensInfo"},
  1110. { 0x0208, "FlashInfo"},
  1111. { 0x0209, "AEMeteringSegments"},
  1112. { 0x020a, "FlashADump"},
  1113. { 0x020b, "FlashBDump"},
  1114. { 0x020d, "WB_RGGBLevelsDaylight"},
  1115. { 0x020e, "WB_RGGBLevelsShade"},
  1116. { 0x020f, "WB_RGGBLevelsCloudy"},
  1117. { 0x0210, "WB_RGGBLevelsTungsten"},
  1118. { 0x0211, "WB_RGGBLevelsFluorescentD"},
  1119. { 0x0212, "WB_RGGBLevelsFluorescentN"},
  1120. { 0x0213, "WB_RGGBLevelsFluorescentW"},
  1121. { 0x0214, "WB_RGGBLevelsFlash"},
  1122. { 0x0215, "CameraInfo"},
  1123. { 0x0216, "BatteryInfo"},
  1124. { 0x021f, "AFInfo"},
  1125. { 0x0222, "ColorInfo"},
  1126. { 0x0229, "SerialNumber"},
  1127. TAG_TABLE_END
  1128. };
  1129. static tag_info_array tag_table_VND_MINOLTA = {
  1130. { 0x0000, "Version"},
  1131. { 0x0001, "CameraSettingsStdOld"},
  1132. { 0x0003, "CameraSettingsStdNew"},
  1133. { 0x0004, "CameraSettings7D"},
  1134. { 0x0018, "ImageStabilizationData"},
  1135. { 0x0020, "WBInfoA100"},
  1136. { 0x0040, "CompressedImageSize"},
  1137. { 0x0081, "Thumbnail"},
  1138. { 0x0088, "ThumbnailOffset"},
  1139. { 0x0089, "ThumbnailLength"},
  1140. { 0x0100, "SceneMode"},
  1141. { 0x0101, "ColorMode"},
  1142. { 0x0102, "Quality"},
  1143. { 0x0104, "FlashExposureComp"},
  1144. { 0x0105, "Teleconverter"},
  1145. { 0x0107, "ImageStabilization"},
  1146. { 0x0109, "RawAndJpgRecording"},
  1147. { 0x010a, "ZoneMatching"},
  1148. { 0x010b, "ColorTemperature"},
  1149. { 0x010c, "LensID"},
  1150. { 0x0111, "ColorCompensationFilter"},
  1151. { 0x0112, "WhiteBalanceFineTune"},
  1152. { 0x0113, "ImageStabilizationA100"},
  1153. { 0x0114, "CameraSettings5D"},
  1154. { 0x0115, "WhiteBalance"},
  1155. { 0x0e00, "PrintIM"},
  1156. { 0x0f00, "CameraSettingsZ1"},
  1157. TAG_TABLE_END
  1158. };
  1159. static tag_info_array tag_table_VND_SIGMA = {
  1160. { 0x0002, "SerialNumber"},
  1161. { 0x0003, "DriveMode"},
  1162. { 0x0004, "ResolutionMode"},
  1163. { 0x0005, "AutofocusMode"},
  1164. { 0x0006, "FocusSetting"},
  1165. { 0x0007, "WhiteBalance"},
  1166. { 0x0008, "ExposureMode"},
  1167. { 0x0009, "MeteringMode"},
  1168. { 0x000a, "LensRange"},
  1169. { 0x000b, "ColorSpace"},
  1170. { 0x000c, "Exposure"},
  1171. { 0x000d, "Contrast"},
  1172. { 0x000e, "Shadow"},
  1173. { 0x000f, "Highlight"},
  1174. { 0x0010, "Saturation"},
  1175. { 0x0011, "Sharpness"},
  1176. { 0x0012, "FillLight"},
  1177. { 0x0014, "ColorAdjustment"},
  1178. { 0x0015, "AdjustmentMode"},
  1179. { 0x0016, "Quality"},
  1180. { 0x0017, "Firmware"},
  1181. { 0x0018, "Software"},
  1182. { 0x0019, "AutoBracket"},
  1183. TAG_TABLE_END
  1184. };
  1185. static tag_info_array tag_table_VND_KYOCERA = {
  1186. { 0x0001, "FormatThumbnail"},
  1187. { 0x0E00, "PrintImageMatchingInfo"},
  1188. TAG_TABLE_END
  1189. };
  1190. static tag_info_array tag_table_VND_RICOH = {
  1191. { 0x0001, "MakerNoteDataType"},
  1192. { 0x0002, "Version"},
  1193. { 0x0E00, "PrintImageMatchingInfo"},
  1194. { 0x2001, "RicohCameraInfoMakerNoteSubIFD"},
  1195. TAG_TABLE_END
  1196. };
  1197. typedef enum mn_byte_order_t {
  1198. MN_ORDER_INTEL = 0,
  1199. MN_ORDER_MOTOROLA = 1,
  1200. MN_ORDER_NORMAL
  1201. } mn_byte_order_t;
  1202. typedef enum mn_offset_mode_t {
  1203. MN_OFFSET_NORMAL,
  1204. MN_OFFSET_MAKER
  1205. } mn_offset_mode_t;
  1206. typedef struct {
  1207. tag_table_type tag_table;
  1208. char * make;
  1209. char * id_string;
  1210. int id_string_len;
  1211. int offset;
  1212. mn_byte_order_t byte_order;
  1213. mn_offset_mode_t offset_mode;
  1214. } maker_note_type;
  1215. /* Remember to update PHP_MINFO if updated */
  1216. static const maker_note_type maker_note_array[] = {
  1217. { tag_table_VND_CANON, "Canon", NULL, 0, 0, MN_ORDER_INTEL, MN_OFFSET_NORMAL},
  1218. { tag_table_VND_CASIO, "CASIO", NULL, 0, 0, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
  1219. { tag_table_VND_FUJI, "FUJIFILM", "FUJIFILM\x0C\x00\x00\x00", 12, 12, MN_ORDER_INTEL, MN_OFFSET_MAKER},
  1220. { tag_table_VND_NIKON, "NIKON", "Nikon\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1221. { tag_table_VND_NIKON_990, "NIKON", NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1222. { tag_table_VND_OLYMPUS, "OLYMPUS OPTICAL CO.,LTD", "OLYMP\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1223. { tag_table_VND_SAMSUNG, "SAMSUNG", NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1224. { tag_table_VND_PANASONIC, "Panasonic", "Panasonic\x00\x00\x00", 12, 12, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1225. { tag_table_VND_DJI, "DJI", NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1226. { tag_table_VND_SONY, "SONY", "SONY DSC \x00\x00\x00", 12, 12, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1227. { tag_table_VND_SONY, "SONY", NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1228. { tag_table_VND_PENTAX, "PENTAX", "AOC\x00", 6, 6, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1229. { tag_table_VND_MINOLTA, "Minolta, KONICA MINOLTA", NULL, 0, 0, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1230. { tag_table_VND_SIGMA, "SIGMA, FOVEON", "SIGMA\x00\x00\x00", 10, 10, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1231. { tag_table_VND_SIGMA, "SIGMA, FOVEON", "FOVEON\x00\x00\x00", 10, 10, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1232. { tag_table_VND_KYOCERA, "KYOCERA, CONTAX", "KYOCERA \x00\x00\x00", 22, 22, MN_ORDER_NORMAL, MN_OFFSET_MAKER},
  1233. { tag_table_VND_RICOH, "RICOH", "Ricoh", 5, 5, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
  1234. { tag_table_VND_RICOH, "RICOH", "RICOH", 5, 5, MN_ORDER_MOTOROLA, MN_OFFSET_NORMAL},
  1235. /* These re-uses existing formats */
  1236. { tag_table_VND_OLYMPUS, "AGFA", "AGFA \x00\x01", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL},
  1237. { tag_table_VND_OLYMPUS, "EPSON", "EPSON\x00\x01\x00", 8, 8, MN_ORDER_NORMAL, MN_OFFSET_NORMAL}
  1238. };
  1239. /* }}} */
  1240. static HashTable *exif_make_tag_ht(tag_info_type *tag_table)
  1241. {
  1242. HashTable *ht = malloc(sizeof(HashTable));
  1243. zend_hash_init(ht, 0, NULL, NULL, 1);
  1244. while (tag_table->Tag != TAG_END_OF_LIST) {
  1245. if (!zend_hash_index_add_ptr(ht, tag_table->Tag, tag_table->Desc)) {
  1246. zend_error(E_CORE_ERROR, "Duplicate tag %x", tag_table->Tag);
  1247. }
  1248. tag_table++;
  1249. }
  1250. return ht;
  1251. }
  1252. static void exif_tag_ht_dtor(zval *zv)
  1253. {
  1254. HashTable *ht = Z_PTR_P(zv);
  1255. zend_hash_destroy(ht);
  1256. free(ht);
  1257. }
  1258. static HashTable *exif_get_tag_ht(tag_info_type *tag_table)
  1259. {
  1260. HashTable *ht;
  1261. if (!EXIF_G(tag_table_cache)) {
  1262. EXIF_G(tag_table_cache) = malloc(sizeof(HashTable));
  1263. zend_hash_init(EXIF_G(tag_table_cache), 0, NULL, exif_tag_ht_dtor, 1);
  1264. }
  1265. ht = zend_hash_index_find_ptr(EXIF_G(tag_table_cache), (uintptr_t) tag_table);
  1266. if (ht) {
  1267. return ht;
  1268. }
  1269. ht = exif_make_tag_ht(tag_table);
  1270. zend_hash_index_add_new_ptr(EXIF_G(tag_table_cache), (uintptr_t) tag_table, ht);
  1271. return ht;
  1272. }
  1273. /* {{{ exif_get_tagname
  1274. Get headername for tag_num or NULL if not defined */
  1275. static char *exif_get_tagname(int tag_num, tag_table_type tag_table)
  1276. {
  1277. return zend_hash_index_find_ptr(exif_get_tag_ht(tag_table), tag_num);
  1278. }
  1279. /* }}} */
  1280. static char *exif_get_tagname_debug(int tag_num, tag_table_type tag_table)
  1281. {
  1282. char *desc = zend_hash_index_find_ptr(exif_get_tag_ht(tag_table), tag_num);
  1283. if (desc) {
  1284. return desc;
  1285. }
  1286. return "UndefinedTag";
  1287. }
  1288. static char *exif_get_tagname_key(int tag_num, char *buf, size_t buf_size, tag_table_type tag_table)
  1289. {
  1290. char *desc = zend_hash_index_find_ptr(exif_get_tag_ht(tag_table), tag_num);
  1291. if (desc) {
  1292. return desc;
  1293. }
  1294. snprintf(buf, buf_size, "UndefinedTag:0x%04X", tag_num);
  1295. return buf;
  1296. }
  1297. /* {{{ exif_char_dump
  1298. * Do not use! This is a debug function... */
  1299. #ifdef EXIF_DEBUG
  1300. static char* exif_char_dump(char * addr, int len, int offset)
  1301. {
  1302. static char buf[4096+1];
  1303. static char tmp[20];
  1304. int c, i, p=0, n = 5+31;
  1305. p += slprintf(buf+p, sizeof(buf)-p, "\nDump Len: %08X (%d)", len, len);
  1306. if (len) {
  1307. for(i=0; i<len+15 && p+n<=sizeof(buf); i++) {
  1308. if (i%16==0) {
  1309. p += slprintf(buf+p, sizeof(buf)-p, "\n%08X: ", i+offset);
  1310. }
  1311. if (i<len) {
  1312. c = *((unsigned char *)addr++);
  1313. p += slprintf(buf+p, sizeof(buf)-p, "%02X ", c);
  1314. tmp[i%16] = c>=32 ? c : '.';
  1315. tmp[(i%16)+1] = '\0';
  1316. } else {
  1317. p += slprintf(buf+p, sizeof(buf)-p, " ");
  1318. }
  1319. if (i%16==15) {
  1320. p += slprintf(buf+p, sizeof(buf)-p, " %s", tmp);
  1321. if (i>=len) {
  1322. break;
  1323. }
  1324. }
  1325. }
  1326. }
  1327. buf[sizeof(buf)-1] = '\0';
  1328. return buf;
  1329. }
  1330. #endif
  1331. /* }}} */
  1332. /* {{{ php_jpg_get16
  1333. Get 16 bits motorola order (always) for jpeg header stuff.
  1334. */
  1335. static int php_jpg_get16(void *value)
  1336. {
  1337. return (((uchar *)value)[0] << 8) | ((uchar *)value)[1];
  1338. }
  1339. /* }}} */
  1340. /* {{{ php_ifd_get16u
  1341. * Convert a 16 bit unsigned value from file's native byte order */
  1342. static int php_ifd_get16u(void *value, int motorola_intel)
  1343. {
  1344. if (motorola_intel) {
  1345. return (((uchar *)value)[0] << 8) | ((uchar *)value)[1];
  1346. } else {
  1347. return (((uchar *)value)[1] << 8) | ((uchar *)value)[0];
  1348. }
  1349. }
  1350. /* }}} */
  1351. /* {{{ php_ifd_get16s
  1352. * Convert a 16 bit signed value from file's native byte order */
  1353. static signed short php_ifd_get16s(void *value, int motorola_intel)
  1354. {
  1355. return (signed short)php_ifd_get16u(value, motorola_intel);
  1356. }
  1357. /* }}} */
  1358. /* {{{ php_ifd_get32u
  1359. * Convert a 32 bit unsigned value from file's native byte order */
  1360. static unsigned php_ifd_get32u(void *void_value, int motorola_intel)
  1361. {
  1362. uchar *value = (uchar *) void_value;
  1363. if (motorola_intel) {
  1364. return ((unsigned)value[0] << 24)
  1365. | ((unsigned)value[1] << 16)
  1366. | ((unsigned)value[2] << 8 )
  1367. | ((unsigned)value[3] );
  1368. } else {
  1369. return ((unsigned)value[3] << 24)
  1370. | ((unsigned)value[2] << 16)
  1371. | ((unsigned)value[1] << 8 )
  1372. | ((unsigned)value[0] );
  1373. }
  1374. }
  1375. /* }}} */
  1376. /* {{{ php_ifd_get64u
  1377. * Convert a 64 bit unsigned value from file's native byte order */
  1378. static uint64_t php_ifd_get64u(void *void_value, int motorola_intel)
  1379. {
  1380. uchar *value = (uchar *) void_value;
  1381. if (motorola_intel) {
  1382. return ((uint64_t)value[0] << 56)
  1383. | ((uint64_t)value[1] << 48)
  1384. | ((uint64_t)value[2] << 40)
  1385. | ((uint64_t)value[3] << 32)
  1386. | ((uint64_t)value[4] << 24)
  1387. | ((uint64_t)value[5] << 16)
  1388. | ((uint64_t)value[6] << 8 )
  1389. | ((uint64_t)value[7] );
  1390. } else {
  1391. return ((uint64_t)value[7] << 56)
  1392. | ((uint64_t)value[6] << 48)
  1393. | ((uint64_t)value[5] << 40)
  1394. | ((uint64_t)value[4] << 32)
  1395. | ((uint64_t)value[3] << 24)
  1396. | ((uint64_t)value[2] << 16)
  1397. | ((uint64_t)value[1] << 8 )
  1398. | ((uint64_t)value[0] );
  1399. }
  1400. }
  1401. /* }}} */
  1402. /* {{{ php_ifd_get32u
  1403. * Convert a 32 bit signed value from file's native byte order */
  1404. static unsigned php_ifd_get32s(void *value, int motorola_intel)
  1405. {
  1406. return (int) php_ifd_get32u(value, motorola_intel);
  1407. }
  1408. /* }}} */
  1409. /* {{{ php_ifd_set16u
  1410. * Write 16 bit unsigned value to data */
  1411. static void php_ifd_set16u(char *data, unsigned int value, int motorola_intel)
  1412. {
  1413. if (motorola_intel) {
  1414. data[0] = (value & 0xFF00) >> 8;
  1415. data[1] = (value & 0x00FF);
  1416. } else {
  1417. data[1] = (value & 0xFF00) >> 8;
  1418. data[0] = (value & 0x00FF);
  1419. }
  1420. }
  1421. /* }}} */
  1422. /* {{{ php_ifd_set32u
  1423. * Convert a 32 bit unsigned value from file's native byte order */
  1424. static void php_ifd_set32u(char *data, size_t value, int motorola_intel)
  1425. {
  1426. if (motorola_intel) {
  1427. data[0] = (value & 0xFF000000) >> 24;
  1428. data[1] = (char) ((value & 0x00FF0000) >> 16);
  1429. data[2] = (value & 0x0000FF00) >> 8;

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