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

Last change on this file since 9412 was 9412, checked in by cljosse, 13 years ago
File size: 45.6 KB
Line 
1<?php
2
3/******************************************************************************
4*
5* Filename:     XMP.php
6*
7* Description:  Provides functions for reading and writing information to/from
8*               the 'App 1' Extensible Metadata Platform (XMP) segment of JPEG
9*               format files. This XMP segment is XML based and contains the
10*               Resource Description Framework (RDF) data, which itself can
11*               contain the Dublin Core Metadata Initiative (DCMI) information.
12*
13* Author:      Evan Hunter
14*
15* Date:         27/7/2004
16*
17* Project:      JPEG Metadata
18*
19* Revision:     1.10
20*
21* Changes:      1.00 -> 1.04 : changed put_IPTC to fix a bug preventing the correct
22*               insertion of a XMP block where none existed previously
23*
24*               1.04 -> 1.10 : changed put_XMP_text to fix some array indexes which were missing qoutes
25*
26* URL:          http://electronics.ozhiker.com
27*
28* Copyright:    Copyright " . $auteur . " 2004
29*
30* License:      This file is part of the PHP JPEG Metadata Toolkit.
31*
32*               The PHP JPEG Metadata Toolkit is free software; you can
33*               redistribute it and/or modify it under the terms of the
34*               GNU General Public License as published by the Free Software
35*               Foundation; either version 2 of the License, or (at your
36*               option) any later version.
37*
38*               The PHP JPEG Metadata Toolkit is distributed in the hope
39*               that it will be useful, but WITHOUT ANY WARRANTY; without
40*               even the implied warranty of MERCHANTABILITY or FITNESS
41*               FOR A PARTICULAR PURPOSE.  See the GNU General Public License
42*               for more details.
43*
44*               You should have received a copy of the GNU General Public
45*               License along with the PHP JPEG Metadata Toolkit; if not,
46*               write to the Free Software Foundation, Inc., 59 Temple
47*               Place, Suite 330, Boston, MA  02111-1307  USA
48*
49*               If you require a different license for commercial or other
50*               purposes, please contact the author: evan@ozhiker.com
51*
52******************************************************************************/
53
54include_once INCLUDE_PATH.'XML.php';
55
56
57
58
59
60/******************************************************************************
61*
62* Function:     get_XMP_text
63*
64* Description:  Retrieves the Extensible Metadata Platform (XMP) information
65*               from an App1 JPEG segment and returns the raw XML text as a
66*               string. This includes the Resource Description Framework (RDF)
67*               information and may include Dublin Core Metadata Initiative (DCMI)
68*               information. Uses information supplied by the get_jpeg_header_data
69*               function
70*
71* Parameters:   jpeg_header_data - a JPEG header data array in the same format
72*                                  as from get_jpeg_header_data
73*
74* Returns:      xmp_data - the string of raw XML text
75*               FALSE - if an APP 1 XMP segment could not be found,
76*                       or if an error occured
77*
78******************************************************************************/
79
80function get_XMP_text( $jpeg_header_data )
81{
82        //Cycle through the header segments
83        for( $i = 0; $i < count( $jpeg_header_data ); $i++ )
84        {
85                // If we find an APP1 header,
86                if ( strcmp ( $jpeg_header_data[$i]['SegName'], "APP1" ) == 0 )
87                {
88                        // And if it has the Adobe XMP/RDF label (http://ns.adobe.com/xap/1.0/\x00) ,
89                        if( strncmp ( $jpeg_header_data[$i]['SegData'], "http://ns.adobe.com/xap/1.0/\x00", 29) == 0 )
90                        {
91                                // Found a XMP/RDF block
92                                // Return the XMP text
93                                $xmp_data = substr ( $jpeg_header_data[$i]['SegData'], 29 );
94
95                                return $xmp_data;
96                        }
97                }
98        }
99        return FALSE;
100}
101
102/******************************************************************************
103* End of Function:     get_XMP_text
104******************************************************************************/
105
106
107
108
109
110
111/******************************************************************************
112*
113* Function:     put_XMP_text
114*
115* Description:  Adds or modifies the Extensible Metadata Platform (XMP) information
116*               in an App1 JPEG segment. If a XMP segment already exists, it is
117*               replaced, otherwise a new one is inserted, using the supplied data.
118*               Uses information supplied by the get_jpeg_header_data function
119*
120* Parameters:   jpeg_header_data - a JPEG header data array in the same format
121*                                  as from get_jpeg_header_data
122*               newXMP - a string containing the XMP text to be stored in the XMP
123*                        segment. Should be constructed using the write_XMP_array_to_text
124*                        function
125*
126* Returns:      jpeg_header_data - the JPEG header data array with the
127*                                  XMP segment added.
128*               FALSE - if an error occured
129*
130******************************************************************************/
131
132function put_XMP_text( $jpeg_header_data, $newXMP )
133{
134        //Cycle through the header segments
135        for( $i = 0; $i < count( $jpeg_header_data ); $i++ )
136        {
137                // If we find an APP1 header,
138                if ( strcmp ( $jpeg_header_data[$i]['SegName'], "APP1" ) == 0 )
139                {
140                        // And if it has the Adobe XMP/RDF label (http://ns.adobe.com/xap/1.0/\x00) ,
141                        if( strncmp ( $jpeg_header_data[$i]['SegData'], "http://ns.adobe.com/xap/1.0/\x00", 29) == 0 )
142                        {
143                                // Found a preexisting XMP/RDF block - Replace it with the new one and return.
144                                $jpeg_header_data[$i]['SegData'] = "http://ns.adobe.com/xap/1.0/\x00" . $newXMP;
145                                return $jpeg_header_data;
146                        }
147                }
148        }
149
150        // No pre-existing XMP/RDF found - insert a new one after any pre-existing APP0 or APP1 blocks
151        // Change: changed to initialise $i properly as of revision 1.04
152        $i = 0;
153        // Loop until a block is found that isn't an APP0 or APP1
154        while ( ( $jpeg_header_data[$i]['SegName'] == "APP0" ) || ( $jpeg_header_data[$i]['SegName'] == "APP1" ) )
155        {
156                $i++;
157        }
158
159
160
161        // Insert a new XMP/RDF APP1 segment at the specified point.
162        // Change: changed to properly construct array element as of revision 1.04 - requires two array statements not one, requires insertion at $i, not $i - 1
163        array_splice($jpeg_header_data, $i, 0, array( array(       "SegType" => 0xE1,
164                                                                        "SegName" => "APP1",
165                                                                        "SegDesc" => $GLOBALS[ "JPEG_Segment_Descriptions" ][ 0xE1 ],
166                                                                        "SegData" => "http://ns.adobe.com/xap/1.0/\x00" . $newXMP ) ) );
167
168        // Return the headers with the new segment inserted
169        return $jpeg_header_data;
170}
171
172/******************************************************************************
173* End of Function:     put_XMP_text
174******************************************************************************/
175
176
177
178
179
180
181/******************************************************************************
182*
183* Function:     read_XMP_array_from_text
184*
185* Description:  An alias for read_xml_array_from_text.
186*               Parses a string containing XMP data (XML), and returns the resulting
187*               tree structure array, which contains all the XMP (XML) information.
188*               Note: White space and comments in the XMP data (XML) are ignored
189*               Note: All text information contained in the tree structure
190*                     is encoded as Unicode UTF-8. Hence text will appear as
191*                     normal ASCII except where there is an extended character.
192*
193* Parameters:   xmptext - a string containing the XMP data (XML) to be parsed
194*
195* Returns:      output - the tree structure array containing the XMP (XML) information
196*               FALSE - if an error occured
197*
198******************************************************************************/
199
200function read_XMP_array_from_text( $xmptext )
201{
202        return read_xml_array_from_text( $xmptext );
203}
204
205/******************************************************************************
206* End of Function:     read_XMP_array_from_text
207******************************************************************************/
208
209
210
211
212
213/******************************************************************************
214*
215* Function:     write_XMP_array_to_text
216*
217* Description:  Takes a tree structure array containing XMP (in the same format
218*               as returned by read_XMP_array_from_text, and constructs a string
219*               containing the equivalent XMP, including the XMP Packet header
220*               and trailer. Produces XMP text which has correct indents, encoded
221*               using UTF-8.
222*               Note: All text information contained in the tree structure
223*                     can be either 7-bit ASCII or encoded as Unicode UTF-8,
224*                     since UTF-8 passes 7-bit ASCII text unchanged.
225*
226* Parameters:   xmparray - the tree structure array containing the information to
227*                          be converted to XMP text
228*
229* Returns:      output_XMP_text - the string containing the equivalent XMP text
230*
231******************************************************************************/
232
233function write_XMP_array_to_text( $xmparray )
234{
235        // Add the XMP packet header
236        // The sequence 0xEFBBBF is the UTF-8 encoded version of the Unicode “zero
237        // width non-breaking space character” (U+FEFF), which is used for detecting
238        // whether UTF-16 or UTF-8 is being used.
239        $output_XMP_text = "<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'?>\n";
240
241        // Photoshop Seems to add this, but there doesn't appear to be
242        // any information on what it means
243        // TODO : XMP, Find out what the adobe-xap-filters tag means
244        $output_XMP_text .= "<?adobe-xap-filters esc=\"CR\"?>\n";
245
246        // Add the XML text
247        $output_XMP_text .= write_xml_array_to_text( $xmparray, 0 );
248
249
250        // The XMP standard recommends adding 2-4k of white space at the
251        // end for in place editing, so we will add it to the XML now
252        $output_XMP_text .= str_repeat("                                                                                                   \n", 30);
253
254        // Add the XMP packet trailer
255        $output_XMP_text .= "<?xpacket end='w'?>";
256
257        // Return the resulting XMP text
258        return $output_XMP_text;
259}
260
261/******************************************************************************
262* End of Function:     write_XMP_array_to_text
263******************************************************************************/
264
265
266
267
268
269
270/******************************************************************************
271*
272* Function:     Interpret_XMP_to_HTML
273*
274* Description:  Generates html showing the information contained in an Extensible
275*               Metadata Platform (XMP) tree structure array, as retrieved
276*               with read_XMP_array_from_text
277*
278* Parameters:   XMP_array - a XMP tree structure array as from read_XMP_array_from_text
279*
280* Returns:      output - the HTML string
281*
282******************************************************************************/
283
284function Interpret_XMP_to_HTML( $XMP_array )
285{
286        // Create a string to receive the output html
287        $output ="";
288
289        // Check if the XMP tree structure array is valid
290        if ( $XMP_array !== FALSE )
291        {
292                // Check if there is a rdf:RDF tag at either the first or second level
293                if ( ( $XMP_array[0]['tag'] ==  "x:xapmeta" ) && ( $XMP_array[0]['children'][0]['tag'] ==  "rdf:RDF" ) )
294                {
295                        // RDF found at second level - Save it's position
296                        $RDF_Contents = &$XMP_array[0]['children'][0]['children'];
297                }
298                else if ( ( $XMP_array[0]['tag'] ==  "x:xmpmeta" ) && ( $XMP_array[0]['children'][0]['tag'] ==  "rdf:RDF" ) )
299                {
300                        // RDF found at second level - Save it's position
301                        $RDF_Contents = &$XMP_array[0]['children'][0]['children'];
302                }
303                else if ( $XMP_array[0]['tag'] ==  "rdf:RDF" )
304                {
305                        // RDF found at first level - Save it's position
306                        $RDF_Contents = &$XMP_array[0]['children'];
307                }
308                else
309                {
310                        // RDF section not found - abort
311                        return "";
312                }
313
314                // Add heading to html output
315                $output .= "<fieldset><legend>Contains Extensible Metadata Platform (XMP) / Resource Description Framework (RDF) Information</legend>";
316
317                // Cycle through each of the items in the RDF tree array, and process them
318                foreach ($RDF_Contents as $RDF_Item)
319                {
320                        // Check if the item is a rdf:Description tag - these are the only ones that can be processed
321
322                        if ( ( $RDF_Item['tag'] == "rdf:Description" ) && ( array_key_exists( 'children', $RDF_Item ) ) )
323                        {
324                                // Item is a rdf:Description tag.
325
326                                // Cycle through each of the attributes for this tag, looking
327                                // for a xmlns: attribute, which tells us what Namespace the
328                                // sub-items will be in.
329                                foreach( $RDF_Item['attributes'] as $key => $val )
330                                {
331                                        // Check for the xmlns: namespace attribute
332                                        if ( substr( $key,0,6) == "xmlns:" )
333                                        {
334                                                // Found a xmlns: attribute
335                                                // Extract the namespace string
336                                                // Add heading to the HTML according to which Namespace the RDF items have
337                                                switch ( substr( $key,6) )
338                                                {
339                                                        case "photoshop":
340                                                                $entete  = "Photoshop RDF Segment";
341                                                                break;
342                                                        case "xapBJ":
343                                                                $entete  = "Basic Job Ticket RDF Segment";
344                                                                break;
345                                                        case "xapMM":
346                                                                $entete  = "Media Management RDF Segment";
347                                                                break;
348                                                        case "xapRights":
349                                                                $entete  = "Rights Management RDF Segment";
350                                                                break;
351                                                        case "dc":
352                                                                $entete  = "Dublin Core Metadata Initiative RDF Segment";
353                                                                break;
354                                                        case "xmp":
355                                                        case "xap":
356                                                                $entete  = "XMP Basic Segment";
357                                                                break;
358                                                        case "xmpTPg":
359                                                                $entete  = "XMP Paged-Text Segment";
360                                                                break;
361                                                        case "xmpTPg":
362                                                                $entete  = "Adobe PDF Segment";
363                                                                break;
364                                                        case "tiff":
365                                                                $entete  = "XMP - embedded TIFF Segment";
366                                                                break;
367                                                        case "exif":
368                                                                $entete  = "XMP - embedded EXIF Segment";
369                                                                break;
370                                                        case "xapGImg":  // Sub Category - Do nothing
371                                                                break;
372                                                        case "stDim":  // Sub Category - Do nothing
373                                                                break;
374                                                        case "stEvt":  // Sub Category - Do nothing
375                                                                break;
376                                                        case "stRef":  // Sub Category - Do nothing
377                                                                break;
378                                                        case "stVer":  // Sub Category - Do nothing
379                                                                break;
380                                                        case "stJob":  // Sub Category - Do nothing
381                                                                break;
382
383                                                        default:
384                                                                $entete  = "Unknown RDF Segment '" . substr( $key,6) . "'";
385                                                                break;
386                                                }
387                                        }
388                                }
389                               $output .= "<fieldset class='fieldset' id='". substr( $key,6) ."'  ><legend> $entete  </legend>";
390                                // Add the start of the table to the HTML output
391                                $output .= "\n<table  class=\"XMP_Table\" border=1>\n";
392                                // Check if this element has sub-items
393                                 $tabval=$RDF_Item;
394                                 $tabval['Type_src']="xmp";
395                                if ( array_key_exists( 'children', $RDF_Item ) )
396                                {
397                                        // Cycle through each of the sub-items
398                                        foreach( $RDF_Item['children'] as $child_item )
399                                        {    // Get an interpretation of the sub-item's caption and value
400                                               list($tag_caption, $value_str) = Interpret_RDF_Item( $child_item );
401                                                // Escape the text of the caption for html
402                                                $tag_caption = HTML_UTF8_Escape( $tag_caption );
403                                                // Escape the text of the value for html and turn newlines to <br>
404                                                $value_str = nl2br( HTML_UTF8_Escape( $value_str ) );
405
406                                                // Check if the value is empty - if it is, put a no-break-space in
407                                                // to ensure the table cell gets drawn
408                                                if ( $value_str == "" )
409                                                {
410                                                        $value_str = "&nbsp;";
411                                                }
412                                                // Add the table row to the output html
413
414                                                $tabval['Tag Name']=$tag_caption; 
415                                                $tabval['Text Value']=$value_str ;
416                                                $output .= OutPut_exif($tabval); 
417                                         }
418                                }
419
420                                // Add the end of the table to the html
421                                $output .= "</table></fieldset>";
422
423
424                        }
425                        else
426                        {
427                                // Don't know how to process tags other than rdf:Description - do nothing
428                        }
429                }
430
431
432
433        }
434        // Return the resulting HTML
435        return $output."</fieldset>";
436}
437
438/******************************************************************************
439* End of Function:     Interpret_XMP_to_HTML
440******************************************************************************/
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459/******************************************************************************
460*
461*         INTERNAL FUNCTIONS
462*
463******************************************************************************/
464
465
466
467
468
469
470
471
472
473
474
475
476/******************************************************************************
477*
478* Internal Function:     Interpret_RDF_Item
479*
480* Description:  Used by Interpret_XMP_to_HTML
481*               Used by get_RDF_field_html_value
482*               Used by interpret_RDF_collection
483*               Generates a caption and text representation of the value of a
484*               particular RDF item.
485*
486* Parameters:   Item - The RDF item to evaluate
487*
488* Returns:      tag_caption - the caption of the tag
489*               value_str - the text representation of the value
490*
491******************************************************************************/
492
493function Interpret_RDF_Item( $Item )
494{
495
496        // TODO: Many RDF items have not been tested - only photoshop 7.0 and CS items
497
498        // Create a string to receive the HTML output
499        $value_str = "";
500
501        // Check if the item has is in the lookup table of tag captions
502        if ( array_key_exists( $Item['tag'], $GLOBALS[ 'XMP_tag_captions' ] ) )
503        {
504                // Item is in list of captions, get the caption
505                $tag_caption = $GLOBALS[ 'XMP_tag_captions' ][ $Item['tag'] ];
506        }
507        else
508        {
509                // Item has no caption - make one
510                $tag_caption = "Unknown field " . $Item['tag'];
511        }
512
513
514        // Process specially the item according to it's tag
515        switch ( $Item['tag'] )
516        {
517
518                case "photoshop:DateCreated":            // This is in year month day order
519                        // Extract the year,month and day
520                        list( $year, $month, $day ) = sscanf( $Item['value'], "%d-%d-%d" );
521                        // Make a new date string with Day, Month, Year
522                        $value_str = "$day/$month/$year";
523                        break;
524
525                default :
526                        $value_str = get_RDF_field_html_value( $Item );
527                        break;
528        }
529
530
531
532
533        // Return the captiona and value
534        return array($tag_caption, $value_str);
535}
536
537
538/******************************************************************************
539* End of Function:     Interpret_RDF_Item
540******************************************************************************/
541
542
543
544
545
546/******************************************************************************
547*
548* Internal Function:     get_RDF_field_html_value
549*
550* Description:  Attempts to build a text representation of the value of an RDF
551*               item. This includes handling any collections or sub-resources.
552*
553* Parameters:   rdf_item - The RDF item to evaluate
554*
555* Returns:      output_str - the text representation of the field value
556*
557******************************************************************************/
558
559function get_RDF_field_html_value( $rdf_item )
560{
561        // Create a string to receive the output text
562        $output_str = "";
563
564        // Check if the item has a value
565        if ( array_key_exists( 'value', $rdf_item ) )
566        {
567                // The item does have a value - add it to the text
568                $output_str .= $rdf_item['value'];
569        }
570
571        // Check if the item has any attributes
572        if ( array_key_exists( 'attributes', $rdf_item ) )
573        {
574                // Cycle through each of the attributes
575                foreach( $rdf_item['attributes'] as $key => $val )
576                {
577                        // Check if this attribute is rdf:parseType = 'Resource' i.e. a sub-resource indicator
578                        if ( ( $key == "rdf:parseType" ) && ( $val == "Resource" ) )
579                        {
580                                // This item has a attribute indicating sub-resources
581                                // Check that the item has sub items
582                                if ( array_key_exists( 'children', $rdf_item ) )
583                                {
584                                        // The item does have sub-items,
585                                        // Cycle through each, Interpreting them and adding the result to the output text
586                                        foreach( $rdf_item['children'] as $child )
587                                        {
588                                                list($tag_caption, $value_str) = Interpret_RDF_Item( $child );
589                                                $output_str .= "$tag_caption  =  $value_str\n";
590                                        }
591                                        // The output text will have an extra \n on it - remove it
592                                        $output_str = rtrim( $output_str );
593                                }
594                        }
595                }
596        }
597                // If the item did not have sub-resources, it may still have sub-items - check for this
598        else if ( array_key_exists( 'children', $rdf_item ) )
599        {
600                // Non-resource Sub-items found, Cycle through each
601                foreach( $rdf_item['children'] as $child_item )
602                {
603                        // Check if this sub-item has a tag
604                        if ( array_key_exists( 'tag', $child_item ) )
605                        {
606                                // Sub item has a tag, Process it according to the tag
607                                switch ( $child_item[ 'tag' ] )
608                                {
609                                        // Collections
610                                        case "rdf:Alt":
611                                                $output_str .= "List of Alternates:\n";
612                                                $output_str .= interpret_RDF_collection( $child_item );
613                                                break;
614
615                                        case "rdf:Bag":
616                                                $output_str .= "Unordered List:\n";
617                                                $output_str .= interpret_RDF_collection( $child_item );
618                                                break;
619
620                                        case "rdf:Seq":
621                                                $output_str .= "Ordered List:\n";
622                                                $output_str .= interpret_RDF_collection( $child_item );
623                                                break;
624
625                                        // Sub-Resource
626                                        case "rdf:Description":
627                                                // Check that the item has sub items
628                                                if ( array_key_exists( 'children', $child_item ) )
629                                                {
630                                                        // The item does have sub-items,
631                                                        // Cycle through each, Interpreting them and adding the result to the output text
632                                                        foreach( $child_item['children'] as $child )
633                                                        {
634                                                                list($tag_caption, $value_str) = Interpret_RDF_Item( $child );
635                                                                $output_str .= "$tag_caption  =  $value_str\n";
636                                                        }
637                                                        // The output text will have an extra \n on it - remove it
638                                                        $output_str = rtrim( $output_str );
639                                                }
640                                                break;
641
642                                        // Other
643                                        default:
644                                                $output_str .= "Unknown Sub Item type:". $child_item[ 'tag' ]. "\n";
645                                                break;
646                                }
647                        } // sub-item Has no tags, look for a value
648                        else if ( array_key_exists( 'value', $child_item ) )
649                        {
650                                $output_str .= $rdf_item['value'] . "\n";
651                        }
652                        else
653                        {
654                                // no info - do nothing
655                        }
656
657                }
658        }
659
660        // return the resulting value string
661        return $output_str;
662}
663
664/******************************************************************************
665* End of Function:     get_RDF_field_html_value
666******************************************************************************/
667
668
669
670
671
672
673
674
675/******************************************************************************
676*
677* Internal Function:     interpret_RDF_collection
678*
679* Description:  Attempts to build a text representation of the value of an RDF
680*               collection item. This includes handling any sub-collections or
681*               sub-resources.
682*
683* Parameters:   rdf_item - The RDF collection item to evaluate
684*
685* Returns:      output_str - the text representation of the collection value
686*
687******************************************************************************/
688
689function interpret_RDF_collection( $item )
690{
691        // Create a string to receive the output
692        $output_str = "";
693
694        // Check if the collection item has sub-items
695        if ( array_key_exists( 'children', $item ) )
696        {
697
698                // Cycle through each of the sub-items
699                foreach( $item['children'] as $list_item )
700                {
701                        // Check that the sub item has a tag, and don't process it if it doesn't
702                        if ( ! array_key_exists( 'tag', $list_item ) )
703                        {
704                                continue 1;
705                        }
706
707                        // Check that the sub-item tag is either rdf:li or rdf:_1 ....
708                        // This signifies it is a list item of the collection
709                        if ( ( $list_item['tag'] == "rdf:li" ) ||
710                             ( preg_match ( "rdf:_\d+", $list_item['tag'] ) == 1 ) )
711                        {
712                                // A List item has been found
713                                // Check if there are sub-resources,
714                                // starting by checking if there are attributes
715                                if ( array_key_exists( 'attributes', $list_item ) )
716                                {
717                                        // Cycle through each of the attributes
718                                        foreach( $list_item['attributes'] as $key => $val )
719                                        {
720                                                // Check if this attribute is rdf:parseType = 'Resource' i.e. a sub-resource indicator
721                                                if ( ( $key == "rdf:parseType" ) && ( $val == "Resource" ) )
722                                                {
723                                                        // This item has a attribute indicating sub-resources
724                                                        // Check that the item has sub items
725                                                        if ( array_key_exists( 'children', $list_item ) )
726                                                        {
727                                                                // The item does have sub-items,
728                                                                // Cycle through each, Interpreting them and adding the result to the output text
729                                                                foreach( $list_item['children'] as $child )
730                                                                {
731                                                                        list($tag_caption, $value_str) = Interpret_RDF_Item( $child );
732                                                                        $output_str .= "$tag_caption  =  $value_str\n";
733                                                                }
734                                                                // The output text will have an extra \n on it - remove it
735                                                                $output_str = rtrim( $output_str );
736                                                        }
737                                                }
738                                        }
739                                }
740
741                                // Check if the list item has a value
742                                if ( array_key_exists( 'value', $list_item ) )
743                                {
744                                        // Value found, add it to the output
745                                        $output_str .= get_RDF_field_html_value( $list_item ) . "\n";
746                                }
747
748                        }
749                }
750                // The list of sub-items formed will have a trailing \n, remove it.
751                $output_str = rtrim( $output_str );
752
753        }
754        else
755        {
756                // No sub-items in collection - can't do anything
757        }
758
759        // Return the output value
760        return $output_str;
761
762}
763
764/******************************************************************************
765* End of Function:     interpret_RDF_collection
766******************************************************************************/
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782/******************************************************************************
783* Global Variable:      XMP_tag_captions
784*
785* Contents:     The Captions of the known XMP fields, indexed by their field name
786*
787******************************************************************************/
788
789$GLOBALS[ 'XMP_tag_captions' ] = array (
790
791"dc:contributor" => "Other Contributor(s)",
792"dc:coverage" => "Coverage (scope)",
793"dc:creator" => "Creator(s) (Authors)",
794"dc:date" => "Date",
795"dc:description" => "Description (Caption)",
796"dc:format" => "MIME Data Format",
797"dc:identifier" => "Unique Resource Identifer",
798"dc:language" => "Language(s)",
799"dc:publisher" => "Publisher(s)",
800"dc:relation" => "Relations to other documents",
801"dc:rights" => "Rights Statement",
802"dc:source" => "Source (from which this Resource is derived)",
803"dc:subject" => "Subject and Keywords",
804"dc:title" => "Title",
805"dc:type" => "Resource Type",
806
807"xmp:Advisory" => "Externally Editied Properties",
808"xmp:BaseURL" => "Base URL for relative URL's",
809"xmp:CreateDate" => "Original Creation Date",
810"xmp:CreatorTool" => "Creator Tool",
811"xmp:Identifier" => "Identifier(s)",
812"xmp:MetadataDate" => "Metadata Last Modify Date",
813"xmp:ModifyDate" => "Resource Last Modify Date",
814"xmp:Nickname" => "Nickname",
815"xmp:Thumbnails" => "Thumbnails",
816
817"xmpidq:Scheme" => "Identification Scheme",
818
819// These are not in spec but Photoshop CS seems to use them
820"xap:Advisory" => "Externally Editied Properties",
821"xap:BaseURL" => "Base URL for relative URL's",
822"xap:CreateDate" => "Original Creation Date",
823"xap:CreatorTool" => "Creator Tool",
824"xap:Identifier" => "Identifier(s)",
825"xap:MetadataDate" => "Metadata Last Modify Date",
826"xap:ModifyDate" => "Resource Last Modify Date",
827"xap:Nickname" => "Nickname",
828"xap:Thumbnails" => "Thumbnails",
829"xapidq:Scheme" => "Identification Scheme",
830
831
832"xapRights:Certificate" => "Certificate",
833"xapRights:Copyright" => "Copyright",
834"xapRights:Marked" => "Marked",
835"xapRights:Owner" => "Owner",
836"xapRights:UsageTerms" => "Legal Terms of Usage",
837"xapRights:WebStatement" => "Web Page describing rights statement (Owner URL)",
838
839"xapMM:ContainedResources" => "Contained Resources",
840"xapMM:ContributorResources" => "Contributor Resources",
841"xapMM:DerivedFrom" => "Derived From",
842"xapMM:DocumentID" => "Document ID",
843"xapMM:History" => "History",
844"xapMM:LastURL" => "Last Written URL",
845"xapMM:ManagedFrom" => "Managed From",
846"xapMM:Manager" => "Asset Management System",
847"xapMM:ManageTo" => "Manage To",
848"xapMM:xmpMM:ManageUI" => "Managed Resource URI",
849"xapMM:ManagerVariant" => "Particular Variant of Asset Management System",
850"xapMM:RenditionClass" => "Rendition Class",
851"xapMM:RenditionParams" => "Rendition Parameters",
852"xapMM:RenditionOf" => "Rendition Of",
853"xapMM:SaveID" => "Save ID",
854"xapMM:VersionID" => "Version ID",
855"xapMM:Versions" => "Versions",
856
857"xapBJ:JobRef" => "Job Reference",
858
859"xmpTPg:MaxPageSize" => "Largest Page Size",
860"xmpTPg:NPages" => "Number of pages",
861
862"pdf:Keywords" => "Keywords",
863"pdf:PDFVersion" => "PDF file version",
864"pdf:Producer" => "PDF Creation Tool",
865
866"photoshop:AuthorsPosition" => "Authors Position",
867"photoshop:CaptionWriter" => "Caption Writer",
868"photoshop:Category" => "Category",
869"photoshop:City" => "City",
870"photoshop:Country" => "Country",
871"photoshop:Credit" => "Credit",
872"photoshop:DateCreated" => "Creation Date",
873"photoshop:Headline" => "Headline",
874"photoshop:History" => "History",                       // Not in XMP spec
875"photoshop:Instructions" => "Instructions",
876"photoshop:Source" => "Source",
877"photoshop:State" => "State",
878"photoshop:SupplementalCategories" => "Supplemental Categories",
879"photoshop:TransmissionReference" => "Technical (Transmission) Reference",
880"photoshop:Urgency" => "Urgency",
881
882
883"tiff:ImageWidth" => "Image Width",
884"tiff:ImageLength" => "Image Length",
885"tiff:BitsPerSample" => "Bits Per Sample",
886"tiff:Compression" => "Compression",
887"tiff:PhotometricInterpretation" => "Photometric Interpretation",
888"tiff:Orientation" => "Orientation",
889"tiff:SamplesPerPixel" => "Samples Per Pixel",
890"tiff:PlanarConfiguration" => "Planar Configuration",
891"tiff:YCbCrSubSampling" => "YCbCr Sub-Sampling",
892"tiff:YCbCrPositioning" => "YCbCr Positioning",
893"tiff:XResolution" => "X Resolution",
894"tiff:YResolution" => "Y Resolution",
895"tiff:ResolutionUnit" => "Resolution Unit",
896"tiff:TransferFunction" => "Transfer Function",
897"tiff:WhitePoint" => "White Point",
898"tiff:PrimaryChromaticities" => "Primary Chromaticities",
899"tiff:YCbCrCoefficients" => "YCbCr Coefficients",
900"tiff:ReferenceBlackWhite" => "Black & White Reference",
901"tiff:DateTime" => "Date & Time",
902"tiff:ImageDescription" => "Image Description",
903"tiff:Make" => "Make",
904"tiff:Model" => "Model",
905"tiff:Software" => "Software",
906"tiff:Artist" => "Artist",
907"tiff:Copyright" => "Copyright",
908
909
910"exif:ExifVersion" => "Exif Version",
911"exif:FlashpixVersion" => "Flash pix Version",
912"exif:ColorSpace" => "Color Space",
913"exif:ComponentsConfiguration" => "Components Configuration",
914"exif:CompressedBitsPerPixel" => "Compressed Bits Per Pixel",
915"exif:PixelXDimension" => "Pixel X Dimension",
916"exif:PixelYDimension" => "Pixel Y Dimension",
917"exif:MakerNote" => "Maker Note",
918"exif:UserComment" => "User Comment",
919"exif:RelatedSoundFile" => "Related Sound File",
920"exif:DateTimeOriginal" => "Date & Time of Original",
921"exif:DateTimeDigitized" => "Date & Time Digitized",
922"exif:ExposureTime" => "Exposure Time",
923"exif:FNumber" => "F Number",
924"exif:ExposureProgram" => "Exposure Program",
925"exif:SpectralSensitivity" => "Spectral Sensitivity",
926"exif:ISOSpeedRatings" => "ISO Speed Ratings",
927"exif:OECF" => "Opto-Electronic Conversion Function",
928"exif:ShutterSpeedValue" => "Shutter Speed Value",
929"exif:ApertureValue" => "Aperture Value",
930"exif:BrightnessValue" => "Brightness Value",
931"exif:ExposureBiasValue" => "Exposure Bias Value",
932"exif:MaxApertureValue" => "Max Aperture Value",
933"exif:SubjectDistance" => "Subject Distance",
934"exif:MeteringMode" => "Metering Mode",
935"exif:LightSource" => "Light Source",
936"exif:Flash" => "Flash",
937"exif:FocalLength" => "Focal Length",
938"exif:SubjectArea" => "Subject Area",
939"exif:FlashEnergy" => "Flash Energy",
940"exif:SpatialFrequencyResponse" => "Spatial Frequency Response",
941"exif:FocalPlaneXResolution" => "Focal Plane X Resolution",
942"exif:FocalPlaneYResolution" => "Focal Plane Y Resolution",
943"exif:FocalPlaneResolutionUnit" => "Focal Plane Resolution Unit",
944"exif:SubjectLocation" => "Subject Location",
945"exif:SensingMethod" => "Sensing Method",
946"exif:FileSource" => "File Source",
947"exif:SceneType" => "Scene Type",
948"exif:CFAPattern" => "Colour Filter Array Pattern",
949"exif:CustomRendered" => "Custom Rendered",
950"exif:ExposureMode" => "Exposure Mode",
951"exif:WhiteBalance" => "White Balance",
952"exif:DigitalZoomRatio" => "Digital Zoom Ratio",
953"exif:FocalLengthIn35mmFilm" => "Focal Length In 35mm Film",
954"exif:SceneCaptureType" => "Scene Capture Type",
955"exif:GainControl" => "Gain Control",
956"exif:Contrast" => "Contrast",
957"exif:Saturation" => "Saturation",
958"exif:Sharpness" => "Sharpness",
959"exif:DeviceSettingDescription" => "Device Setting Description",
960"exif:SubjectDistanceRange" => "Subject Distance Range",
961"exif:ImageUniqueID" => "Image Unique ID",
962"exif:GPSVersionID" => "GPS Version ID",
963"exif:GPSLatitude" => "GPS Latitude",
964"exif:GPSLongitude" => "GPS Longitude",
965"exif:GPSAltitudeRef" => "GPS Altitude Reference",
966"exif:GPSAltitude" => "GPS Altitude",
967"exif:GPSTimeStamp" => "GPS Time Stamp",
968"exif:GPSSatellites" => "GPS Satellites",
969"exif:GPSStatus" => "GPS Status",
970"exif:GPSMeasureMode" => "GPS Measure Mode",
971"exif:GPSDOP" => "GPS Degree Of Precision",
972"exif:GPSSpeedRef" => "GPS Speed Reference",
973"exif:GPSSpeed" => "GPS Speed",
974"exif:GPSTrackRef" => "GPS Track Reference",
975"exif:GPSTrack" => "GPS Track",
976"exif:GPSImgDirectionRef" => "GPS Image Direction Reference",
977"exif:GPSImgDirection" => "GPS Image Direction",
978"exif:GPSMapDatum" => "GPS Map Datum",
979"exif:GPSDestLatitude" => "GPS Destination Latitude",
980"exif:GPSDestLongitude" => "GPS Destnation Longitude",
981"exif:GPSDestBearingRef" => "GPS Destination Bearing Reference",
982"exif:GPSDestBearing" => "GPS Destination Bearing",
983"exif:GPSDestDistanceRef" => "GPS Destination Distance Reference",
984"exif:GPSDestDistance" => "GPS Destination Distance",
985"exif:GPSProcessingMethod" => "GPS Processing Method",
986"exif:GPSAreaInformation" => "GPS Area Information",
987"exif:GPSDifferential" => "GPS Differential",
988
989"stDim:w" => "Width",
990"stDim:h" => "Height",
991"stDim:unit" => "Units",
992
993"xapGImg:height" => "Height",
994"xapGImg:width" => "Width",
995"xapGImg:format" => "Format",
996"xapGImg:image" => "Image",
997
998"stEvt:action" => "Action",
999"stEvt:instanceID" => "Instance ID",
1000"stEvt:parameters" => "Parameters",
1001"stEvt:softwareAgent" => "Software Agent",
1002"stEvt:when" => "When",
1003
1004"stRef:instanceID" => "Instance ID",
1005"stRef:documentID" => "Document ID",
1006"stRef:versionID" => "Version ID",
1007"stRef:renditionClass" => "Rendition Class",
1008"stRef:renditionParams" => "Rendition Parameters",
1009"stRef:manager" => "Asset Management System",
1010"stRef:managerVariant" => "Particular Variant of Asset Management System",
1011"stRef:manageTo" => "Manage To",
1012"stRef:manageUI" => "Managed Resource URI",
1013
1014"stVer:comments" => "",
1015"stVer:event" => "",
1016"stVer:modifyDate" => "",
1017"stVer:modifier" => "",
1018"stVer:version" => "",
1019
1020
1021
1022"stJob:name" => "Job Name",
1023"stJob:id" => "Unique Job ID",
1024"stJob:url" => "URL for External Job Management File",
1025
1026// Exif Flash
1027"exif:Fired" => "Fired",
1028"exif:Return" => "Return",
1029"exif:Mode" => "Mode",
1030"exif:Function" => "Function",
1031"exif:RedEyeMode" => "Red Eye Mode",
1032
1033// Exif OECF/SFR
1034"exif:Columns" => "Columns",
1035"exif:Rows" => "Rows",
1036"exif:Names" => "Names",
1037"exif:Values" => "Values",
1038
1039// Exif CFAPattern
1040"exif:Columns" => "Columns",
1041"exif:Rows" => "Rows",
1042"exif:Values" => "Values",
1043
1044
1045// Exif DeviceSettings
1046"exif:Columns" => "Columns",
1047"exif:Rows" => "Rows",
1048"exif:Settings" => "Settings",
1049
1050
1051
1052);
1053
1054/******************************************************************************
1055* End of Global Variable:     XMP_tag_captions
1056******************************************************************************/
1057
1058
1059?>
Note: See TracBrowser for help on using the repository browser.