File indexing completed on 2024-05-12 17:26:02

0001 <?php
0002 /////////////////////////////////////////////////////////////////
0003 /// getID3() by James Heinrich <info@getid3.org>               //
0004 //  available at http://getid3.sourceforge.net                 //
0005 //            or http://www.getid3.org                         //
0006 //          also https://github.com/JamesHeinrich/getID3       //
0007 /////////////////////////////////////////////////////////////////
0008 // See readme.txt for more details                             //
0009 /////////////////////////////////////////////////////////////////
0010 //                                                             //
0011 // module.tag.xmp.php                                          //
0012 // module for analyzing XMP metadata (e.g. in JPEG files)      //
0013 // dependencies: NONE                                          //
0014 //                                                             //
0015 /////////////////////////////////////////////////////////////////
0016 //                                                             //
0017 // Module originally written [2009-Mar-26] by                  //
0018 //      Nigel Barnes <ngbarnesØhotmail*com>                    //
0019 // Bundled into getID3 with permission                         //
0020 //   called by getID3 in module.graphic.jpg.php                //
0021 //                                                            ///
0022 /////////////////////////////////////////////////////////////////
0023 
0024 /**************************************************************************************************
0025  * SWISScenter Source                                                              Nigel Barnes
0026  *
0027  *  Provides functions for reading information from the 'APP1' Extensible Metadata
0028  *  Platform (XMP) segment of JPEG format files.
0029  *  This XMP segment is XML based and contains the Resource Description Framework (RDF)
0030  *  data, which itself can contain the Dublin Core Metadata Initiative (DCMI) information.
0031  *
0032  *  This code uses segments from the JPEG Metadata Toolkit project by Evan Hunter.
0033  *************************************************************************************************/
0034 class Image_XMP
0035 {
0036   /**
0037   * @var string
0038   * The name of the image file that contains the XMP fields to extract and modify.
0039   * @see Image_XMP()
0040   */
0041   public $_sFilename = null;
0042 
0043   /**
0044   * @var array
0045   * The XMP fields that were extracted from the image or updated by this class.
0046   * @see getAllTags()
0047   */
0048   public $_aXMP = array();
0049 
0050   /**
0051   * @var boolean
0052   * True if an APP1 segment was found to contain XMP metadata.
0053   * @see isValid()
0054   */
0055   public $_bXMPParse = false;
0056 
0057   /**
0058   * Returns the status of XMP parsing during instantiation
0059   *
0060   * You'll normally want to call this method before trying to get XMP fields.
0061   *
0062   * @return boolean
0063   * Returns true if an APP1 segment was found to contain XMP metadata.
0064   */
0065   public function isValid()
0066   {
0067     return $this->_bXMPParse;
0068   }
0069 
0070   /**
0071   * Get a copy of all XMP tags extracted from the image
0072   *
0073   * @return array - An array of XMP fields as it extracted by the XMPparse() function
0074   */
0075   public function getAllTags()
0076   {
0077     return $this->_aXMP;
0078   }
0079 
0080   /**
0081   * Reads all the JPEG header segments from an JPEG image file into an array
0082   *
0083   * @param string $filename - the filename of the JPEG file to read
0084   * @return array $headerdata - Array of JPEG header segments
0085   * @return boolean FALSE - if headers could not be read
0086   */
0087   public function _get_jpeg_header_data($filename)
0088   {
0089     // prevent refresh from aborting file operations and hosing file
0090     ignore_user_abort(true);
0091 
0092     // Attempt to open the jpeg file - the at symbol supresses the error message about
0093     // not being able to open files. The file_exists would have been used, but it
0094     // does not work with files fetched over http or ftp.
0095     if (is_readable($filename) && is_file($filename) && ($filehnd = fopen($filename, 'rb'))) {
0096       // great
0097     } else {
0098       return false;
0099     }
0100 
0101     // Read the first two characters
0102     $data = fread($filehnd, 2);
0103 
0104     // Check that the first two characters are 0xFF 0xD8  (SOI - Start of image)
0105     if ($data != "\xFF\xD8")
0106     {
0107       // No SOI (FF D8) at start of file - This probably isn't a JPEG file - close file and return;
0108       echo '<p>This probably is not a JPEG file</p>'."\n";
0109       fclose($filehnd);
0110       return false;
0111     }
0112 
0113     // Read the third character
0114     $data = fread($filehnd, 2);
0115 
0116     // Check that the third character is 0xFF (Start of first segment header)
0117     if ($data{0} != "\xFF")
0118     {
0119       // NO FF found - close file and return - JPEG is probably corrupted
0120       fclose($filehnd);
0121       return false;
0122     }
0123 
0124     // Flag that we havent yet hit the compressed image data
0125     $hit_compressed_image_data = false;
0126 
0127     // Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
0128     //                                       2) we have hit the compressed image data (no more headers are allowed after data)
0129     //                                       3) or end of file is hit
0130 
0131     while (($data{1} != "\xD9") && (!$hit_compressed_image_data) && (!feof($filehnd)))
0132     {
0133       // Found a segment to look at.
0134       // Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
0135       if ((ord($data{1}) < 0xD0) || (ord($data{1}) > 0xD7))
0136       {
0137         // Segment isn't a Restart marker
0138         // Read the next two bytes (size)
0139         $sizestr = fread($filehnd, 2);
0140 
0141         // convert the size bytes to an integer
0142         $decodedsize = unpack('nsize', $sizestr);
0143 
0144         // Save the start position of the data
0145         $segdatastart = ftell($filehnd);
0146 
0147         // Read the segment data with length indicated by the previously read size
0148         $segdata = fread($filehnd, $decodedsize['size'] - 2);
0149 
0150         // Store the segment information in the output array
0151         $headerdata[] = array(
0152           'SegType'      => ord($data{1}),
0153           'SegName'      => $GLOBALS['JPEG_Segment_Names'][ord($data{1})],
0154           'SegDataStart' => $segdatastart,
0155           'SegData'      => $segdata,
0156         );
0157       }
0158 
0159       // If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
0160       if ($data{1} == "\xDA")
0161       {
0162         // Flag that we have hit the compressed image data - exit loop as no more headers available.
0163         $hit_compressed_image_data = true;
0164       }
0165       else
0166       {
0167         // Not an SOS - Read the next two bytes - should be the segment marker for the next segment
0168         $data = fread($filehnd, 2);
0169 
0170         // Check that the first byte of the two is 0xFF as it should be for a marker
0171         if ($data{0} != "\xFF")
0172         {
0173           // NO FF found - close file and return - JPEG is probably corrupted
0174           fclose($filehnd);
0175           return false;
0176         }
0177       }
0178     }
0179 
0180     // Close File
0181     fclose($filehnd);
0182     // Alow the user to abort from now on
0183     ignore_user_abort(false);
0184 
0185     // Return the header data retrieved
0186     return $headerdata;
0187   }
0188 
0189 
0190   /**
0191   * Retrieves XMP information from an APP1 JPEG segment and returns the raw XML text as a string.
0192   *
0193   * @param string $filename - the filename of the JPEG file to read
0194   * @return string $xmp_data - the string of raw XML text
0195   * @return boolean FALSE - if an APP 1 XMP segment could not be found, or if an error occured
0196   */
0197   public function _get_XMP_text($filename)
0198   {
0199     //Get JPEG header data
0200     $jpeg_header_data = $this->_get_jpeg_header_data($filename);
0201 
0202     //Cycle through the header segments
0203     for ($i = 0; $i < count($jpeg_header_data); $i++)
0204     {
0205       // If we find an APP1 header,
0206       if (strcmp($jpeg_header_data[$i]['SegName'], 'APP1') == 0)
0207       {
0208         // And if it has the Adobe XMP/RDF label (http://ns.adobe.com/xap/1.0/\x00) ,
0209         if (strncmp($jpeg_header_data[$i]['SegData'], 'http://ns.adobe.com/xap/1.0/'."\x00", 29) == 0)
0210         {
0211           // Found a XMP/RDF block
0212           // Return the XMP text
0213           $xmp_data = substr($jpeg_header_data[$i]['SegData'], 29);
0214 
0215           return trim($xmp_data); // trim() should not be neccesary, but some files found in the wild with null-terminated block (known samples from Apple Aperture) causes problems elsewhere (see http://www.getid3.org/phpBB3/viewtopic.php?f=4&t=1153)
0216         }
0217       }
0218     }
0219     return false;
0220   }
0221 
0222     /**
0223      * Parses a string containing XMP data (XML), and returns an array
0224      * which contains all the XMP (XML) information.
0225      *
0226      * @param $xmltext
0227      *
0228      * @return array $xmp_array - an array containing all xmp details retrieved.
0229      */
0230   public function read_XMP_array_from_text($xmltext)
0231   {
0232     // Check if there actually is any text to parse
0233     if (trim($xmltext) == '')
0234     {
0235       return false;
0236     }
0237 
0238     // Create an instance of a xml parser to parse the XML text
0239     $xml_parser = xml_parser_create('UTF-8');
0240 
0241     // Change: Fixed problem that caused the whitespace (especially newlines) to be destroyed when converting xml text to an xml array, as of revision 1.10
0242 
0243     // We would like to remove unneccessary white space, but this will also
0244     // remove things like newlines (&#xA;) in the XML values, so white space
0245     // will have to be removed later
0246     if (xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 0) == false)
0247     {
0248       // Error setting case folding - destroy the parser and return
0249       xml_parser_free($xml_parser);
0250       return false;
0251     }
0252 
0253     // to use XML code correctly we have to turn case folding
0254     // (uppercasing) off. XML is case sensitive and upper
0255     // casing is in reality XML standards violation
0256     if (xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0) == false)
0257     {
0258       // Error setting case folding - destroy the parser and return
0259       xml_parser_free($xml_parser);
0260       return false;
0261     }
0262 
0263     // Parse the XML text into a array structure
0264     if (xml_parse_into_struct($xml_parser, $xmltext, $values, $tags) == 0)
0265     {
0266       // Error Parsing XML - destroy the parser and return
0267       xml_parser_free($xml_parser);
0268       return false;
0269     }
0270 
0271     // Destroy the xml parser
0272     xml_parser_free($xml_parser);
0273 
0274     // Clear the output array
0275     $xmp_array = array();
0276 
0277     // The XMP data has now been parsed into an array ...
0278 
0279     // Cycle through each of the array elements
0280     $current_property = ''; // current property being processed
0281     $container_index = -1; // -1 = no container open, otherwise index of container content
0282     foreach ($values as $xml_elem)
0283     {
0284       // Syntax and Class names
0285       switch ($xml_elem['tag'])
0286       {
0287         case 'x:xmpmeta':
0288           // only defined attribute is x:xmptk written by Adobe XMP Toolkit; value is the version of the toolkit
0289           break;
0290 
0291         case 'rdf:RDF':
0292           // required element immediately within x:xmpmeta; no data here
0293           break;
0294 
0295         case 'rdf:Description':
0296           switch ($xml_elem['type'])
0297           {
0298             case 'open':
0299             case 'complete':
0300               if (array_key_exists('attributes', $xml_elem))
0301               {
0302                 // rdf:Description may contain wanted attributes
0303                 foreach (array_keys($xml_elem['attributes']) as $key)
0304                 {
0305                   // Check whether we want this details from this attribute
0306 //                  if (in_array($key, $GLOBALS['XMP_tag_captions']))
0307                   if (true)
0308                   {
0309                     // Attribute wanted
0310                     $xmp_array[$key] = $xml_elem['attributes'][$key];
0311                   }
0312                 }
0313               }
0314             case 'cdata':
0315             case 'close':
0316               break;
0317           }
0318 
0319         case 'rdf:ID':
0320         case 'rdf:nodeID':
0321           // Attributes are ignored
0322           break;
0323 
0324         case 'rdf:li':
0325           // Property member
0326           if ($xml_elem['type'] == 'complete')
0327           {
0328             if (array_key_exists('attributes', $xml_elem))
0329             {
0330               // If Lang Alt (language alternatives) then ensure we take the default language
0331               if (isset($xml_elem['attributes']['xml:lang']) && ($xml_elem['attributes']['xml:lang'] != 'x-default'))
0332               {
0333                 break;
0334               }
0335             }
0336             if ($current_property != '')
0337             {
0338               $xmp_array[$current_property][$container_index] = (isset($xml_elem['value']) ? $xml_elem['value'] : '');
0339               $container_index += 1;
0340             }
0341           //else unidentified attribute!!
0342           }
0343           break;
0344 
0345         case 'rdf:Seq':
0346         case 'rdf:Bag':
0347         case 'rdf:Alt':
0348           // Container found
0349           switch ($xml_elem['type'])
0350           {
0351             case 'open':
0352               $container_index = 0;
0353               break;
0354             case 'close':
0355               $container_index = -1;
0356               break;
0357             case 'cdata':
0358               break;
0359           }
0360           break;
0361 
0362         default:
0363           // Check whether we want the details from this attribute
0364 //          if (in_array($xml_elem['tag'], $GLOBALS['XMP_tag_captions']))
0365           if (true)
0366           {
0367             switch ($xml_elem['type'])
0368             {
0369               case 'open':
0370                 // open current element
0371                 $current_property = $xml_elem['tag'];
0372                 break;
0373 
0374               case 'close':
0375                 // close current element
0376                 $current_property = '';
0377                 break;
0378 
0379               case 'complete':
0380                 // store attribute value
0381                 $xmp_array[$xml_elem['tag']] = (isset($xml_elem['attributes']) ? $xml_elem['attributes'] : (isset($xml_elem['value']) ? $xml_elem['value'] : ''));
0382                 break;
0383 
0384               case 'cdata':
0385                 // ignore
0386                 break;
0387             }
0388           }
0389           break;
0390       }
0391 
0392     }
0393     return $xmp_array;
0394   }
0395 
0396 
0397   /**
0398   * Constructor
0399   *
0400   * @param string - Name of the image file to access and extract XMP information from.
0401   */
0402   public function Image_XMP($sFilename)
0403   {
0404     $this->_sFilename = $sFilename;
0405 
0406     if (is_file($this->_sFilename))
0407     {
0408       // Get XMP data
0409       $xmp_data = $this->_get_XMP_text($sFilename);
0410       if ($xmp_data)
0411       {
0412         $this->_aXMP = $this->read_XMP_array_from_text($xmp_data);
0413         $this->_bXMPParse = true;
0414       }
0415     }
0416   }
0417 
0418 }
0419 
0420 /**
0421 * Global Variable: XMP_tag_captions
0422 *
0423 * The Property names of all known XMP fields.
0424 * Note: this is a full list with unrequired properties commented out.
0425 */
0426 /*
0427 $GLOBALS['XMP_tag_captions'] = array(
0428 // IPTC Core
0429   'Iptc4xmpCore:CiAdrCity',
0430   'Iptc4xmpCore:CiAdrCtry',
0431   'Iptc4xmpCore:CiAdrExtadr',
0432   'Iptc4xmpCore:CiAdrPcode',
0433   'Iptc4xmpCore:CiAdrRegion',
0434   'Iptc4xmpCore:CiEmailWork',
0435   'Iptc4xmpCore:CiTelWork',
0436   'Iptc4xmpCore:CiUrlWork',
0437   'Iptc4xmpCore:CountryCode',
0438   'Iptc4xmpCore:CreatorContactInfo',
0439   'Iptc4xmpCore:IntellectualGenre',
0440   'Iptc4xmpCore:Location',
0441   'Iptc4xmpCore:Scene',
0442   'Iptc4xmpCore:SubjectCode',
0443 // Dublin Core Schema
0444   'dc:contributor',
0445   'dc:coverage',
0446   'dc:creator',
0447   'dc:date',
0448   'dc:description',
0449   'dc:format',
0450   'dc:identifier',
0451   'dc:language',
0452   'dc:publisher',
0453   'dc:relation',
0454   'dc:rights',
0455   'dc:source',
0456   'dc:subject',
0457   'dc:title',
0458   'dc:type',
0459 // XMP Basic Schema
0460   'xmp:Advisory',
0461   'xmp:BaseURL',
0462   'xmp:CreateDate',
0463   'xmp:CreatorTool',
0464   'xmp:Identifier',
0465   'xmp:Label',
0466   'xmp:MetadataDate',
0467   'xmp:ModifyDate',
0468   'xmp:Nickname',
0469   'xmp:Rating',
0470   'xmp:Thumbnails',
0471   'xmpidq:Scheme',
0472 // XMP Rights Management Schema
0473   'xmpRights:Certificate',
0474   'xmpRights:Marked',
0475   'xmpRights:Owner',
0476   'xmpRights:UsageTerms',
0477   'xmpRights:WebStatement',
0478 // These are not in spec but Photoshop CS seems to use them
0479   'xap:Advisory',
0480   'xap:BaseURL',
0481   'xap:CreateDate',
0482   'xap:CreatorTool',
0483   'xap:Identifier',
0484   'xap:MetadataDate',
0485   'xap:ModifyDate',
0486   'xap:Nickname',
0487   'xap:Rating',
0488   'xap:Thumbnails',
0489   'xapidq:Scheme',
0490   'xapRights:Certificate',
0491   'xapRights:Copyright',
0492   'xapRights:Marked',
0493   'xapRights:Owner',
0494   'xapRights:UsageTerms',
0495   'xapRights:WebStatement',
0496 // XMP Media Management Schema
0497   'xapMM:DerivedFrom',
0498   'xapMM:DocumentID',
0499   'xapMM:History',
0500   'xapMM:InstanceID',
0501   'xapMM:ManagedFrom',
0502   'xapMM:Manager',
0503   'xapMM:ManageTo',
0504   'xapMM:ManageUI',
0505   'xapMM:ManagerVariant',
0506   'xapMM:RenditionClass',
0507   'xapMM:RenditionParams',
0508   'xapMM:VersionID',
0509   'xapMM:Versions',
0510   'xapMM:LastURL',
0511   'xapMM:RenditionOf',
0512   'xapMM:SaveID',
0513 // XMP Basic Job Ticket Schema
0514   'xapBJ:JobRef',
0515 // XMP Paged-Text Schema
0516   'xmpTPg:MaxPageSize',
0517   'xmpTPg:NPages',
0518   'xmpTPg:Fonts',
0519   'xmpTPg:Colorants',
0520   'xmpTPg:PlateNames',
0521 // Adobe PDF Schema
0522   'pdf:Keywords',
0523   'pdf:PDFVersion',
0524   'pdf:Producer',
0525 // Photoshop Schema
0526   'photoshop:AuthorsPosition',
0527   'photoshop:CaptionWriter',
0528   'photoshop:Category',
0529   'photoshop:City',
0530   'photoshop:Country',
0531   'photoshop:Credit',
0532   'photoshop:DateCreated',
0533   'photoshop:Headline',
0534   'photoshop:History',
0535 // Not in XMP spec
0536   'photoshop:Instructions',
0537   'photoshop:Source',
0538   'photoshop:State',
0539   'photoshop:SupplementalCategories',
0540   'photoshop:TransmissionReference',
0541   'photoshop:Urgency',
0542 // EXIF Schemas
0543   'tiff:ImageWidth',
0544   'tiff:ImageLength',
0545   'tiff:BitsPerSample',
0546   'tiff:Compression',
0547   'tiff:PhotometricInterpretation',
0548   'tiff:Orientation',
0549   'tiff:SamplesPerPixel',
0550   'tiff:PlanarConfiguration',
0551   'tiff:YCbCrSubSampling',
0552   'tiff:YCbCrPositioning',
0553   'tiff:XResolution',
0554   'tiff:YResolution',
0555   'tiff:ResolutionUnit',
0556   'tiff:TransferFunction',
0557   'tiff:WhitePoint',
0558   'tiff:PrimaryChromaticities',
0559   'tiff:YCbCrCoefficients',
0560   'tiff:ReferenceBlackWhite',
0561   'tiff:DateTime',
0562   'tiff:ImageDescription',
0563   'tiff:Make',
0564   'tiff:Model',
0565   'tiff:Software',
0566   'tiff:Artist',
0567   'tiff:Copyright',
0568   'exif:ExifVersion',
0569   'exif:FlashpixVersion',
0570   'exif:ColorSpace',
0571   'exif:ComponentsConfiguration',
0572   'exif:CompressedBitsPerPixel',
0573   'exif:PixelXDimension',
0574   'exif:PixelYDimension',
0575   'exif:MakerNote',
0576   'exif:UserComment',
0577   'exif:RelatedSoundFile',
0578   'exif:DateTimeOriginal',
0579   'exif:DateTimeDigitized',
0580   'exif:ExposureTime',
0581   'exif:FNumber',
0582   'exif:ExposureProgram',
0583   'exif:SpectralSensitivity',
0584   'exif:ISOSpeedRatings',
0585   'exif:OECF',
0586   'exif:ShutterSpeedValue',
0587   'exif:ApertureValue',
0588   'exif:BrightnessValue',
0589   'exif:ExposureBiasValue',
0590   'exif:MaxApertureValue',
0591   'exif:SubjectDistance',
0592   'exif:MeteringMode',
0593   'exif:LightSource',
0594   'exif:Flash',
0595   'exif:FocalLength',
0596   'exif:SubjectArea',
0597   'exif:FlashEnergy',
0598   'exif:SpatialFrequencyResponse',
0599   'exif:FocalPlaneXResolution',
0600   'exif:FocalPlaneYResolution',
0601   'exif:FocalPlaneResolutionUnit',
0602   'exif:SubjectLocation',
0603   'exif:SensingMethod',
0604   'exif:FileSource',
0605   'exif:SceneType',
0606   'exif:CFAPattern',
0607   'exif:CustomRendered',
0608   'exif:ExposureMode',
0609   'exif:WhiteBalance',
0610   'exif:DigitalZoomRatio',
0611   'exif:FocalLengthIn35mmFilm',
0612   'exif:SceneCaptureType',
0613   'exif:GainControl',
0614   'exif:Contrast',
0615   'exif:Saturation',
0616   'exif:Sharpness',
0617   'exif:DeviceSettingDescription',
0618   'exif:SubjectDistanceRange',
0619   'exif:ImageUniqueID',
0620   'exif:GPSVersionID',
0621   'exif:GPSLatitude',
0622   'exif:GPSLongitude',
0623   'exif:GPSAltitudeRef',
0624   'exif:GPSAltitude',
0625   'exif:GPSTimeStamp',
0626   'exif:GPSSatellites',
0627   'exif:GPSStatus',
0628   'exif:GPSMeasureMode',
0629   'exif:GPSDOP',
0630   'exif:GPSSpeedRef',
0631   'exif:GPSSpeed',
0632   'exif:GPSTrackRef',
0633   'exif:GPSTrack',
0634   'exif:GPSImgDirectionRef',
0635   'exif:GPSImgDirection',
0636   'exif:GPSMapDatum',
0637   'exif:GPSDestLatitude',
0638   'exif:GPSDestLongitude',
0639   'exif:GPSDestBearingRef',
0640   'exif:GPSDestBearing',
0641   'exif:GPSDestDistanceRef',
0642   'exif:GPSDestDistance',
0643   'exif:GPSProcessingMethod',
0644   'exif:GPSAreaInformation',
0645   'exif:GPSDifferential',
0646   'stDim:w',
0647   'stDim:h',
0648   'stDim:unit',
0649   'xapGImg:height',
0650   'xapGImg:width',
0651   'xapGImg:format',
0652   'xapGImg:image',
0653   'stEvt:action',
0654   'stEvt:instanceID',
0655   'stEvt:parameters',
0656   'stEvt:softwareAgent',
0657   'stEvt:when',
0658   'stRef:instanceID',
0659   'stRef:documentID',
0660   'stRef:versionID',
0661   'stRef:renditionClass',
0662   'stRef:renditionParams',
0663   'stRef:manager',
0664   'stRef:managerVariant',
0665   'stRef:manageTo',
0666   'stRef:manageUI',
0667   'stVer:comments',
0668   'stVer:event',
0669   'stVer:modifyDate',
0670   'stVer:modifier',
0671   'stVer:version',
0672   'stJob:name',
0673   'stJob:id',
0674   'stJob:url',
0675 // Exif Flash
0676   'exif:Fired',
0677   'exif:Return',
0678   'exif:Mode',
0679   'exif:Function',
0680   'exif:RedEyeMode',
0681 // Exif OECF/SFR
0682   'exif:Columns',
0683   'exif:Rows',
0684   'exif:Names',
0685   'exif:Values',
0686 // Exif CFAPattern
0687   'exif:Columns',
0688   'exif:Rows',
0689   'exif:Values',
0690 // Exif DeviceSettings
0691   'exif:Columns',
0692   'exif:Rows',
0693   'exif:Settings',
0694 );
0695 */
0696 
0697 /**
0698 * Global Variable: JPEG_Segment_Names
0699 *
0700 * The names of the JPEG segment markers, indexed by their marker number
0701 */
0702 $GLOBALS['JPEG_Segment_Names'] = array(
0703   0x01 => 'TEM',
0704   0x02 => 'RES',
0705   0xC0 => 'SOF0',
0706   0xC1 => 'SOF1',
0707   0xC2 => 'SOF2',
0708   0xC3 => 'SOF4',
0709   0xC4 => 'DHT',
0710   0xC5 => 'SOF5',
0711   0xC6 => 'SOF6',
0712   0xC7 => 'SOF7',
0713   0xC8 => 'JPG',
0714   0xC9 => 'SOF9',
0715   0xCA => 'SOF10',
0716   0xCB => 'SOF11',
0717   0xCC => 'DAC',
0718   0xCD => 'SOF13',
0719   0xCE => 'SOF14',
0720   0xCF => 'SOF15',
0721   0xD0 => 'RST0',
0722   0xD1 => 'RST1',
0723   0xD2 => 'RST2',
0724   0xD3 => 'RST3',
0725   0xD4 => 'RST4',
0726   0xD5 => 'RST5',
0727   0xD6 => 'RST6',
0728   0xD7 => 'RST7',
0729   0xD8 => 'SOI',
0730   0xD9 => 'EOI',
0731   0xDA => 'SOS',
0732   0xDB => 'DQT',
0733   0xDC => 'DNL',
0734   0xDD => 'DRI',
0735   0xDE => 'DHP',
0736   0xDF => 'EXP',
0737   0xE0 => 'APP0',
0738   0xE1 => 'APP1',
0739   0xE2 => 'APP2',
0740   0xE3 => 'APP3',
0741   0xE4 => 'APP4',
0742   0xE5 => 'APP5',
0743   0xE6 => 'APP6',
0744   0xE7 => 'APP7',
0745   0xE8 => 'APP8',
0746   0xE9 => 'APP9',
0747   0xEA => 'APP10',
0748   0xEB => 'APP11',
0749   0xEC => 'APP12',
0750   0xED => 'APP13',
0751   0xEE => 'APP14',
0752   0xEF => 'APP15',
0753   0xF0 => 'JPG0',
0754   0xF1 => 'JPG1',
0755   0xF2 => 'JPG2',
0756   0xF3 => 'JPG3',
0757   0xF4 => 'JPG4',
0758   0xF5 => 'JPG5',
0759   0xF6 => 'JPG6',
0760   0xF7 => 'JPG7',
0761   0xF8 => 'JPG8',
0762   0xF9 => 'JPG9',
0763   0xFA => 'JPG10',
0764   0xFB => 'JPG11',
0765   0xFC => 'JPG12',
0766   0xFD => 'JPG13',
0767   0xFE => 'COM',
0768 );