ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
Image_XMP Class Reference

getID3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g // More...

+ Collaboration diagram for Image_XMP:

Public Member Functions

 isValid ()
 Returns the status of XMP parsing during instantiation. More...
 
 getAllTags ()
 Get a copy of all XMP tags extracted from the image. More...
 
 _get_jpeg_header_data ($filename)
 Reads all the JPEG header segments from an JPEG image file into an array. More...
 
 _get_XMP_text ($filename)
 Retrieves XMP information from an APP1 JPEG segment and returns the raw XML text as a string. More...
 
 read_XMP_array_from_text ($xmltext)
 Parses a string containing XMP data (XML), and returns an array which contains all the XMP (XML) information. More...
 
 Image_XMP ($sFilename)
 Constructor. More...
 

Data Fields

 $_sFilename = null
 
 $_aXMP = array()
 
 $_bXMPParse = false
 

Detailed Description

getID3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g //

Definition at line 34 of file module.tag.xmp.php.

Member Function Documentation

◆ _get_jpeg_header_data()

Image_XMP::_get_jpeg_header_data (   $filename)

Reads all the JPEG header segments from an JPEG image file into an array.

Parameters
string$filename- the filename of the JPEG file to read
Returns
array $headerdata - Array of JPEG header segments
boolean FALSE - if headers could not be read

Definition at line 87 of file module.tag.xmp.php.

88 {
89 // prevent refresh from aborting file operations and hosing file
90 ignore_user_abort(true);
91
92 // Attempt to open the jpeg file - the at symbol supresses the error message about
93 // not being able to open files. The file_exists would have been used, but it
94 // does not work with files fetched over http or ftp.
95 if (is_readable($filename) && is_file($filename) && ($filehnd = fopen($filename, 'rb'))) {
96 // great
97 } else {
98 return false;
99 }
100
101 // Read the first two characters
102 $data = fread($filehnd, 2);
103
104 // Check that the first two characters are 0xFF 0xD8 (SOI - Start of image)
105 if ($data != "\xFF\xD8")
106 {
107 // No SOI (FF D8) at start of file - This probably isn't a JPEG file - close file and return;
108 echo '<p>This probably is not a JPEG file</p>'."\n";
109 fclose($filehnd);
110 return false;
111 }
112
113 // Read the third character
114 $data = fread($filehnd, 2);
115
116 // Check that the third character is 0xFF (Start of first segment header)
117 if ($data{0} != "\xFF")
118 {
119 // NO FF found - close file and return - JPEG is probably corrupted
120 fclose($filehnd);
121 return false;
122 }
123
124 // Flag that we havent yet hit the compressed image data
125 $hit_compressed_image_data = false;
126
127 // Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
128 // 2) we have hit the compressed image data (no more headers are allowed after data)
129 // 3) or end of file is hit
130
131 while (($data{1} != "\xD9") && (!$hit_compressed_image_data) && (!feof($filehnd)))
132 {
133 // Found a segment to look at.
134 // Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
135 if ((ord($data{1}) < 0xD0) || (ord($data{1}) > 0xD7))
136 {
137 // Segment isn't a Restart marker
138 // Read the next two bytes (size)
139 $sizestr = fread($filehnd, 2);
140
141 // convert the size bytes to an integer
142 $decodedsize = unpack('nsize', $sizestr);
143
144 // Save the start position of the data
145 $segdatastart = ftell($filehnd);
146
147 // Read the segment data with length indicated by the previously read size
148 $segdata = fread($filehnd, $decodedsize['size'] - 2);
149
150 // Store the segment information in the output array
151 $headerdata[] = array(
152 'SegType' => ord($data{1}),
153 'SegName' => $GLOBALS['JPEG_Segment_Names'][ord($data{1})],
154 'SegDataStart' => $segdatastart,
155 'SegData' => $segdata,
156 );
157 }
158
159 // If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
160 if ($data{1} == "\xDA")
161 {
162 // Flag that we have hit the compressed image data - exit loop as no more headers available.
163 $hit_compressed_image_data = true;
164 }
165 else
166 {
167 // Not an SOS - Read the next two bytes - should be the segment marker for the next segment
168 $data = fread($filehnd, 2);
169
170 // Check that the first byte of the two is 0xFF as it should be for a marker
171 if ($data{0} != "\xFF")
172 {
173 // NO FF found - close file and return - JPEG is probably corrupted
174 fclose($filehnd);
175 return false;
176 }
177 }
178 }
179
180 // Close File
181 fclose($filehnd);
182 // Alow the user to abort from now on
183 ignore_user_abort(false);
184
185 // Return the header data retrieved
186 return $headerdata;
187 }
$filename
Definition: buildRTE.php:89
$data
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.

