summaryrefslogtreecommitdiff
path: root/includes/media/XMPInfo.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/media/XMPInfo.php')
-rw-r--r--includes/media/XMPInfo.php1139
1 files changed, 1139 insertions, 0 deletions
diff --git a/includes/media/XMPInfo.php b/includes/media/XMPInfo.php
new file mode 100644
index 00000000..1d580ff7
--- /dev/null
+++ b/includes/media/XMPInfo.php
@@ -0,0 +1,1139 @@
+<?php
+/**
+* This class is just a container for a big array
+* used by XMPReader to determine which XMP items to
+* extract.
+*/
+class XMPInfo {
+
+ /** get the items array
+ * @return Array XMP item configuration array.
+ */
+ public static function getItems ( ) {
+ if( !self::$ranHooks ) {
+ // This is for if someone makes a custom metadata extension.
+ // For example, a medical wiki might want to decode DICOM xmp properties.
+ wfRunHooks('XMPGetInfo', Array(&self::$items));
+ self::$ranHooks = true; // Only want to do this once.
+ }
+ return self::$items;
+ }
+
+ static private $ranHooks = false;
+
+ /**
+ * XMPInfo::$items keeps a list of all the items
+ * we are interested to extract, as well as
+ * information about the item like what type
+ * it is.
+ *
+ * Format is an array of namespaces,
+ * each containing an array of tags
+ * each tag is an array of information about the
+ * tag, including:
+ * * map_group - what group (used for precedence during conflicts)
+ * * mode - What type of item (self::MODE_SIMPLE usually, see above for all values)
+ * * validate - method to validate input. Could also post-process the input. A string value is assumed to be a static method of XMPValidate. Can also take a array( 'className', 'methodName' ).
+ * * choices - array of potential values (format of 'value' => true ). Only used with validateClosed
+ * * rangeLow and rangeHigh - alternative to choices for numeric ranges. Again for validateClosed only.
+ * * children - for MODE_STRUCT items, allowed children.
+ * * structPart - Indicates that this element can only appear as a member of a structure.
+ *
+ * currently this just has a bunch of exif values as this class is only half-done
+ */
+
+ static private $items = array(
+ 'http://ns.adobe.com/exif/1.0/' => array(
+ 'ApertureValue' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'BrightnessValue' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'CompressedBitsPerPixel' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'DigitalZoomRatio' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'ExposureBiasValue' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'ExposureIndex' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'ExposureTime' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'FlashEnergy' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
+ ),
+ 'FNumber' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'FocalLength' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'FocalPlaneXResolution' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'FocalPlaneYResolution' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'GPSAltitude' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
+ ),
+ 'GPSDestBearing' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'GPSDestDistance' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'GPSDOP' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'GPSImgDirection' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'GPSSpeed' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'GPSTrack' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'MaxApertureValue' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'ShutterSpeedValue' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ 'SubjectDistance' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
+ ),
+ /* Flash */
+ 'Flash' => array(
+ 'mode' => XMPReader::MODE_STRUCT,
+ 'children' => array(
+ 'Fired' => true,
+ 'Function' => true,
+ 'Mode' => true,
+ 'RedEyeMode' => true,
+ 'Return' => true,
+ ),
+ 'validate' => 'validateFlash',
+ 'map_group' => 'exif',
+ ),
+ 'Fired' => array(
+ 'map_group' => 'exif',
+ 'validate' => 'validateBoolean',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'Function' => array(
+ 'map_group' => 'exif',
+ 'validate' => 'validateBoolean',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'Mode' => array(
+ 'map_group' => 'exif',
+ 'validate' => 'validateClosed',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'choices' => array( '0' => true, '1' => true,
+ '2' => true, '3' => true ),
+ 'structPart'=> true,
+ ),
+ 'Return' => array(
+ 'map_group' => 'exif',
+ 'validate' => 'validateClosed',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'choices' => array( '0' => true,
+ '2' => true, '3' => true ),
+ 'structPart'=> true,
+ ),
+ 'RedEyeMode' => array(
+ 'map_group' => 'exif',
+ 'validate' => 'validateBoolean',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ /* End Flash */
+ 'ISOSpeedRatings' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger'
+ ),
+ /* end rational things */
+ 'ColorSpace' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '65535' => true ),
+ ),
+ 'ComponentsConfiguration' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true, '3' => true, '4' => true,
+ '5' => true, '6' => true )
+ ),
+ 'Contrast' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true, '2' => true )
+ ),
+ 'CustomRendered' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true )
+ ),
+ 'DateTimeOriginal' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
+ ),
+ 'DateTimeDigitized' => array( /* xmp:CreateDate */
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
+ ),
+ /* todo: there might be interesting information in
+ * exif:DeviceSettingDescription, but need to find an
+ * example
+ */
+ 'ExifVersion' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'ExposureMode' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 2,
+ ),
+ 'ExposureProgram' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 8,
+ ),
+ 'FileSource' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '3' => true )
+ ),
+ 'FlashpixVersion' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'FocalLengthIn35mmFilm' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ ),
+ 'FocalPlaneResolutionUnit' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '3' => true ),
+ ),
+ 'GainControl' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 4,
+ ),
+ /* this value is post-processed out later */
+ 'GPSAltitudeRef' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true ),
+ ),
+ 'GPSAreaInformation' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'GPSDestBearingRef' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'T' => true, 'M' => true ),
+ ),
+ 'GPSDestDistanceRef' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'K' => true, 'M' => true,
+ 'N' => true ),
+ ),
+ 'GPSDestLatitude' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
+ ),
+ 'GPSDestLongitude' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
+ ),
+ 'GPSDifferential' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true ),
+ ),
+ 'GPSImgDirectionRef' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'T' => true, 'M' => true ),
+ ),
+ 'GPSLatitude' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
+ ),
+ 'GPSLongitude' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
+ ),
+ 'GPSMapDatum' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'GPSMeasureMode' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '3' => true )
+ ),
+ 'GPSProcessingMethod' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'GPSSatellites' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'GPSSpeedRef' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'K' => true, 'M' => true,
+ 'N' => true ),
+ ),
+ 'GPSStatus' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'A' => true, 'V' => true )
+ ),
+ 'GPSTimeStamp' => array(
+ 'map_group' => 'exif',
+ // Note: in exif, GPSDateStamp does not include
+ // the time, where here it does.
+ 'map_name' => 'GPSDateStamp',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
+ ),
+ 'GPSTrackRef' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'T' => true, 'M' => true )
+ ),
+ 'GPSVersionID' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'ImageUniqueID' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'LightSource' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ /* can't use a range, as it skips... */
+ 'choices' => array( '0' => true, '1' => true,
+ '2' => true, '3' => true, '4' => true,
+ '9' => true, '10' => true, '11' => true,
+ '12' => true, '13' => true,
+ '14' => true, '15' => true,
+ '17' => true, '18' => true,
+ '19' => true, '20' => true,
+ '21' => true, '22' => true,
+ '23' => true, '24' => true,
+ '255' => true,
+ ),
+ ),
+ 'MeteringMode' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 6,
+ 'choices' => array( '255' => true ),
+ ),
+ /* Pixel(X|Y)Dimension are rather useless, but for
+ * completeness since we do it with exif.
+ */
+ 'PixelXDimension' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ ),
+ 'PixelYDimension' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ ),
+ 'Saturation' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 2,
+ ),
+ 'SceneCaptureType' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 3,
+ ),
+ 'SceneType' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true ),
+ ),
+ // Note, 6 is not valid SensingMethod.
+ 'SensingMethod' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 1,
+ 'rangeHigh' => 5,
+ 'choices' => array( '7' => true, 8 => true ),
+ ),
+ 'Sharpness' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 2,
+ ),
+ 'SpectralSensitivity' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ // This tag should perhaps be displayed to user better.
+ 'SubjectArea' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger',
+ ),
+ 'SubjectDistanceRange' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
+ 'rangeHigh' => 3,
+ ),
+ 'SubjectLocation' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger',
+ ),
+ 'UserComment' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_LANG,
+ ),
+ 'WhiteBalance' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true )
+ ),
+ ),
+ 'http://ns.adobe.com/tiff/1.0/' => array(
+ 'Artist' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'BitsPerSample' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger',
+ ),
+ 'Compression' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '6' => true ),
+ ),
+ /* this prop should not be used in XMP. dc:rights is the correct prop */
+ 'Copyright' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_LANG,
+ ),
+ 'DateTime' => array( /* proper prop is xmp:ModifyDate */
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
+ ),
+ 'ImageDescription' => array( /* proper one is dc:description */
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_LANG,
+ ),
+ 'ImageLength' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ ),
+ 'ImageWidth' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ ),
+ 'Make' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'Model' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ /**** Do not extract this property
+ * It interferes with auto exif rotation.
+ * 'Orientation' => array(
+ * 'map_group' => 'exif',
+ * 'mode' => XMPReader::MODE_SIMPLE,
+ * 'validate' => 'validateClosed',
+ * 'choices' => array( '1' => true, '2' => true, '3' => true, '4' => true, 5 => true,
+ * '6' => true, '7' => true, '8' => true ),
+ *),
+ ******/
+ 'PhotometricInterpretation' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '6' => true ),
+ ),
+ 'PlanerConfiguration' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true ),
+ ),
+ 'PrimaryChromaticities' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
+ ),
+ 'ReferenceBlackWhite' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
+ ),
+ 'ResolutionUnit' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '3' => true ),
+ ),
+ 'SamplesPerPixel' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ ),
+ 'Software' => array( /* see xmp:CreatorTool */
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ /* ignore TransferFunction */
+ 'WhitePoint' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
+ ),
+ 'XResolution' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
+ ),
+ 'YResolution' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
+ ),
+ 'YCbCrCoefficients' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
+ ),
+ 'YCbCrPositioning' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true ),
+ ),
+ 'YCbCrSubSampling' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true ),
+ ),
+ ),
+ 'http://ns.adobe.com/exif/1.0/aux/' => array(
+ 'Lens' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'SerialNumber' => array(
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'OwnerName' => array(
+ 'map_group' => 'exif',
+ 'map_name' => 'CameraOwnerName',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ ),
+ 'http://purl.org/dc/elements/1.1/' => array(
+ 'title' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'ObjectName',
+ 'mode' => XMPReader::MODE_LANG
+ ),
+ 'description' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'ImageDescription',
+ 'mode' => XMPReader::MODE_LANG
+ ),
+ 'contributor' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'dc-contributor',
+ 'mode' => XMPReader::MODE_BAG
+ ),
+ 'coverage' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'dc-coverage',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'creator' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'Artist', //map with exif Artist, iptc byline (2:80)
+ 'mode' => XMPReader::MODE_SEQ,
+ ),
+ 'date' => array(
+ 'map_group' => 'general',
+ // Note, not mapped with other date properties, as this type of date is
+ // non-specific: "A point or period of time associated with an event in
+ // the lifecycle of the resource"
+ 'map_name' => 'dc-date',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateDate',
+ ),
+ /* Do not extract dc:format, as we've got better ways to determine mimetype */
+ 'identifier' => array(
+ 'map_group' => 'deprecated',
+ 'map_name' => 'Identifier',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'language' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'LanguageCode', /* mapped with iptc 2:135 */
+ 'mode' => XMPReader::MODE_BAG,
+ 'validate' => 'validateLangCode',
+ ),
+ 'publisher' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'dc-publisher',
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ // for related images/resources
+ 'relation' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'dc-relation',
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ 'rights' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'Copyright',
+ 'mode' => XMPReader::MODE_LANG,
+ ),
+ // Note: source is not mapped with iptc source, since iptc
+ // source describes the source of the image in terms of a person
+ // who provided the image, where this is to describe an image that the
+ // current one is based on.
+ 'source' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'dc-source',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'subject' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'Keywords', /* maps to iptc 2:25 */
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ 'type' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'dc-type',
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ ),
+ 'http://ns.adobe.com/xap/1.0/' => array(
+ 'CreateDate' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'DateTimeDigitized',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
+ ),
+ 'CreatorTool' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'Software',
+ 'mode' => XMPReader::MODE_SIMPLE
+ ),
+ 'Identifier' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ 'Label' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'ModifyDate' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'DateTime',
+ 'validate' => 'validateDate',
+ ),
+ 'MetadataDate' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ // map_name to be consistent with other date names.
+ 'map_name' => 'DateTimeMetadata',
+ 'validate' => 'validateDate',
+ ),
+ 'Nickname' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'Rating' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRating',
+ ),
+ ),
+ 'http://ns.adobe.com/xap/1.0/rights/' => array(
+ 'Certificate' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'RightsCertificate',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'Marked' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'Copyrighted',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateBoolean',
+ ),
+ 'Owner' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'CopyrightOwner',
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ // this seems similar to dc:rights.
+ 'UsageTerms' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_LANG,
+ ),
+ 'WebStatement' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ ),
+ // XMP media management.
+ 'http://ns.adobe.com/xap/1.0/mm/' => array(
+ // if we extract the exif UniqueImageID, might
+ // as well do this too.
+ 'OriginalDocumentID' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ // It might also be useful to do xmpMM:LastURL
+ // and xmpMM:DerivedFrom as you can potentially,
+ // get the url of this document/source for this
+ // document. However whats more likely is you'd
+ // get a file:// url for the path of the doc,
+ // which is somewhat of a privacy issue.
+ ),
+ 'http://creativecommons.org/ns#' => array(
+ 'license' => array(
+ 'map_name' => 'LicenseUrl',
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'morePermissions' => array(
+ 'map_name' => 'MorePermissionsUrl',
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'attributionURL' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'AttributionUrl',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'attributionName' => array(
+ 'map_group' => 'general',
+ 'map_name' => 'PreferredAttributionName',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ ),
+ //Note, this property affects how jpeg metadata is extracted.
+ 'http://ns.adobe.com/xmp/note/' => array(
+ 'HasExtendedXMP' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ ),
+ /* Note, in iptc schemas, the legacy properties are denoted
+ * as deprecated, since other properties should used instead,
+ * and properties marked as deprecated in the standard are
+ * are marked as general here as they don't have replacements
+ */
+ 'http://ns.adobe.com/photoshop/1.0/' => array(
+ 'City' => array(
+ 'map_group' => 'deprecated',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CityDest',
+ ),
+ 'Country' => array(
+ 'map_group' => 'deprecated',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CountryDest',
+ ),
+ 'State' => array(
+ 'map_group' => 'deprecated',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'ProvinceOrStateDest',
+ ),
+ 'DateCreated' => array(
+ 'map_group' => 'deprecated',
+ // marking as deprecated as the xmp prop preferred
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'DateTimeOriginal',
+ 'validate' => 'validateDate',
+ // note this prop is an XMP, not IPTC date
+ ),
+ 'CaptionWriter' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'Writer',
+ ),
+ 'Instructions' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'SpecialInstructions',
+ ),
+ 'TransmissionReference' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'OriginalTransmissionRef',
+ ),
+ 'AuthorsPosition' => array(
+ /* This corresponds with 2:85
+ * By-line Title, which needs to be
+ * handled weirdly to correspond
+ * with iptc/exif. */
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE
+ ),
+ 'Credit' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'Source' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'Urgency' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'Category' => array(
+ // Note, this prop is deprecated, but in general
+ // group since it doesn't have a replacement.
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'iimCategory',
+ ),
+ 'SupplementalCategories' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'iimSupplementalCategory',
+ ),
+ 'Headline' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE
+ ),
+ ),
+ 'http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/' => array(
+ 'CountryCode' => array(
+ 'map_group' => 'deprecated',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CountryCodeDest',
+ ),
+ 'IntellectualGenre' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ // Note, this is a six digit code.
+ // See: http://cv.iptc.org/newscodes/scene/
+ // Since these aren't really all that common,
+ // we just show the number.
+ 'Scene' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_BAG,
+ 'validate' => 'validateInteger',
+ 'map_name' => 'SceneCode',
+ ),
+ /* Note: SubjectCode should be an 8 ascii digits.
+ * it is not really an integer (has leading 0's,
+ * cannot have a +/- sign), but validateInteger
+ * will let it through.
+ */
+ 'SubjectCode' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'SubjectNewsCode',
+ 'validate' => 'validateInteger'
+ ),
+ 'Location' => array(
+ 'map_group' => 'deprecated',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'SublocationDest',
+ ),
+ 'CreatorContactInfo' => array(
+ /* Note this maps to 2:118 in iim
+ * (Contact) field. However those field
+ * types are slightly different - 2:118
+ * is free form text field, where this
+ * is more structured.
+ */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_STRUCT,
+ 'map_name' => 'Contact',
+ 'children' => array(
+ 'CiAdrExtadr' => true,
+ 'CiAdrCity' => true,
+ 'CiAdrCtry' => true,
+ 'CiEmailWork' => true,
+ 'CiTelWork' => true,
+ 'CiAdrPcode' => true,
+ 'CiAdrRegion' => true,
+ 'CiUrlWork' => true,
+ ),
+ ),
+ 'CiAdrExtadr' => array( /* address */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiAdrCity' => array( /* city */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiAdrCtry' => array( /* country */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiEmailWork' => array( /* email (possibly separated by ',') */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiTelWork' => array( /* telephone */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiAdrPcode' => array( /* postal code */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiAdrRegion' => array( /* province/state */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CiUrlWork' => array( /* url. Multiple may be separated by comma. */
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ /* End contact info struct properties */
+ ),
+ 'http://iptc.org/std/Iptc4xmpExt/2008-02-29/' => array(
+ 'Event' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ ),
+ 'OrganisationInImageName' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'OrganisationInImage'
+ ),
+ 'PersonInImage' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_BAG,
+ ),
+ 'MaxAvailHeight' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ 'map_name' => 'OriginalImageHeight',
+ ),
+ 'MaxAvailWidth' => array(
+ 'map_group' => 'general',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ 'map_name' => 'OriginalImageWidth',
+ ),
+ // LocationShown and LocationCreated are handled
+ // specially because they are hierarchical, but we
+ // also want to merge with the old non-hierarchical.
+ 'LocationShown' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_BAGSTRUCT,
+ 'children' => array(
+ 'WorldRegion' => true,
+ 'CountryCode' => true, /* iso code */
+ 'CountryName' => true,
+ 'ProvinceState' => true,
+ 'City' => true,
+ 'Sublocation' => true,
+ ),
+ ),
+ 'LocationCreated' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_BAGSTRUCT,
+ 'children' => array(
+ 'WorldRegion' => true,
+ 'CountryCode' => true, /* iso code */
+ 'CountryName' => true,
+ 'ProvinceState' => true,
+ 'City' => true,
+ 'Sublocation' => true,
+ ),
+ ),
+ 'WorldRegion' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CountryCode' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'CountryName' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ 'map_name' => 'Country',
+ ),
+ 'ProvinceState' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ 'map_name' => 'ProvinceOrState',
+ ),
+ 'City' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+ 'Sublocation' => array(
+ 'map_group' => 'special',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart'=> true,
+ ),
+
+ /* Other props that might be interesting but
+ * Not currently extracted:
+ * ArtworkOrObject, (info about objects in picture)
+ * DigitalSourceType
+ * RegistryId
+ */
+ ),
+
+ /* Plus props we might want to consider:
+ * (Note: some of these have unclear/incomplete definitions
+ * from the iptc4xmp standard).
+ * ImageSupplier (kind of like iptc source field)
+ * ImageSupplierId (id code for image from supplier)
+ * CopyrightOwner
+ * ImageCreator
+ * Licensor
+ * Various model release fields
+ * Property release fields.
+ */
+ );
+}