diff options
Diffstat (limited to 'includes/jpeg_metadata_tk/Photoshop_File_Info.php')
| -rw-r--r-- | includes/jpeg_metadata_tk/Photoshop_File_Info.php | 2498 |
1 files changed, 2498 insertions, 0 deletions
diff --git a/includes/jpeg_metadata_tk/Photoshop_File_Info.php b/includes/jpeg_metadata_tk/Photoshop_File_Info.php new file mode 100644 index 0000000..1da7a8c --- /dev/null +++ b/includes/jpeg_metadata_tk/Photoshop_File_Info.php @@ -0,0 +1,2498 @@ +<?php + +/****************************************************************************** +* +* Filename: Photoshop_File_Info.php +* +* Description: Provides functions that mimic the way Photoshop reads and writes +* metadata in it's 'File Info' dialog +* +* Author: Evan Hunter +* +* Date: 11/11/2004 +* +* Project: JPEG Metadata +* +* Revision: 1.11 +* Changes: 1.10 -> 1.11 : Changed displayed toolkit version numbers to reference Toolkit_Version.php +* +* URL: http://electronics.ozhiker.com +* +* License: This file is part of the PHP JPEG Metadata Toolkit. +* +* The PHP JPEG Metadata Toolkit is free software; you can +* redistribute it and/or modify it under the terms of the +* GNU General Public License as published by the Free Software +* Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* The PHP JPEG Metadata Toolkit is distributed in the hope +* that it will be useful, but WITHOUT ANY WARRANTY; without +* even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License +* for more details. +* +* You should have received a copy of the GNU General Public +* License along with the PHP JPEG Metadata Toolkit; if not, +* write to the Free Software Foundation, Inc., 59 Temple +* Place, Suite 330, Boston, MA 02111-1307 USA +* +* If you require a different license for commercial or other +* purposes, please contact the author: evan@ozhiker.com +* +******************************************************************************/ + +// TODO: XMP sections: XAPMM, TIFF, EXIF + + +require_once 'Toolkit_Version.php'; // Change: added as of version 1.11 + + +/****************************************************************************** +* Global Variable: Software Name +* +* Contents: The string that is appended to fields which store the name of +* the software editor. +* +******************************************************************************/ + +$GLOBALS[ "Software Name" ] = "(PHP JPEG Metadata Toolkit v" . $GLOBALS['Toolkit_Version'] . ")"; // Change: Changed version numbers to reference Toolkit_Version.php - as of version 1.11 + +/****************************************************************************** +* End of Global Variable: Software Name +******************************************************************************/ + + + + + + +/****************************************************************************** +* +* Function: get_photoshop_file_info +* +* Description: Retrieves Photoshop 'File Info' metadata in the same way that Photoshop +* does. The results are returned in an array as below: +* +* $file_info_array = array( +* "title" => "", +* "author" => "", +* "authorsposition" => "", // Note: Not used in Photoshop 7 or higher +* "caption" => "", +* "captionwriter" => "", +* "jobname" => "", // Note: Not used in Photoshop CS +* "copyrightstatus" => "", +* "copyrightnotice" => "", +* "ownerurl" => "", +* "keywords" => array( 0 => "", 1 => "", ... ), +* "category" => "", // Note: Max 3 characters +* "supplementalcategories" => array( 0 => "", 1 => "", ... ), +* "date" => "", // Note: DATE MUST BE IN YYYY-MM-DD format +* "city" => "", +* "state" => "", +* "country" => "", +* "credit" => "", +* "source" => "", +* "headline" => "", +* "instructions" => "", +* "transmissionreference" => "", +* "urgency" => "" ); +* +* Parameters: Exif_array - an array containing the EXIF information to be +* searched, as retrieved by get_EXIF_JPEG. (saves having to parse the EXIF again) +* XMP_array - an array containing the XMP information to be +* searched, as retrieved by read_XMP_array_from_text. (saves having to parse the XMP again) +* IRB_array - an array containing the Photoshop IRB information +* to be searched, as retrieved by get_Photoshop_IRB. (saves having to parse the IRB again) +* +* Returns: outputarray - an array as above, containing the Photoshop File Info data +* +******************************************************************************/ + +function get_photoshop_file_info( $Exif_array, $XMP_array, $IRB_array ) +{ + + // Create a blank array to receive the output + $outputarray = array( + "title" => "", + "author" => "", + "authorsposition" => "", + "caption" => "", + "captionwriter" => "", + "jobname" => "", + "copyrightstatus" => "", + "copyrightnotice" => "", + "ownerurl" => "", + "keywords" => array(), + "category" => "", + "supplementalcategories" => array(), + "date" => "", + "city" => "", + "state" => "", + "country" => "", + "credit" => "", + "source" => "", + "headline" => "", + "instructions" => "", + "transmissionreference" => "", + "urgency" => "" ); + + + /***************************************/ + + // XMP Processing + + + // Retrieve the dublin core section from the XMP header + + // Extract the Dublin Core section from the XMP + $dublincore_block = find_XMP_block( $XMP_array, "dc" ); + + // Check that the Dublin Core section exists + if ( $dublincore_block != FALSE ) + { + // Dublin Core Description Field contains caption + // Extract Description + $Item = find_XMP_item( $dublincore_block, "dc:description" ); + + // Check if Description Tag existed + if ( $Item != FALSE ) + { + // Ensure that the Description value exists and save it. + if ( ( array_key_exists( 'children', $Item ) ) && + ( $Item['children'][0]['tag'] == "rdf:Alt" ) && + ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) ) + { + $outputarray = add_to_field( $outputarray, 'caption' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "\n" ); + } + } + + /***************************************/ + + // Dublin Core Creator Field contains author + // Extract Description + $Item = find_XMP_item( $dublincore_block, "dc:creator" ); + + // Check if Creator Tag existed + if ( $Item != FALSE ) + { + // Ensure that the Creator value exists and save it. + if ( ( !empty( $Item['children'][0] ) ) && + ( $Item['children'][0]['tag'] =="rdf:Seq" ) && + ( !empty( $Item['children'][0]['children'][0]['empty'] ) ) ) + { + $outputarray = add_to_field( $outputarray, 'author' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "\n" ); + } + } + + /***************************************/ + + // Dublin Core Title Field contains title + // Extract Title + $Item = find_XMP_item( $dublincore_block, "dc:title" ); + + // Check if Title Tag existed + if ( $Item != FALSE ) + { + // Ensure that the Title value exists and save it. + if ( ( array_key_exists( 'children', $Item ) ) && + ( $Item['children'][0]['tag'] =="rdf:Alt" ) && + ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) ) + { + + $outputarray = add_to_field( $outputarray, 'title' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "," ); + } + } + + /***************************************/ + + // Dublin Core Rights Field contains copyrightnotice + // Extract Rights + $Item = find_XMP_item( $dublincore_block, "dc:rights" ); + + // Check if Rights Tag existed + if ( $Item != FALSE ) + { + // Ensure that the Rights value exists and save it. + if ( ( array_key_exists( 'children', $Item ) ) && + ( $Item['children'][0]['tag'] =="rdf:Alt" ) && + ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) ) + { + + $outputarray = add_to_field( $outputarray, 'copyrightnotice' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "," ); + } + } + + /***************************************/ + + // Dublin Core Subject Field contains keywords + // Extract Subject + $Item = find_XMP_item( $dublincore_block, "dc:subject" ); + + // Check if Subject Tag existed + if ( $Item != FALSE ) + { + // Ensure that the Subject values exist + if ( ( array_key_exists( 'children', $Item ) ) && ( $Item['children'][0]['tag'] =="rdf:Bag" ) ) + { + // Cycle through each Subject value and save them + foreach ( $Item['children'][0]['children'] as $keywords ) + { + if ( ! in_array ( HTML_UTF8_Escape( $keywords['value'] ), $outputarray['keywords'])) + { + if ( array_key_exists( 'value', $keywords ) ) + { + $outputarray['keywords'][] = HTML_UTF8_Escape( $keywords['value'] ); + } + } + } + } + } + + + } + + /***************************************/ + + // Find the Photoshop Information within the XMP block + $photoshop_block = find_XMP_block( $XMP_array, "photoshop" ); + + // Check that the Photoshop Information exists + if ( $photoshop_block != FALSE ) + { + // The Photoshop CaptionWriter tag contains captionwriter - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:CaptionWriter" ); + + // Check that the CaptionWriter Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'captionwriter' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Headline tag contains headline - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Headline" ); + + // Check that the Headline Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'headline' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Instructions tag contains instructions - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Instructions" ); + + // Check that the Instructions Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'instructions' , HTML_UTF8_Escape( $Item['value'] ), "\n" ); + } + + /***************************************/ + + // The Photoshop AuthorsPosition tag contains authorsposition - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:AuthorsPosition" ); + + // Check that the AuthorsPosition Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'authorsposition' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Credit tag contains credit - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Credit" ); + + // Check that the Credit Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'credit' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Source tag contains source - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Source" ); + + // Check that the Credit Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'source' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop City tag contains city - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:City" ); + + // Check that the City Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'city' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop State tag contains state - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:State" ); + + // Check that the State Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'state' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Country tag contains country - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Country" ); + + // Check that the Country Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'country' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop TransmissionReference tag contains transmissionreference - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:TransmissionReference" ); + + // Check that the TransmissionReference Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'transmissionreference' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Category tag contains category - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Category" ); + + // Check that the TransmissionReference Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'category' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop DateCreated tag contains date - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:DateCreated" ); + + // Check that the DateCreated Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'date' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop Urgency tag contains urgency - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:Urgency" ); + + // Check that the Urgency Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'urgency' , HTML_UTF8_Escape( $Item['value'] ), "," ); + } + + /***************************************/ + + // The Photoshop SupplementalCategories tag contains supplementalcategories - Find it + $Item = find_XMP_item( $photoshop_block, "photoshop:SupplementalCategories" ); + + // Check that the SupplementalCategories Field exists + if ( $Item != FALSE ) + { + // Check that the values exist + if ( ( array_key_exists( 'children', $Item ) ) && ( $Item['children'][0]['tag'] =="rdf:Bag" ) ) + { + // Cycle through the values and save them + foreach ( $Item['children'][0]['children'] as $sup_category ) + { + if ( ( array_key_exists( 'value', $sup_category ) ) && + ( ! in_array ( HTML_UTF8_Escape( $sup_category['value'] ), $outputarray['supplementalcategories'])) ) + { + if ( array_key_exists( 'value', $sup_category ) ) + { + $outputarray['supplementalcategories'][] = HTML_UTF8_Escape( $sup_category['value'] ); + } + } + } + } + } + + } + + /***************************************/ + + // Find the Job Reference Information within the XMP block + $job_block = find_XMP_block( $XMP_array, "xapBJ" ); + + // Check that the Job Reference Information exists + if ( $job_block != FALSE ) + { + // The JobRef Field contains jobname - Find it + $Item = find_XMP_item( $job_block, "xapBJ:JobRef" ); + + // Check that the JobRef Field exists + if ( $Item != FALSE ) + { + // Check that the value exists and save it + if ( ( array_key_exists( 'children', $Item ) ) && + ( $Item['children'][0]['tag'] =="rdf:Bag" ) && + ( array_key_exists( 'children', $Item['children'][0] ) ) && + ( $Item['children'][0]['children'][0]['tag'] =="rdf:li" ) && + ( array_key_exists( 'children', $Item['children'][0]['children'][0] ) ) && + ( $Item['children'][0]['children'][0]['children'][0]['tag'] =="stJob:name" ) && + ( array_key_exists( 'value', $Item['children'][0]['children'][0]['children'][0] ) ) ) + { + $outputarray = add_to_field( $outputarray, 'jobname' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['children'][0]['value'] ), "," ); + } + } + } + + + /***************************************/ + + // Find the Rights Information within the XMP block + $rights_block = find_XMP_block( $XMP_array, "xapRights" ); + + // Check that the Rights Information exists + if ( $rights_block != FALSE ) + { + // The WebStatement Field contains ownerurl - Find it + $Item = find_XMP_item( $rights_block, "xapRights:WebStatement" ); + + // Check that the WebStatement Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + $outputarray = add_to_field( $outputarray, 'ownerurl' , HTML_UTF8_Escape( $Item['value'] ), "\n" ); + } + + /***************************************/ + + // The Marked Field contains copyrightstatus - Find it + $Item = find_XMP_item( $rights_block, "xapRights:Marked" ); + + // Check that the Marked Field exists and save the value + if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) ) + { + if ( $Item['value'] == "True" ) + { + $outputarray = add_to_field( $outputarray, 'copyrightstatus' , "Copyrighted Work", "," ); + } + else + { + $outputarray = add_to_field( $outputarray, 'copyrightstatus' , "Public Domain", "," ); + } + } + + } + + + + + + /***************************************/ + + // Photoshop IRB Processing + + // Check that the Photoshop IRB exists + if ( $IRB_array != FALSE ) + { + // Create a translation table to convert carriage returns to linefeeds + $irbtrans = array("\x0d" => "\x0a"); + + // The Photoshop IRB Copyright flag (0x040A) contains copyrightstatus - find it + $IRB_copyright_flag = find_Photoshop_IRB_Resource( $IRB_array, 0x040A ); + + // Check if the Copyright flag Field exists, and save the value + if( $IRB_copyright_flag != FALSE ) + { + // Check the value of the copyright flag + if ( hexdec( bin2hex( $IRB_copyright_flag['ResData'] ) ) == 1 ) + { + // Save the value + $outputarray = add_to_field( $outputarray, 'copyrightstatus' , "Copyrighted Work", "," ); + } + else + { + // Do nothing - copyrightstatus will be set to unmarked if still blank at end + } + } + + /***************************************/ + + // The Photoshop IRB URL (0x040B) contains ownerurl - find it + $IRB_url = find_Photoshop_IRB_Resource( $IRB_array, 0x040B ); + + // Check if the URL Field exists and save the value + if( $IRB_url != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'ownerurl' , strtr( $IRB_url['ResData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // Extract any IPTC block from the Photoshop IRB information + $IPTC_array = get_Photoshop_IPTC( $IRB_array ); + + // Check if the IPTC block exits + if ( ( $IPTC_array != FALSE ) && ( count( $IPTC_array ) != 0 ) ) + { + // The IPTC Caption/Abstract Field contains caption - find it + $record = find_IPTC_Resource( $IPTC_array, "2:120" ); + + // Check if the Caption/Abstract Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'caption' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Caption Writer/Editor Field contains captionwriter - find it + $record = find_IPTC_Resource( $IPTC_array, "2:122" ); + + // Check if the Caption Writer/Editor Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'captionwriter' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Headline Field contains headline - find it + $record = find_IPTC_Resource( $IPTC_array, "2:105" ); + + // Check if the Headline Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'headline' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Special Instructions Field contains instructions - find it + $record = find_IPTC_Resource( $IPTC_array, "2:40" ); + + // Check if the Special Instructions Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'instructions' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC By-Line Field contains author - find it + $record = find_IPTC_Resource( $IPTC_array, "2:80" ); + + // Check if the By-Line Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'author' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC By-Line Title Field contains authorsposition - find it + $record = find_IPTC_Resource( $IPTC_array, "2:85" ); + + // Check if the By-Line Title Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'authorsposition' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Credit Field contains credit - find it + $record = find_IPTC_Resource( $IPTC_array, "2:110" ); + + // Check if the Credit Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'credit' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Source Field contains source - find it + $record = find_IPTC_Resource( $IPTC_array, "2:115" ); + + // Check if the Source Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'source' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Object Name Field contains title - find it + $record = find_IPTC_Resource( $IPTC_array, "2:05" ); + + // Check if the Object Name Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'title' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Date Created Field contains date - find it + $record = find_IPTC_Resource( $IPTC_array, "2:55" ); + + // Check if the Date Created Field exists and save the value + if ( $record != FALSE ) + { + $date_array = unpack( "a4Year/a2Month/A2Day", $record['RecData'] ); + $tmpdate = $date_array['Year'] . "-" . $date_array['Month'] . "-" . $date_array['Day']; + $outputarray = add_to_field( $outputarray, 'date' , strtr( $tmpdate, $irbtrans ), "," ); + + } + + /***************************************/ + + // The IPTC City Field contains city - find it + $record = find_IPTC_Resource( $IPTC_array, "2:90" ); + + // Check if the City Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'city' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Province/State Field contains state - find it + $record = find_IPTC_Resource( $IPTC_array, "2:95" ); + + // Check if the Province/State Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'state' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Country/Primary Location Name Field contains country - find it + $record = find_IPTC_Resource( $IPTC_array, "2:101" ); + + // Check if the Country/Primary Location Name Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'country' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Original Transmission Reference Field contains transmissionreference - find it + $record = find_IPTC_Resource( $IPTC_array, "2:103" ); + + // Check if the Original Transmission Reference Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'transmissionreference' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + /***************************************/ + + // The IPTC Category Field contains category - find it + $record = find_IPTC_Resource( $IPTC_array, "2:15" ); + + // Check if the Category Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'category' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + + /***************************************/ + + // Cycle through the IPTC records looking for Supplemental Category records + foreach ($IPTC_array as $record) + { + // Check if a Supplemental Category record has been found + if ( $record['IPTC_Type'] == "2:20" ) + { + // A Supplemental Category record has been found, save it's value if the value doesn't already exist + if ( ! in_array ( $record['RecData'], $outputarray['supplementalcategories'])) + { + $outputarray['supplementalcategories'][] = strtr( $record['RecData'], array("\x0a" => "", "\x0d" => "
") ) ; + } + } + } + + + /***************************************/ + + // The IPTC Urgency Field contains urgency - find it + $record = find_IPTC_Resource( $IPTC_array, "2:10" ); + + // Check if the Urgency Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'urgency' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + + + /***************************************/ + + // Cycle through the IPTC records looking for Keywords records + foreach ($IPTC_array as $record) + { + // Check if a Keywords record has been found + if ( $record['IPTC_Type'] == "2:25" ) + { + // A Keywords record has been found, save it's value if the value doesn't already exist + if ( ! in_array ( $record['RecData'], $outputarray['keywords'])) + { + $outputarray['keywords'][] = strtr( $record['RecData'], array("\x0a" => "", "\x0d" => "
") ) ; + } + } + } + + + /***************************************/ + + // The IPTC Copyright Notice Field contains copyrightnotice - find it + $record = find_IPTC_Resource( $IPTC_array, "2:116" ); + + // Check if the Copyright Field exists and save the value + if ( $record != FALSE ) + { + $outputarray = add_to_field( $outputarray, 'copyrightnotice' , strtr( $record['RecData'], $irbtrans ), "\n" ); + } + + } + } + + + + + /***************************************/ + + // EXIF Processing + + + // Retreive Information from the EXIF data if it exists + + if ( ( $Exif_array != FALSE ) || ( count( $Exif_array ) == 0 ) ) + { + // Check the Image Description Tag - it can contain the caption + if ( array_key_exists( 270, $Exif_array[0] ) ) + { + $outputarray = add_to_field( $outputarray, 'caption' , $Exif_array[0][270]['Data'][0], "\n" ); + } + + /***************************************/ + + // Check the Copyright Information Tag - it contains the copyrightnotice + if ( array_key_exists( 33432, $Exif_array[0] ) ) + { + $outputarray = add_to_field( $outputarray, 'copyrightnotice' , HTML_UTF8_UnEscape( $Exif_array[0][33432]['Data'][0] ), "\n" ); + } + + /***************************************/ + + // Check the Artist Name Tag - it contains the author + if ( array_key_exists( 315, $Exif_array[0] ) ) + { + $outputarray = add_to_field( $outputarray, 'author' , HTML_UTF8_UnEscape( $Exif_array[0][315]['Data'][0] ), "\n" ); + } + + } + + + /***************************/ + + // FINISHED RETRIEVING INFORMATION + + // Perform final processing + + + // Check if any urgency information was found + if ( $outputarray["urgency"] == "" ) + { + // No urgency information was found - set it to default (None) + $outputarray["urgency"] = "none"; + } + + // Check if any copyrightstatus information was found + if ( $outputarray["copyrightstatus"] == "" ) + { + // No copyrightstatus information was found - set it to default (Unmarked) + $outputarray["copyrightstatus"] = "unmarked"; + } + + // Return the resulting Photoshop File Info Array + return $outputarray; + +} + +/****************************************************************************** +* End of Function: get_photoshop_file_info +******************************************************************************/ + + + + + + +/****************************************************************************** +* +* Function: put_photoshop_file_info +* +* Description: Stores Photoshop 'File Info' metadata in the same way that Photoshop +* does. The 'File Info' metadata must be in an array similar to that +* returned by get_photoshop_file_info, as follows: +* +* $file_info_array = array( +* "title" => "", +* "author" => "", +* "authorsposition" => "", // Note: Not used in Photoshop 7 or higher +* "caption" => "", +* "captionwriter" => "", +* "jobname" => "", // Note: Not used in Photoshop CS +* "copyrightstatus" => "", +* "copyrightnotice" => "", +* "ownerurl" => "", +* "keywords" => array( 0 => "", 1 => "", ... ), +* "category" => "", // Note: Max 3 characters +* "supplementalcategories" => array( 0 => "", 1 => "", ... ), +* "date" => "", // Note: DATE MUST BE IN YYYY-MM-DD format +* "city" => "", +* "state" => "", +* "country" => "", +* "credit" => "", +* "source" => "", +* "headline" => "", +* "instructions" => "", +* "transmissionreference" => "", +* "urgency" => "" ); +* +* Parameters: jpeg_header_data - a JPEG header data array in the same format +* as from get_jpeg_header_data. This contains the +* header information which is to be updated. +* new_ps_file_info_array - An array as above, which contains the +* 'File Info' metadata information to be +* written. +* Old_Exif_array - an array containing the EXIF information to be +* updated, as retrieved by get_EXIF_JPEG. (saves having to parse the EXIF again) +* Old_XMP_array - an array containing the XMP information to be +* updated, as retrieved by read_XMP_array_from_text. (saves having to parse the XMP again) +* Old_IRB_array - an array containing the Photoshop IRB information +* to be updated, as retrieved by get_Photoshop_IRB. (saves having to parse the IRB again) +* +* Returns: jpeg_header_data - a JPEG header data array in the same format +* as from get_jpeg_header_data, containing the +* Photshop 'File Info' metadata. This can then +* be written to a file using put_jpeg_header_data. +* +******************************************************************************/ + +function put_photoshop_file_info( $jpeg_header_data, $new_ps_file_info_array, $Old_Exif_array, $Old_XMP_array, $Old_IRB_array ) +{ + /*******************************************/ + // PREPROCESSING + + // Check that the date is in the correct format (YYYY-MM-DD) + + // Explode the date into pieces using the - symbol + $date_pieces = explode( "-", $new_ps_file_info_array[ 'date' ] ); + + // If there are not 3 pieces to the date, it is invalid + if ( count( $date_pieces ) != 3 ) + { + // INVALID DATE + echo "Invalid Date - must be YYYY-MM-DD format<br>"; + return FALSE; + } + + // Cycle through each piece of the date + foreach( $date_pieces as $piece ) + { + // If the piece is not numeric, then the date is invalid. + if ( ! is_numeric( $piece ) ) + { + // INVALID DATE + echo "Invalid Date - must be YYYY-MM-DD format<br>"; + return FALSE; + } + } + + // Make a unix timestamp at midnight on the date specified + $date_stamp = mktime( 0,0,0, $date_pieces[1], $date_pieces[2], $date_pieces[0] ); + + + + + // Create a translation table to remove carriage return characters + $trans = array( "\x0d" => "" ); + + // Cycle through each of the File Info elements + foreach( $new_ps_file_info_array as $valkey => $val ) + { + // If the element is 'Keywords' or 'Supplemental Categories', then + // it is an array, and needs to be treated as one + if ( ( $valkey != 'supplementalcategories' ) && ( $valkey != 'keywords' ) ) + { + // Not Keywords or Supplemental Categories + // Convert escaped HTML characters to UTF8 and remove carriage returns + $new_ps_file_info_array[ $valkey ] = strtr( HTML_UTF8_UnEscape( $val ), $trans ); + } + else + { + // Either Keywords or Supplemental Categories + // Cycle through the array, + foreach( $val as $subvalkey => $subval ) + { + // Convert escaped HTML characters to UTF8 and remove carriage returns + $new_ps_file_info_array[ $valkey ][ $subvalkey ] = strtr( HTML_UTF8_UnEscape( $subval ), $trans ); + } + } + } + + + + + + /*******************************************/ + + // EXIF Processing + + + // Check if the EXIF array exists + if( $Old_Exif_array == FALSE ) + { + // EXIF Array doesn't exist - create a new one + $new_Exif_array = array ( 'Byte_Align' => "MM", + 'Makernote_Tag' => false, + 'Tags Name' => "TIFF", + 0 => array( "Tags Name" => "TIFF" ) ); + } + else + { + // EXIF Array Does Exist - use it + $new_Exif_array = $Old_Exif_array; + } + + + + // Update the EXIF Image Description Tag with the new value + $new_Exif_array[0][270] = array ( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 270 ]['Name'], + "Tag Number" => 270, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 270 ]['Type'], + "Data" => array( HTML_UTF8_Escape( $new_ps_file_info_array[ 'caption' ]) )); + + // Update the EXIF Artist Name Tag with the new value + $new_Exif_array[0][315] = array ( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 315 ]['Name'], + "Tag Number" => 315, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 315 ]['Type'], + "Data" => array( HTML_UTF8_Escape( $new_ps_file_info_array[ 'author' ] ) ) ); + + // Update the EXIF Copyright Information Tag with the new value + $new_Exif_array[0][33432] = array ( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 33432 ]['Name'], + "Tag Number" => 33432, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 33432 ]['Type'], + "Data" => array( HTML_UTF8_Escape( $new_ps_file_info_array[ 'copyrightnotice' ]) ) ); + + + // Photoshop checks if the "Date and Time of Original" and "Date and Time when Digitized" tags exist + // If they don't exist, it means that the EXIF date may be wiped out if it is changed, so Photoshop + // copies the EXIF date to these two tags + + if ( ( array_key_exists( 306, $new_Exif_array[0] ) )&& + ( array_key_exists( 34665, $new_Exif_array[0] ) ) && + ( array_key_exists( 0, $new_Exif_array[0][34665] ) ) ) + { + // Replace "Date and Time of Original" if it doesn't exist + if ( ! array_key_exists( 36867, $new_Exif_array[0][34665][0] ) ) + { + $new_Exif_array[0][34665][0][36867] = array ( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['EXIF'][ 36867 ]['Name'], + "Tag Number" => 36867, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['EXIF'][ 36867 ]['Type'], + "Data" => $new_Exif_array[0][306]['Data'] ); + } + + // Replace "Date and Time when Digitized" if it doesn't exist + if ( ! array_key_exists( 36868, $new_Exif_array[0][34665][0] ) ) + { + $new_Exif_array[0][34665][0][36868] = array ( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['EXIF'][ 36868 ]['Name'], + "Tag Number" => 36868, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['EXIF'][ 36868 ]['Type'], + "Data" => $new_Exif_array[0][306]['Data'] ); + } + } + + + // Photoshop changes the EXIF date Tag (306) to the current date, not the date that was entered in File Info + $exif_date = date ( "Y:m:d H:i:s" ); + + // Update the EXIF Date and Time Tag with the new value + $new_Exif_array[0][306] = array ( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 306 ]['Name'], + "Tag Number" => 306, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 306 ]['Type'], + "Data" => array( $exif_date ) ); + + + + // Photoshop replaces the EXIF Software or Firmware Tag with "Adobe Photoshop ..." + // This toolkit instead preserves existing value and appends the toolkit name to the end of it + + // Check if the EXIF Software or Firmware Tag exists + if ( array_key_exists( 305, $new_Exif_array[0] ) ) + { + // An existing EXIF Software or Firmware Tag was found + // Check if the existing Software or Firmware Tag already contains the Toolkit's name + if ( stristr ( $new_Exif_array[0][305]['Data'][0], $GLOBALS[ "Software Name" ]) == FALSE ) + { + // Toolkit Name string not found in the existing Software/Firmware string - append it. + $firmware_str = $new_Exif_array[0][305]['Data'][0] . " " . $GLOBALS[ "Software Name" ]; + } + else + { + // Toolkit name already exists in Software/Firmware string - don't put another copy in the string + $firmware_str = $new_Exif_array[0][305]['Data'][0]; + } + } + else + { + // No Software/Firmware string exists - create one + $firmware_str = $GLOBALS[ "Software Name" ]; + } + + // Update the EXIF Software/Firmware Tag with the new value + $new_Exif_array[0][305] = array( "Tag Name" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 305 ]['Name'], + "Tag Number" => 305, + "Data Type" => 2, + "Type" => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 305 ]['Type'], + "Data" => array( HTML_UTF8_Escape( $firmware_str ) ) ); + + + + + + /*******************************************/ + + // Photoshop IRB Processing + + + // Check if there is an existing Photoshop IRB array + if ($Old_IRB_array == FALSE ) + { + // No existing IRB array - create one + $new_IRB_array = array(); + } + else + { + // There is an existing Photoshop IRB array - use it + $new_IRB_array = $Old_IRB_array; + } + + // Remove any existing Copyright Flag, URL, or IPTC resources - these will be re-written + foreach( $new_IRB_array as $resno => $res ) + { + if ( ( $res[ 'ResID' ] == 0x040A ) || + ( $res[ 'ResID' ] == 0x040B ) || + ( $res[ 'ResID' ] == 0x0404 ) ) + { + array_splice( $new_IRB_array, $resno, 1 ); + } + } + + + // Add a new Copyright Flag resource + if ( $new_ps_file_info_array[ 'copyrightstatus' ] == "Copyrighted Work" ) + { + $PS_copyright_flag = "\x01"; // Copyrighted + } + else + { + $PS_copyright_flag = "\x00"; // Public domain or Unmarked + } + $new_IRB_array[] = array( 'ResID' => 0x040A, + 'ResName' => $GLOBALS[ "Photoshop_ID_Names" ][0x040A], + 'ResDesc' => $GLOBALS[ "Photoshop_ID_Descriptions" ][0x040A], + 'ResEmbeddedName' => "", + 'ResData' => $PS_copyright_flag ); + + + + // Add a new URL resource + $new_IRB_array[] = array( 'ResID' => 0x040B, + 'ResName' => $GLOBALS[ "Photoshop_ID_Names" ][0x040B], + 'ResDesc' => $GLOBALS[ "Photoshop_ID_Descriptions" ][0x040B], + 'ResEmbeddedName' => "", + 'ResData' => $new_ps_file_info_array[ 'ownerurl' ] ); + + + + // Create IPTC resource + + // IPTC requires date to be in the following format YYYYMMDD + $iptc_date = date( "Ymd", $date_stamp ); + + // Create the new IPTC array + $new_IPTC_array = array ( + 0 => + array ( + 'IPTC_Type' => '2:00', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:00'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:00'], + 'RecData' => "\x00\x02", + ), + 1 => + array ( + 'IPTC_Type' => '2:120', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:120'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:120'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'caption' ] ), 0 , 2000 ), + ), + 2 => + array ( + 'IPTC_Type' => '2:122', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:122'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:122'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'captionwriter' ] ), 0 , 32 ), + ), + 3 => + array ( + 'IPTC_Type' => '2:105', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:105'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:105'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'headline' ] ), 0 , 256 ), + ), + 4 => + array ( + 'IPTC_Type' => '2:40', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:40'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:40'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'instructions' ] ), 0, 256 ), + ), + 5 => + array ( + 'IPTC_Type' => '2:80', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:80'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:80'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'author' ] ), 0, 32 ), + ), + 6 => + array ( + 'IPTC_Type' => '2:85', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:85'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:85'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'authorsposition' ] ), 0, 32 ), + ), + 7 => + array ( + 'IPTC_Type' => '2:110', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:110'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:110'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'credit' ] ), 0, 32 ), + ), + 8 => + array ( + 'IPTC_Type' => '2:115', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:115'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:115'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'source' ] ), 0, 32 ), + ), + 9 => + array ( + 'IPTC_Type' => '2:05', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:05'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:05'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'title' ] ), 0, 64 ), + ), + 10 => + array ( + 'IPTC_Type' => '2:55', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:55'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:55'], + 'RecData' => "$iptc_date", + ), + 11 => + array ( + 'IPTC_Type' => '2:90', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:90'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:90'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'city' ] ), 0, 32 ), + ), + 12 => + array ( + 'IPTC_Type' => '2:95', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:95'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:95'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'state' ] ), 0, 32 ), + ), + 13 => + array ( + 'IPTC_Type' => '2:101', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:101'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:101'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'country' ] ), 0, 64 ), + ), + 14 => + array ( + 'IPTC_Type' => '2:103', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:103'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:103'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'transmissionreference' ] ), 0, 32 ), + ), + 15 => + array ( + 'IPTC_Type' => '2:15', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:15'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:15'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'category' ] ), 0, 3 ), + ), + 21 => + array ( + 'IPTC_Type' => '2:116', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:10'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:10'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'copyrightnotice' ] ), 0, 128 ), + ), + ); + + // Check the value of urgency is valid + if ( ( $new_ps_file_info_array[ 'urgency' ] > 0 ) && ( $new_ps_file_info_array[ 'urgency' ] < 9 ) ) + { + // Add the Urgency item to the IPTC array + $new_IPTC_array[] = array ( + 'IPTC_Type' => '2:10', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:10'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:10'], + 'RecData' => substr( HTML_UTF8_Escape( $new_ps_file_info_array[ 'urgency' ] ), 0, 1 ), + ); + } + + // Cycle through the Supplemental Categories, + foreach( $new_ps_file_info_array[ 'supplementalcategories' ] as $supcat ) + { + // Add this Supplemental Category to the IPTC array + $new_IPTC_array[] = array ( + 'IPTC_Type' => '2:20', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:20'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:20'], + 'RecData' => HTML_UTF8_Escape( $supcat ), + ); + } + + + // Cycle through the Keywords, + foreach( $new_ps_file_info_array[ 'keywords' ] as $keyword ) + { + // Add this Keyword to the IPTC array + $new_IPTC_array[] = array ( + 'IPTC_Type' => '2:25', + 'RecName' => $GLOBALS[ "IPTC_Entry_Names" ]['2:25'], + 'RecDesc' => $GLOBALS[ "IPTC_Entry_Descriptions" ]['2:25'], + 'RecData' => $keyword, + ); + } + + + /***********************************/ + + // XMP Processing + + // Check if XMP existed previously + if ($Old_XMP_array == FALSE ) + { + // XMP didn't exist - create a new one based on a blank structure + $new_XMP_array = XMP_Check( $GLOBALS[ 'Blank XMP Structure' ], array( ) ); + } + else + { + // XMP does exist + // Some old XMP processors used x:xapmeta, check for this + if ( $Old_XMP_array[0]['tag'] == 'x:xapmeta' ) + { + // x:xapmeta found - change it to x:xmpmeta + $Old_XMP_array[0]['tag'] = 'x:xmpmeta'; + } + + // Ensure that the existing XMP has all required fields, and add any that are missing + $new_XMP_array = XMP_Check( $GLOBALS[ 'Blank XMP Structure' ], $Old_XMP_array ); + } + + + // Process the XMP Photoshop block + + // Find the Photoshop Information within the XMP block + $photoshop_block = & find_XMP_block( $new_XMP_array, "photoshop" ); + + // The Photoshop CaptionWriter tag contains captionwriter - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:CaptionWriter" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'captionwriter' ]; + + // The Photoshop Category tag contains category - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Category" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'category' ]; + + // The Photoshop DateCreated tag contains date - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:DateCreated" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'date' ]; + + // The Photoshop City tag contains city - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:City" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'city' ]; + + // The Photoshop State tag contains state - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:State" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'state' ]; + + // The Photoshop Country tag contains country - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Country" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'country' ]; + + // The Photoshop AuthorsPosition tag contains authorsposition - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:AuthorsPosition" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'authorsposition' ]; + + // The Photoshop Credit tag contains credit - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Credit" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'credit' ]; + + // The Photoshop Source tag contains source - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Source" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'source' ]; + + // The Photoshop Headline tag contains headline - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Headline" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'headline' ]; + + // The Photoshop Instructions tag contains instructions - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Instructions" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'instructions' ]; + + // The Photoshop TransmissionReference tag contains transmissionreference - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:TransmissionReference" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'transmissionreference' ]; + + // The Photoshop Urgency tag contains urgency - Find it and Update the value + $Item = & find_XMP_item( $photoshop_block, "photoshop:Urgency" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'urgency' ]; + + // The Photoshop SupplementalCategories tag contains supplementalcategories - Find it + $Item = & find_XMP_item( $photoshop_block, "photoshop:SupplementalCategories" ); + + // Create an array to receive the XML list items for the Supplemental Categories + $new_supcat_array = array( ); + + // Cycle through the Supplemental Categories + foreach ( $new_ps_file_info_array[ 'supplementalcategories' ] as $sup_category ) + { + // Add a new list item for this Supplemental Category + $new_supcat_array[] = array( 'tag' => 'rdf:li', 'value' => $sup_category ); + } + + // Add the array of Supplemental Category List Items to the Photoshop SupplementalCategories tag + $Item[ 'children' ][ 0 ][ 'children' ] = $new_supcat_array; + + + + // Process the XMP XAP block + + // Find the XAP Information within the XMP block + $XAP_block = & find_XMP_block( $new_XMP_array, "xap" ); + + // The XAP CreateDate tag contains date XMP was first created - Find it and Update the value + $Item = & find_XMP_item( $XAP_block, "xap:CreateDate" ); + + // Check if the CreateDate is blank + if ( $Item[ 'value' ] == "" ) + { + // CreateDate is blank - we must have just added it - set it to the current date + $Item[ 'value' ] = date( "Y-m-d\TH:i:s" ); + $Item[ 'value' ] .= get_Local_Timezone_Offset( ); + } + + + // The XAP ModifyDate tag contains last resource change date - Find it and Update the value to the current date + $Item = & find_XMP_item( $XAP_block, "xap:ModifyDate" ); + $Item[ 'value' ] = date( "Y-m-d\TH:i:s" ); + $Item[ 'value' ] .= get_Local_Timezone_Offset( ); + + // The XAP ModifyDate tag contains last XMP change date - Find it and Update the value to the current date + $Item = & find_XMP_item( $XAP_block, "xap:MetadataDate" ); + $Item[ 'value' ] = date( "Y-m-d\TH:i:s" ); + $Item[ 'value' ] .= get_Local_Timezone_Offset( ); + + + + // The XAP CreatorTool tag contains name of the software editor - Find it + $Item = & find_XMP_item( $XAP_block, "xap:CreatorTool" ); + + // Photoshop replaces the CreatorTool with "Adobe Photoshop ..." + // This toolkit instead preserves existing value and appends the toolkit name to the end of it + + // Check if a CreatorTool already exists + if ( $Item[ 'value' ] != "" ) + { + // An existing CreatorTool was found + // Check if the existing CreatorTool already contains the Toolkit's name + if ( stristr ( $Item[ 'value' ], $GLOBALS[ "Software Name" ]) == FALSE ) + { + // Toolkit Name string not found in the existing CreatorTool string - append it. + $Item[ 'value' ] = $Item[ 'value' ] . " " . $GLOBALS[ "Software Name" ]; + } + else + { + // Toolkit name already exists in CreatorTool string - leave as is + } + } + else + { + // No CreatorTool string exists - create one + $Item[ 'value' ] = $GLOBALS[ "Software Name" ]; + } + + + + + // Process the XMP Basic Job Information block + + // Find the XAP Basic Job Information within the XMP block + $XAPBJ_block = & find_XMP_block( $new_XMP_array, "xapBJ" ); + + // The XAP Basic Job JobRef tag contains urgency - Find it and Update the value + $Item = & find_XMP_item( $XAPBJ_block, "xapBJ:JobRef" ); + $Item[ 'children' ][ 0 ][ 'children' ] = + array( array ( 'tag' => 'rdf:li', + 'attributes' => array ( 'rdf:parseType' => 'Resource' ), + 'children' => array ( 0 => array ( 'tag' => 'stJob:name', + 'value' => $new_ps_file_info_array[ 'jobname' ] ), + ), + ), + ); + + + + + // Process the XMP XAP Rights Information block + + // Find the XAP Rights Information within the XMP block + $XAPRights_block = & find_XMP_block( $new_XMP_array, "xapRights" ); + + + + // The XAP Rights Marked tag should only be present if copyrightstatus is 'Copyrighted Work' or 'Public Domain' + // If copyrightstatus 'Unmarked' or anything else, the XAP Rights Marked tag should be missing + + + // Remove any existing XAP Rights Marked tags - they will be replaced + foreach( $XAPRights_block as $tagno => $tag ) + { + if ( $tag[ 'tag' ] == "xapRights:Marked" ) + { + array_splice( $XAPRights_block, $tagno, 1 ); + } + } + + // Check the value of the copyrightstatus flag + if ( $new_ps_file_info_array[ 'copyrightstatus' ] == "Copyrighted Work" ) + { + // Copyrighted - add the tag + $XAPRights_block[] = array ( 'tag' => 'xapRights:Marked', 'value' => 'True' ); + } + else if ( $new_ps_file_info_array[ 'copyrightstatus' ] == "Public Domain" ) + { + // Public domain - add the tag + $XAPRights_block[] = array ( 'tag' => 'xapRights:Marked', 'value' => 'False' ); + } + else + { + // Unmarked or Other - Do nothing - don't add a Marked tag + } + + + // The XAP Rights WebStatement tag contains ownerurl - Find it and Update the value + $Item = & find_XMP_item( $XAPRights_block, "xapRights:WebStatement" ); + $Item[ 'value' ] = $new_ps_file_info_array[ 'ownerurl' ]; + + + + + // Process the XMP Dublin Core block + + // Find the Dublin Core Information within the XMP block + $DC_block = & find_XMP_block( $new_XMP_array, "dc" ); + + + // The Dublin Core description tag contains caption - Find it and Update the value + $Item = & find_XMP_item( $DC_block, "dc:description" ); + $Item[ 'children' ][ 0 ][ 'children' ] = array( array( 'tag' => "rdf:li", + 'value' => $new_ps_file_info_array[ 'caption' ], + 'attributes' => array( 'xml:lang' => "x-default" ) ) ); + + + // The Dublin Core title tag contains title - Find it and Update the value + $Item = & find_XMP_item( $DC_block, "dc:title" ); + $Item[ 'children' ][ 0 ][ 'children' ] = array( array( 'tag' => "rdf:li", + 'value' => $new_ps_file_info_array[ 'title' ], + 'attributes' => array( 'xml:lang' => "x-default" ) ) ); + + + // The Dublin Core rights tag contains copyrightnotice - Find it and Update the value + $Item = & find_XMP_item( $DC_block, "dc:rights" ); + $Item[ 'children' ][ 0 ][ 'children' ] = array( array( 'tag' => "rdf:li", + 'value' => $new_ps_file_info_array[ 'copyrightnotice' ], + 'attributes' => array( 'xml:lang' => "x-default" ) ) ); + + // The Dublin Core creator tag contains author - Find it and Update the value + $Item = & find_XMP_item( $DC_block, "dc:creator" ); + $Item[ 'children' ][ 0 ][ 'children' ] = array( array( 'tag' => "rdf:li", + 'value' => $new_ps_file_info_array[ 'author' ]) ); + + // The Dublin Core subject tag contains keywords - Find it + $Item = & find_XMP_item( $DC_block, "dc:subject" ); + + // Create an array to receive the Keywords List Items + $new_keywords_array = array( ); + + // Cycle through each keyword + foreach( $new_ps_file_info_array[ 'keywords' ] as $keyword ) + { + // Add a List item for this keyword + $new_keywords_array[] = array( 'tag' => "rdf:li", 'value' => $keyword ); + } + // Add the Keywords List Items array to the Dublin Core subject tag + $Item[ 'children' ][ 0 ][ 'children' ] = $new_keywords_array; + + + + /***************************************/ + + // FINISHED UPDATING VALUES + + // Insert the new IPTC array into the Photoshop IRB array + $new_IRB_array = put_Photoshop_IPTC( $new_IRB_array, $new_IPTC_array ); + + // Write the EXIF array to the JPEG header + $jpeg_header_data = put_EXIF_JPEG( $new_Exif_array, $jpeg_header_data ); + + // Convert the XMP array to XMP text + $xmp_text = write_XMP_array_to_text( $new_XMP_array ); + + // Write the XMP text to the JPEG Header + $jpeg_header_data = put_XMP_text( $jpeg_header_data, $xmp_text ); + + // Write the Photoshop IRB array to the JPEG header + $jpeg_header_data = put_Photoshop_IRB( $jpeg_header_data, $new_IRB_array ); + + return $jpeg_header_data; + +} + +/****************************************************************************** +* End of Function: put_photoshop_file_info +******************************************************************************/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/****************************************************************************** +* +* INTERNAL FUNCTIONS +* +******************************************************************************/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/****************************************************************************** +* +* Function: get_Local_Timezone_Offset +* +* Description: Returns a string indicating the time difference between the local +* timezone and GMT in hours and minutes, e.g. +10:00 or -06:30 +* +* Parameters: None +* +* Returns: $tz_str - a string containing the timezone offset +* +******************************************************************************/ + +function get_Local_Timezone_Offset( ) +{ + // Retrieve the Timezone offset in seconds + $tz_seconds = date( "Z" ); + + // Check if the offset is less than zero + if ( $tz_seconds < 0 ) + { + // Offset is less than zero - add a Minus sign to the output + $tz_str = "-"; + } + else + { + // Offset is greater than or equal to zero - add a Plus sign to the output + $tz_str = "+"; + } + + // Add the absolute offset to the output, formatted as HH:MM + $tz_str .= gmdate( "H:i", abs($tz_seconds) ); + + // Return the result + return $tz_str; +} + +/****************************************************************************** +* End of Function: get_Local_Timezone_Offset +******************************************************************************/ + + + +/****************************************************************************** +* +* Function: XMP_Check +* +* Description: Checks a given XMP array against a reference array, and adds any +* missing blocks and tags +* +* NOTE: This is a recursive function +* +* Parameters: reference_array - The standard XMP array which contains all required tags +* check_array - The XMP array to check +* +* Returns: output - a string containing the timezone offset +* +******************************************************************************/ + +function XMP_Check( $reference_array, $check_array) +{ + // Cycle through each of the elements of the reference XMP array + foreach( $reference_array as $valkey => $val ) + { + + // Search for the current reference tag within the XMP array to be checked + $tagpos = find_XMP_Tag( $check_array, $val ); + + // Check if the tag was found + if ( $tagpos === FALSE ) + { + // Tag not found - Add tag to array being checked + $tagpos = count( $check_array ); + $check_array[ $tagpos ] = $val; + } + + // Check if the reference tag has children + if ( array_key_exists( 'children', $val ) ) + { + // Reference tag has children - these need to be checked too + + // Determine if the array being checked has children for this tag + if ( ! array_key_exists( 'children', $check_array[ $tagpos ] ) ) + { + // Array being checked has no children - add a blank children array + $check_array[ $tagpos ][ 'children' ] = array( ); + } + + // Recurse, checking the children tags against the reference children + $check_array[ $tagpos ][ 'children' ] = XMP_Check( $val[ 'children' ] , $check_array[ $tagpos ][ 'children' ] ); + } + else + { + // No children - don't need to check anything else + } + } + + // Return the checked XMP array + return $check_array; +} + + +/****************************************************************************** +* End of Function: XMP_Check +******************************************************************************/ + + + + +/****************************************************************************** +* +* Function: find_XMP_Tag +* +* Description: Searches one level of an XMP array for a specific tag, and +* returns the tag position. Does not descend the XMP tree. +* +* Parameters: XMP_array - The XMP array which should be searched +* tag - The XMP tag to search for (in same format as would be found in XMP array) +* +* Returns: output - a string containing the timezone offset +* +******************************************************************************/ + +function find_XMP_Tag( $XMP_array, $tag ) +{ + $namespacestr = ""; + + // Some tags have a namespace attribute which defines them (i.e. rdf:Description tags) + + // Check if the tag being searched for has attributs + if ( array_key_exists( 'attributes', $tag ) ) + { + // Tag has attributes - cycle through them + foreach( $tag['attributes'] as $key => $val ) + { + // Check if the current attribute is the namespace attribute - i.e. starts with xmlns: + if ( strcasecmp( substr($key,0,6), "xmlns:" ) == 0 ) + { + // Found a namespace attribute - save it for later. + $namespacestr = $key; + } + } + } + + + + // Cycle through the elements of the XMP array to be searched. + foreach( $XMP_array as $valkey => $val ) + { + + // Check if the current element is a rdf:Description tag + if ( strcasecmp ( $tag[ 'tag' ], 'rdf:Description' ) == 0 ) + { + // Current element is a rdf:Description tag + // Check if the namespace attribute is the same as in the tag that is being searched for + if ( array_key_exists( $namespacestr, $val['attributes'] ) ) + { + // Namespace is the same - this is the correct tag - return it's position + return $valkey; + } + } + // Otherwise check if the current element has the same name as the tag in question + else if ( strcasecmp ( $val[ 'tag' ], $tag[ 'tag' ] ) == 0 ) + { + // Tags have same name - this is the correct tag - return it's position + return $valkey; + } + } + + // Cycled through all tags without finding the correct one - return error value + return FALSE; +} + +/****************************************************************************** +* End of Function: find_XMP_Tag +******************************************************************************/ + + + + +/****************************************************************************** +* +* Function: create_GUID +* +* Description: Creates a Globally Unique IDentifier, in the format that is used +* by XMP (and Windows). This value is not guaranteed to be 100% unique, +* but it is ridiculously unlikely that two identical values will be produced +* +* Parameters: none +* +* Returns: output - a string containing the timezone offset +* +******************************************************************************/ + +function create_GUID( ) +{ + // Create a md5 sum of a random number - this is a 32 character hex string + $raw_GUID = md5( uniqid( getmypid() . rand( ) . (double)microtime()*1000000, TRUE ) ); + + // Format the string into 8-4-4-4-12 (numbers are the number of characters in each block) + return substr($raw_GUID,0,8) . "-" . substr($raw_GUID,8,4) . "-" . substr($raw_GUID,12,4) . "-" . substr($raw_GUID,16,4) . "-" . substr($raw_GUID,20,12); +} + +/****************************************************************************** +* End of Function: create_GUID +******************************************************************************/ + + + + + +/****************************************************************************** +* +* Function: add_to_field +* +* Description: Adds a value to a particular field in a Photoshop File Info array, +* first checking whether the value is already there. If the value is +* already in the array, it is not changed, otherwise the value is appended +* to whatever is already in that field of the array +* +* Parameters: field_array - The Photoshop File Info array to receive the new value +* field - The File Info field which the value is for +* value - The value to be written into the File Info +* separator - The string to place between values when having to append the value +* +* Returns: output - the Photoshop File Info array with the value added +* +******************************************************************************/ + +function add_to_field( $field_array, $field, $value, $separator ) +{ + // Check if the value is blank + if ( $value == "" ) + { + // Value is blank - return File Info array unchanged + return $field_array; + } + + // Check if the value can be found anywhere within the existing value for this field + if ( stristr ( $field_array[ $field ], $value ) == FALSE) + { + // Value could not be found + // Check if the existing value for the field is blank + if ( $field_array[$field] != "" ) + { + // Existing value for field is not blank - append a separator + $field_array[$field] .= $separator; + } + // Append the value to the field + $field_array[$field] .= $value; + } + + // Return the File Info Array + return $field_array; +} + +/****************************************************************************** +* End of Function: add_to_field +******************************************************************************/ + + + +/****************************************************************************** +* +* Function: find_IPTC_Resource +* +* Description: Searches an IPTC array for a particular record, and returns it if found +* +* Parameters: IPTC_array - The IPTC array to search +* record_type - The IPTC record number to search for (e.g. 2:151 ) +* +* Returns: output - the contents of the record if found +* FALSE - otherwise +* +******************************************************************************/ + +function find_IPTC_Resource( $IPTC_array, $record_type ) +{ + // Cycle through the ITPC records + foreach ($IPTC_array as $record) + { + // Check the IPTC type against the required type + if ( $record['IPTC_Type'] == $record_type ) + { + // IPTC type matches - return this record + return $record; + } + } + + // No matching record found - return error code + return FALSE; +} + +/****************************************************************************** +* End of Function: find_IPTC_Resource +******************************************************************************/ + + + + +/****************************************************************************** +* +* Function: find_Photoshop_IRB_Resource +* +* Description: Searches a Photoshop IRB array for a particular resource, and returns it if found +* +* Parameters: IRB_array - The IRB array to search +* resource_ID - The IRB resource number to search for (e.g. 0x03F9 ) +* +* Returns: output - the contents of the resource if found +* FALSE - otherwise +* +******************************************************************************/ + +function find_Photoshop_IRB_Resource( $IRB_array, $resource_ID ) +{ + // Cycle through the IRB resources + foreach( $IRB_array as $IRB_Resource ) + { + // Check the IRB resource ID against the required ID + if ( $resource_ID == $IRB_Resource['ResID'] ) + { + // Resource ID matches - return this resource + return $IRB_Resource; + } + } + + // No matching resource found - return error code + return FALSE; +} + +/****************************************************************************** +* End of Function: find_Photoshop_IRB_Resource +******************************************************************************/ + + + + + + + + +/****************************************************************************** +* +* Function: find_XMP_item +* +* Description: Searches a one level of a XMP array for a particular item by name, and returns it if found. +* Does not descend through the XMP array +* +* Parameters: Item_Array - The XMP array to search +* item_name - The name of the tag to serch for (e.g. photoshop:CaptionWriter ) +* +* Returns: output - the contents of the tag if found +* FALSE - otherwise +* +******************************************************************************/ + +function find_XMP_item( & $Item_Array, $item_name ) +{ + // Cycle through the top level of the XMP array + foreach( $Item_Array as $Item_Key => $Item ) + { + // Check this tag name against the required tag name + if( $Item['tag'] == $item_name ) + { + // The tag names match - return the item + return $Item_Array[ $Item_Key ]; + } + } + + // No matching tag found - return error code + return FALSE; +} + +/****************************************************************************** +* End of Function: find_XMP_item +******************************************************************************/ + + + + + +/****************************************************************************** +* +* Function: find_XMP_block +* +* Description: Searches a for a particular rdf:Description block within a XMP array, and returns its children if found. +* +* Parameters: XMP_array - The XMP array to search as returned by read_XMP_array_from_text +* block_name - The namespace of the XMP block to be found (e.g. photoshop or xapRights ) +* +* Returns: output - the children of the tag if found +* FALSE - otherwise +* +******************************************************************************/ + +function find_XMP_block( & $XMP_array, $block_name ) +{ + // Check that the rdf:RDF section can be found (which contains the rdf:Description tags + if ( ( $XMP_array !== FALSE ) && + ( ( $XMP_array[0]['tag'] == "x:xapmeta" ) || + ( $XMP_array[0]['tag'] == "x:xmpmeta" ) ) && + ( $XMP_array[0]['children'][0]['tag'] == "rdf:RDF" ) ) + { + // Found rdf:RDF + // Make it's children easily accessible + $RDF_Contents = $XMP_array[0]['children'][0]['children']; + + // Cycle through the children (rdf:Description tags) + foreach ($RDF_Contents as $RDF_Key => $RDF_Item) + { + // Check if this is a rdf:description tag that has children + if ( ( $RDF_Item['tag'] == "rdf:Description" ) && + ( array_key_exists( 'children', $RDF_Item ) ) ) + { + // RDF Description tag has children, + // Cycle through it's attributes + foreach( $RDF_Item['attributes'] as $key => $val ) + { + // Check if this attribute matches the namespace block name required + if ( $key == "xmlns:$block_name" ) + { + // Namespace matches required block name - return it's children + return $XMP_array[0]['children'][0]['children'][ $RDF_Key ]['children']; + } + } + } + } + } + + // No matching rdf:Description block found + return FALSE; +} + +/****************************************************************************** +* End of Function: find_XMP_block +******************************************************************************/ + + + + + + + + + +/****************************************************************************** +* Global Variable: Blank XMP Structure +* +* Contents: A template XMP array which can be used to create a new XMP segment +* +******************************************************************************/ + +// Create a GUID to be used in this template array +$new_GUID = create_GUID( ); + +$GLOBALS[ 'Blank XMP Structure' ] = +array ( + 0 => + array ( + 'tag' => 'x:xmpmeta', + 'attributes' => + array ( + 'xmlns:x' => 'adobe:ns:meta/', + 'x:xmptk' => 'XMP toolkit 3.0-28, framework 1.6', + ), + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:RDF', + 'attributes' => + array ( + 'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'xmlns:iX' => 'http://ns.adobe.com/iX/1.0/', + ), + 'children' => + array ( + 1 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:pdf' => 'http://ns.adobe.com/pdf/1.3/', + ), + ), + 2 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:photoshop' => 'http://ns.adobe.com/photoshop/1.0/', + ), + 'children' => + array ( + 0 => + array ( + 'tag' => 'photoshop:CaptionWriter', + 'value' => '', + ), + 1 => + array ( + 'tag' => 'photoshop:Category', + 'value' => '', + ), + 2 => + array ( + 'tag' => 'photoshop:DateCreated', + 'value' => '', + ), + 3 => + array ( + 'tag' => 'photoshop:City', + 'value' => '', + ), + 4 => + array ( + 'tag' => 'photoshop:State', + 'value' => '', + ), + 5 => + array ( + 'tag' => 'photoshop:Country', + 'value' => '', + ), + 6 => + array ( + 'tag' => 'photoshop:Credit', + 'value' => '', + ), + 7 => + array ( + 'tag' => 'photoshop:Source', + 'value' => '', + ), + 8 => + array ( + 'tag' => 'photoshop:Headline', + 'value' => '', + ), + 9 => + array ( + 'tag' => 'photoshop:Instructions', + 'value' => '', + ), + 10 => + array ( + 'tag' => 'photoshop:TransmissionReference', + 'value' => '', + ), + 11 => + array ( + 'tag' => 'photoshop:Urgency', + 'value' => '', + ), + 12 => + array ( + 'tag' => 'photoshop:SupplementalCategories', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Bag', + ), + ), + ), + 13 => + array ( + 'tag' => 'photoshop:AuthorsPosition', + 'value' => '', + ), + ), + ), + 4 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:xap' => 'http://ns.adobe.com/xap/1.0/', + ), + 'children' => + array ( + 0 => + array ( + 'tag' => 'xap:CreateDate', + 'value' => '', + ), + 1 => + array ( + 'tag' => 'xap:ModifyDate', + 'value' => '', + ), + 2 => + array ( + 'tag' => 'xap:MetadataDate', + 'value' => '', + ), + 3 => + array ( + 'tag' => 'xap:CreatorTool', + 'value' => '', + ), + ), + ), + 5 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'about' => "uuid:$new_GUID", + 'xmlns:stJob' => 'http://ns.adobe.com/xap/1.0/sType/Job#', + 'xmlns:xapBJ' => 'http://ns.adobe.com/xap/1.0/bj/', + ), + 'children' => + array ( + 0 => + array ( + 'tag' => 'xapBJ:JobRef', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Bag', + 'children' => + array ( + ), + ), + ), + ), + ), + ), + 6 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:xapRights' => 'http://ns.adobe.com/xap/1.0/rights/', + ), + 'children' => + array ( + 1 => + array ( + 'tag' => 'xapRights:WebStatement', + 'value' => '', + ), + ), + ), + 7 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/', + ), + 'children' => + array ( + 0 => + array ( + 'tag' => 'dc:format', + 'value' => 'image/jpeg', + ), + 1 => + array ( + 'tag' => 'dc:title', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Alt', + ), + ), + ), + 2 => + array ( + 'tag' => 'dc:description', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Alt', + ), + ), + ), + 3 => + array ( + 'tag' => 'dc:rights', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Alt', + ), + ), + ), + 4 => + array ( + 'tag' => 'dc:creator', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Seq', + ), + ), + ), + 5 => + array ( + 'tag' => 'dc:subject', + 'children' => + array ( + 0 => + array ( + 'tag' => 'rdf:Bag', + ), + ), + ), + ), + ), + +/* 0 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:exif' => 'http://ns.adobe.com/exif/1.0/', + ), + 'children' => + array ( + +//EXIF DATA GOES HERE - Not Implemented yet + ), + ), +*/ +/* + 2 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:tiff' => 'http://ns.adobe.com/tiff/1.0/', + ), + 'children' => + array ( +// TIFF DATA GOES HERE - Not Implemented yet + 0 => + array ( + 'tag' => 'tiff:Make', + 'value' => 'NIKON CORPORATION', + ), + ), + ), +*/ +/* + 3 => + array ( + 'tag' => 'rdf:Description', + 'attributes' => + array ( + 'rdf:about' => "uuid:$new_GUID", + 'xmlns:stRef' => 'http://ns.adobe.com/xap/1.0/sType/ResourceRef#', + 'xmlns:xapMM' => 'http://ns.adobe.com/xap/1.0/mm/', + ), + 'children' => + array ( +// XAPMM DATA GOES HERE - Not Implemented yet + 0 => + array ( + 'tag' => 'xapMM:DocumentID', + 'value' => 'adobe:docid:photoshop:dceba4c2-e699-11d8-94b2-b6ec48319f2d', + ), + 1 => + array ( + 'tag' => 'xapMM:DerivedFrom', + 'attributes' => + array ( + 'rdf:parseType' => 'Resource', + ), + 'children' => + array ( + 0 => + array ( + 'tag' => 'stRef:documentID', + 'value' => 'adobe:docid:photoshop:5144475b-e698-11d8-94b2-b6ec48319f2d', + ), + 1 => + array ( + 'tag' => 'stRef:instanceID', + 'value' => "uuid:$new_GUID", + ), + ), + ), + ), + ), +*/ + + ), + ), + ), + ), +); + + + +/****************************************************************************** +* End of Global Variable: Blank XMP Structure +******************************************************************************/ + + + + + +?> |
