source: extensions/edit_gmaps/admin/include/GPS_File_Info.php @ 9412

Last change on this file since 9412 was 9412, checked in by cljosse, 13 years ago
File size: 77.4 KB
Line 
1<?php
2
3/******************************************************************************
4*
5* Filename:     Photoshop_File_Info.php
6*
7* Description:  Provides functions that mimic the way Photoshop reads and writes
8*               metadata in it's 'File Info' dialog
9*
10* Author:      Evan Hunter
11*
12* Date:         11/11/2004
13*
14* Project:      JPEG Metadata
15*
16* Revision:     1.11
17* Changes:      1.10 -> 1.11 : Changed displayed toolkit version numbers to reference Toolkit_Version.php
18*
19* URL:          http://electronics.ozhiker.com
20*
21* License:      This file is part of the PHP JPEG Metadata Toolkit.
22*
23*               The PHP JPEG Metadata Toolkit is free software; you can
24*               redistribute it and/or modify it under the terms of the
25*               GNU General Public License as published by the Free Software
26*               Foundation; either version 2 of the License, or (at your
27*               option) any later version.
28*
29*               The PHP JPEG Metadata Toolkit is distributed in the hope
30*               that it will be useful, but WITHOUT ANY WARRANTY; without
31*               even the implied warranty of MERCHANTABILITY or FITNESS
32*               FOR A PARTICULAR PURPOSE.  See the GNU General Public License
33*               for more details.
34*
35*               You should have received a copy of the GNU General Public
36*               License along with the PHP JPEG Metadata Toolkit; if not,
37*               write to the Free Software Foundation, Inc., 59 Temple
38*               Place, Suite 330, Boston, MA  02111-1307  USA
39*
40*               If you require a different license for commercial or other
41*               purposes, please contact the author: evan@ozhiker.com
42*
43******************************************************************************/
44
45// TODO: XMP sections: XAPMM, TIFF, EXIF
46
47
48include 'Toolkit_Version.php';          // Change: added as of version 1.11
49
50
51/******************************************************************************
52* Global Variable:      Software Name
53*
54* Contents:     The string that is appended to fields which store the name of
55*               the software editor.
56*
57******************************************************************************/
58
59$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
60
61/******************************************************************************
62* End of Global Variable:     Software Name
63******************************************************************************/
64
65
66
67
68
69
70/******************************************************************************
71*
72* Function:     get_photoshop_file_info
73*
74* Description:  Retrieves Photoshop 'File Info' metadata in the same way that Photoshop
75*               does. The results are returned in an array as below:
76*
77*               $file_info_array = array(
78*                       "title"                  => "",
79*                       "author"                 => "",
80*                       "authorsposition"        => "",      // Note: Not used in Photoshop 7 or higher
81*                       "caption"                => "",
82*                       "captionwriter"          => "",
83*                       "jobname"                => "",      // Note: Not used in Photoshop CS
84*                       "copyrightstatus"        => "",
85*                       "copyrightnotice"        => "",
86*                       "ownerurl"               => "",
87*                       "keywords"               => array( 0 => "", 1 => "", ... ),
88*                       "category"               => "",     // Note: Max 3 characters
89*                       "supplementalcategories" => array( 0 => "", 1 => "", ... ),
90*                       "date"                   => "",     // Note: DATE MUST BE IN YYYY-MM-DD format
91*                       "city"                   => "",
92*                       "state"                  => "",
93*                       "country"                => "",
94*                       "credit"                 => "",
95*                       "source"                 => "",
96*                       "headline"               => "",
97*                       "instructions"           => "",
98*                       "transmissionreference"  => "",
99*                       "urgency"                => "" );
100*
101* Parameters:   Exif_array - an array containing the EXIF information to be
102*                            searched, as retrieved by get_EXIF_JPEG. (saves having to parse the EXIF again)
103*               XMP_array - an array containing the XMP information to be
104*                           searched, as retrieved by read_XMP_array_from_text. (saves having to parse the XMP again)
105*               IRB_array - an array containing the Photoshop IRB information
106*                           to be searched, as retrieved by get_Photoshop_IRB. (saves having to parse the IRB again)
107*
108* Returns:      outputarray - an array as above, containing the Photoshop File Info data
109*
110******************************************************************************/
111include_once INCLUDE_PATH.'fonctions.php';
112
113function get_photoshop_file_info( $Exif_array, $XMP_array, $IRB_array )
114{
115
116        // Create a blank array to receive the output
117        $outputarray = array(
118                 "GPSLatitudeRef" => "",
119                 "GPSLatitude"=> "",
120                 "GPSLongitudeRef" => "", 
121                 "GPSLongitude" => "",
122                 "GPSAltitude" => "",
123                 "GPSAltitudeRef" => "",
124 );
125
126        /***************************************/
127
128        // XMP Processing
129
130
131        // Retrieve the dublin core section from the XMP header
132
133        // Extract the Dublin Core section from the XMP
134        $dublincore_block = find_XMP_block( $XMP_array, "dc" );
135
136        // Check that the Dublin Core section exists
137        if ( $dublincore_block != FALSE )
138        {
139                // Dublin Core Description Field contains caption
140                // Extract Description
141                $Item = find_XMP_item( $dublincore_block, "dc:description" );
142
143                // Check if Description Tag existed
144                if ( $Item != FALSE )
145                {
146                        // Ensure that the Description value exists and save it.
147                        if  ( ( array_key_exists( 'children', $Item ) ) &&
148                              ( $Item['children'][0]['tag'] == "rdf:Alt" ) &&
149                              ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) )
150                        {
151                                $outputarray = add_to_field( $outputarray, 'caption' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "\n" );
152                        }
153                }
154
155                /***************************************/
156
157                // Dublin Core Creator Field contains author
158                // Extract Description
159                $Item = find_XMP_item( $dublincore_block, "dc:creator" );
160
161                // Check if Creator Tag existed
162                if ( $Item != FALSE )
163                {
164                        // Ensure that the Creator value exists and save it.
165                        if  ( ( array_key_exists( 'children', $Item ) ) &&
166                              ( $Item['children'][0]['tag'] =="rdf:Seq" ) &&
167                              ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) )
168                        {
169                                $outputarray = add_to_field( $outputarray, 'author' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "\n" );
170                        }
171                }
172
173                /***************************************/
174
175                // Dublin Core Title Field contains title
176                // Extract Title
177                $Item = find_XMP_item( $dublincore_block, "dc:title" );
178
179                // Check if Title Tag existed
180                if ( $Item != FALSE )
181                {
182                        // Ensure that the Title value exists and save it.
183                        if  ( ( array_key_exists( 'children', $Item ) ) &&
184                              ( $Item['children'][0]['tag'] =="rdf:Alt" ) &&
185                              ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) )
186                        {
187
188                                $outputarray = add_to_field( $outputarray, 'title' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "," );
189                        }
190                }
191
192                /***************************************/
193
194                // Dublin Core Rights Field contains copyrightnotice
195                // Extract Rights
196                $Item = find_XMP_item( $dublincore_block, "dc:rights" );
197
198                // Check if Rights Tag existed
199                if ( $Item != FALSE )
200                {
201                        // Ensure that the Rights value exists and save it.
202                        if  ( ( array_key_exists( 'children', $Item ) ) &&
203                              ( $Item['children'][0]['tag'] =="rdf:Alt" ) &&
204                              ( array_key_exists( 'value', $Item['children'][0]['children'][0] ) ) )
205                        {
206
207                                $outputarray = add_to_field( $outputarray, 'copyrightnotice' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['value'] ), "," );
208                        }
209                }
210
211                /***************************************/
212
213                // Dublin Core Subject Field contains keywords
214                // Extract Subject
215                $Item = find_XMP_item( $dublincore_block, "dc:subject" );
216
217                // Check if Subject Tag existed
218                if ( $Item != FALSE )
219                {
220                        // Ensure that the Subject values exist
221                        if  ( ( array_key_exists( 'children', $Item ) ) && ( $Item['children'][0]['tag'] =="rdf:Bag" ) )
222                        {
223                                // Cycle through each Subject value and save them
224                                foreach ( $Item['children'][0]['children'] as $keywords )
225                                {
226                                        if ( ! in_array ( HTML_UTF8_Escape( $keywords['value'] ), $outputarray['keywords']))
227                                        {
228                                                if  ( array_key_exists( 'value', $keywords ) )
229                                                {
230                                                        $outputarray['keywords'][] = HTML_UTF8_Escape( $keywords['value'] );
231                                                }
232                                        }
233                                }
234                        }
235                }
236
237
238        }
239
240        /***************************************/
241
242        // Find the Photoshop Information within the XMP block
243        $photoshop_block = find_XMP_block( $XMP_array, "photoshop" );
244
245        // Check that the Photoshop Information exists
246        if ( $photoshop_block != FALSE )
247        {
248                // The Photoshop CaptionWriter tag contains captionwriter - Find it
249                $Item = find_XMP_item( $photoshop_block, "photoshop:CaptionWriter" );
250
251                // Check that the CaptionWriter Field exists and save the value
252                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
253                {
254                        $outputarray = add_to_field( $outputarray, 'captionwriter' , HTML_UTF8_Escape( $Item['value'] ), "," );
255                }
256
257                /***************************************/
258
259                // The Photoshop Headline tag contains headline - Find it
260                $Item = find_XMP_item( $photoshop_block, "photoshop:Headline" );
261
262                // Check that the Headline Field exists and save the value
263                if ( ( $Item != FALSE )  && ( array_key_exists( 'value', $Item ) ) )
264                {
265                        $outputarray = add_to_field( $outputarray, 'headline' , HTML_UTF8_Escape( $Item['value'] ), "," );
266                }
267
268                /***************************************/
269
270                // The Photoshop Instructions tag contains instructions - Find it
271                $Item = find_XMP_item( $photoshop_block, "photoshop:Instructions" );
272
273                // Check that the Instructions Field exists and save the value
274                if ( ( $Item != FALSE )  && ( array_key_exists( 'value', $Item ) ) )
275                {
276                        $outputarray = add_to_field( $outputarray, 'instructions' , HTML_UTF8_Escape( $Item['value'] ), "\n" );
277                }
278
279                /***************************************/
280
281                // The Photoshop AuthorsPosition tag contains authorsposition - Find it
282                $Item = find_XMP_item( $photoshop_block, "photoshop:AuthorsPosition" );
283
284                // Check that the AuthorsPosition Field exists and save the value
285                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
286                {
287                        $outputarray = add_to_field( $outputarray, 'authorsposition' , HTML_UTF8_Escape( $Item['value'] ), "," );
288                }
289
290                /***************************************/
291
292                // The Photoshop Credit tag contains credit - Find it
293                $Item = find_XMP_item( $photoshop_block, "photoshop:Credit" );
294
295                // Check that the Credit Field exists and save the value
296                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
297                {
298                        $outputarray = add_to_field( $outputarray, 'credit' , HTML_UTF8_Escape( $Item['value'] ), "," );
299                }
300
301                /***************************************/
302
303                // The Photoshop Source tag contains source - Find it
304                $Item = find_XMP_item( $photoshop_block, "photoshop:Source" );
305
306                // Check that the Credit Field exists and save the value
307                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
308                {
309                        $outputarray = add_to_field( $outputarray, 'source' , HTML_UTF8_Escape( $Item['value'] ), "," );
310                }
311
312                /***************************************/
313
314                // The Photoshop City tag contains city - Find it
315                $Item = find_XMP_item( $photoshop_block, "photoshop:City" );
316
317                // Check that the City Field exists and save the value
318                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
319                {
320                        $outputarray = add_to_field( $outputarray, 'city' , HTML_UTF8_Escape( $Item['value'] ), "," );
321                }
322
323                /***************************************/
324
325                // The Photoshop State tag contains state - Find it
326                $Item = find_XMP_item( $photoshop_block, "photoshop:State" );
327
328                // Check that the State Field exists and save the value
329                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
330                {
331                        $outputarray = add_to_field( $outputarray, 'state' , HTML_UTF8_Escape( $Item['value'] ), "," );
332                }
333
334                /***************************************/
335
336                // The Photoshop Country tag contains country - Find it
337                $Item = find_XMP_item( $photoshop_block, "photoshop:Country" );
338
339                // Check that the Country Field exists and save the value
340                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
341                {
342                        $outputarray = add_to_field( $outputarray, 'country' , HTML_UTF8_Escape( $Item['value'] ), "," );
343                }
344
345                /***************************************/
346
347                // The Photoshop TransmissionReference tag contains transmissionreference - Find it
348                $Item = find_XMP_item( $photoshop_block, "photoshop:TransmissionReference" );
349
350                // Check that the TransmissionReference Field exists and save the value
351                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
352                {
353                        $outputarray = add_to_field( $outputarray, 'transmissionreference' , HTML_UTF8_Escape( $Item['value'] ), "," );
354                }
355
356                /***************************************/
357
358                // The Photoshop Category tag contains category - Find it
359                $Item = find_XMP_item( $photoshop_block, "photoshop:Category" );
360
361                // Check that the TransmissionReference Field exists and save the value
362                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
363                {
364                        $outputarray = add_to_field( $outputarray, 'category' , HTML_UTF8_Escape( $Item['value'] ), "," );
365                }
366
367                /***************************************/
368
369                // The Photoshop DateCreated tag contains date - Find it
370                $Item = find_XMP_item( $photoshop_block, "photoshop:DateCreated" );
371
372                // Check that the DateCreated Field exists and save the value
373                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
374                {
375                        $outputarray = add_to_field( $outputarray, 'date' , HTML_UTF8_Escape( $Item['value'] ), "," );
376                }
377
378                /***************************************/
379
380                // The Photoshop Urgency tag contains urgency - Find it
381                $Item = find_XMP_item( $photoshop_block, "photoshop:Urgency" );
382
383                // Check that the Urgency Field exists and save the value
384                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
385                {
386                        $outputarray = add_to_field( $outputarray, 'urgency' , HTML_UTF8_Escape( $Item['value'] ), "," );
387                }
388
389                /***************************************/
390
391                // The Photoshop SupplementalCategories tag contains supplementalcategories - Find it
392                $Item = find_XMP_item( $photoshop_block, "photoshop:SupplementalCategories" );
393
394                // Check that the SupplementalCategories Field exists
395                if ( $Item != FALSE )
396                {
397                        // Check that the values exist
398                        if  ( ( array_key_exists( 'children', $Item ) ) && ( $Item['children'][0]['tag'] =="rdf:Bag" ) )
399                        {
400                                // Cycle through the values and save them
401                                foreach ( $Item['children'][0]['children'] as $sup_category )
402                                {
403                                        if ( ( array_key_exists( 'value', $sup_category ) ) &&
404                                             ( ! in_array ( HTML_UTF8_Escape( $sup_category['value'] ), $outputarray['supplementalcategories'])) )
405                                        {
406                                                if ( array_key_exists( 'value', $sup_category ) )
407                                                {
408                                                        $outputarray['supplementalcategories'][] = HTML_UTF8_Escape( $sup_category['value'] );
409                                                }
410                                        }
411                                }
412                        }
413                }
414
415        }
416
417        /***************************************/
418
419        // Find the Job Reference Information within the XMP block
420        $job_block = find_XMP_block( $XMP_array, "xapBJ" );
421
422        // Check that the Job Reference Information exists
423        if ( $job_block != FALSE )
424        {
425                // The JobRef Field contains jobname - Find it
426                $Item = find_XMP_item( $job_block, "xapBJ:JobRef" );
427
428                // Check that the JobRef Field exists
429                if ( $Item != FALSE )
430                {
431                        // Check that the value exists and save it
432                        if ( ( array_key_exists( 'children', $Item ) ) &&
433                             ( $Item['children'][0]['tag'] =="rdf:Bag" ) &&
434                             ( array_key_exists( 'children', $Item['children'][0] ) ) &&
435                             ( $Item['children'][0]['children'][0]['tag'] =="rdf:li" ) &&
436                             ( array_key_exists( 'children', $Item['children'][0]['children'][0] ) ) &&
437                             ( $Item['children'][0]['children'][0]['children'][0]['tag'] =="stJob:name" ) &&
438                             ( array_key_exists( 'value', $Item['children'][0]['children'][0]['children'][0] ) ) )
439                        {
440                                $outputarray = add_to_field( $outputarray, 'jobname' , HTML_UTF8_Escape( $Item['children'][0]['children'][0]['children'][0]['value'] ), "," );
441                        }
442                }
443        }
444
445
446        /***************************************/
447
448        // Find the Rights Information within the XMP block
449        $rights_block = find_XMP_block( $XMP_array, "xapRights" );
450
451        // Check that the Rights Information exists
452        if ( $rights_block != FALSE )
453        {
454                // The WebStatement Field contains ownerurl - Find it
455                $Item = find_XMP_item( $rights_block, "xapRights:WebStatement" );
456
457                // Check that the WebStatement Field exists and save the value
458                if ( ( $Item != FALSE )  && ( array_key_exists( 'value', $Item ) ) )
459                {
460                        $outputarray = add_to_field( $outputarray, 'ownerurl' , HTML_UTF8_Escape( $Item['value'] ), "\n" );
461                }
462
463                /***************************************/
464
465                // The Marked Field contains copyrightstatus - Find it
466                $Item = find_XMP_item( $rights_block, "xapRights:Marked" );
467
468                // Check that the Marked Field exists and save the value
469                if ( ( $Item != FALSE ) && ( array_key_exists( 'value', $Item ) ) )
470                {
471                        if ( $Item['value'] == "True" )
472                        {
473                                $outputarray = add_to_field( $outputarray, 'copyrightstatus' , "Copyrighted Work", "," );
474                        }
475                        else
476                        {
477                                $outputarray = add_to_field( $outputarray, 'copyrightstatus' , "Public Domain", "," );
478                        }
479                }
480
481        }
482
483
484
485
486
487        /***************************************/
488
489        // Photoshop IRB Processing
490
491        // Check that the Photoshop IRB exists
492        if ( $IRB_array != FALSE )
493        {
494                // Create a translation table to convert carriage returns to linefeeds
495                $irbtrans = array("\x0d" => "\x0a");
496
497                // The Photoshop IRB Copyright flag (0x040A) contains copyrightstatus - find it
498                $IRB_copyright_flag = find_Photoshop_IRB_Resource( $IRB_array, 0x040A );
499
500                // Check if the Copyright flag Field exists, and save the value
501                if( $IRB_copyright_flag != FALSE )
502                {
503                        // Check the value of the copyright flag
504                        if ( hexdec( bin2hex( $IRB_copyright_flag['ResData'] ) ) == 1 )
505                        {
506                                // Save the value
507                                $outputarray = add_to_field( $outputarray, 'copyrightstatus' , "Copyrighted Work", "," );
508                        }
509                        else
510                        {
511                                // Do nothing - copyrightstatus will be set to unmarked if still blank at end
512                        }
513                }
514
515                /***************************************/
516
517                // The Photoshop IRB URL (0x040B) contains ownerurl - find it
518                $IRB_url = find_Photoshop_IRB_Resource( $IRB_array, 0x040B );
519
520                // Check if the URL Field exists and save the value
521                if( $IRB_url != FALSE )
522                {
523                        $outputarray = add_to_field( $outputarray, 'ownerurl' , strtr( $IRB_url['ResData'], $irbtrans ), "\n" );
524                }
525
526                /***************************************/
527
528                // Extract any IPTC block from the Photoshop IRB information
529                $IPTC_array = get_Photoshop_IPTC( $IRB_array );
530
531                // Check if the IPTC block exits
532                if ( ( $IPTC_array != FALSE ) && ( count( $IPTC_array ) != 0 ) )
533                {
534                        // The IPTC Caption/Abstract Field contains caption - find it
535                        $record = find_IPTC_Resource( $IPTC_array, "2:120" );
536
537                        // Check if the Caption/Abstract Field exists and save the value
538                        if ( $record != FALSE  )
539                        {
540                                $outputarray = add_to_field( $outputarray, 'caption' , strtr( $record['RecData'], $irbtrans ), "\n" );
541                        }
542
543                        /***************************************/
544
545                        // The IPTC Caption Writer/Editor Field contains captionwriter - find it
546                        $record = find_IPTC_Resource( $IPTC_array, "2:122" );
547
548                        // Check if the Caption Writer/Editor Field exists and save the value
549                        if ( $record != FALSE  )
550                        {
551                                $outputarray = add_to_field( $outputarray, 'captionwriter' , strtr( $record['RecData'], $irbtrans ), "\n" );
552                        }
553
554                        /***************************************/
555
556                        // The IPTC Headline Field contains headline - find it
557                        $record = find_IPTC_Resource( $IPTC_array, "2:105" );
558
559                        // Check if the Headline Field exists and save the value
560                        if ( $record != FALSE  )
561                        {
562                                $outputarray = add_to_field( $outputarray, 'headline' , strtr( $record['RecData'], $irbtrans ), "\n" );
563                        }
564
565                        /***************************************/
566
567                        // The IPTC Special Instructions Field contains instructions - find it
568                        $record = find_IPTC_Resource( $IPTC_array, "2:40" );
569
570                        // Check if the Special Instructions Field exists and save the value
571                        if ( $record != FALSE  )
572                        {
573                                $outputarray = add_to_field( $outputarray, 'instructions' , strtr( $record['RecData'], $irbtrans ), "\n" );
574                        }
575
576                        /***************************************/
577
578                        // The IPTC By-Line Field contains author - find it
579                        $record = find_IPTC_Resource( $IPTC_array, "2:80" );
580
581                        // Check if the By-Line Field exists and save the value
582                        if ( $record != FALSE  )
583                        {
584                                $outputarray = add_to_field( $outputarray, 'author' , strtr( $record['RecData'], $irbtrans ), "\n" );
585                        }
586
587                        /***************************************/
588
589                        // The IPTC By-Line Title Field contains authorsposition - find it
590                        $record = find_IPTC_Resource( $IPTC_array, "2:85" );
591
592                        // Check if the By-Line Title Field exists and save the value
593                        if ( $record != FALSE  )
594                        {
595                                $outputarray = add_to_field( $outputarray, 'authorsposition' , strtr( $record['RecData'], $irbtrans ), "\n" );
596                        }
597
598                        /***************************************/
599
600                        // The IPTC Credit Field contains credit - find it
601                        $record = find_IPTC_Resource( $IPTC_array, "2:110" );
602
603                        // Check if the Credit Field exists and save the value
604                        if ( $record != FALSE  )
605                        {
606                                $outputarray = add_to_field( $outputarray, 'credit' , strtr( $record['RecData'], $irbtrans ), "\n" );
607                        }
608
609                        /***************************************/
610
611                        // The IPTC Source Field contains source - find it
612                        $record = find_IPTC_Resource( $IPTC_array, "2:115" );
613
614                        // Check if the Source Field exists and save the value
615                        if ( $record != FALSE  )
616                        {
617                                $outputarray = add_to_field( $outputarray, 'source' , strtr( $record['RecData'], $irbtrans ), "\n" );
618                        }
619
620                        /***************************************/
621
622                        // The IPTC Object Name Field contains title - find it
623                        $record = find_IPTC_Resource( $IPTC_array, "2:05" );
624
625                        // Check if the Object Name Field exists and save the value
626                        if ( $record != FALSE  )
627                        {
628                                $outputarray = add_to_field( $outputarray, 'title' , strtr( $record['RecData'], $irbtrans ), "\n" );
629                        }
630
631                        /***************************************/
632
633                        // The IPTC Date Created Field contains date - find it
634                        $record = find_IPTC_Resource( $IPTC_array, "2:55" );
635
636                        // Check if the Date Created Field exists and save the value
637                        if ( $record != FALSE  )
638                        {
639                                $date_array = unpack( "a4Year/a2Month/A2Day", $record['RecData'] );
640                                $tmpdate = $date_array['Year'] . "-" . $date_array['Month'] . "-" . $date_array['Day'];
641                                $outputarray = add_to_field( $outputarray, 'date' , strtr( $tmpdate, $irbtrans ), "," );
642
643                        }
644
645                        /***************************************/
646
647                        // The IPTC City Field contains city - find it
648                        $record = find_IPTC_Resource( $IPTC_array, "2:90" );
649
650                        // Check if the City Field exists and save the value
651                        if ( $record != FALSE  )
652                        {
653                                $outputarray = add_to_field( $outputarray, 'city' , strtr( $record['RecData'], $irbtrans ), "\n" );
654                        }
655
656                        /***************************************/
657
658                        // The IPTC Province/State Field contains state - find it
659                        $record = find_IPTC_Resource( $IPTC_array, "2:95" );
660
661                        // Check if the Province/State Field exists and save the value
662                        if ( $record != FALSE  )
663                        {
664                                $outputarray = add_to_field( $outputarray, 'state' , strtr( $record['RecData'], $irbtrans ), "\n" );
665                        }
666
667                        /***************************************/
668
669                        // The IPTC Country/Primary Location Name Field contains country - find it
670                        $record = find_IPTC_Resource( $IPTC_array, "2:101" );
671
672                        // Check if the Country/Primary Location Name Field exists and save the value
673                        if ( $record != FALSE  )
674                        {
675                                $outputarray = add_to_field( $outputarray, 'country' , strtr( $record['RecData'], $irbtrans ), "\n" );
676                        }
677
678                        /***************************************/
679
680                        // The IPTC Original Transmission Reference Field contains transmissionreference - find it
681                        $record = find_IPTC_Resource( $IPTC_array, "2:103" );
682
683                        // Check if the Original Transmission Reference Field exists and save the value
684                        if ( $record != FALSE  )
685                        {
686                                $outputarray = add_to_field( $outputarray, 'transmissionreference' , strtr( $record['RecData'], $irbtrans ), "\n" );
687                        }
688
689                        /***************************************/
690
691                        // The IPTC Category Field contains category - find it
692                        $record = find_IPTC_Resource( $IPTC_array, "2:15" );
693
694                        // Check if the Category Field exists and save the value
695                        if ( $record != FALSE  )
696                        {
697                                $outputarray = add_to_field( $outputarray, 'category' , strtr( $record['RecData'], $irbtrans ), "\n" );
698                        }
699
700
701                        /***************************************/
702
703                        // Cycle through the IPTC records looking for Supplemental Category records
704                        foreach ($IPTC_array as $record)
705                        {
706                                // Check if a Supplemental Category record has been found
707                                if ( $record['IPTC_Type'] == "2:20" )
708                                {
709                                        // A Supplemental Category record has been found, save it's value if the value doesn't already exist
710                                        if ( ! in_array ( $record['RecData'], $outputarray['supplementalcategories']))
711                                        {
712                                                $outputarray['supplementalcategories'][] = strtr( $record['RecData'], array("\x0a" => "", "\x0d" => "&#xA;") ) ;
713                                        }
714                                }
715                        }
716
717
718                        /***************************************/
719
720                        // The IPTC Urgency Field contains urgency - find it
721                        $record = find_IPTC_Resource( $IPTC_array, "2:10" );
722
723                        // Check if the Urgency Field exists and save the value
724                        if ( $record != FALSE  )
725                        {
726                                $outputarray = add_to_field( $outputarray, 'urgency' , strtr( $record['RecData'], $irbtrans ), "\n" );
727                        }
728
729
730
731                        /***************************************/
732
733                        // Cycle through the IPTC records looking for Keywords records
734                        foreach ($IPTC_array as $record)
735                        {
736                                // Check if a Keywords record has been found
737                                if ( $record['IPTC_Type'] == "2:25" )
738                                {
739                                        // A Keywords record has been found, save it's value if the value doesn't already exist
740                                        if ( ! in_array ( $record['RecData'], $outputarray['keywords']))
741                                        {
742                                                $outputarray['keywords'][] = strtr( $record['RecData'], array("\x0a" => "", "\x0d" => "&#xA;") ) ;
743                                        }
744                                }
745                        }
746
747
748                        /***************************************/
749
750                        // The IPTC Copyright Notice Field contains copyrightnotice - find it
751                        $record = find_IPTC_Resource( $IPTC_array, "2:116" );
752
753                        // Check if the Copyright Field exists and save the value
754                        if ( $record != FALSE  )
755                        {
756                                $outputarray = add_to_field( $outputarray, 'copyrightnotice' , strtr( $record['RecData'], $irbtrans ), "\n" );
757                        }
758
759                }
760        }
761
762
763
764
765        /***************************************/
766
767        // EXIF Processing
768
769
770        // Retreive Information from the EXIF data if it exists
771
772        if ( ( $Exif_array != FALSE ) || ( count( $Exif_array ) == 0 ) )
773        {
774                // Check the Image Description Tag - it can contain the caption
775                if ( array_key_exists( 270, $Exif_array[0] ) )
776                {
777                        $outputarray = add_to_field( $outputarray, 'caption' , $Exif_array[0][270]['Data'][0], "\n" );
778                }
779
780                /***************************************/
781
782                // Check the Copyright Information Tag - it contains the copyrightnotice
783                if ( array_key_exists( 33432, $Exif_array[0] ) )
784                {
785                        $outputarray = add_to_field( $outputarray, 'copyrightnotice' , HTML_UTF8_UnEscape( $Exif_array[0][33432]['Data'][0] ), "\n" );
786                }
787
788                /***************************************/
789
790                // Check the Artist Name Tag - it contains the author
791                if ( array_key_exists( 315, $Exif_array[0] ) )
792                {
793                        $outputarray = add_to_field( $outputarray, 'author' , HTML_UTF8_UnEscape( $Exif_array[0][315]['Data'][0] ), "\n" );
794                } 
795                /***************************************************/
796
797                if ( array_key_exists( 34853, $Exif_array[0] )  ) {
798
799
800                 // Tag "GPS" found - use it for the default GPS $outputarray = add_to_field(
801                    $outputarray = add_to_field( $outputarray, 'GPSLongitudeRef' , HTML_UTF8_UnEscape(  $Exif_array[0][34853]['Data'][0][1]['Text Value']), "\n" );
802
803                    $outputarray = add_to_field( $outputarray, 'GPSLongitude' , HTML_UTF8_UnEscape( $Exif_array[0][34853]['Data'][0][2]['Text Value']), "\n" );
804                    $outputarray = add_to_field( $outputarray, 'GPSLatitudeRef' , HTML_UTF8_UnEscape( $Exif_array[0][34853]['Data'][0][3]['Text Value']), "\n" );
805                    $outputarray = add_to_field( $outputarray, 'GPSLatitude' , HTML_UTF8_UnEscape( $Exif_array[0][34853]['Data'][0][4]['Text Value']), "\n" );
806                    $outputarray = add_to_field( $outputarray, 'GPSAltitudeRef' , HTML_UTF8_UnEscape( $Exif_array[0][34853]['Data'][0][5]['Text Value']), "\n" );
807                    $outputarray = add_to_field( $outputarray, 'GPSAltitude' , HTML_UTF8_UnEscape( $Exif_array[0][34853]['Data'][0][6]['Text Value']), "\n" );
808
809                } 
810               
811           } 
812
813
814        /***************************/
815
816        // FINISHED RETRIEVING INFORMATION
817
818        // Perform final processing
819
820
821        // Check if any urgency information was found
822        if ( $outputarray["urgency"] == "" )
823        {
824                // No urgency information was found - set it to default (None)
825                $outputarray["urgency"] = "none";
826        }
827
828        // Check if any copyrightstatus information was found
829        if ( $outputarray["copyrightstatus"] == "" )
830        {
831                // No copyrightstatus information was found - set it to default (Unmarked)
832                $outputarray["copyrightstatus"] = "unmarked";
833        }
834
835        // Return the resulting Photoshop File Info Array
836        return $outputarray;
837
838}
839
840/******************************************************************************
841* End of Function:     get_photoshop_file_info
842******************************************************************************/
843
844
845
846
847
848
849/******************************************************************************
850*
851* Function:     put_photoshop_file_info
852*
853* Description:  Stores Photoshop 'File Info' metadata in the same way that Photoshop
854*               does. The 'File Info' metadata must be in an array similar to that
855*               returned by get_photoshop_file_info, as follows:
856*
857*               $file_info_array = array(
858*                       "title"                  => "",
859*                       "author"                 => "",
860*                       "authorsposition"        => "",      // Note: Not used in Photoshop 7 or higher
861*                       "caption"                => "",
862*                       "captionwriter"          => "",
863*                       "jobname"                => "",      // Note: Not used in Photoshop CS
864*                       "copyrightstatus"        => "",
865*                       "copyrightnotice"        => "",
866*                       "ownerurl"               => "",
867*                       "keywords"               => array( 0 => "", 1 => "", ... ),
868*                       "category"               => "",     // Note: Max 3 characters
869*                        "supplementalcategories" => array( 0 => "", 1 => "", ... ),
870*                       "date"                   => "",     // Note: DATE MUST BE IN YYYY-MM-DD format
871*                       "city"                   => "",
872*                       "state"                  => "",
873*                       "country"                => "",
874*                       "credit"                 => "",
875*                       "source"                 => "",
876*                       "headline"               => "",
877*                       "instructions"           => "",
878*                       "transmissionreference"  => "",
879*                       "urgency"                => "" );
880*
881* Parameters:   jpeg_header_data - a JPEG header data array in the same format
882*                                  as from get_jpeg_header_data. This contains the
883*                                  header information which is to be updated.
884*               new_ps_file_info_array - An array as above, which contains the
885*                                        'File Info' metadata information to be
886*                                        written.
887*               Old_Exif_array - an array containing the EXIF information to be
888*                                updated, as retrieved by get_EXIF_JPEG. (saves having to parse the EXIF again)
889*               Old_XMP_array - an array containing the XMP information to be
890*                               updated, as retrieved by read_XMP_array_from_text. (saves having to parse the XMP again)
891*               Old_IRB_array - an array containing the Photoshop IRB information
892*                                to be updated, as retrieved by get_Photoshop_IRB. (saves having to parse the IRB again)
893*
894* Returns:      jpeg_header_data - a JPEG header data array in the same format
895*                                  as from get_jpeg_header_data, containing the
896*                                  Photshop 'File Info' metadata. This can then
897*                                  be written to a file using put_jpeg_header_data.
898*
899******************************************************************************/
900
901function put_GPS_file_info( $jpeg_header_data, $new_ps_file_info_array, $Old_Exif_array, $Old_XMP_array, $Old_IRB_array )
902{
903        /*******************************************/
904
905        // EXIF Processing
906
907
908        // Check if the EXIF array exists
909        if( $Old_Exif_array == FALSE )
910        {
911                // EXIF Array doesn't exist - create a new one
912                $new_Exif_array = array (       'Byte_Align' => "MM",
913                                                'Makernote_Tag' => false,
914                                                'Tags Name' => "TIFF",
915                                                 0 => array( "Tags Name" => "TIFF" ) );
916        }
917        else
918        {
919                // EXIF Array Does Exist - use it
920                $new_Exif_array = $Old_Exif_array;
921        }
922
923       
924     
925        /******************* GPS ***************/
926   $Exif_array=  $Old_Exif_array ;     
927   $new_exif=$new_ps_file_info_array;   
928   
929         $exist=array_key_exists( 34853,  $new_Exif_array[0] )  ;
930        //print_r($new_exif) ;
931            // Update
932  $val= explode(" ",$new_exif['latDMS']); 
933 for (  $i=0;$i<3;$i++)
934      {
935        $v2= explode("/",$val[$i]); 
936        $datlat[$i]['Numerator']= HTML_UTF8_Escape( $v2[0]) ;
937        $datlat[$i]['Denominator']= HTML_UTF8_Escape( $v2[1]) ;
938     }
939
940  $val= explode(" ",$new_exif['lonDMS']); 
941 for (  $i=0;$i<3;$i++)
942      {
943        $v2= explode("/",$val[$i]); 
944        $datlon[$i]['Numerator']= HTML_UTF8_Escape( $v2[0]) ;
945        $datlon[$i]['Denominator']= HTML_UTF8_Escape( $v2[1] );
946     }
947
948        $v2= explode("/",$new_exif['altDMS']); 
949        $datalt['Numerator']= HTML_UTF8_Escape( $v2[0] );
950        $datalt['Denominator']= HTML_UTF8_Escape( $v2[1]) ;
951
952    $Data_Type=array( 1,2,5,2,5,1,5) ;
953
954    $mesdata=array( 
955                   array(2,2,0,0),
956                   array($new_exif['latRef']) ,
957                   $datlat,
958                    array($new_exif['lonRef']) ,
959                    $datlon,
960                    array($new_exif['altRef']) ,
961                    array($datalt)
962                   );
963
964  $textvalues=array( 
965                   array(2,2,0,0),
966                   array($new_exif['latRef']) ,
967                   $datlat,
968                    array($new_exif['lonRef']) ,
969                    $datlon,
970                    array($new_exif['altRef']) ,
971                    array($datalt)
972                   );     
973                 
974$gps_blocks=    array("Tags Name" =>  $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 34853 ]['Tags Name'], 
975                                   "Tiff Offset" => "30");
976                 
977            for($i=0;$i<7;$i++)
978                   {   
979                    $gps_blocks[$i]= array (       
980                                "Tag Number" => $i,
981                                "Tag Name"   => $GLOBALS[ "IFD_Tag_Definitions" ][ 'GPS' ][$i]['Name'],
982                                "Tag Description"   => "",
983                                "Data Type"  => $Data_Type[$i], 
984                                "Type"       => $GLOBALS[ "IFD_Tag_Definitions" ][ 'GPS' ][$i]['Type'],
985                                "Units" => isset($GLOBALS[ "IFD_Tag_Definitions" ][ 'GPS' ][$i]['Units'])?$GLOBALS[ "IFD_Tag_Definitions" ][ 'GPS' ][$i]['Units']: "",
986                                                       
987                                "Data"       =>    $mesdata[$i]  ,
988                                "Text Value" => isset($GLOBALS[ "IFD_Tag_Definitions" ][ 'GPS' ][$i]['0'])?$GLOBALS[ "IFD_Tag_Definitions" ][ 'GPS' ][$i]['0']:"",
989                                "Decoded" => 1
990                              );
991  }       
992                 
993        $new_Exif_array[0][34853] = array( 
994                                            "Tag Number" => 34853,
995                                            "Tag Name"   => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 34853 ]['Name'],
996                                            "Tag Description"   => "",
997                                            "Data Type"  => 4,
998                                            "Type"       => $GLOBALS[ "IFD_Tag_Definitions" ]['TIFF'][ 34853 ]['Type'] ,
999                                            "Units" => "",
1000                                             "Data"       => 
1001                                                               array($gps_blocks) ,                                   
1002                                                               
1003                                                "Text Value" => "",
1004                                                "Decoded" => 1
1005                                             
1006                                              )  ;
1007                                   
1008
1009
1010/**/
1011
1012
1013
1014        /*******************************************/
1015
1016        // Photoshop IRB Processing
1017
1018
1019        // Check if there is an existing Photoshop IRB array
1020        if ($Old_IRB_array == FALSE )
1021        {
1022                // No existing IRB array - create one
1023                $new_IRB_array = array();
1024        }
1025        else
1026        {
1027                // There is an existing Photoshop IRB array - use it
1028                $new_IRB_array = $Old_IRB_array;
1029        }
1030
1031   
1032        /***********************************/
1033
1034        // XMP Processing
1035
1036        // Check if XMP existed previously
1037        if ($Old_XMP_array == FALSE )
1038        {
1039                // XMP didn't exist - create a new one based on a blank structure
1040                $new_XMP_array = XMP_Check( $GLOBALS[ 'Blank XMP Structure' ], array( ) );
1041        }
1042        else
1043        {
1044                // XMP does exist
1045                // Some old XMP processors used x:xapmeta, check for this
1046                if ( $Old_XMP_array[0]['tag'] == 'x:xapmeta' )
1047                {
1048                        // x:xapmeta found - change it to x:xmpmeta
1049                        $Old_XMP_array[0]['tag'] = 'x:xmpmeta';
1050                }
1051
1052                // Ensure that the existing XMP has all required fields, and add any that are missing
1053                $new_XMP_array = XMP_Check( $GLOBALS[ 'Blank XMP Structure' ], $Old_XMP_array );
1054        }
1055
1056
1057
1058
1059
1060        /***************************************/
1061
1062        // FINISHED UPDATING VALUES
1063
1064        // Insert the new IPTC array into the Photoshop IRB array
1065       // $new_IRB_array = put_Photoshop_IPTC( $new_IRB_array, $new_IPTC_array );
1066
1067        // Write the EXIF array to the JPEG header
1068        $jpeg_header_data = put_EXIF_JPEG( $new_Exif_array, $jpeg_header_data );
1069
1070        // Convert the XMP array to XMP text
1071        $xmp_text = write_XMP_array_to_text( $new_XMP_array );
1072
1073        // Write the XMP text to the JPEG Header
1074        $jpeg_header_data = put_XMP_text( $jpeg_header_data, $xmp_text );
1075
1076        // Write the Photoshop IRB array to the JPEG header
1077        $jpeg_header_data = put_Photoshop_IRB( $jpeg_header_data, $new_IRB_array );
1078
1079        return $jpeg_header_data;
1080
1081}
1082
1083/******************************************************************************
1084* End of Function:     put_photoshop_file_info
1085******************************************************************************/
1086
1087
1088
1089
1090/******************************************************************************
1091*
1092*         INTERNAL FUNCTIONS
1093*
1094******************************************************************************/
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129/******************************************************************************
1130*
1131* Function:     get_Local_Timezone_Offset
1132*
1133* Description:  Returns a string indicating the time difference between the local
1134*               timezone and GMT in hours and minutes, e.g.  +10:00 or -06:30
1135*
1136* Parameters:   None
1137*
1138* Returns:      $tz_str - a string containing the timezone offset
1139*
1140******************************************************************************/
1141
1142function get_Local_Timezone_Offset( )
1143{
1144        // Retrieve the Timezone offset in seconds
1145        $tz_seconds = date( "Z" );
1146
1147        // Check if the offset is less than zero
1148        if ( $tz_seconds < 0 )
1149        {
1150                // Offset is less than zero - add a Minus sign to the output
1151                $tz_str = "-";
1152        }
1153        else
1154        {
1155                // Offset is greater than or equal to zero - add a Plus sign to the output
1156                $tz_str = "+";
1157        }
1158
1159        // Add the absolute offset to the output, formatted as HH:MM
1160        $tz_str .= gmdate( "H:i", abs($tz_seconds) );
1161
1162        // Return the result
1163        return $tz_str;
1164}
1165
1166/******************************************************************************
1167* End of Function:     get_Local_Timezone_Offset
1168******************************************************************************/
1169
1170
1171
1172/******************************************************************************
1173*
1174* Function:     XMP_Check
1175*
1176* Description:  Checks a given XMP array against a reference array, and adds any
1177*               missing blocks and tags
1178*
1179*               NOTE: This is a recursive function
1180*
1181* Parameters:   reference_array - The standard XMP array which contains all required tags
1182*               check_array - The XMP array to check
1183*
1184* Returns:      output - a string containing the timezone offset
1185*
1186******************************************************************************/
1187
1188function XMP_Check( $reference_array, $check_array)
1189{
1190        // Cycle through each of the elements of the reference XMP array
1191        foreach( $reference_array as $valkey => $val )
1192        {
1193
1194                // Search for the current reference tag within the XMP array to be checked
1195                $tagpos = find_XMP_Tag( $check_array,  $val );
1196
1197                // Check if the tag was found
1198                if ( $tagpos === FALSE )
1199                {
1200                        // Tag not found - Add tag to array being checked
1201                        $tagpos = count( $check_array );
1202                        $check_array[ $tagpos ] = $val;
1203                }
1204
1205                // Check if the reference tag has children
1206                if ( array_key_exists( 'children', $val ) )
1207                {
1208                        // Reference tag has children - these need to be checked too
1209
1210                        // Determine if the array being checked has children for this tag
1211                        if ( ! array_key_exists( 'children', $check_array[ $tagpos ] ) )
1212                        {
1213                                // Array being checked has no children - add a blank children array
1214                                $check_array[ $tagpos ][ 'children' ] = array( );
1215                        }
1216
1217                        // Recurse, checking the children tags against the reference children
1218                        $check_array[ $tagpos ][ 'children' ] = XMP_Check( $val[ 'children' ] , $check_array[ $tagpos ][ 'children' ] );
1219                }
1220                else
1221                {
1222                        // No children - don't need to check anything else
1223                }
1224        }
1225
1226        // Return the checked XMP array
1227        return $check_array;
1228}
1229
1230
1231/******************************************************************************
1232* End of Function:     XMP_Check
1233******************************************************************************/
1234
1235
1236
1237
1238/******************************************************************************
1239*
1240* Function:     find_XMP_Tag
1241*
1242* Description:  Searches one level of an XMP array for a specific tag, and
1243*               returns the tag position. Does not descend the XMP tree.
1244*
1245* Parameters:   XMP_array - The XMP array which should be searched
1246*               tag - The XMP tag to search for (in same format as would be found in XMP array)
1247*
1248* Returns:      output - a string containing the timezone offset
1249*
1250******************************************************************************/
1251
1252function find_XMP_Tag( $XMP_array, $tag )
1253{
1254        $namespacestr = "";
1255
1256        // Some tags have a namespace attribute which defines them (i.e. rdf:Description tags)
1257
1258        // Check if the tag being searched for has attributs
1259        if ( array_key_exists( 'attributes', $tag ) )
1260        {
1261                // Tag has attributes - cycle through them
1262                foreach( $tag['attributes'] as $key => $val )
1263                {
1264                        // Check if the current attribute is the namespace attribute - i.e. starts with xmlns:
1265                        if ( strcasecmp( substr($key,0,6), "xmlns:" ) == 0 )
1266                        {
1267                                // Found a namespace attribute - save it for later.
1268                                $namespacestr = $key;
1269                        }
1270                }
1271        }
1272
1273
1274
1275        // Cycle through the elements of the XMP array to be searched.
1276        foreach( $XMP_array as $valkey => $val )
1277        {
1278
1279                // Check if the current element is a rdf:Description tag
1280                if ( strcasecmp ( $tag[ 'tag' ], 'rdf:Description' ) == 0 )
1281                {
1282                        // Current element is a rdf:Description tag
1283                        // Check if the namespace attribute is the same as in the tag that is being searched for
1284                        if ( array_key_exists( $namespacestr, $val['attributes'] ) )
1285                        {
1286                                // Namespace is the same - this is the correct tag - return it's position
1287                                return $valkey;
1288                        }
1289                }
1290                // Otherwise check if the current element has the same name as the tag in question
1291                else if ( strcasecmp ( $val[ 'tag' ], $tag[ 'tag' ] ) == 0 )
1292                {
1293                        // Tags have same name - this is the correct tag - return it's position
1294                        return $valkey;
1295                }
1296        }
1297
1298        // Cycled through all tags without finding the correct one - return error value
1299        return FALSE;
1300}
1301
1302/******************************************************************************
1303* End of Function:     find_XMP_Tag
1304******************************************************************************/
1305
1306
1307
1308
1309/******************************************************************************
1310*
1311* Function:     create_GUID
1312*
1313* Description:  Creates a Globally Unique IDentifier, in the format that is used
1314*               by XMP (and Windows). This value is not guaranteed to be 100% unique,
1315*               but it is ridiculously unlikely that two identical values will be produced
1316*
1317* Parameters:   none
1318*
1319* Returns:      output - a string containing the timezone offset
1320*
1321******************************************************************************/
1322
1323function create_GUID( )
1324{
1325        // Create a md5 sum of a random number - this is a 32 character hex string
1326        $raw_GUID = md5( uniqid( getmypid() . rand( ) . (double)microtime()*1000000, TRUE ) );
1327
1328        // Format the string into 8-4-4-4-12 (numbers are the number of characters in each block)
1329        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);
1330}
1331
1332/******************************************************************************
1333* End of Function:     create_GUID
1334******************************************************************************/
1335
1336
1337
1338
1339
1340/******************************************************************************
1341*
1342* Function:     add_to_field
1343*
1344* Description:  Adds a value to a particular field in a Photoshop File Info array,
1345*               first checking whether the value is already there. If the value is
1346*               already in the array, it is not changed, otherwise the value is appended
1347*               to whatever is already in that field of the array
1348*
1349* Parameters:   field_array - The Photoshop File Info array to receive the new value
1350*               field - The File Info field which the value is for
1351*               value - The value to be written into the File Info
1352*               separator - The string to place between values when having to append the value
1353*
1354* Returns:      output - the Photoshop File Info array with the value added
1355*
1356******************************************************************************/
1357
1358function add_to_field( $field_array, $field, $value, $separator )
1359{
1360        // Check if the value is blank
1361        if ( $value == "" )
1362        {
1363                // Value is blank - return File Info array unchanged
1364                return $field_array;
1365        }
1366
1367        // Check if the value can be found anywhere within the existing value for this field
1368        if ( stristr ( $field_array[ $field ], $value ) == FALSE)
1369        {
1370                // Value could not be found
1371                // Check if the existing value for the field is blank
1372                if ( $field_array[$field] != "" )
1373                {
1374                        // Existing value for field is not blank - append a separator
1375                        $field_array[$field] .= $separator;
1376                }
1377                // Append the value to the field
1378                $field_array[$field] .= $value;
1379        }
1380
1381        // Return the File Info Array
1382        return $field_array;
1383}
1384
1385/******************************************************************************
1386* End of Function:     add_to_field
1387******************************************************************************/
1388
1389
1390
1391/******************************************************************************
1392*
1393* Function:     find_IPTC_Resource
1394*
1395* Description:  Searches an IPTC array for a particular record, and returns it if found
1396*
1397* Parameters:   IPTC_array - The IPTC array to search
1398*               record_type - The IPTC record number to search for (e.g.  2:151 )
1399*
1400* Returns:      output - the contents of the record if found
1401*               FALSE - otherwise
1402*
1403******************************************************************************/
1404
1405function find_IPTC_Resource( $IPTC_array, $record_type )
1406{
1407        // Cycle through the ITPC records
1408        foreach ($IPTC_array as $record)
1409        {
1410                // Check the IPTC type against the required type
1411                if ( $record['IPTC_Type'] == $record_type )
1412                {
1413                        // IPTC type matches - return this record
1414                        return $record;
1415                }
1416        }
1417
1418        // No matching record found - return error code
1419        return FALSE;
1420}
1421
1422/******************************************************************************
1423* End of Function:     find_IPTC_Resource
1424******************************************************************************/
1425
1426
1427
1428
1429/******************************************************************************
1430*
1431* Function:     find_Photoshop_IRB_Resource
1432*
1433* Description:  Searches a Photoshop IRB array for a particular resource, and returns it if found
1434*
1435* Parameters:   IRB_array - The IRB array to search
1436*               resource_ID - The IRB resource number to search for (e.g.  0x03F9 )
1437*
1438* Returns:      output - the contents of the resource if found
1439*               FALSE - otherwise
1440*
1441******************************************************************************/
1442
1443function find_Photoshop_IRB_Resource( $IRB_array, $resource_ID )
1444{
1445        // Cycle through the IRB resources
1446        foreach( $IRB_array as $IRB_Resource )
1447        {
1448                // Check the IRB resource ID against the required ID
1449                if ( $resource_ID == $IRB_Resource['ResID'] )
1450                {
1451                        // Resource ID matches - return this resource
1452                        return $IRB_Resource;
1453                }
1454        }
1455
1456        // No matching resource found - return error code
1457        return FALSE;
1458}
1459
1460/******************************************************************************
1461* End of Function:     find_Photoshop_IRB_Resource
1462******************************************************************************/
1463
1464
1465
1466
1467
1468
1469
1470
1471/******************************************************************************
1472*
1473* Function:     find_XMP_item
1474*
1475* Description:  Searches a one level of a XMP array for a particular item by name, and returns it if found.
1476*               Does not descend through the XMP array
1477*
1478* Parameters:   Item_Array - The XMP array to search
1479*               item_name - The name of the tag to serch for (e.g.  photoshop:CaptionWriter )
1480*
1481* Returns:      output - the contents of the tag if found
1482*               FALSE - otherwise
1483*
1484******************************************************************************/
1485
1486function & find_XMP_item( & $Item_Array, $item_name )
1487{
1488        // Cycle through the top level of the XMP array
1489        foreach( $Item_Array as $Item_Key => $Item )
1490        {
1491                // Check this tag name against the required tag name
1492                if( $Item['tag'] == $item_name )
1493                {
1494                        // The tag names match - return the item
1495                        return $Item_Array[ $Item_Key ];
1496                }
1497        }
1498
1499        // No matching tag found - return error code
1500        return $Item_Array;
1501}
1502
1503/******************************************************************************
1504* End of Function:     find_XMP_item
1505******************************************************************************/
1506
1507
1508
1509
1510
1511/******************************************************************************
1512*
1513* Function:     find_XMP_block
1514*
1515* Description:  Searches a for a particular rdf:Description block within a XMP array, and returns its children if found.
1516*
1517* Parameters:   XMP_array - The XMP array to search as returned by read_XMP_array_from_text
1518*               block_name - The namespace of the XMP block to be found (e.g.  photoshop or xapRights )
1519*
1520* Returns:      output - the children of the tag if found
1521*               FALSE - otherwise
1522*
1523******************************************************************************/
1524
1525function & find_XMP_block( & $XMP_array, $block_name )
1526{
1527        // Check that the rdf:RDF section can be found (which contains the rdf:Description tags
1528        if ( ( $XMP_array !== FALSE ) &&
1529             ( ( $XMP_array[0]['tag'] ==  "x:xapmeta" ) ||
1530               ( $XMP_array[0]['tag'] ==  "x:xmpmeta" ) ) &&
1531             ( $XMP_array[0]['children'][0]['tag'] ==  "rdf:RDF" ) )
1532        {
1533                // Found rdf:RDF
1534                // Make it's children easily accessible
1535                $RDF_Contents = $XMP_array[0]['children'][0]['children'];
1536
1537                // Cycle through the children (rdf:Description tags)
1538                foreach ($RDF_Contents as $RDF_Key => $RDF_Item)
1539                {
1540                        // Check if this is a rdf:description tag that has children
1541                        if ( ( $RDF_Item['tag'] == "rdf:Description" ) &&
1542                             ( array_key_exists( 'children', $RDF_Item ) ) )
1543                        {
1544                                // RDF Description tag has children,
1545                                // Cycle through it's attributes
1546                                foreach( $RDF_Item['attributes'] as $key => $val )
1547                                {
1548                                        // Check if this attribute matches the namespace block name required
1549                                        if ( $key == "xmlns:$block_name" )
1550                                        {
1551                                                // Namespace matches required block name - return it's children
1552                                                return  $XMP_array[0]['children'][0]['children'][ $RDF_Key ]['children'];
1553                                        }
1554                                }
1555                        }
1556                }
1557        }
1558
1559        // No matching rdf:Description block found
1560        return $XMP_array;
1561}
1562
1563/******************************************************************************
1564* End of Function:     find_XMP_block
1565******************************************************************************/
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575/******************************************************************************
1576* Global Variable:      Blank XMP Structure
1577*
1578* Contents:     A template XMP array which can be used to create a new XMP segment
1579*
1580******************************************************************************/
1581
1582// Create a GUID to be used in this template array
1583$new_GUID = create_GUID( );
1584
1585$GLOBALS[ 'Blank XMP Structure' ] =
1586array (
1587  0 =>
1588  array (
1589    'tag' => 'x:xmpmeta',
1590    'attributes' =>
1591    array (
1592      'xmlns:x' => 'adobe:ns:meta/',
1593      'x:xmptk' => 'XMP toolkit 3.0-28, framework 1.6',
1594    ),
1595    'children' =>
1596    array (
1597      0 =>
1598      array (
1599        'tag' => 'rdf:RDF',
1600        'attributes' =>
1601        array (
1602          'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
1603          'xmlns:iX' => 'http://ns.adobe.com/iX/1.0/',
1604        ),
1605        'children' =>
1606        array (
1607          1 =>
1608          array (
1609            'tag' => 'rdf:Description',
1610            'attributes' =>
1611            array (
1612              'rdf:about' => "uuid:$new_GUID",
1613              'xmlns:pdf' => 'http://ns.adobe.com/pdf/1.3/',
1614            ),
1615          ),
1616          2 =>
1617          array (
1618            'tag' => 'rdf:Description',
1619            'attributes' =>
1620            array (
1621              'rdf:about' => "uuid:$new_GUID",
1622              'xmlns:photoshop' => 'http://ns.adobe.com/photoshop/1.0/',
1623            ),
1624            'children' =>
1625            array (
1626              0 =>
1627              array (
1628                'tag' => 'photoshop:CaptionWriter',
1629                'value' => '',
1630              ),
1631              1 =>
1632              array (
1633                'tag' => 'photoshop:Category',
1634                'value' => '',
1635              ),
1636              2 =>
1637              array (
1638                'tag' => 'photoshop:DateCreated',
1639                'value' => '',
1640              ),
1641              3 =>
1642              array (
1643                'tag' => 'photoshop:City',
1644                'value' => '',
1645              ),
1646              4 =>
1647              array (
1648                'tag' => 'photoshop:State',
1649                'value' => '',
1650              ),
1651              5 =>
1652              array (
1653                'tag' => 'photoshop:Country',
1654                'value' => '',
1655              ),
1656              6 =>
1657              array (
1658                'tag' => 'photoshop:Credit',
1659                'value' => '',
1660              ),
1661              7 =>
1662              array (
1663                'tag' => 'photoshop:Source',
1664                'value' => '',
1665              ),
1666              8 =>
1667              array (
1668                'tag' => 'photoshop:Headline',
1669                'value' => '',
1670              ),
1671              9 =>
1672              array (
1673                'tag' => 'photoshop:Instructions',
1674                'value' => '',
1675              ),
1676              10 =>
1677              array (
1678                'tag' => 'photoshop:TransmissionReference',
1679                'value' => '',
1680              ),
1681              11 =>
1682              array (
1683                'tag' => 'photoshop:Urgency',
1684                'value' => '',
1685              ),
1686              12 =>
1687              array (
1688                'tag' => 'photoshop:SupplementalCategories',
1689                'children' =>
1690                array (
1691                  0 =>
1692                  array (
1693                    'tag' => 'rdf:Bag',
1694                  ),
1695                ),
1696              ),
1697              13 =>
1698              array (
1699                'tag' => 'photoshop:AuthorsPosition',
1700                'value' => '',
1701              ),
1702            ),
1703          ),
1704          4 =>
1705          array (
1706            'tag' => 'rdf:Description',
1707            'attributes' =>
1708            array (
1709              'rdf:about' => "uuid:$new_GUID",
1710              'xmlns:xap' => 'http://ns.adobe.com/xap/1.0/',
1711            ),
1712            'children' =>
1713            array (
1714              0 =>
1715              array (
1716                'tag' => 'xap:CreateDate',
1717                'value' => '',
1718              ),
1719              1 =>
1720              array (
1721                'tag' => 'xap:ModifyDate',
1722                'value' => '',
1723              ),
1724              2 =>
1725              array (
1726                'tag' => 'xap:MetadataDate',
1727                'value' => '',
1728              ),
1729              3 =>
1730              array (
1731                'tag' => 'xap:CreatorTool',
1732                'value' => '',
1733              ),
1734            ),
1735          ),
1736          5 =>
1737          array (
1738            'tag' => 'rdf:Description',
1739            'attributes' =>
1740            array (
1741              'about' => "uuid:$new_GUID",
1742              'xmlns:stJob' => 'http://ns.adobe.com/xap/1.0/sType/Job#',
1743              'xmlns:xapBJ' => 'http://ns.adobe.com/xap/1.0/bj/',
1744            ),
1745            'children' =>
1746            array (
1747              0 =>
1748              array (
1749                'tag' => 'xapBJ:JobRef',
1750                'children' =>
1751                array (
1752                  0 =>
1753                  array (
1754                    'tag' => 'rdf:Bag',
1755                    'children' =>
1756                    array (
1757                    ),
1758                  ),
1759                ),
1760              ),
1761            ),
1762          ),
1763          6 =>
1764          array (
1765            'tag' => 'rdf:Description',
1766            'attributes' =>
1767            array (
1768              'rdf:about' => "uuid:$new_GUID",
1769              'xmlns:xapRights' => 'http://ns.adobe.com/xap/1.0/rights/',
1770            ),
1771            'children' =>
1772            array (
1773              1 =>
1774              array (
1775                'tag' => 'xapRights:WebStatement',
1776                'value' => '',
1777              ),
1778            ),
1779          ),
1780          7 =>
1781          array (
1782            'tag' => 'rdf:Description',
1783            'attributes' =>
1784            array (
1785              'rdf:about' => "uuid:$new_GUID",
1786              'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
1787            ),
1788            'children' =>
1789            array (
1790              0 =>
1791              array (
1792                'tag' => 'dc:format',
1793                'value' => 'image/jpeg',
1794              ),
1795              1 =>
1796              array (
1797                'tag' => 'dc:title',
1798                'children' =>
1799                array (
1800                  0 =>
1801                  array (
1802                    'tag' => 'rdf:Alt',
1803                  ),
1804                ),
1805              ),
1806              2 =>
1807              array (
1808                'tag' => 'dc:description',
1809                'children' =>
1810                array (
1811                  0 =>
1812                  array (
1813                    'tag' => 'rdf:Alt',
1814                  ),
1815                ),
1816              ),
1817              3 =>
1818              array (
1819                'tag' => 'dc:rights',
1820                'children' =>
1821                array (
1822                  0 =>
1823                  array (
1824                    'tag' => 'rdf:Alt',
1825                  ),
1826                ),
1827              ),
1828              4 =>
1829              array (
1830                'tag' => 'dc:creator',
1831                'children' =>
1832                array (
1833                  0 =>
1834                  array (
1835                    'tag' => 'rdf:Seq',
1836                  ),
1837                ),
1838              ),
1839              5 =>
1840              array (
1841                'tag' => 'dc:subject',
1842                'children' =>
1843                array (
1844                  0 =>
1845                  array (
1846                    'tag' => 'rdf:Bag',
1847                  ),
1848                ),
1849              ),
1850            ),
1851          ),
1852
1853/*          0 =>
1854          array (
1855            'tag' => 'rdf:Description',
1856            'attributes' =>
1857            array (
1858              'rdf:about' => "uuid:$new_GUID",
1859              'xmlns:exif' => 'http://ns.adobe.com/exif/1.0/',
1860            ),
1861            'children' =>
1862            array (
1863
1864//EXIF DATA GOES HERE - Not Implemented yet
1865            ),
1866          ),
1867*/
1868/*
1869          2 =>
1870          array (
1871            'tag' => 'rdf:Description',
1872            'attributes' =>
1873            array (
1874              'rdf:about' => "uuid:$new_GUID",
1875              'xmlns:tiff' => 'http://ns.adobe.com/tiff/1.0/',
1876            ),
1877            'children' =>
1878            array (
1879// TIFF DATA GOES HERE - Not Implemented yet
1880              0 =>
1881              array (
1882                'tag' => 'tiff:Make',
1883                'value' => 'NIKON CORPORATION',
1884              ),
1885            ),
1886          ),
1887*/
1888/*
1889          3 =>
1890          array (
1891            'tag' => 'rdf:Description',
1892            'attributes' =>
1893            array (
1894              'rdf:about' => "uuid:$new_GUID",
1895              'xmlns:stRef' => 'http://ns.adobe.com/xap/1.0/sType/ResourceRef#',
1896              'xmlns:xapMM' => 'http://ns.adobe.com/xap/1.0/mm/',
1897            ),
1898            'children' =>
1899            array (
1900// XAPMM DATA GOES HERE - Not Implemented yet
1901              0 =>
1902              array (
1903                'tag' => 'xapMM:DocumentID',
1904                'value' => 'adobe:docid:photoshop:dceba4c2-e699-11d8-94b2-b6ec48319f2d',
1905              ),
1906              1 =>
1907              array (
1908                'tag' => 'xapMM:DerivedFrom',
1909                'attributes' =>
1910                array (
1911                  'rdf:parseType' => 'Resource',
1912                ),
1913                'children' =>
1914                array (
1915                  0 =>
1916                  array (
1917                    'tag' => 'stRef:documentID',
1918                    'value' => 'adobe:docid:photoshop:5144475b-e698-11d8-94b2-b6ec48319f2d',
1919                  ),
1920                  1 =>
1921                  array (
1922                    'tag' => 'stRef:instanceID',
1923                    'value' => "uuid:$new_GUID",
1924                  ),
1925                ),
1926              ),
1927            ),
1928          ),
1929*/
1930
1931        ),
1932      ),
1933    ),
1934  ),
1935);
1936
1937
1938
1939/******************************************************************************
1940* End of Global Variable:     Blank XMP Structure
1941******************************************************************************/
1942
1943
1944
1945
1946
1947?>
Note: See TracBrowser for help on using the repository browser.