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