1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org>               //
5//  available at https://github.com/JamesHeinrich/getID3       //
6//            or https://www.getid3.org                        //
7//            or http://getid3.sourceforge.net                 //
8//  see readme.txt for more details                            //
9/////////////////////////////////////////////////////////////////
10//                                                             //
11// module.archive.tiff.php                                     //
12// module for analyzing TIFF files                             //
13// dependencies: NONE                                          //
14//                                                            ///
15/////////////////////////////////////////////////////////////////
16
17if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
18	exit;
19}
20
21class getid3_tiff extends getid3_handler
22{
23	/**
24	 * @return bool
25	 */
26	public function Analyze() {
27		$info = &$this->getid3->info;
28
29		$this->fseek($info['avdataoffset']);
30		$TIFFheader = $this->fread(4);
31
32		switch (substr($TIFFheader, 0, 2)) {
33			case 'II':
34				$info['tiff']['byte_order'] = 'Intel';
35				break;
36			case 'MM':
37				$info['tiff']['byte_order'] = 'Motorola';
38				break;
39			default:
40				$this->error('Invalid TIFF byte order identifier ('.substr($TIFFheader, 0, 2).') at offset '.$info['avdataoffset']);
41				return false;
42		}
43
44		$info['fileformat']          = 'tiff';
45		$info['video']['dataformat'] = 'tiff';
46		$info['video']['lossless']   = true;
47		$info['tiff']['ifd']         = array();
48		$CurrentIFD                  = array();
49
50		$FieldTypeByteLength = array(1=>1, 2=>1, 3=>2, 4=>4, 5=>8);
51
52		$nextIFDoffset = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']);
53
54		while ($nextIFDoffset > 0) {
55
56			$CurrentIFD['offset'] = $nextIFDoffset;
57
58			$this->fseek($info['avdataoffset'] + $nextIFDoffset);
59			$CurrentIFD['fieldcount'] = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
60
61			for ($i = 0; $i < $CurrentIFD['fieldcount']; $i++) {
62				$CurrentIFD['fields'][$i]['raw']['tag']      = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
63				$CurrentIFD['fields'][$i]['raw']['type']     = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
64				$CurrentIFD['fields'][$i]['raw']['length']   = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']);
65				$CurrentIFD['fields'][$i]['raw']['valoff']   =                       $this->fread(4); // To save time and space the Value Offset contains the Value instead of pointing to the Value if and only if the Value fits into 4 bytes. If the Value is shorter than 4 bytes, it is left-justified within the 4-byte Value Offset, i.e., stored in the lowernumbered bytes. Whether the Value fits within 4 bytes is determined by the Type and Count of the field.
66				$CurrentIFD['fields'][$i]['raw']['tag_name'] = $this->TIFFcommentName($CurrentIFD['fields'][$i]['raw']['tag']);
67
68				switch ($CurrentIFD['fields'][$i]['raw']['type']) {
69					case 1: // BYTE  An 8-bit unsigned integer.
70						if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
71							$CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['valoff'], 0, 1), $info['tiff']['byte_order']);
72						} else {
73							$CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
74						}
75						break;
76
77					case 2: // ASCII 8-bit bytes  that store ASCII codes; the last byte must be null.
78						if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
79							$CurrentIFD['fields'][$i]['value']  = substr($CurrentIFD['fields'][$i]['raw']['valoff'], 3);
80						} else {
81							$CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
82						}
83						break;
84
85					case 3: // SHORT A 16-bit (2-byte) unsigned integer.
86						if ($CurrentIFD['fields'][$i]['raw']['length'] <= 2) {
87							$CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['valoff'], 0, 2), $info['tiff']['byte_order']);
88						} else {
89							$CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
90						}
91						break;
92
93					case 4: // LONG  A 32-bit (4-byte) unsigned integer.
94						if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
95							$CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
96						} else {
97							$CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
98						}
99						break;
100
101					case 5: // RATIONAL   Two LONG_s:  the first represents the numerator of a fraction, the second the denominator.
102					case 7: // UNDEFINED An 8-bit byte that may contain anything, depending on the definition of the field.
103						$CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
104						break;
105
106					// Warning: It is possible that other TIFF field types will be added in the future. Readers should skip over fields containing an unexpected field type.
107					// In TIFF 6.0, some new field types have been defined:
108					// These new field types are also governed by the byte order (II or MM) in the TIFF header.
109					case 6: // SBYTE An 8-bit signed (twos-complement) integer.
110					case 8: // SSHORT A 16-bit (2-byte) signed (twos-complement) integer.
111					case 9: // SLONG A 32-bit (4-byte) signed (twos-complement) integer.
112					case 10: // SRATIONAL Two SLONGs: the first represents the numerator of a fraction, the second the denominator.
113					case 11: // FLOAT Single precision (4-byte) IEEE format
114					case 12: // DOUBLE Double precision (8-byte) IEEE format
115					default:
116						$this->warning('unhandled IFD field type '.$CurrentIFD['fields'][$i]['raw']['type'].' for IFD entry '.$i);
117						break;
118				}
119			}
120
121			$info['tiff']['ifd'][] = $CurrentIFD;
122			$CurrentIFD = array();
123			$nextIFDoffset = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']);
124
125		}
126
127		foreach ($info['tiff']['ifd'] as $IFDid => $IFDarray) {
128			foreach ($IFDarray['fields'] as $key => $fieldarray) {
129				switch ($fieldarray['raw']['tag']) {
130					case 256: // ImageWidth
131					case 257: // ImageLength
132					case 258: // BitsPerSample
133					case 259: // Compression
134						if (!isset($fieldarray['value'])) {
135							$this->fseek($fieldarray['offset']);
136							$info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $this->fread($fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]);
137
138						}
139						break;
140
141					case 270: // ImageDescription
142					case 271: // Make
143					case 272: // Model
144					case 305: // Software
145					case 306: // DateTime
146					case 315: // Artist
147					case 316: // HostComputer
148						if (isset($fieldarray['value'])) {
149							$info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $fieldarray['value'];
150						} else {
151							$this->fseek($fieldarray['offset']);
152							$info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $this->fread($fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]);
153
154						}
155						break;
156					case 700:
157						$XMPmagic = '<?xpacket';
158						$this->fseek($fieldarray['offset']);
159						$xmpkey = (isset($info['tiff']['XMP']) ? count($info['tiff']['XMP']) : 0);
160						$info['tiff']['XMP'][$xmpkey]['raw'] = $this->fread($fieldarray['raw']['length']);
161						if (substr($info['tiff']['XMP'][$xmpkey]['raw'], 0, strlen($XMPmagic)) != $XMPmagic) {
162							$this->warning('did not find expected XMP data at offset '.$fieldarray['offset']);
163							unset($info['tiff']['XMP'][$xmpkey]['raw']);
164						}
165						break;
166				}
167				switch ($fieldarray['raw']['tag']) {
168					case 256: // ImageWidth
169						$info['video']['resolution_x'] = $fieldarray['value'];
170						break;
171
172					case 257: // ImageLength
173						$info['video']['resolution_y'] = $fieldarray['value'];
174						break;
175
176					case 258: // BitsPerSample
177						if (isset($fieldarray['value'])) {
178							$info['video']['bits_per_sample'] = $fieldarray['value'];
179						} else {
180							$info['video']['bits_per_sample'] = 0;
181							for ($i = 0; $i < $fieldarray['raw']['length']; $i++) {
182								$info['video']['bits_per_sample'] += $this->TIFFendian2Int(substr($info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'], $i * $FieldTypeByteLength[$fieldarray['raw']['type']], $FieldTypeByteLength[$fieldarray['raw']['type']]), $info['tiff']['byte_order']);
183							}
184						}
185						break;
186
187					case 259: // Compression
188						$info['video']['codec'] = $this->TIFFcompressionMethod($fieldarray['value']);
189						break;
190
191					case 270: // ImageDescription
192					case 271: // Make
193					case 272: // Model
194					case 305: // Software
195					case 306: // DateTime
196					case 315: // Artist
197					case 316: // HostComputer
198						$TIFFcommentName = strtolower($fieldarray['raw']['tag_name']);
199						if (isset($info['tiff']['comments'][$TIFFcommentName])) {
200							$info['tiff']['comments'][$TIFFcommentName][] =       $info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'];
201						} else {
202							$info['tiff']['comments'][$TIFFcommentName]   = array($info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data']);
203						}
204						break;
205
206					default:
207						break;
208				}
209			}
210		}
211
212		return true;
213	}
214
215	/**
216	 * @param string $bytestring
217	 * @param string $byteorder
218	 *
219	 * @return int|float|false
220	 */
221	public function TIFFendian2Int($bytestring, $byteorder) {
222		if ($byteorder == 'Intel') {
223			return getid3_lib::LittleEndian2Int($bytestring);
224		} elseif ($byteorder == 'Motorola') {
225			return getid3_lib::BigEndian2Int($bytestring);
226		}
227		return false;
228	}
229
230	/**
231	 * @param int $id
232	 *
233	 * @return string
234	 */
235	public function TIFFcompressionMethod($id) {
236		// https://en.wikipedia.org/wiki/TIFF#TIFF_Compression_Tag
237		static $TIFFcompressionMethod = array();
238		if (empty($TIFFcompressionMethod)) {
239			$TIFFcompressionMethod = array(
240				0x0001 => 'Uncompressed',
241				0x0002 => 'Huffman',
242				0x0003 => 'CCITT T.4',
243				0x0004 => 'CCITT T.6',
244				0x0005 => 'LZW',
245				0x0006 => 'JPEG-old',
246				0x0007 => 'JPEG',
247				0x0008 => 'deflate',
248				0x0009 => 'JBIG ITU-T T.85',
249				0x000A => 'JBIG ITU-T T.43',
250				0x7FFE => 'NeXT RLE 2-bit',
251				0x8005 => 'PackBits',
252				0x8029 => 'ThunderScan RLE 4-bit',
253				0x807F => 'RasterPadding',
254				0x8080 => 'RLE-LW',
255				0x8081 => 'RLE-CT',
256				0x8082 => 'RLE-BL',
257				0x80B2 => 'deflate-PK',
258				0x80B3 => 'Kodak-DCS',
259				0x8765 => 'JBIG',
260				0x8798 => 'JPEG2000',
261				0x8799 => 'Nikon NEF',
262				0x879B => 'JBIG2',
263			);
264		}
265		return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')');
266	}
267
268	/**
269	 * @param int $id
270	 *
271	 * @return string
272	 */
273	public function TIFFcommentName($id) {
274		// https://www.awaresystems.be/imaging/tiff/tifftags.html
275		static $TIFFcommentName = array();
276		if (empty($TIFFcommentName)) {
277			$TIFFcommentName = array(
278				254 => 'NewSubfileType',
279				255 => 'SubfileType',
280				256 => 'ImageWidth',
281				257 => 'ImageLength',
282				258 => 'BitsPerSample',
283				259 => 'Compression',
284				262 => 'PhotometricInterpretation',
285				263 => 'Threshholding',
286				264 => 'CellWidth',
287				265 => 'CellLength',
288				266 => 'FillOrder',
289				269 => 'DocumentName',
290				270 => 'ImageDescription',
291				271 => 'Make',
292				272 => 'Model',
293				273 => 'StripOffsets',
294				274 => 'Orientation',
295				277 => 'SamplesPerPixel',
296				278 => 'RowsPerStrip',
297				279 => 'StripByteCounts',
298				280 => 'MinSampleValue',
299				281 => 'MaxSampleValue',
300				282 => 'XResolution',
301				283 => 'YResolution',
302				284 => 'PlanarConfiguration',
303				285 => 'PageName',
304				286 => 'XPosition',
305				287 => 'YPosition',
306				288 => 'FreeOffsets',
307				289 => 'FreeByteCounts',
308				290 => 'GrayResponseUnit',
309				291 => 'GrayResponseCurve',
310				292 => 'T4Options',
311				293 => 'T6Options',
312				296 => 'ResolutionUnit',
313				297 => 'PageNumber',
314				301 => 'TransferFunction',
315				305 => 'Software',
316				306 => 'DateTime',
317				315 => 'Artist',
318				316 => 'HostComputer',
319				317 => 'Predictor',
320				318 => 'WhitePoint',
321				319 => 'PrimaryChromaticities',
322				320 => 'ColorMap',
323				321 => 'HalftoneHints',
324				322 => 'TileWidth',
325				323 => 'TileLength',
326				324 => 'TileOffsets',
327				325 => 'TileByteCounts',
328				326 => 'BadFaxLines',
329				327 => 'CleanFaxData',
330				328 => 'ConsecutiveBadFaxLines',
331				330 => 'SubIFDs',
332				332 => 'InkSet',
333				333 => 'InkNames',
334				334 => 'NumberOfInks',
335				336 => 'DotRange',
336				337 => 'TargetPrinter',
337				338 => 'ExtraSamples',
338				339 => 'SampleFormat',
339				340 => 'SMinSampleValue',
340				341 => 'SMaxSampleValue',
341				342 => 'TransferRange',
342				343 => 'ClipPath',
343				344 => 'XClipPathUnits',
344				345 => 'YClipPathUnits',
345				346 => 'Indexed',
346				347 => 'JPEGTables',
347				351 => 'OPIProxy',
348				400 => 'GlobalParametersIFD',
349				401 => 'ProfileType',
350				402 => 'FaxProfile',
351				403 => 'CodingMethods',
352				404 => 'VersionYear',
353				405 => 'ModeNumber',
354				433 => 'Decode',
355				434 => 'DefaultImageColor',
356				512 => 'JPEGProc',
357				513 => 'JPEGInterchangeFormat',
358				514 => 'JPEGInterchangeFormatLngth',
359				515 => 'JPEGRestartInterval',
360				517 => 'JPEGLosslessPredictors',
361				518 => 'JPEGPointTransforms',
362				519 => 'JPEGQTables',
363				520 => 'JPEGDCTables',
364				521 => 'JPEGACTables',
365				529 => 'YCbCrCoefficients',
366				530 => 'YCbCrSubSampling',
367				531 => 'YCbCrPositioning',
368				532 => 'ReferenceBlackWhite',
369				559 => 'StripRowCounts',
370				700 => 'XMP',
371
372				32781 => 'ImageID',
373				33432 => 'Copyright',
374				34732 => 'ImageLayer',
375
376				// Private Tags - https://www.awaresystems.be/imaging/tiff/tifftags/private.html
377				32932 => 'Wang Annotation',                    // Annotation data, as used in 'Imaging for Windows'.
378				33445 => 'MD FileTag',                         // Specifies the pixel data format encoding in the Molecular Dynamics GEL file format.
379				33446 => 'MD ScalePixel',                      // Specifies a scale factor in the Molecular Dynamics GEL file format.
380				33447 => 'MD ColorTable',                      // Used to specify the conversion from 16bit to 8bit in the Molecular Dynamics GEL file format.
381				33448 => 'MD LabName',                         // Name of the lab that scanned this file, as used in the Molecular Dynamics GEL file format.
382				33449 => 'MD SampleInfo',                      // Information about the sample, as used in the Molecular Dynamics GEL file format.
383				33450 => 'MD PrepDate',                        // Date the sample was prepared, as used in the Molecular Dynamics GEL file format.
384				33451 => 'MD PrepTime',                        // Time the sample was prepared, as used in the Molecular Dynamics GEL file format.
385				33452 => 'MD FileUnits',                       // Units for data in this file, as used in the Molecular Dynamics GEL file format.
386				33550 => 'ModelPixelScaleTag',                 // Used in interchangeable GeoTIFF files.
387				33723 => 'IPTC',                               // IPTC (International Press Telecommunications Council) metadata.
388				33918 => 'INGR Packet Data Tag',               // Intergraph Application specific storage.
389				33919 => 'INGR Flag Registers',                // Intergraph Application specific flags.
390				33920 => 'IrasB Transformation Matrix',        // Originally part of Intergraph's GeoTIFF tags, but likely understood by IrasB only.
391				33922 => 'ModelTiepointTag',                   // Originally part of Intergraph's GeoTIFF tags, but now used in interchangeable GeoTIFF files.
392				34264 => 'ModelTransformationTag',             // Used in interchangeable GeoTIFF files.
393				34377 => 'Photoshop',                          // Collection of Photoshop 'Image Resource Blocks'.
394				34665 => 'Exif IFD',                           // A pointer to the Exif IFD.
395				34675 => 'ICC Profile',                        // ICC profile data.
396				34735 => 'GeoKeyDirectoryTag',                 // Used in interchangeable GeoTIFF files.
397				34736 => 'GeoDoubleParamsTag',                 // Used in interchangeable GeoTIFF files.
398				34737 => 'GeoAsciiParamsTag',                  // Used in interchangeable GeoTIFF files.
399				34853 => 'GPS IFD',                            // A pointer to the Exif-related GPS Info IFD.
400				34908 => 'HylaFAX FaxRecvParams',              // Used by HylaFAX.
401				34909 => 'HylaFAX FaxSubAddress',              // Used by HylaFAX.
402				34910 => 'HylaFAX FaxRecvTime',                // Used by HylaFAX.
403				37724 => 'ImageSourceData',                    // Used by Adobe Photoshop.
404				40965 => 'Interoperability IFD',               // A pointer to the Exif-related Interoperability IFD.
405				42112 => 'GDAL_METADATA',                      // Used by the GDAL library, holds an XML list of name=value 'metadata' values about the image as a whole, and about specific samples.
406				42113 => 'GDAL_NODATA',                        // Used by the GDAL library, contains an ASCII encoded nodata or background pixel value.
407				50215 => 'Oce Scanjob Description',            // Used in the Oce scanning process.
408				50216 => 'Oce Application Selector',           // Used in the Oce scanning process.
409				50217 => 'Oce Identification Number',          // Used in the Oce scanning process.
410				50218 => 'Oce ImageLogic Characteristics',     // Used in the Oce scanning process.
411				50706 => 'DNGVersion',                         // Used in IFD 0 of DNG files.
412				50707 => 'DNGBackwardVersion',                 // Used in IFD 0 of DNG files.
413				50708 => 'UniqueCameraModel',                  // Used in IFD 0 of DNG files.
414				50709 => 'LocalizedCameraModel',               // Used in IFD 0 of DNG files.
415				50710 => 'CFAPlaneColor',                      // Used in Raw IFD of DNG files.
416				50711 => 'CFALayout',                          // Used in Raw IFD of DNG files.
417				50712 => 'LinearizationTable',                 // Used in Raw IFD of DNG files.
418				50713 => 'BlackLevelRepeatDim',                // Used in Raw IFD of DNG files.
419				50714 => 'BlackLevel',                         // Used in Raw IFD of DNG files.
420				50715 => 'BlackLevelDeltaH',                   // Used in Raw IFD of DNG files.
421				50716 => 'BlackLevelDeltaV',                   // Used in Raw IFD of DNG files.
422				50717 => 'WhiteLevel',                         // Used in Raw IFD of DNG files.
423				50718 => 'DefaultScale',                       // Used in Raw IFD of DNG files.
424				50719 => 'DefaultCropOrigin',                  // Used in Raw IFD of DNG files.
425				50720 => 'DefaultCropSize',                    // Used in Raw IFD of DNG files.
426				50721 => 'ColorMatrix1',                       // Used in IFD 0 of DNG files.
427				50722 => 'ColorMatrix2',                       // Used in IFD 0 of DNG files.
428				50723 => 'CameraCalibration1',                 // Used in IFD 0 of DNG files.
429				50724 => 'CameraCalibration2',                 // Used in IFD 0 of DNG files.
430				50725 => 'ReductionMatrix1',                   // Used in IFD 0 of DNG files.
431				50726 => 'ReductionMatrix2',                   // Used in IFD 0 of DNG files.
432				50727 => 'AnalogBalance',                      // Used in IFD 0 of DNG files.
433				50728 => 'AsShotNeutral',                      // Used in IFD 0 of DNG files.
434				50729 => 'AsShotWhiteXY',                      // Used in IFD 0 of DNG files.
435				50730 => 'BaselineExposure',                   // Used in IFD 0 of DNG files.
436				50731 => 'BaselineNoise',                      // Used in IFD 0 of DNG files.
437				50732 => 'BaselineSharpness',                  // Used in IFD 0 of DNG files.
438				50733 => 'BayerGreenSplit',                    // Used in Raw IFD of DNG files.
439				50734 => 'LinearResponseLimit',                // Used in IFD 0 of DNG files.
440				50735 => 'CameraSerialNumber',                 // Used in IFD 0 of DNG files.
441				50736 => 'LensInfo',                           // Used in IFD 0 of DNG files.
442				50737 => 'ChromaBlurRadius',                   // Used in Raw IFD of DNG files.
443				50738 => 'AntiAliasStrength',                  // Used in Raw IFD of DNG files.
444				50740 => 'DNGPrivateData',                     // Used in IFD 0 of DNG files.
445				50741 => 'MakerNoteSafety',                    // Used in IFD 0 of DNG files.
446				50778 => 'CalibrationIlluminant1',             // Used in IFD 0 of DNG files.
447				50779 => 'CalibrationIlluminant2',             // Used in IFD 0 of DNG files.
448				50780 => 'BestQualityScale',                   // Used in Raw IFD of DNG files.
449				50784 => 'Alias Layer Metadata',               // Alias Sketchbook Pro layer usage description.
450				50908 => 'TIFF_RSID',                          // This private tag is used in a GEOTIFF standard by DGIWG.
451				50909 => 'GEO_METADATA',                       // This private tag is used in a GEOTIFF standard by DGIWG.
452
453				// EXIF tags - https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html
454				33434 => 'ExposureTime',                               // Exposure time, given in seconds.
455				33437 => 'FNumber',                                    // The F number.
456				34850 => 'ExposureProgram',                            // The class of the program used by the camera to set exposure when the picture is taken.
457				34852 => 'SpectralSensitivity',                        // Indicates the spectral sensitivity of each channel of the camera used.
458				34855 => 'ISOSpeedRatings',                            // Indicates the ISO Speed and ISO Latitude of the camera or input device as specified in ISO 12232.
459				34856 => 'OECF',                                       // Indicates the Opto-Electric Conversion Function (OECF) specified in ISO 14524.
460				36864 => 'ExifVersion',                                // The version of the supported Exif standard.
461				36867 => 'DateTimeOriginal',                           // The date and time when the original image data was generated.
462				36868 => 'DateTimeDigitized',                          // The date and time when the image was stored as digital data.
463				37121 => 'ComponentsConfiguration',                    // Specific to compressed data; specifies the channels and complements PhotometricInterpretation
464				37122 => 'CompressedBitsPerPixel',                     // Specific to compressed data; states the compressed bits per pixel.
465				37377 => 'ShutterSpeedValue',                          // Shutter speed.
466				37378 => 'ApertureValue',                              // The lens aperture.
467				37379 => 'BrightnessValue',                            // The value of brightness.
468				37380 => 'ExposureBiasValue',                          // The exposure bias.
469				37381 => 'MaxApertureValue',                           // The smallest F number of the lens.
470				37382 => 'SubjectDistance',                            // The distance to the subject, given in meters.
471				37383 => 'MeteringMode',                               // The metering mode.
472				37384 => 'LightSource',                                // The kind of light source.
473				37385 => 'Flash',                                      // Indicates the status of flash when the image was shot.
474				37386 => 'FocalLength',                                // The actual focal length of the lens, in mm.
475				37396 => 'SubjectArea',                                // Indicates the location and area of the main subject in the overall scene.
476				37500 => 'MakerNote',                                  // Manufacturer specific information.
477				37510 => 'UserComment',                                // Keywords or comments on the image; complements ImageDescription.
478				37520 => 'SubsecTime',                                 // A tag used to record fractions of seconds for the DateTime tag.
479				37521 => 'SubsecTimeOriginal',                         // A tag used to record fractions of seconds for the DateTimeOriginal tag.
480				37522 => 'SubsecTimeDigitized',                        // A tag used to record fractions of seconds for the DateTimeDigitized tag.
481				40960 => 'FlashpixVersion',                            // The Flashpix format version supported by a FPXR file.
482				40961 => 'ColorSpace',                                 // The color space information tag is always recorded as the color space specifier.
483				40962 => 'PixelXDimension',                            // Specific to compressed data; the valid width of the meaningful image.
484				40963 => 'PixelYDimension',                            // Specific to compressed data; the valid height of the meaningful image.
485				40964 => 'RelatedSoundFile',                           // Used to record the name of an audio file related to the image data.
486				41483 => 'FlashEnergy',                                // Indicates the strobe energy at the time the image is captured, as measured in Beam Candle Power Seconds
487				41484 => 'SpatialFrequencyResponse',                   // Records the camera or input device spatial frequency table and SFR values in the direction of image width, image height, and diagonal direction, as specified in ISO 12233.
488				41486 => 'FocalPlaneXResolution',                      // Indicates the number of pixels in the image width (X) direction per FocalPlaneResolutionUnit on the camera focal plane.
489				41487 => 'FocalPlaneYResolution',                      // Indicates the number of pixels in the image height (Y) direction per FocalPlaneResolutionUnit on the camera focal plane.
490				41488 => 'FocalPlaneResolutionUnit',                   // Indicates the unit for measuring FocalPlaneXResolution and FocalPlaneYResolution.
491				41492 => 'SubjectLocation',                            // Indicates the location of the main subject in the scene.
492				41493 => 'ExposureIndex',                              // Indicates the exposure index selected on the camera or input device at the time the image is captured.
493				41495 => 'SensingMethod',                              // Indicates the image sensor type on the camera or input device.
494				41728 => 'FileSource',                                 // Indicates the image source.
495				41729 => 'SceneType',                                  // Indicates the type of scene.
496				41730 => 'CFAPattern',                                 // Indicates the color filter array (CFA) geometric pattern of the image sensor when a one-chip color area sensor is used.
497				41985 => 'CustomRendered',                             // Indicates the use of special processing on image data, such as rendering geared to output.
498				41986 => 'ExposureMode',                               // Indicates the exposure mode set when the image was shot.
499				41987 => 'WhiteBalance',                               // Indicates the white balance mode set when the image was shot.
500				41988 => 'DigitalZoomRatio',                           // Indicates the digital zoom ratio when the image was shot.
501				41989 => 'FocalLengthIn35mmFilm',                      // Indicates the equivalent focal length assuming a 35mm film camera, in mm.
502				41990 => 'SceneCaptureType',                           // Indicates the type of scene that was shot.
503				41991 => 'GainControl',                                // Indicates the degree of overall image gain adjustment.
504				41992 => 'Contrast',                                   // Indicates the direction of contrast processing applied by the camera when the image was shot.
505				41993 => 'Saturation',                                 // Indicates the direction of saturation processing applied by the camera when the image was shot.
506				41994 => 'Sharpness',                                  // Indicates the direction of sharpness processing applied by the camera when the image was shot.
507				41995 => 'DeviceSettingDescription',                   // This tag indicates information on the picture-taking conditions of a particular camera model.
508				41996 => 'SubjectDistanceRange',                       // Indicates the distance to the subject.
509				42016 => 'ImageUniqueID',                              // Indicates an identifier assigned uniquely to each image.
510			);
511		}
512		return (isset($TIFFcommentName[$id]) ? $TIFFcommentName[$id] : 'unknown/invalid ('.$id.')');
513	}
514
515
516}
517