References $data, $filename, and $GLOBALS.

Referenced by _get_XMP_text().

+ Here is the caller graph for this function:

◆ _get_XMP_text()

Image_XMP::_get_XMP_text (   $filename)

Retrieves XMP information from an APP1 JPEG segment and returns the raw XML text as a string.

Parameters
string$filename- the filename of the JPEG file to read
Returns
string $xmp_data - the string of raw XML text
boolean FALSE - if an APP 1 XMP segment could not be found, or if an error occured

Definition at line 197 of file module.tag.xmp.php.

198 {
199 //Get JPEG header data
200 $jpeg_header_data = $this->_get_jpeg_header_data($filename);
201
202 //Cycle through the header segments
203 for ($i = 0; $i < count($jpeg_header_data); $i++)
204 {
205 // If we find an APP1 header,
206 if (strcmp($jpeg_header_data[$i]['SegName'], 'APP1') == 0)
207 {
208 // And if it has the Adobe XMP/RDF label (http://ns.adobe.com/xap/1.0/\x00) ,
209 if (strncmp($jpeg_header_data[$i]['SegData'], 'http://ns.adobe.com/xap/1.0/'."\x00", 29) == 0)
210 {
211 // Found a XMP/RDF block
212 // Return the XMP text
213 $xmp_data = substr($jpeg_header_data[$i]['SegData'], 29);
214
215 return trim($xmp_data); // trim() should not be neccesary, but some files found in the wild with null-terminated block (known samples from Apple Aperture) causes problems elsewhere (see http://www.getid3.org/phpBB3/viewtopic.php?f=4&t=1153)
216 }
217 }
218 }
219 return false;
220 }
_get_jpeg_header_data($filename)
Reads all the JPEG header segments from an JPEG image file into an array.

References $filename, and _get_jpeg_header_data().

Referenced by Image_XMP().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getAllTags()

Image_XMP::getAllTags ( )

Get a copy of all XMP tags extracted from the image.

Returns
array - An array of XMP fields as it extracted by the XMPparse() function

Definition at line 75 of file module.tag.xmp.php.

76 {
77 return $this->_aXMP;
78 }

References $_aXMP.

◆ Image_XMP()

Image_XMP::Image_XMP (   $sFilename)

Constructor.

Parameters
string- Name of the image file to access and extract XMP information from.

Definition at line 402 of file module.tag.xmp.php.

403 {
404 $this->_sFilename = $sFilename;
405
406 if (is_file($this->_sFilename))
407 {
408 // Get XMP data
409 $xmp_data = $this->_get_XMP_text($sFilename);
410 if ($xmp_data)
411 {
412 $this->_aXMP = $this->read_XMP_array_from_text($xmp_data);
413 $this->_bXMPParse = true;
414 }
415 }
416 }
read_XMP_array_from_text($xmltext)
Parses a string containing XMP data (XML), and returns an array which contains all the XMP (XML) info...
_get_XMP_text($filename)
Retrieves XMP information from an APP1 JPEG segment and returns the raw XML text as a string.

References _get_XMP_text(), and read_XMP_array_from_text().

+ Here is the call graph for this function:

◆ isValid()

Image_XMP::isValid ( )

Returns the status of XMP parsing during instantiation.

You'll normally want to call this method before trying to get XMP fields.

Returns
boolean Returns true if an APP1 segment was found to contain XMP metadata.

Definition at line 65 of file module.tag.xmp.php.

66 {
67 return $this->_bXMPParse;
68 }

References $_bXMPParse.

◆ read_XMP_array_from_text()

Image_XMP::read_XMP_array_from_text (   $xmltext)

Parses a string containing XMP data (XML), and returns an array which contains all the XMP (XML) information.

Parameters
string$xml_text- a string containing the XMP data (XML) to be parsed
Returns
array $xmp_array - an array containing all xmp details retrieved.
boolean FALSE - couldn't parse the XMP data

Definition at line 230 of file module.tag.xmp.php.

