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