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