231 {
232 // Check if there actually is any text to parse
233 if (trim($xmltext) == '')
234 {
235 return false;
236 }
237
238 // Create an instance of a xml parser to parse the XML text
239 $xml_parser = xml_parser_create('UTF-8');
240
241 // Change: Fixed problem that caused the whitespace (especially newlines) to be destroyed when converting xml text to an xml array, as of revision 1.10
242
243 // We would like to remove unneccessary white space, but this will also
244 // remove things like newlines (&#xA;) in the XML values, so white space
245 // will have to be removed later
246 if (xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 0) == false)
247 {
248 // Error setting case folding - destroy the parser and return
249 xml_parser_free($xml_parser);
250 return false;
251 }
252
253 // to use XML code correctly we have to turn case folding
254 // (uppercasing) off. XML is case sensitive and upper
255 // casing is in reality XML standards violation
256 if (xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0) == false)
257 {
258 // Error setting case folding - destroy the parser and return
259 xml_parser_free($xml_parser);
260 return false;
261 }
262
263 // Parse the XML text into a array structure
264 if (xml_parse_into_struct($xml_parser, $xmltext, $values, $tags) == 0)
265 {
266 // Error Parsing XML - destroy the parser and return
267 xml_parser_free($xml_parser);
268 return false;
269 }
270
271 // Destroy the xml parser
272 xml_parser_free($xml_parser);
273
274 // Clear the output array
275 $xmp_array = array();
276
277 // The XMP data has now been parsed into an array ...
278
279 // Cycle through each of the array elements
280 $current_property = ''; // current property being processed
281 $container_index = -1; // -1 = no container open, otherwise index of container content
282 foreach ($values as $xml_elem)
283 {
284 // Syntax and Class names
285 switch ($xml_elem['tag'])
286 {
287 case 'x:xmpmeta':
288 // only defined attribute is x:xmptk written by Adobe XMP Toolkit; value is the version of the toolkit
289 break;
290
291 case 'rdf:RDF':
292 // required element immediately within x:xmpmeta; no data here
293 break;
294
295 case 'rdf:Description':
296 switch ($xml_elem['type'])
297 {
298 case 'open':
299 case 'complete':
300 if (array_key_exists('attributes', $xml_elem))
301 {
302 // rdf:Description may contain wanted attributes
303 foreach (array_keys($xml_elem['attributes']) as $key)
304 {
305 // Check whether we want this details from this attribute
306// if (in_array($key, $GLOBALS['XMP_tag_captions']))
307 if (true)
308 {
309 // Attribute wanted
310 $xmp_array[$key] = $xml_elem['attributes'][$key];
311 }
312 }
313 }
314 case 'cdata':
315 case 'close':
316 break;
317 }
318
319 case 'rdf:ID':
320 case 'rdf:nodeID':
321 // Attributes are ignored
322 break;
323
324 case 'rdf:li':
325 // Property member
326 if ($xml_elem['type'] == 'complete')
327 {
328 if (array_key_exists('attributes', $xml_elem))
329 {
330 // If Lang Alt (language alternatives) then ensure we take the default language
331 if (isset($xml_elem['attributes']['xml:lang']) && ($xml_elem['attributes']['xml:lang'] != 'x-default'))
332 {
333 break;
334 }
335 }
336 if ($current_property != '')
337 {
338 $xmp_array[$current_property][$container_index] = (isset($xml_elem['value']) ? $xml_elem['value'] : '');
339 $container_index += 1;
340 }
341 //else unidentified attribute!!
342 }
343 break;
344
345 case 'rdf:Seq':
346 case 'rdf:Bag':
347 case 'rdf:Alt':
348 // Container found
349 switch ($xml_elem['type'])
350 {
351 case 'open':
352 $container_index = 0;
353 break;
354 case 'close':
355 $container_index = -1;
356 break;
357 case 'cdata':
358 break;
359 }
360 break;
361
362 default:
363 // Check whether we want the details from this attribute
364// if (in_array($xml_elem['tag'], $GLOBALS['XMP_tag_captions']))
365 if (true)
366 {
367 switch ($xml_elem['type'])
368 {
369 case 'open':
370 // open current element
371 $current_property = $xml_elem['tag'];
372 break;
373
374 case 'close':
375 // close current element
376 $current_property = '';
377 break;
378
379 case 'complete':
380 // store attribute value
381 $xmp_array[$xml_elem['tag']] = (isset($xml_elem['attributes']) ? $xml_elem['attributes'] : (isset($xml_elem['value']) ? $xml_elem['value'] : ''));
382 break;
383
384 case 'cdata':
385 // ignore
386 break;
387 }
388 }
389 break;
390 }
391
392 }
393 return $xmp_array;
394 }

Referenced by Image_XMP().

+ Here is the caller graph for this function:

Field Documentation

◆ $_aXMP

Image_XMP::$_aXMP = array()

Definition at line 48 of file module.tag.xmp.php.

Referenced by getAllTags().

◆ $_bXMPParse

Image_XMP::$_bXMPParse = false

Definition at line 55 of file module.tag.xmp.php.

Referenced by isValid().

◆ $_sFilename

Image_XMP::$_sFilename = null

Definition at line 41 of file module.tag.xmp.php.


The documentation for this class was generated from the following file: