Merge "Typo fix"
[mediawiki.git] / includes / media / XMPInfo.php
blobf0b2cb5e85c473730c391c92add1b59814d32bdf
1 <?php
2 /**
3 * Definitions for XMPReader class.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
20 * @file
21 * @ingroup Media
24 /**
25 * This class is just a container for a big array
26 * used by XMPReader to determine which XMP items to
27 * extract.
29 class XMPInfo {
31 /** get the items array
32 * @return Array XMP item configuration array.
34 public static function getItems() {
35 if ( !self::$ranHooks ) {
36 // This is for if someone makes a custom metadata extension.
37 // For example, a medical wiki might want to decode DICOM xmp properties.
38 wfRunHooks( 'XMPGetInfo', Array( &self::$items ) );
39 self::$ranHooks = true; // Only want to do this once.
41 return self::$items;
44 static private $ranHooks = false;
46 /**
47 * XMPInfo::$items keeps a list of all the items
48 * we are interested to extract, as well as
49 * information about the item like what type
50 * it is.
52 * Format is an array of namespaces,
53 * each containing an array of tags
54 * each tag is an array of information about the
55 * tag, including:
56 * * map_group - what group (used for precedence during conflicts)
57 * * mode - What type of item (self::MODE_SIMPLE usually, see above for all values)
58 * * validate - method to validate input. Could also post-process the input. A string value is assumed to be a static method of XMPValidate. Can also take a array( 'className', 'methodName' ).
59 * * choices - array of potential values (format of 'value' => true ). Only used with validateClosed
60 * * rangeLow and rangeHigh - alternative to choices for numeric ranges. Again for validateClosed only.
61 * * children - for MODE_STRUCT items, allowed children.
62 * * structPart - Indicates that this element can only appear as a member of a structure.
64 * currently this just has a bunch of exif values as this class is only half-done
66 static private $items = array(
67 'http://ns.adobe.com/exif/1.0/' => array(
68 'ApertureValue' => array(
69 'map_group' => 'exif',
70 'mode' => XMPReader::MODE_SIMPLE,
71 'validate' => 'validateRational'
73 'BrightnessValue' => array(
74 'map_group' => 'exif',
75 'mode' => XMPReader::MODE_SIMPLE,
76 'validate' => 'validateRational'
78 'CompressedBitsPerPixel' => array(
79 'map_group' => 'exif',
80 'mode' => XMPReader::MODE_SIMPLE,
81 'validate' => 'validateRational'
83 'DigitalZoomRatio' => array(
84 'map_group' => 'exif',
85 'mode' => XMPReader::MODE_SIMPLE,
86 'validate' => 'validateRational'
88 'ExposureBiasValue' => array(
89 'map_group' => 'exif',
90 'mode' => XMPReader::MODE_SIMPLE,
91 'validate' => 'validateRational'
93 'ExposureIndex' => array(
94 'map_group' => 'exif',
95 'mode' => XMPReader::MODE_SIMPLE,
96 'validate' => 'validateRational'
98 'ExposureTime' => array(
99 'map_group' => 'exif',
100 'mode' => XMPReader::MODE_SIMPLE,
101 'validate' => 'validateRational'
103 'FlashEnergy' => array(
104 'map_group' => 'exif',
105 'mode' => XMPReader::MODE_SIMPLE,
106 'validate' => 'validateRational',
108 'FNumber' => array(
109 'map_group' => 'exif',
110 'mode' => XMPReader::MODE_SIMPLE,
111 'validate' => 'validateRational'
113 'FocalLength' => array(
114 'map_group' => 'exif',
115 'mode' => XMPReader::MODE_SIMPLE,
116 'validate' => 'validateRational'
118 'FocalPlaneXResolution' => array(
119 'map_group' => 'exif',
120 'mode' => XMPReader::MODE_SIMPLE,
121 'validate' => 'validateRational'
123 'FocalPlaneYResolution' => array(
124 'map_group' => 'exif',
125 'mode' => XMPReader::MODE_SIMPLE,
126 'validate' => 'validateRational'
128 'GPSAltitude' => array(
129 'map_group' => 'exif',
130 'mode' => XMPReader::MODE_SIMPLE,
131 'validate' => 'validateRational',
133 'GPSDestBearing' => array(
134 'map_group' => 'exif',
135 'mode' => XMPReader::MODE_SIMPLE,
136 'validate' => 'validateRational'
138 'GPSDestDistance' => array(
139 'map_group' => 'exif',
140 'mode' => XMPReader::MODE_SIMPLE,
141 'validate' => 'validateRational'
143 'GPSDOP' => array(
144 'map_group' => 'exif',
145 'mode' => XMPReader::MODE_SIMPLE,
146 'validate' => 'validateRational'
148 'GPSImgDirection' => array(
149 'map_group' => 'exif',
150 'mode' => XMPReader::MODE_SIMPLE,
151 'validate' => 'validateRational'
153 'GPSSpeed' => array(
154 'map_group' => 'exif',
155 'mode' => XMPReader::MODE_SIMPLE,
156 'validate' => 'validateRational'
158 'GPSTrack' => array(
159 'map_group' => 'exif',
160 'mode' => XMPReader::MODE_SIMPLE,
161 'validate' => 'validateRational'
163 'MaxApertureValue' => array(
164 'map_group' => 'exif',
165 'mode' => XMPReader::MODE_SIMPLE,
166 'validate' => 'validateRational'
168 'ShutterSpeedValue' => array(
169 'map_group' => 'exif',
170 'mode' => XMPReader::MODE_SIMPLE,
171 'validate' => 'validateRational'
173 'SubjectDistance' => array(
174 'map_group' => 'exif',
175 'mode' => XMPReader::MODE_SIMPLE,
176 'validate' => 'validateRational'
178 /* Flash */
179 'Flash' => array(
180 'mode' => XMPReader::MODE_STRUCT,
181 'children' => array(
182 'Fired' => true,
183 'Function' => true,
184 'Mode' => true,
185 'RedEyeMode' => true,
186 'Return' => true,
188 'validate' => 'validateFlash',
189 'map_group' => 'exif',
191 'Fired' => array(
192 'map_group' => 'exif',
193 'validate' => 'validateBoolean',
194 'mode' => XMPReader::MODE_SIMPLE,
195 'structPart'=> true,
197 'Function' => array(
198 'map_group' => 'exif',
199 'validate' => 'validateBoolean',
200 'mode' => XMPReader::MODE_SIMPLE,
201 'structPart'=> true,
203 'Mode' => array(
204 'map_group' => 'exif',
205 'validate' => 'validateClosed',
206 'mode' => XMPReader::MODE_SIMPLE,
207 'choices' => array( '0' => true, '1' => true,
208 '2' => true, '3' => true ),
209 'structPart'=> true,
211 'Return' => array(
212 'map_group' => 'exif',
213 'validate' => 'validateClosed',
214 'mode' => XMPReader::MODE_SIMPLE,
215 'choices' => array( '0' => true,
216 '2' => true, '3' => true ),
217 'structPart'=> true,
219 'RedEyeMode' => array(
220 'map_group' => 'exif',
221 'validate' => 'validateBoolean',
222 'mode' => XMPReader::MODE_SIMPLE,
223 'structPart'=> true,
225 /* End Flash */
226 'ISOSpeedRatings' => array(
227 'map_group' => 'exif',
228 'mode' => XMPReader::MODE_SEQ,
229 'validate' => 'validateInteger'
231 /* end rational things */
232 'ColorSpace' => array(
233 'map_group' => 'exif',
234 'mode' => XMPReader::MODE_SIMPLE,
235 'validate' => 'validateClosed',
236 'choices' => array( '1' => true, '65535' => true ),
238 'ComponentsConfiguration' => array(
239 'map_group' => 'exif',
240 'mode' => XMPReader::MODE_SEQ,
241 'validate' => 'validateClosed',
242 'choices' => array( '1' => true, '2' => true, '3' => true, '4' => true,
243 '5' => true, '6' => true )
245 'Contrast' => array(
246 'map_group' => 'exif',
247 'mode' => XMPReader::MODE_SIMPLE,
248 'validate' => 'validateClosed',
249 'choices' => array( '0' => true, '1' => true, '2' => true )
251 'CustomRendered' => array(
252 'map_group' => 'exif',
253 'mode' => XMPReader::MODE_SIMPLE,
254 'validate' => 'validateClosed',
255 'choices' => array( '0' => true, '1' => true )
257 'DateTimeOriginal' => array(
258 'map_group' => 'exif',
259 'mode' => XMPReader::MODE_SIMPLE,
260 'validate' => 'validateDate',
262 'DateTimeDigitized' => array( /* xmp:CreateDate */
263 'map_group' => 'exif',
264 'mode' => XMPReader::MODE_SIMPLE,
265 'validate' => 'validateDate',
267 /* todo: there might be interesting information in
268 * exif:DeviceSettingDescription, but need to find an
269 * example
271 'ExifVersion' => array(
272 'map_group' => 'exif',
273 'mode' => XMPReader::MODE_SIMPLE,
275 'ExposureMode' => array(
276 'map_group' => 'exif',
277 'mode' => XMPReader::MODE_SIMPLE,
278 'validate' => 'validateClosed',
279 'rangeLow' => 0,
280 'rangeHigh' => 2,
282 'ExposureProgram' => array(
283 'map_group' => 'exif',
284 'mode' => XMPReader::MODE_SIMPLE,
285 'validate' => 'validateClosed',
286 'rangeLow' => 0,
287 'rangeHigh' => 8,
289 'FileSource' => array(
290 'map_group' => 'exif',
291 'mode' => XMPReader::MODE_SIMPLE,
292 'validate' => 'validateClosed',
293 'choices' => array( '3' => true )
295 'FlashpixVersion' => array(
296 'map_group' => 'exif',
297 'mode' => XMPReader::MODE_SIMPLE,
299 'FocalLengthIn35mmFilm' => array(
300 'map_group' => 'exif',
301 'mode' => XMPReader::MODE_SIMPLE,
302 'validate' => 'validateInteger',
304 'FocalPlaneResolutionUnit' => array(
305 'map_group' => 'exif',
306 'mode' => XMPReader::MODE_SIMPLE,
307 'validate' => 'validateClosed',
308 'choices' => array( '2' => true, '3' => true ),
310 'GainControl' => array(
311 'map_group' => 'exif',
312 'mode' => XMPReader::MODE_SIMPLE,
313 'validate' => 'validateClosed',
314 'rangeLow' => 0,
315 'rangeHigh' => 4,
317 /* this value is post-processed out later */
318 'GPSAltitudeRef' => array(
319 'map_group' => 'exif',
320 'mode' => XMPReader::MODE_SIMPLE,
321 'validate' => 'validateClosed',
322 'choices' => array( '0' => true, '1' => true ),
324 'GPSAreaInformation' => array(
325 'map_group' => 'exif',
326 'mode' => XMPReader::MODE_SIMPLE,
328 'GPSDestBearingRef' => array(
329 'map_group' => 'exif',
330 'mode' => XMPReader::MODE_SIMPLE,
331 'validate' => 'validateClosed',
332 'choices' => array( 'T' => true, 'M' => true ),
334 'GPSDestDistanceRef' => array(
335 'map_group' => 'exif',
336 'mode' => XMPReader::MODE_SIMPLE,
337 'validate' => 'validateClosed',
338 'choices' => array( 'K' => true, 'M' => true,
339 'N' => true ),
341 'GPSDestLatitude' => array(
342 'map_group' => 'exif',
343 'mode' => XMPReader::MODE_SIMPLE,
344 'validate' => 'validateGPS',
346 'GPSDestLongitude' => array(
347 'map_group' => 'exif',
348 'mode' => XMPReader::MODE_SIMPLE,
349 'validate' => 'validateGPS',
351 'GPSDifferential' => array(
352 'map_group' => 'exif',
353 'mode' => XMPReader::MODE_SIMPLE,
354 'validate' => 'validateClosed',
355 'choices' => array( '0' => true, '1' => true ),
357 'GPSImgDirectionRef' => array(
358 'map_group' => 'exif',
359 'mode' => XMPReader::MODE_SIMPLE,
360 'validate' => 'validateClosed',
361 'choices' => array( 'T' => true, 'M' => true ),
363 'GPSLatitude' => array(
364 'map_group' => 'exif',
365 'mode' => XMPReader::MODE_SIMPLE,
366 'validate' => 'validateGPS',
368 'GPSLongitude' => array(
369 'map_group' => 'exif',
370 'mode' => XMPReader::MODE_SIMPLE,
371 'validate' => 'validateGPS',
373 'GPSMapDatum' => array(
374 'map_group' => 'exif',
375 'mode' => XMPReader::MODE_SIMPLE,
377 'GPSMeasureMode' => array(
378 'map_group' => 'exif',
379 'mode' => XMPReader::MODE_SIMPLE,
380 'validate' => 'validateClosed',
381 'choices' => array( '2' => true, '3' => true )
383 'GPSProcessingMethod' => array(
384 'map_group' => 'exif',
385 'mode' => XMPReader::MODE_SIMPLE,
387 'GPSSatellites' => array(
388 'map_group' => 'exif',
389 'mode' => XMPReader::MODE_SIMPLE,
391 'GPSSpeedRef' => array(
392 'map_group' => 'exif',
393 'mode' => XMPReader::MODE_SIMPLE,
394 'validate' => 'validateClosed',
395 'choices' => array( 'K' => true, 'M' => true,
396 'N' => true ),
398 'GPSStatus' => array(
399 'map_group' => 'exif',
400 'mode' => XMPReader::MODE_SIMPLE,
401 'validate' => 'validateClosed',
402 'choices' => array( 'A' => true, 'V' => true )
404 'GPSTimeStamp' => array(
405 'map_group' => 'exif',
406 // Note: in exif, GPSDateStamp does not include
407 // the time, where here it does.
408 'map_name' => 'GPSDateStamp',
409 'mode' => XMPReader::MODE_SIMPLE,
410 'validate' => 'validateDate',
412 'GPSTrackRef' => array(
413 'map_group' => 'exif',
414 'mode' => XMPReader::MODE_SIMPLE,
415 'validate' => 'validateClosed',
416 'choices' => array( 'T' => true, 'M' => true )
418 'GPSVersionID' => array(
419 'map_group' => 'exif',
420 'mode' => XMPReader::MODE_SIMPLE,
422 'ImageUniqueID' => array(
423 'map_group' => 'exif',
424 'mode' => XMPReader::MODE_SIMPLE,
426 'LightSource' => array(
427 'map_group' => 'exif',
428 'mode' => XMPReader::MODE_SIMPLE,
429 'validate' => 'validateClosed',
430 /* can't use a range, as it skips... */
431 'choices' => array( '0' => true, '1' => true,
432 '2' => true, '3' => true, '4' => true,
433 '9' => true, '10' => true, '11' => true,
434 '12' => true, '13' => true,
435 '14' => true, '15' => true,
436 '17' => true, '18' => true,
437 '19' => true, '20' => true,
438 '21' => true, '22' => true,
439 '23' => true, '24' => true,
440 '255' => true,
443 'MeteringMode' => array(
444 'map_group' => 'exif',
445 'mode' => XMPReader::MODE_SIMPLE,
446 'validate' => 'validateClosed',
447 'rangeLow' => 0,
448 'rangeHigh' => 6,
449 'choices' => array( '255' => true ),
451 /* Pixel(X|Y)Dimension are rather useless, but for
452 * completeness since we do it with exif.
454 'PixelXDimension' => array(
455 'map_group' => 'exif',
456 'mode' => XMPReader::MODE_SIMPLE,
457 'validate' => 'validateInteger',
459 'PixelYDimension' => array(
460 'map_group' => 'exif',
461 'mode' => XMPReader::MODE_SIMPLE,
462 'validate' => 'validateInteger',
464 'Saturation' => array(
465 'map_group' => 'exif',
466 'mode' => XMPReader::MODE_SIMPLE,
467 'validate' => 'validateClosed',
468 'rangeLow' => 0,
469 'rangeHigh' => 2,
471 'SceneCaptureType' => array(
472 'map_group' => 'exif',
473 'mode' => XMPReader::MODE_SIMPLE,
474 'validate' => 'validateClosed',
475 'rangeLow' => 0,
476 'rangeHigh' => 3,
478 'SceneType' => array(
479 'map_group' => 'exif',
480 'mode' => XMPReader::MODE_SIMPLE,
481 'validate' => 'validateClosed',
482 'choices' => array( '1' => true ),
484 // Note, 6 is not valid SensingMethod.
485 'SensingMethod' => array(
486 'map_group' => 'exif',
487 'mode' => XMPReader::MODE_SIMPLE,
488 'validate' => 'validateClosed',
489 'rangeLow' => 1,
490 'rangeHigh' => 5,
491 'choices' => array( '7' => true, 8 => true ),
493 'Sharpness' => array(
494 'map_group' => 'exif',
495 'mode' => XMPReader::MODE_SIMPLE,
496 'validate' => 'validateClosed',
497 'rangeLow' => 0,
498 'rangeHigh' => 2,
500 'SpectralSensitivity' => array(
501 'map_group' => 'exif',
502 'mode' => XMPReader::MODE_SIMPLE,
504 // This tag should perhaps be displayed to user better.
505 'SubjectArea' => array(
506 'map_group' => 'exif',
507 'mode' => XMPReader::MODE_SEQ,
508 'validate' => 'validateInteger',
510 'SubjectDistanceRange' => array(
511 'map_group' => 'exif',
512 'mode' => XMPReader::MODE_SIMPLE,
513 'validate' => 'validateClosed',
514 'rangeLow' => 0,
515 'rangeHigh' => 3,
517 'SubjectLocation' => array(
518 'map_group' => 'exif',
519 'mode' => XMPReader::MODE_SEQ,
520 'validate' => 'validateInteger',
522 'UserComment' => array(
523 'map_group' => 'exif',
524 'mode' => XMPReader::MODE_LANG,
526 'WhiteBalance' => array(
527 'map_group' => 'exif',
528 'mode' => XMPReader::MODE_SIMPLE,
529 'validate' => 'validateClosed',
530 'choices' => array( '0' => true, '1' => true )
533 'http://ns.adobe.com/tiff/1.0/' => array(
534 'Artist' => array(
535 'map_group' => 'exif',
536 'mode' => XMPReader::MODE_SIMPLE,
538 'BitsPerSample' => array(
539 'map_group' => 'exif',
540 'mode' => XMPReader::MODE_SEQ,
541 'validate' => 'validateInteger',
543 'Compression' => array(
544 'map_group' => 'exif',
545 'mode' => XMPReader::MODE_SIMPLE,
546 'validate' => 'validateClosed',
547 'choices' => array( '1' => true, '6' => true ),
549 /* this prop should not be used in XMP. dc:rights is the correct prop */
550 'Copyright' => array(
551 'map_group' => 'exif',
552 'mode' => XMPReader::MODE_LANG,
554 'DateTime' => array( /* proper prop is xmp:ModifyDate */
555 'map_group' => 'exif',
556 'mode' => XMPReader::MODE_SIMPLE,
557 'validate' => 'validateDate',
559 'ImageDescription' => array( /* proper one is dc:description */
560 'map_group' => 'exif',
561 'mode' => XMPReader::MODE_LANG,
563 'ImageLength' => array(
564 'map_group' => 'exif',
565 'mode' => XMPReader::MODE_SIMPLE,
566 'validate' => 'validateInteger',
568 'ImageWidth' => array(
569 'map_group' => 'exif',
570 'mode' => XMPReader::MODE_SIMPLE,
571 'validate' => 'validateInteger',
573 'Make' => array(
574 'map_group' => 'exif',
575 'mode' => XMPReader::MODE_SIMPLE,
577 'Model' => array(
578 'map_group' => 'exif',
579 'mode' => XMPReader::MODE_SIMPLE,
581 /**** Do not extract this property
582 * It interferes with auto exif rotation.
583 * 'Orientation' => array(
584 * 'map_group' => 'exif',
585 * 'mode' => XMPReader::MODE_SIMPLE,
586 * 'validate' => 'validateClosed',
587 * 'choices' => array( '1' => true, '2' => true, '3' => true, '4' => true, 5 => true,
588 * '6' => true, '7' => true, '8' => true ),
590 ******/
591 'PhotometricInterpretation' => array(
592 'map_group' => 'exif',
593 'mode' => XMPReader::MODE_SIMPLE,
594 'validate' => 'validateClosed',
595 'choices' => array( '2' => true, '6' => true ),
597 'PlanerConfiguration' => array(
598 'map_group' => 'exif',
599 'mode' => XMPReader::MODE_SIMPLE,
600 'validate' => 'validateClosed',
601 'choices' => array( '1' => true, '2' => true ),
603 'PrimaryChromaticities' => array(
604 'map_group' => 'exif',
605 'mode' => XMPReader::MODE_SEQ,
606 'validate' => 'validateRational',
608 'ReferenceBlackWhite' => array(
609 'map_group' => 'exif',
610 'mode' => XMPReader::MODE_SEQ,
611 'validate' => 'validateRational',
613 'ResolutionUnit' => array(
614 'map_group' => 'exif',
615 'mode' => XMPReader::MODE_SIMPLE,
616 'validate' => 'validateClosed',
617 'choices' => array( '2' => true, '3' => true ),
619 'SamplesPerPixel' => array(
620 'map_group' => 'exif',
621 'mode' => XMPReader::MODE_SIMPLE,
622 'validate' => 'validateInteger',
624 'Software' => array( /* see xmp:CreatorTool */
625 'map_group' => 'exif',
626 'mode' => XMPReader::MODE_SIMPLE,
628 /* ignore TransferFunction */
629 'WhitePoint' => array(
630 'map_group' => 'exif',
631 'mode' => XMPReader::MODE_SEQ,
632 'validate' => 'validateRational',
634 'XResolution' => array(
635 'map_group' => 'exif',
636 'mode' => XMPReader::MODE_SIMPLE,
637 'validate' => 'validateRational',
639 'YResolution' => array(
640 'map_group' => 'exif',
641 'mode' => XMPReader::MODE_SIMPLE,
642 'validate' => 'validateRational',
644 'YCbCrCoefficients' => array(
645 'map_group' => 'exif',
646 'mode' => XMPReader::MODE_SEQ,
647 'validate' => 'validateRational',
649 'YCbCrPositioning' => array(
650 'map_group' => 'exif',
651 'mode' => XMPReader::MODE_SIMPLE,
652 'validate' => 'validateClosed',
653 'choices' => array( '1' => true, '2' => true ),
655 /********
656 * Disable extracting this property (bug 31944)
657 * Several files have a string instead of a Seq
658 * for this property. XMPReader doesn't handle
659 * mismatched types very gracefully (it marks
660 * the entire file as invalid, instead of just
661 * the relavent prop). Since this prop
662 * doesn't communicate all that useful information
663 * just disable this prop for now, until such
664 * XMPReader is more graceful (bug 32172)
665 * 'YCbCrSubSampling' => array(
666 * 'map_group' => 'exif',
667 * 'mode' => XMPReader::MODE_SEQ,
668 * 'validate' => 'validateClosed',
669 * 'choices' => array( '1' => true, '2' => true ),
670 * ),
673 'http://ns.adobe.com/exif/1.0/aux/' => array(
674 'Lens' => array(
675 'map_group' => 'exif',
676 'mode' => XMPReader::MODE_SIMPLE,
678 'SerialNumber' => array(
679 'map_group' => 'exif',
680 'mode' => XMPReader::MODE_SIMPLE,
682 'OwnerName' => array(
683 'map_group' => 'exif',
684 'map_name' => 'CameraOwnerName',
685 'mode' => XMPReader::MODE_SIMPLE,
688 'http://purl.org/dc/elements/1.1/' => array(
689 'title' => array(
690 'map_group' => 'general',
691 'map_name' => 'ObjectName',
692 'mode' => XMPReader::MODE_LANG
694 'description' => array(
695 'map_group' => 'general',
696 'map_name' => 'ImageDescription',
697 'mode' => XMPReader::MODE_LANG
699 'contributor' => array(
700 'map_group' => 'general',
701 'map_name' => 'dc-contributor',
702 'mode' => XMPReader::MODE_BAG
704 'coverage' => array(
705 'map_group' => 'general',
706 'map_name' => 'dc-coverage',
707 'mode' => XMPReader::MODE_SIMPLE,
709 'creator' => array(
710 'map_group' => 'general',
711 'map_name' => 'Artist', //map with exif Artist, iptc byline (2:80)
712 'mode' => XMPReader::MODE_SEQ,
714 'date' => array(
715 'map_group' => 'general',
716 // Note, not mapped with other date properties, as this type of date is
717 // non-specific: "A point or period of time associated with an event in
718 // the lifecycle of the resource"
719 'map_name' => 'dc-date',
720 'mode' => XMPReader::MODE_SEQ,
721 'validate' => 'validateDate',
723 /* Do not extract dc:format, as we've got better ways to determine mimetype */
724 'identifier' => array(
725 'map_group' => 'deprecated',
726 'map_name' => 'Identifier',
727 'mode' => XMPReader::MODE_SIMPLE,
729 'language' => array(
730 'map_group' => 'general',
731 'map_name' => 'LanguageCode', /* mapped with iptc 2:135 */
732 'mode' => XMPReader::MODE_BAG,
733 'validate' => 'validateLangCode',
735 'publisher' => array(
736 'map_group' => 'general',
737 'map_name' => 'dc-publisher',
738 'mode' => XMPReader::MODE_BAG,
740 // for related images/resources
741 'relation' => array(
742 'map_group' => 'general',
743 'map_name' => 'dc-relation',
744 'mode' => XMPReader::MODE_BAG,
746 'rights' => array(
747 'map_group' => 'general',
748 'map_name' => 'Copyright',
749 'mode' => XMPReader::MODE_LANG,
751 // Note: source is not mapped with iptc source, since iptc
752 // source describes the source of the image in terms of a person
753 // who provided the image, where this is to describe an image that the
754 // current one is based on.
755 'source' => array(
756 'map_group' => 'general',
757 'map_name' => 'dc-source',
758 'mode' => XMPReader::MODE_SIMPLE,
760 'subject' => array(
761 'map_group' => 'general',
762 'map_name' => 'Keywords', /* maps to iptc 2:25 */
763 'mode' => XMPReader::MODE_BAG,
765 'type' => array(
766 'map_group' => 'general',
767 'map_name' => 'dc-type',
768 'mode' => XMPReader::MODE_BAG,
771 'http://ns.adobe.com/xap/1.0/' => array(
772 'CreateDate' => array(
773 'map_group' => 'general',
774 'map_name' => 'DateTimeDigitized',
775 'mode' => XMPReader::MODE_SIMPLE,
776 'validate' => 'validateDate',
778 'CreatorTool' => array(
779 'map_group' => 'general',
780 'map_name' => 'Software',
781 'mode' => XMPReader::MODE_SIMPLE
783 'Identifier' => array(
784 'map_group' => 'general',
785 'mode' => XMPReader::MODE_BAG,
787 'Label' => array(
788 'map_group' => 'general',
789 'mode' => XMPReader::MODE_SIMPLE,
791 'ModifyDate' => array(
792 'map_group' => 'general',
793 'mode' => XMPReader::MODE_SIMPLE,
794 'map_name' => 'DateTime',
795 'validate' => 'validateDate',
797 'MetadataDate' => array(
798 'map_group' => 'general',
799 'mode' => XMPReader::MODE_SIMPLE,
800 // map_name to be consistent with other date names.
801 'map_name' => 'DateTimeMetadata',
802 'validate' => 'validateDate',
804 'Nickname' => array(
805 'map_group' => 'general',
806 'mode' => XMPReader::MODE_SIMPLE,
808 'Rating' => array(
809 'map_group' => 'general',
810 'mode' => XMPReader::MODE_SIMPLE,
811 'validate' => 'validateRating',
814 'http://ns.adobe.com/xap/1.0/rights/' => array(
815 'Certificate' => array(
816 'map_group' => 'general',
817 'map_name' => 'RightsCertificate',
818 'mode' => XMPReader::MODE_SIMPLE,
820 'Marked' => array(
821 'map_group' => 'general',
822 'map_name' => 'Copyrighted',
823 'mode' => XMPReader::MODE_SIMPLE,
824 'validate' => 'validateBoolean',
826 'Owner' => array(
827 'map_group' => 'general',
828 'map_name' => 'CopyrightOwner',
829 'mode' => XMPReader::MODE_BAG,
831 // this seems similar to dc:rights.
832 'UsageTerms' => array(
833 'map_group' => 'general',
834 'mode' => XMPReader::MODE_LANG,
836 'WebStatement' => array(
837 'map_group' => 'general',
838 'mode' => XMPReader::MODE_SIMPLE,
841 // XMP media management.
842 'http://ns.adobe.com/xap/1.0/mm/' => array(
843 // if we extract the exif UniqueImageID, might
844 // as well do this too.
845 'OriginalDocumentID' => array(
846 'map_group' => 'general',
847 'mode' => XMPReader::MODE_SIMPLE,
849 // It might also be useful to do xmpMM:LastURL
850 // and xmpMM:DerivedFrom as you can potentially,
851 // get the url of this document/source for this
852 // document. However whats more likely is you'd
853 // get a file:// url for the path of the doc,
854 // which is somewhat of a privacy issue.
856 'http://creativecommons.org/ns#' => array(
857 'license' => array(
858 'map_name' => 'LicenseUrl',
859 'map_group' => 'general',
860 'mode' => XMPReader::MODE_SIMPLE,
862 'morePermissions' => array(
863 'map_name' => 'MorePermissionsUrl',
864 'map_group' => 'general',
865 'mode' => XMPReader::MODE_SIMPLE,
867 'attributionURL' => array(
868 'map_group' => 'general',
869 'map_name' => 'AttributionUrl',
870 'mode' => XMPReader::MODE_SIMPLE,
872 'attributionName' => array(
873 'map_group' => 'general',
874 'map_name' => 'PreferredAttributionName',
875 'mode' => XMPReader::MODE_SIMPLE,
878 //Note, this property affects how jpeg metadata is extracted.
879 'http://ns.adobe.com/xmp/note/' => array(
880 'HasExtendedXMP' => array(
881 'map_group' => 'special',
882 'mode' => XMPReader::MODE_SIMPLE,
885 /* Note, in iptc schemas, the legacy properties are denoted
886 * as deprecated, since other properties should used instead,
887 * and properties marked as deprecated in the standard are
888 * are marked as general here as they don't have replacements
890 'http://ns.adobe.com/photoshop/1.0/' => array(
891 'City' => array(
892 'map_group' => 'deprecated',
893 'mode' => XMPReader::MODE_SIMPLE,
894 'map_name' => 'CityDest',
896 'Country' => array(
897 'map_group' => 'deprecated',
898 'mode' => XMPReader::MODE_SIMPLE,
899 'map_name' => 'CountryDest',
901 'State' => array(
902 'map_group' => 'deprecated',
903 'mode' => XMPReader::MODE_SIMPLE,
904 'map_name' => 'ProvinceOrStateDest',
906 'DateCreated' => array(
907 'map_group' => 'deprecated',
908 // marking as deprecated as the xmp prop preferred
909 'mode' => XMPReader::MODE_SIMPLE,
910 'map_name' => 'DateTimeOriginal',
911 'validate' => 'validateDate',
912 // note this prop is an XMP, not IPTC date
914 'CaptionWriter' => array(
915 'map_group' => 'general',
916 'mode' => XMPReader::MODE_SIMPLE,
917 'map_name' => 'Writer',
919 'Instructions' => array(
920 'map_group' => 'general',
921 'mode' => XMPReader::MODE_SIMPLE,
922 'map_name' => 'SpecialInstructions',
924 'TransmissionReference' => array(
925 'map_group' => 'general',
926 'mode' => XMPReader::MODE_SIMPLE,
927 'map_name' => 'OriginalTransmissionRef',
929 'AuthorsPosition' => array(
930 /* This corresponds with 2:85
931 * By-line Title, which needs to be
932 * handled weirdly to correspond
933 * with iptc/exif. */
934 'map_group' => 'special',
935 'mode' => XMPReader::MODE_SIMPLE
937 'Credit' => array(
938 'map_group' => 'general',
939 'mode' => XMPReader::MODE_SIMPLE,
941 'Source' => array(
942 'map_group' => 'general',
943 'mode' => XMPReader::MODE_SIMPLE,
945 'Urgency' => array(
946 'map_group' => 'general',
947 'mode' => XMPReader::MODE_SIMPLE,
949 'Category' => array(
950 // Note, this prop is deprecated, but in general
951 // group since it doesn't have a replacement.
952 'map_group' => 'general',
953 'mode' => XMPReader::MODE_SIMPLE,
954 'map_name' => 'iimCategory',
956 'SupplementalCategories' => array(
957 'map_group' => 'general',
958 'mode' => XMPReader::MODE_BAG,
959 'map_name' => 'iimSupplementalCategory',
961 'Headline' => array(
962 'map_group' => 'general',
963 'mode' => XMPReader::MODE_SIMPLE
966 'http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/' => array(
967 'CountryCode' => array(
968 'map_group' => 'deprecated',
969 'mode' => XMPReader::MODE_SIMPLE,
970 'map_name' => 'CountryCodeDest',
972 'IntellectualGenre' => array(
973 'map_group' => 'general',
974 'mode' => XMPReader::MODE_SIMPLE,
976 // Note, this is a six digit code.
977 // See: http://cv.iptc.org/newscodes/scene/
978 // Since these aren't really all that common,
979 // we just show the number.
980 'Scene' => array(
981 'map_group' => 'general',
982 'mode' => XMPReader::MODE_BAG,
983 'validate' => 'validateInteger',
984 'map_name' => 'SceneCode',
986 /* Note: SubjectCode should be an 8 ascii digits.
987 * it is not really an integer (has leading 0's,
988 * cannot have a +/- sign), but validateInteger
989 * will let it through.
991 'SubjectCode' => array(
992 'map_group' => 'general',
993 'mode' => XMPReader::MODE_BAG,
994 'map_name' => 'SubjectNewsCode',
995 'validate' => 'validateInteger'
997 'Location' => array(
998 'map_group' => 'deprecated',
999 'mode' => XMPReader::MODE_SIMPLE,
1000 'map_name' => 'SublocationDest',
1002 'CreatorContactInfo' => array(
1003 /* Note this maps to 2:118 in iim
1004 * (Contact) field. However those field
1005 * types are slightly different - 2:118
1006 * is free form text field, where this
1007 * is more structured.
1009 'map_group' => 'general',
1010 'mode' => XMPReader::MODE_STRUCT,
1011 'map_name' => 'Contact',
1012 'children' => array(
1013 'CiAdrExtadr' => true,
1014 'CiAdrCity' => true,
1015 'CiAdrCtry' => true,
1016 'CiEmailWork' => true,
1017 'CiTelWork' => true,
1018 'CiAdrPcode' => true,
1019 'CiAdrRegion' => true,
1020 'CiUrlWork' => true,
1023 'CiAdrExtadr' => array( /* address */
1024 'map_group' => 'general',
1025 'mode' => XMPReader::MODE_SIMPLE,
1026 'structPart'=> true,
1028 'CiAdrCity' => array( /* city */
1029 'map_group' => 'general',
1030 'mode' => XMPReader::MODE_SIMPLE,
1031 'structPart'=> true,
1033 'CiAdrCtry' => array( /* country */
1034 'map_group' => 'general',
1035 'mode' => XMPReader::MODE_SIMPLE,
1036 'structPart'=> true,
1038 'CiEmailWork' => array( /* email (possibly separated by ',') */
1039 'map_group' => 'general',
1040 'mode' => XMPReader::MODE_SIMPLE,
1041 'structPart'=> true,
1043 'CiTelWork' => array( /* telephone */
1044 'map_group' => 'general',
1045 'mode' => XMPReader::MODE_SIMPLE,
1046 'structPart'=> true,
1048 'CiAdrPcode' => array( /* postal code */
1049 'map_group' => 'general',
1050 'mode' => XMPReader::MODE_SIMPLE,
1051 'structPart'=> true,
1053 'CiAdrRegion' => array( /* province/state */
1054 'map_group' => 'general',
1055 'mode' => XMPReader::MODE_SIMPLE,
1056 'structPart'=> true,
1058 'CiUrlWork' => array( /* url. Multiple may be separated by comma. */
1059 'map_group' => 'general',
1060 'mode' => XMPReader::MODE_SIMPLE,
1061 'structPart'=> true,
1063 /* End contact info struct properties */
1065 'http://iptc.org/std/Iptc4xmpExt/2008-02-29/' => array(
1066 'Event' => array(
1067 'map_group' => 'general',
1068 'mode' => XMPReader::MODE_SIMPLE,
1070 'OrganisationInImageName' => array(
1071 'map_group' => 'general',
1072 'mode' => XMPReader::MODE_BAG,
1073 'map_name' => 'OrganisationInImage'
1075 'PersonInImage' => array(
1076 'map_group' => 'general',
1077 'mode' => XMPReader::MODE_BAG,
1079 'MaxAvailHeight' => array(
1080 'map_group' => 'general',
1081 'mode' => XMPReader::MODE_SIMPLE,
1082 'validate' => 'validateInteger',
1083 'map_name' => 'OriginalImageHeight',
1085 'MaxAvailWidth' => array(
1086 'map_group' => 'general',
1087 'mode' => XMPReader::MODE_SIMPLE,
1088 'validate' => 'validateInteger',
1089 'map_name' => 'OriginalImageWidth',
1091 // LocationShown and LocationCreated are handled
1092 // specially because they are hierarchical, but we
1093 // also want to merge with the old non-hierarchical.
1094 'LocationShown' => array(
1095 'map_group' => 'special',
1096 'mode' => XMPReader::MODE_BAGSTRUCT,
1097 'children' => array(
1098 'WorldRegion' => true,
1099 'CountryCode' => true, /* iso code */
1100 'CountryName' => true,
1101 'ProvinceState' => true,
1102 'City' => true,
1103 'Sublocation' => true,
1106 'LocationCreated' => array(
1107 'map_group' => 'special',
1108 'mode' => XMPReader::MODE_BAGSTRUCT,
1109 'children' => array(
1110 'WorldRegion' => true,
1111 'CountryCode' => true, /* iso code */
1112 'CountryName' => true,
1113 'ProvinceState' => true,
1114 'City' => true,
1115 'Sublocation' => true,
1118 'WorldRegion' => array(
1119 'map_group' => 'special',
1120 'mode' => XMPReader::MODE_SIMPLE,
1121 'structPart'=> true,
1123 'CountryCode' => array(
1124 'map_group' => 'special',
1125 'mode' => XMPReader::MODE_SIMPLE,
1126 'structPart'=> true,
1128 'CountryName' => array(
1129 'map_group' => 'special',
1130 'mode' => XMPReader::MODE_SIMPLE,
1131 'structPart'=> true,
1132 'map_name' => 'Country',
1134 'ProvinceState' => array(
1135 'map_group' => 'special',
1136 'mode' => XMPReader::MODE_SIMPLE,
1137 'structPart'=> true,
1138 'map_name' => 'ProvinceOrState',
1140 'City' => array(
1141 'map_group' => 'special',
1142 'mode' => XMPReader::MODE_SIMPLE,
1143 'structPart'=> true,
1145 'Sublocation' => array(
1146 'map_group' => 'special',
1147 'mode' => XMPReader::MODE_SIMPLE,
1148 'structPart'=> true,
1151 /* Other props that might be interesting but
1152 * Not currently extracted:
1153 * ArtworkOrObject, (info about objects in picture)
1154 * DigitalSourceType
1155 * RegistryId
1159 /* Plus props we might want to consider:
1160 * (Note: some of these have unclear/incomplete definitions
1161 * from the iptc4xmp standard).
1162 * ImageSupplier (kind of like iptc source field)
1163 * ImageSupplierId (id code for image from supplier)
1164 * CopyrightOwner
1165 * ImageCreator
1166 * Licensor
1167 * Various model release fields
1168 * Property release fields.