* @ingroup Media
*/
class BmpHandler extends BitmapHandler {
-
/**
* @param $file
* @return bool
} catch ( MWException $e ) {
return false;
}
+
return array( $w[1], $h[1] );
}
}
if ( is_null( $checkImageAreaHookResult ) ) {
global $wgMaxImageArea;
- if ( $srcWidth * $srcHeight > $wgMaxImageArea &&
- !( $image->getMimeType() == 'image/jpeg' &&
- self::getScalerType( false, false ) == 'im' ) ) {
+ if ( $srcWidth * $srcHeight > $wgMaxImageArea
+ && !( $image->getMimeType() == 'image/jpeg'
+ && self::getScalerType( false, false ) == 'im' )
+ ) {
# Only ImageMagick can efficiently downsize jpg images without loading
# the entire file in memory
return false;
$width = $params['physicalWidth'];
$height = $params['physicalHeight'];
}
+
return array( $width, $height );
}
'clientWidth' => $params['width'],
'clientHeight' => $params['height'],
# Comment as will be added to the Exif of the thumbnail
- 'comment' => isset( $params['descriptionUrl'] ) ?
- "File source: {$params['descriptionUrl']}" : '',
+ 'comment' => isset( $params['descriptionUrl'] )
+ ? "File source: {$params['descriptionUrl']}"
+ : '',
# Properties of the original image
'srcWidth' => $image->getWidth(),
'srcHeight' => $image->getHeight(),
wfDebug( __METHOD__ . ": creating {$scalerParams['physicalDimensions']} thumbnail at $dstPath using scaler $scaler\n" );
if ( !$image->mustRender() &&
- $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
- && $scalerParams['physicalHeight'] == $scalerParams['srcHeight'] ) {
+ $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
+ && $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
+ ) {
# normaliseParams (or the user) wants us to return the unscaled image
wfDebug( __METHOD__ . ": returning unscaled image\n" );
+
return $this->getClientScalingThumbnailImage( $image, $scalerParams );
}
'width' => $scalerParams['clientWidth'],
'height' => $scalerParams['clientHeight']
);
+
return new ThumbnailImage( $image, $dstUrl, false, $params );
}
# Try to make a target path for the thumbnail
if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
wfDebug( __METHOD__ . ": Unable to create thumbnail destination directory, falling back to client scaling\n" );
+
return $this->getClientScalingThumbnailImage( $image, $scalerParams );
}
wfDebugLog( 'thumbnail',
sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
wfHostname(), $image->getName() ) );
+
return new MediaTransformError( 'thumbnail_error',
$scalerParams['clientWidth'], $scalerParams['clientHeight'] );
}
'width' => $scalerParams['clientWidth'],
'height' => $scalerParams['clientHeight']
);
+
return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
}
} else {
$scaler = 'client';
}
+
return $scaler;
}
'width' => $scalerParams['clientWidth'],
'height' => $scalerParams['clientHeight']
);
+
return new ThumbnailImage( $image, $image->getURL(), null, $params );
}
*/
protected function transformImageMagick( $image, $params ) {
# use ImageMagick
- global $wgSharpenReductionThreshold, $wgSharpenParameter,
- $wgMaxAnimatedGifArea,
+ global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
$wgImageMagickTempDir, $wgImageMagickConvertCommand;
$quality = '';
$quality = "-quality 80"; // 80%
# Sharpening, see bug 6193
if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
- / ( $params['srcWidth'] + $params['srcHeight'] )
- < $wgSharpenReductionThreshold ) {
+ / ( $params['srcWidth'] + $params['srcHeight'] )
+ < $wgSharpenReductionThreshold
+ ) {
$sharpen = "-sharpen " . wfEscapeShellArg( $wgSharpenParameter );
}
if ( version_compare( $this->getMagickVersion(), "6.5.6" ) >= 0 ) {
// JPEG decoder hint to reduce memory, available since IM 6.5.6-2
$decoderHint = "-define jpeg:size={$params['physicalDimensions']}";
}
-
} elseif ( $params['mimeType'] == 'image/png' ) {
$quality = "-quality 95"; // zlib 9, adaptive filtering
// Extract initial frame only; we're so big it'll
// be a total drag. :P
$scene = 0;
-
} elseif ( $this->isAnimatedImage( $image ) ) {
// Coalesce is needed to scale animated GIFs properly (bug 1017).
$animation_pre = '-coalesce';
if ( $retval !== 0 ) {
$this->logErrorForExternalProcess( $retval, $err, $cmd );
+
return $this->getMediaTransformError( $params, $err );
}
if ( $params['mimeType'] == 'image/jpeg' ) {
// Sharpening, see bug 6193
if ( ( $params['physicalWidth'] + $params['physicalHeight'] )
- / ( $params['srcWidth'] + $params['srcHeight'] )
- < $wgSharpenReductionThreshold ) {
+ / ( $params['srcWidth'] + $params['srcHeight'] )
+ < $wgSharpenReductionThreshold
+ ) {
// Hack, since $wgSharpenParamater is written specifically for the command line convert
list( $radius, $sigma ) = explode( 'x', $wgSharpenParameter );
$im->sharpenImage( $radius, $sigma );
return $this->getMediaTransformError( $params,
"Unable to write thumbnail to {$params['dstPath']}" );
}
-
} catch ( ImagickException $e ) {
return $this->getMediaTransformError( $params, $e->getMessage() );
}
return false;
-
}
/**
if ( $retval !== 0 ) {
$this->logErrorForExternalProcess( $retval, $err, $cmd );
+
return $this->getMediaTransformError( $params, $err );
}
+
return false; # No error
}
protected function logErrorForExternalProcess( $retval, $err, $cmd ) {
wfDebugLog( 'thumbnail',
sprintf( 'thumbnail failed on %s: error %d "%s" from "%s"',
- wfHostname(), $retval, trim( $err ), $cmd ) );
+ wfHostname(), $retval, trim( $err ), $cmd ) );
}
+
/**
* Get a MediaTransformError with error 'thumbnail_error'
*
*/
public function getMediaTransformError( $params, $errMsg ) {
return new MediaTransformError( 'thumbnail_error', $params['clientWidth'],
- $params['clientHeight'], $errMsg );
+ $params['clientHeight'], $errMsg );
}
/**
# input routine for this.
$typemap = array(
- 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ),
- 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( __CLASS__, 'imageJpegWrapper' ) ),
- 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ),
- 'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ),
- 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ),
+ 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ),
+ 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( __CLASS__, 'imageJpegWrapper' ) ),
+ 'image/png' => array( 'imagecreatefrompng', 'bits', 'imagepng' ),
+ 'image/vnd.wap.wbmp' => array( 'imagecreatefromwbmp', 'palette', 'imagewbmp' ),
+ 'image/xbm' => array( 'imagecreatefromxbm', 'palette', 'imagexbm' ),
);
if ( !isset( $typemap[$params['mimeType']] ) ) {
$err = 'Image type not supported';
wfDebug( "$err\n" );
$errMsg = wfMessage( 'thumbnail_image-type' )->text();
+
return $this->getMediaTransformError( $params, $errMsg );
}
list( $loader, $colorStyle, $saveType ) = $typemap[$params['mimeType']];
$err = "Incomplete GD library configuration: missing function $loader";
wfDebug( "$err\n" );
$errMsg = wfMessage( 'thumbnail_gd-library', $loader )->text();
+
return $this->getMediaTransformError( $params, $errMsg );
}
$err = "File seems to be missing: {$params['srcPath']}";
wfDebug( "$err\n" );
$errMsg = wfMessage( 'thumbnail_image-missing', $params['srcPath'] )->text();
+
return $this->getMediaTransformError( $params, $errMsg );
}
if ( strlen( $s ) > 0 && ( $s[0] === '-' || $s[0] === '@' ) ) {
$s = '\\' . $s;
}
+
return $s;
}
*/
function escapeMagickOutput( $path, $scene = false ) {
$path = str_replace( '%', '%%', $path );
+
return $this->escapeMagickPath( $path, $scene );
}
} else {
$path .= "[$scene]";
}
+
return $path;
}
$x = preg_match( '/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches );
if ( $x != 1 ) {
wfDebug( __METHOD__ . ": ImageMagick version check failed\n" );
+
return null;
}
$wgMemc->set( "imagemagick-version", $matches[1], 3600 );
+
return $matches[1];
}
+
return $cache;
}
/**
* @param $file File
* @param array $params Rotate parameters.
- * 'rotation' clockwise rotation in degrees, allowed are multiples of 90
+ * 'rotation' clockwise rotation in degrees, allowed are multiples of 90
* @since 1.21
* @return bool
*/
wfProfileOut( 'convert' );
if ( $retval !== 0 ) {
$this->logErrorForExternalProcess( $retval, $err, $cmd );
+
return new MediaTransformError( 'thumbnail_error', 0, 0, $err );
}
+
return false;
case 'imext':
$im = new Imagick();
return new MediaTransformError( 'thumbnail_error', 0, 0,
"Unable to write image to {$params['dstPath']}" );
}
+
return false;
default:
return new MediaTransformError( 'thumbnail_error', 0, 0,
* @ingroup Media
*/
class BitmapMetadataHandler {
-
private $metadata = array();
+
private $metaPriority = array(
20 => array( 'other' ),
40 => array( 'native' ),
100 => array( 'iptc-bad-hash' ),
120 => array( 'exif' ),
);
+
private $iptcType = 'iptc-no-hash';
/**
}
}
}
+
/** Add misc metadata. Warning: atm if the metadata category
* doesn't have a priority, it will be silently discarded.
*
}
}
}
+
return $temp;
}
* is not well tested and a bit fragile.
*/
$xmp->parseExtended( $xmpExt );
-
}
$res = $xmp->getResults();
foreach ( $res as $type => $array ) {
if ( isset( $seg['byteOrder'] ) ) {
$meta->getExif( $filename, $seg['byteOrder'] );
}
+
return $meta->getMetadataArray();
}
unset( $array['text'] );
$array['metadata'] = $meta->getMetadataArray();
$array['metadata']['_MW_PNG_VERSION'] = PNGMetadataExtractor::VERSION;
+
return $array;
}
foreach ( $xmpRes as $type => $xmpSection ) {
$meta->addMetadata( $xmpSection, $type );
}
-
}
unset( $baseArray['comment'] );
$baseArray['metadata'] = $meta->getMetadataArray();
$baseArray['metadata']['_MW_GIF_VERSION'] = GIFMetadataExtractor::VERSION;
+
return $baseArray;
}
$data = $exif->getFilteredData();
if ( $data ) {
$data['MEDIAWIKI_EXIF_VERSION'] = Exif::version();
+
return $data;
} else {
throw new MWException( "Could not extract data from tiff file $filename" );
throw new MWException( "File doesn't exist - $filename" );
}
}
+
/**
* Read the first 2 bytes of a tiff file to figure out
* Little Endian or Big Endian. Needed for exif stuff.
* @ingroup Media
*/
class BitmapHandler_ClientOnly extends BitmapHandler {
-
/**
* @param $image File
* @param $params
if ( !$this->normaliseParams( $image, $params ) ) {
return new TransformParameterError( $params );
}
+
return new ThumbnailImage( $image, $image->getURL(), $image->getLocalRefPath(), $params );
}
}
* @ingroup Media
*/
class DjVuHandler extends ImageHandler {
-
/**
* @return bool
*/
global $wgDjvuRenderer, $wgDjvuDump, $wgDjvuToXML;
if ( !$wgDjvuRenderer || ( !$wgDjvuDump && !$wgDjvuToXML ) ) {
wfDebug( "DjVu is disabled, please set \$wgDjvuRenderer and \$wgDjvuDump\n" );
+
return false;
} else {
return true;
if ( !isset( $params['width'] ) ) {
return false;
}
+
return "page{$page}-{$params['width']}px";
}
if ( !$xml ) {
$width = isset( $params['width'] ) ? $params['width'] : 0;
$height = isset( $params['height'] ) ? $params['height'] : 0;
+
return new MediaTransformError( 'thumbnail_error', $width, $height,
wfMessage( 'djvu_no_xml' )->text() );
}
'height' => $height,
'page' => $page
);
+
return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
wfDebugLog( 'thumbnail',
sprintf( 'thumbnail failed on %s: error %d "%s" from "%s"',
wfHostname(), $retval, trim( $err ), $cmd ) );
+
return new MediaTransformError( 'thumbnail_error', $width, $height, $err );
} else {
$params = array(
'height' => $height,
'page' => $page
);
+
return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
}
}
} else {
$deja = $image->dejaImage;
}
+
return $deja;
}
$metadata = $image->getMetadata();
if ( !$this->isMetadataValid( $image, $metadata ) ) {
wfDebug( "DjVu XML metadata is invalid or missing, should have been fixed in upgradeRow\n" );
+
return false;
}
wfProfileIn( __METHOD__ );
$magic = MimeMagic::singleton();
$mime = $magic->guessTypesForExtension( $wgDjvuOutputExtension );
}
+
return array( $wgDjvuOutputExtension, $mime );
}
function getMetadata( $image, $path ) {
wfDebug( "Getting DjVu metadata for $path\n" );
+
return $this->getDjVuImage( $image, $path )->retrieveMetaData();
}
if ( !$tree ) {
return false;
}
+
return count( $tree->xpath( '//OBJECT' ) );
}
$o = $tree->BODY[0]->PAGE[$page - 1];
if ( $o ) {
$txt = $o['value'];
+
return $txt;
} else {
return false;
}
-
}
-
}
*/
public function isValid() {
$info = $this->getInfo();
+
return $info !== false;
}
return array( $width, $height, 'DjVu',
"width=\"$width\" height=\"$height\"" );
}
+
return false;
}
wfRestoreWarnings();
if ( $file === false ) {
wfDebug( __METHOD__ . ": missing or failed file read\n" );
+
return false;
}
}
}
fclose( $file );
+
return $info;
}
} else {
// @todo FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
extract( unpack( 'a4chunk/Nlength', $header ) );
+
return array( $chunk, $length );
}
}
$subtype = fread( $file, 4 );
if ( $subtype == 'DJVU' ) {
wfDebug( __METHOD__ . ": found first subpage\n" );
+
return $this->getPageInfo( $file, $length );
}
$this->skipChunk( $file, $length - 4 );
} while ( $length != 0 && !feof( $file ) && ftell( $file ) - $start < $formLength );
wfDebug( __METHOD__ . ": multi-page DJVU file contained no pages\n" );
+
return false;
}
list( $chunk, $length ) = $this->readChunk( $file );
if ( $chunk != 'INFO' ) {
wfDebug( __METHOD__ . ": expected INFO chunk, got '$chunk'\n" );
+
return false;
}
if ( $length < 9 ) {
wfDebug( __METHOD__ . ": INFO should be 9 or 10 bytes, found $length\n" );
+
return false;
}
$data = fread( $file, $length );
if ( strlen( $data ) < $length ) {
wfDebug( __METHOD__ . ": INFO chunk cut off\n" );
+
return false;
}
'Cmajor/' .
'vresolution/' .
'Cgamma', $data ) );
+
# Newer files have rotation info in byte 10, but we don't use it yet.
return array(
}
}
wfProfileOut( __METHOD__ );
+
return $xml;
}
if ( preg_match( '/^ *DIRM.*indirect/', $line ) ) {
wfDebug( "Indirect multi-page DjVu document, bad for server!\n" );
+
return false;
}
if ( preg_match( '/^ *FORM:DJVU/', $line ) ) {
}
$xml .= "</BODY>\n</DjVuXML>\n";
+
return $xml;
}
}
if ( preg_match( '/^ *INFO *\[\d*\] *DjVu *(\d+)x(\d+), *\w*, *(\d+) *dpi, *gamma=([0-9.-]+)/', $line, $m ) ) {
- $xml .= Xml::tags( 'OBJECT',
+ $xml .= Xml::tags(
+ 'OBJECT',
array(
#'data' => '',
#'type' => 'image/x.djvu',
#'usemap' => '',
),
"\n" .
- Xml::element( 'PARAM', array( 'name' => 'DPI', 'value' => $m[3] ) ) . "\n" .
- Xml::element( 'PARAM', array( 'name' => 'GAMMA', 'value' => $m[4] ) ) . "\n"
+ Xml::element( 'PARAM', array( 'name' => 'DPI', 'value' => $m[3] ) ) . "\n" .
+ Xml::element( 'PARAM', array( 'name' => 'GAMMA', 'value' => $m[4] ) ) . "\n"
) . "\n";
+
return true;
}
$line = strtok( "\n" );
}
+
# Not found
return false;
}
* @ingroup Media
*/
class Exif {
-
const BYTE = 1; //!< An 8-bit (1-byte) unsigned integer.
const ASCII = 2; //!< An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
const SHORT = 3; //!< A 16-bit (2-byte) unsigned integer.
* extension doesn't fully process some obscure props.
*/
private $byteOrder;
+
//@}
/**
# TIFF Rev. 6.0 Attribute Information (p22)
'IFD0' => array(
# Tags relating to image structure
- 'ImageWidth' => Exif::SHORT_OR_LONG, # Image width
- 'ImageLength' => Exif::SHORT_OR_LONG, # Image height
- 'BitsPerSample' => array( Exif::SHORT, 3 ), # Number of bits per component
+ 'ImageWidth' => Exif::SHORT_OR_LONG, # Image width
+ 'ImageLength' => Exif::SHORT_OR_LONG, # Image height
+ 'BitsPerSample' => array( Exif::SHORT, 3 ), # Number of bits per component
# "When a primary image is JPEG compressed, this designation is not"
# "necessary and is omitted." (p23)
- 'Compression' => Exif::SHORT, # Compression scheme #p23
- 'PhotometricInterpretation' => Exif::SHORT, # Pixel composition #p23
- 'Orientation' => Exif::SHORT, # Orientation of image #p24
- 'SamplesPerPixel' => Exif::SHORT, # Number of components
- 'PlanarConfiguration' => Exif::SHORT, # Image data arrangement #p24
- 'YCbCrSubSampling' => array( Exif::SHORT, 2 ), # Subsampling ratio of Y to C #p24
- 'YCbCrPositioning' => Exif::SHORT, # Y and C positioning #p24-25
- 'XResolution' => Exif::RATIONAL, # Image resolution in width direction
- 'YResolution' => Exif::RATIONAL, # Image resolution in height direction
- 'ResolutionUnit' => Exif::SHORT, # Unit of X and Y resolution #(p26)
+ 'Compression' => Exif::SHORT, # Compression scheme #p23
+ 'PhotometricInterpretation' => Exif::SHORT, # Pixel composition #p23
+ 'Orientation' => Exif::SHORT, # Orientation of image #p24
+ 'SamplesPerPixel' => Exif::SHORT, # Number of components
+ 'PlanarConfiguration' => Exif::SHORT, # Image data arrangement #p24
+ 'YCbCrSubSampling' => array( Exif::SHORT, 2 ), # Subsampling ratio of Y to C #p24
+ 'YCbCrPositioning' => Exif::SHORT, # Y and C positioning #p24-25
+ 'XResolution' => Exif::RATIONAL, # Image resolution in width direction
+ 'YResolution' => Exif::RATIONAL, # Image resolution in height direction
+ 'ResolutionUnit' => Exif::SHORT, # Unit of X and Y resolution #(p26)
# Tags relating to recording offset
- 'StripOffsets' => Exif::SHORT_OR_LONG, # Image data location
- 'RowsPerStrip' => Exif::SHORT_OR_LONG, # Number of rows per strip
- 'StripByteCounts' => Exif::SHORT_OR_LONG, # Bytes per compressed strip
- 'JPEGInterchangeFormat' => Exif::SHORT_OR_LONG, # Offset to JPEG SOI
- 'JPEGInterchangeFormatLength' => Exif::SHORT_OR_LONG, # Bytes of JPEG data
+ 'StripOffsets' => Exif::SHORT_OR_LONG, # Image data location
+ 'RowsPerStrip' => Exif::SHORT_OR_LONG, # Number of rows per strip
+ 'StripByteCounts' => Exif::SHORT_OR_LONG, # Bytes per compressed strip
+ 'JPEGInterchangeFormat' => Exif::SHORT_OR_LONG, # Offset to JPEG SOI
+ 'JPEGInterchangeFormatLength' => Exif::SHORT_OR_LONG, # Bytes of JPEG data
# Tags relating to image data characteristics
- 'TransferFunction' => Exif::IGNORE, # Transfer function
- 'WhitePoint' => array( Exif::RATIONAL, 2 ), # White point chromaticity
- 'PrimaryChromaticities' => array( Exif::RATIONAL, 6 ), # Chromaticities of primarities
- 'YCbCrCoefficients' => array( Exif::RATIONAL, 3 ), # Color space transformation matrix coefficients #p27
- 'ReferenceBlackWhite' => array( Exif::RATIONAL, 6 ), # Pair of black and white reference values
+ 'TransferFunction' => Exif::IGNORE, # Transfer function
+ 'WhitePoint' => array( Exif::RATIONAL, 2 ), # White point chromaticity
+ 'PrimaryChromaticities' => array( Exif::RATIONAL, 6 ), # Chromaticities of primarities
+ 'YCbCrCoefficients' => array( Exif::RATIONAL, 3 ), # Color space transformation matrix coefficients #p27
+ 'ReferenceBlackWhite' => array( Exif::RATIONAL, 6 ), # Pair of black and white reference values
# Other tags
- 'DateTime' => Exif::ASCII, # File change date and time
- 'ImageDescription' => Exif::ASCII, # Image title
- 'Make' => Exif::ASCII, # Image input equipment manufacturer
- 'Model' => Exif::ASCII, # Image input equipment model
- 'Software' => Exif::ASCII, # Software used
- 'Artist' => Exif::ASCII, # Person who created the image
- 'Copyright' => Exif::ASCII, # Copyright holder
+ 'DateTime' => Exif::ASCII, # File change date and time
+ 'ImageDescription' => Exif::ASCII, # Image title
+ 'Make' => Exif::ASCII, # Image input equipment manufacturer
+ 'Model' => Exif::ASCII, # Image input equipment model
+ 'Software' => Exif::ASCII, # Software used
+ 'Artist' => Exif::ASCII, # Person who created the image
+ 'Copyright' => Exif::ASCII, # Copyright holder
),
# Exif IFD Attribute Information (p30-31)
'EXIF' => array(
# TODO: NOTE: Nonexistence of this field is taken to mean nonconformance
# to the Exif 2.1 AND 2.2 standards
- 'ExifVersion' => Exif::UNDEFINED, # Exif version
- 'FlashPixVersion' => Exif::UNDEFINED, # Supported Flashpix version #p32
+ 'ExifVersion' => Exif::UNDEFINED, # Exif version
+ 'FlashPixVersion' => Exif::UNDEFINED, # Supported Flashpix version #p32
# Tags relating to Image Data Characteristics
- 'ColorSpace' => Exif::SHORT, # Color space information #p32
+ 'ColorSpace' => Exif::SHORT, # Color space information #p32
# Tags relating to image configuration
- 'ComponentsConfiguration' => Exif::UNDEFINED, # Meaning of each component #p33
- 'CompressedBitsPerPixel' => Exif::RATIONAL, # Image compression mode
- 'PixelYDimension' => Exif::SHORT_OR_LONG, # Valid image width
- 'PixelXDimension' => Exif::SHORT_OR_LONG, # Valid image height
+ 'ComponentsConfiguration' => Exif::UNDEFINED, # Meaning of each component #p33
+ 'CompressedBitsPerPixel' => Exif::RATIONAL, # Image compression mode
+ 'PixelYDimension' => Exif::SHORT_OR_LONG, # Valid image width
+ 'PixelXDimension' => Exif::SHORT_OR_LONG, # Valid image height
# Tags relating to related user information
- 'MakerNote' => Exif::IGNORE, # Manufacturer notes
- 'UserComment' => Exif::UNDEFINED, # User comments #p34
+ 'MakerNote' => Exif::IGNORE, # Manufacturer notes
+ 'UserComment' => Exif::UNDEFINED, # User comments #p34
# Tags relating to related file information
- 'RelatedSoundFile' => Exif::ASCII, # Related audio file
+ 'RelatedSoundFile' => Exif::ASCII, # Related audio file
# Tags relating to date and time
- 'DateTimeOriginal' => Exif::ASCII, # Date and time of original data generation #p36
- 'DateTimeDigitized' => Exif::ASCII, # Date and time of original data generation
- 'SubSecTime' => Exif::ASCII, # DateTime subseconds
- 'SubSecTimeOriginal' => Exif::ASCII, # DateTimeOriginal subseconds
- 'SubSecTimeDigitized' => Exif::ASCII, # DateTimeDigitized subseconds
+ 'DateTimeOriginal' => Exif::ASCII, # Date and time of original data generation #p36
+ 'DateTimeDigitized' => Exif::ASCII, # Date and time of original data generation
+ 'SubSecTime' => Exif::ASCII, # DateTime subseconds
+ 'SubSecTimeOriginal' => Exif::ASCII, # DateTimeOriginal subseconds
+ 'SubSecTimeDigitized' => Exif::ASCII, # DateTimeDigitized subseconds
# Tags relating to picture-taking conditions (p31)
- 'ExposureTime' => Exif::RATIONAL, # Exposure time
- 'FNumber' => Exif::RATIONAL, # F Number
- 'ExposureProgram' => Exif::SHORT, # Exposure Program #p38
- 'SpectralSensitivity' => Exif::ASCII, # Spectral sensitivity
- 'ISOSpeedRatings' => Exif::SHORT, # ISO speed rating
+ 'ExposureTime' => Exif::RATIONAL, # Exposure time
+ 'FNumber' => Exif::RATIONAL, # F Number
+ 'ExposureProgram' => Exif::SHORT, # Exposure Program #p38
+ 'SpectralSensitivity' => Exif::ASCII, # Spectral sensitivity
+ 'ISOSpeedRatings' => Exif::SHORT, # ISO speed rating
'OECF' => Exif::IGNORE,
# Optoelectronic conversion factor. Note: We don't have support for this atm.
- 'ShutterSpeedValue' => Exif::SRATIONAL, # Shutter speed
- 'ApertureValue' => Exif::RATIONAL, # Aperture
- 'BrightnessValue' => Exif::SRATIONAL, # Brightness
- 'ExposureBiasValue' => Exif::SRATIONAL, # Exposure bias
- 'MaxApertureValue' => Exif::RATIONAL, # Maximum land aperture
- 'SubjectDistance' => Exif::RATIONAL, # Subject distance
- 'MeteringMode' => Exif::SHORT, # Metering mode #p40
- 'LightSource' => Exif::SHORT, # Light source #p40-41
- 'Flash' => Exif::SHORT, # Flash #p41-42
- 'FocalLength' => Exif::RATIONAL, # Lens focal length
- 'SubjectArea' => array( Exif::SHORT, 4 ), # Subject area
- 'FlashEnergy' => Exif::RATIONAL, # Flash energy
- 'SpatialFrequencyResponse' => Exif::IGNORE, # Spatial frequency response. Not supported atm.
- 'FocalPlaneXResolution' => Exif::RATIONAL, # Focal plane X resolution
- 'FocalPlaneYResolution' => Exif::RATIONAL, # Focal plane Y resolution
- 'FocalPlaneResolutionUnit' => Exif::SHORT, # Focal plane resolution unit #p46
- 'SubjectLocation' => array( Exif::SHORT, 2 ), # Subject location
- 'ExposureIndex' => Exif::RATIONAL, # Exposure index
- 'SensingMethod' => Exif::SHORT, # Sensing method #p46
- 'FileSource' => Exif::UNDEFINED, # File source #p47
- 'SceneType' => Exif::UNDEFINED, # Scene type #p47
- 'CFAPattern' => Exif::IGNORE, # CFA pattern. not supported atm.
- 'CustomRendered' => Exif::SHORT, # Custom image processing #p48
- 'ExposureMode' => Exif::SHORT, # Exposure mode #p48
- 'WhiteBalance' => Exif::SHORT, # White Balance #p49
- 'DigitalZoomRatio' => Exif::RATIONAL, # Digital zoom ration
- 'FocalLengthIn35mmFilm' => Exif::SHORT, # Focal length in 35 mm film
- 'SceneCaptureType' => Exif::SHORT, # Scene capture type #p49
- 'GainControl' => Exif::SHORT, # Scene control #p49-50
- 'Contrast' => Exif::SHORT, # Contrast #p50
- 'Saturation' => Exif::SHORT, # Saturation #p50
- 'Sharpness' => Exif::SHORT, # Sharpness #p50
+ 'ShutterSpeedValue' => Exif::SRATIONAL, # Shutter speed
+ 'ApertureValue' => Exif::RATIONAL, # Aperture
+ 'BrightnessValue' => Exif::SRATIONAL, # Brightness
+ 'ExposureBiasValue' => Exif::SRATIONAL, # Exposure bias
+ 'MaxApertureValue' => Exif::RATIONAL, # Maximum land aperture
+ 'SubjectDistance' => Exif::RATIONAL, # Subject distance
+ 'MeteringMode' => Exif::SHORT, # Metering mode #p40
+ 'LightSource' => Exif::SHORT, # Light source #p40-41
+ 'Flash' => Exif::SHORT, # Flash #p41-42
+ 'FocalLength' => Exif::RATIONAL, # Lens focal length
+ 'SubjectArea' => array( Exif::SHORT, 4 ), # Subject area
+ 'FlashEnergy' => Exif::RATIONAL, # Flash energy
+ 'SpatialFrequencyResponse' => Exif::IGNORE, # Spatial frequency response. Not supported atm.
+ 'FocalPlaneXResolution' => Exif::RATIONAL, # Focal plane X resolution
+ 'FocalPlaneYResolution' => Exif::RATIONAL, # Focal plane Y resolution
+ 'FocalPlaneResolutionUnit' => Exif::SHORT, # Focal plane resolution unit #p46
+ 'SubjectLocation' => array( Exif::SHORT, 2 ), # Subject location
+ 'ExposureIndex' => Exif::RATIONAL, # Exposure index
+ 'SensingMethod' => Exif::SHORT, # Sensing method #p46
+ 'FileSource' => Exif::UNDEFINED, # File source #p47
+ 'SceneType' => Exif::UNDEFINED, # Scene type #p47
+ 'CFAPattern' => Exif::IGNORE, # CFA pattern. not supported atm.
+ 'CustomRendered' => Exif::SHORT, # Custom image processing #p48
+ 'ExposureMode' => Exif::SHORT, # Exposure mode #p48
+ 'WhiteBalance' => Exif::SHORT, # White Balance #p49
+ 'DigitalZoomRatio' => Exif::RATIONAL, # Digital zoom ration
+ 'FocalLengthIn35mmFilm' => Exif::SHORT, # Focal length in 35 mm film
+ 'SceneCaptureType' => Exif::SHORT, # Scene capture type #p49
+ 'GainControl' => Exif::SHORT, # Scene control #p49-50
+ 'Contrast' => Exif::SHORT, # Contrast #p50
+ 'Saturation' => Exif::SHORT, # Saturation #p50
+ 'Sharpness' => Exif::SHORT, # Sharpness #p50
'DeviceSettingDescription' => Exif::IGNORE,
# Device settings description. This could maybe be supported. Need to find an
# example file that uses this to see if it has stuff of interest in it.
- 'SubjectDistanceRange' => Exif::SHORT, # Subject distance range #p51
+ 'SubjectDistanceRange' => Exif::SHORT, # Subject distance range #p51
- 'ImageUniqueID' => Exif::ASCII, # Unique image ID
+ 'ImageUniqueID' => Exif::ASCII, # Unique image ID
),
# GPS Attribute Information (p52)
'GPSVersion' => Exif::UNDEFINED,
# Should be an array of 4 Exif::BYTE's. However php treats it as an undefined
# Note exif standard calls this GPSVersionID, but php doesn't like the id suffix
- 'GPSLatitudeRef' => Exif::ASCII, # North or South Latitude #p52-53
- 'GPSLatitude' => array( Exif::RATIONAL, 3 ), # Latitude
- 'GPSLongitudeRef' => Exif::ASCII, # East or West Longitude #p53
- 'GPSLongitude' => array( Exif::RATIONAL, 3 ), # Longitude
+ 'GPSLatitudeRef' => Exif::ASCII, # North or South Latitude #p52-53
+ 'GPSLatitude' => array( Exif::RATIONAL, 3 ), # Latitude
+ 'GPSLongitudeRef' => Exif::ASCII, # East or West Longitude #p53
+ 'GPSLongitude' => array( Exif::RATIONAL, 3 ), # Longitude
'GPSAltitudeRef' => Exif::UNDEFINED,
# Altitude reference. Note, the exif standard says this should be an EXIF::Byte,
# but php seems to disagree.
- 'GPSAltitude' => Exif::RATIONAL, # Altitude
- 'GPSTimeStamp' => array( Exif::RATIONAL, 3 ), # GPS time (atomic clock)
- 'GPSSatellites' => Exif::ASCII, # Satellites used for measurement
- 'GPSStatus' => Exif::ASCII, # Receiver status #p54
- 'GPSMeasureMode' => Exif::ASCII, # Measurement mode #p54-55
- 'GPSDOP' => Exif::RATIONAL, # Measurement precision
- 'GPSSpeedRef' => Exif::ASCII, # Speed unit #p55
- 'GPSSpeed' => Exif::RATIONAL, # Speed of GPS receiver
- 'GPSTrackRef' => Exif::ASCII, # Reference for direction of movement #p55
- 'GPSTrack' => Exif::RATIONAL, # Direction of movement
- 'GPSImgDirectionRef' => Exif::ASCII, # Reference for direction of image #p56
- 'GPSImgDirection' => Exif::RATIONAL, # Direction of image
- 'GPSMapDatum' => Exif::ASCII, # Geodetic survey data used
- 'GPSDestLatitudeRef' => Exif::ASCII, # Reference for latitude of destination #p56
- 'GPSDestLatitude' => array( Exif::RATIONAL, 3 ), # Latitude destination
- 'GPSDestLongitudeRef' => Exif::ASCII, # Reference for longitude of destination #p57
- 'GPSDestLongitude' => array( Exif::RATIONAL, 3 ), # Longitude of destination
- 'GPSDestBearingRef' => Exif::ASCII, # Reference for bearing of destination #p57
- 'GPSDestBearing' => Exif::RATIONAL, # Bearing of destination
- 'GPSDestDistanceRef' => Exif::ASCII, # Reference for distance to destination #p57-58
- 'GPSDestDistance' => Exif::RATIONAL, # Distance to destination
- 'GPSProcessingMethod' => Exif::UNDEFINED, # Name of GPS processing method
- 'GPSAreaInformation' => Exif::UNDEFINED, # Name of GPS area
- 'GPSDateStamp' => Exif::ASCII, # GPS date
- 'GPSDifferential' => Exif::SHORT, # GPS differential correction
+ 'GPSAltitude' => Exif::RATIONAL, # Altitude
+ 'GPSTimeStamp' => array( Exif::RATIONAL, 3 ), # GPS time (atomic clock)
+ 'GPSSatellites' => Exif::ASCII, # Satellites used for measurement
+ 'GPSStatus' => Exif::ASCII, # Receiver status #p54
+ 'GPSMeasureMode' => Exif::ASCII, # Measurement mode #p54-55
+ 'GPSDOP' => Exif::RATIONAL, # Measurement precision
+ 'GPSSpeedRef' => Exif::ASCII, # Speed unit #p55
+ 'GPSSpeed' => Exif::RATIONAL, # Speed of GPS receiver
+ 'GPSTrackRef' => Exif::ASCII, # Reference for direction of movement #p55
+ 'GPSTrack' => Exif::RATIONAL, # Direction of movement
+ 'GPSImgDirectionRef' => Exif::ASCII, # Reference for direction of image #p56
+ 'GPSImgDirection' => Exif::RATIONAL, # Direction of image
+ 'GPSMapDatum' => Exif::ASCII, # Geodetic survey data used
+ 'GPSDestLatitudeRef' => Exif::ASCII, # Reference for latitude of destination #p56
+ 'GPSDestLatitude' => array( Exif::RATIONAL, 3 ), # Latitude destination
+ 'GPSDestLongitudeRef' => Exif::ASCII, # Reference for longitude of destination #p57
+ 'GPSDestLongitude' => array( Exif::RATIONAL, 3 ), # Longitude of destination
+ 'GPSDestBearingRef' => Exif::ASCII, # Reference for bearing of destination #p57
+ 'GPSDestBearing' => Exif::RATIONAL, # Bearing of destination
+ 'GPSDestDistanceRef' => Exif::ASCII, # Reference for distance to destination #p57-58
+ 'GPSDestDistance' => Exif::RATIONAL, # Distance to destination
+ 'GPSProcessingMethod' => Exif::UNDEFINED, # Name of GPS processing method
+ 'GPSAreaInformation' => Exif::UNDEFINED, # Name of GPS area
+ 'GPSDateStamp' => Exif::ASCII, # GPS date
+ 'GPSDifferential' => Exif::SHORT, # GPS differential correction
),
);
$this->mFilteredExifData['GPSAltitude'] = $num / $denom;
if ( $this->mFilteredExifData['GPSAltitudeRef'] === "\1" ) {
- $this->mFilteredExifData['GPSAltitude'] *= - 1;
+ $this->mFilteredExifData['GPSAltitude'] *= -1;
}
unset( $this->mFilteredExifData['GPSAltitudeRef'] );
}
}
unset( $this->mFilteredExifData['GPSVersion'] );
}
-
}
+
/**
* Do userComment tags and similar. See pg. 34 of exif standard.
* basically first 8 bytes is charset, rest is value.
$this->debug( $this->mFilteredExifData[$prop], __FUNCTION__, false );
unset( $this->mFilteredExifData[$prop] );
+
return;
}
$charCode = substr( $this->mFilteredExifData[$prop], 0, 8 );
//only whitespace.
$this->debug( $this->mFilteredExifData[$prop], __FUNCTION__, "$prop: Is only whitespace" );
unset( $this->mFilteredExifData[$prop] );
+
return;
}
$this->mFilteredExifData[$prop] = $val;
}
}
+
/**
* Convert an Exif::UNDEFINED from a raw binary string
* to its value. This is sometimes needed depending on
$this->mFilteredExifData[$prop] = ord( $this->mFilteredExifData[$prop] );
}
}
+
/**
* Convert gps in exif form to a single floating point number
* for example 10 degress 20`40`` S -> -10.34444
$res += ( $num / $denom ) * ( 1 / 3600 );
if ( $dir === 'S' || $dir === 'W' ) {
- $res *= - 1; // make negative
+ $res *= -1; // make negative
}
}
$this->mFormattedExifData = FormatMetadata::getFormattedData(
$this->mFilteredExifData );
}
+
/**#@-*/
/**#@+
if ( !$this->mFormattedExifData ) {
$this->makeFormattedData();
}
+
return $this->mFormattedExifData;
}
+
/**#@-*/
/**
private function isByte( $in ) {
if ( !is_array( $in ) && sprintf( '%d', $in ) == $in && $in >= 0 && $in <= 255 ) {
$this->debug( $in, __FUNCTION__, true );
+
return true;
} else {
$this->debug( $in, __FUNCTION__, false );
+
return false;
}
}
if ( preg_match( "/[^\x0a\x20-\x7e]/", $in ) ) {
$this->debug( $in, __FUNCTION__, 'found a character not in our whitelist' );
+
return false;
}
if ( preg_match( '/^\s*$/', $in ) ) {
$this->debug( $in, __FUNCTION__, 'input consisted solely of whitespace' );
+
return false;
}
private function isShort( $in ) {
if ( !is_array( $in ) && sprintf( '%d', $in ) == $in && $in >= 0 && $in <= 65536 ) {
$this->debug( $in, __FUNCTION__, true );
+
return true;
} else {
$this->debug( $in, __FUNCTION__, false );
+
return false;
}
}
private function isLong( $in ) {
if ( !is_array( $in ) && sprintf( '%d', $in ) == $in && $in >= 0 && $in <= 4294967296 ) {
$this->debug( $in, __FUNCTION__, true );
+
return true;
} else {
$this->debug( $in, __FUNCTION__, false );
+
return false;
}
}
return $this->isLong( $m[1] ) && $this->isLong( $m[2] );
} else {
$this->debug( $in, __FUNCTION__, 'fed a non-fraction value' );
+
return false;
}
}
*/
private function isUndefined( $in ) {
$this->debug( $in, __FUNCTION__, true );
+
return true;
}
private function isSlong( $in ) {
if ( $this->isLong( abs( $in ) ) ) {
$this->debug( $in, __FUNCTION__, true );
+
return true;
} else {
$this->debug( $in, __FUNCTION__, false );
+
return false;
}
}
return $this->isSlong( $m[0] ) && $this->isSlong( $m[1] );
} else {
$this->debug( $in, __FUNCTION__, 'fed a non-fraction value' );
+
return false;
}
}
+
/**#@-*/
/**
$count = count( $val );
if ( $ecount != $count ) {
$this->debug( $val, __FUNCTION__, "Expected $ecount elements for $tag but got $count" );
+
return false;
}
if ( $count > 1 ) {
return false;
}
}
+
return true;
}
// Does not work if not typecast
switch ( (string)$etype ) {
case (string)Exif::BYTE:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isByte( $val );
case (string)Exif::ASCII:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isASCII( $val );
case (string)Exif::SHORT:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isShort( $val );
case (string)Exif::LONG:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isLong( $val );
case (string)Exif::RATIONAL:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isRational( $val );
case (string)Exif::SHORT_OR_LONG:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isShort( $val ) || $this->isLong( $val );
case (string)Exif::UNDEFINED:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isUndefined( $val );
case (string)Exif::SLONG:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isSlong( $val );
case (string)Exif::SRATIONAL:
$this->debug( $val, __FUNCTION__, $debug );
+
return $this->isSrational( $val );
case (string)Exif::IGNORE:
$this->debug( $val, __FUNCTION__, $debug );
+
return false;
default:
$this->debug( $val, __FUNCTION__, "The tag '$tag' is unknown" );
+
return false;
}
}
* @ingroup Media
*/
class ExifBitmapHandler extends BitmapHandler {
-
const BROKEN_FILE = '-1'; // error extracting metadata
const OLD_BROKEN_FILE = '0'; // outdated error extracting metadata.
}
}
$metadata['MEDIAWIKI_EXIF_VERSION'] = 1;
+
return $metadata;
}
# Old special value indicating that there is no Exif data in the file.
# or that there was an error well extracting the metadata.
wfDebug( __METHOD__ . ": back-compat version\n" );
+
return self::METADATA_COMPATIBLE;
}
if ( $metadata === self::BROKEN_FILE ) {
) {
//back-compatible but old
wfDebug( __METHOD__ . ": back-compat version\n" );
+
return self::METADATA_COMPATIBLE;
}
# Wrong (non-compatible) version
wfDebug( __METHOD__ . ": wrong version\n" );
+
return self::METADATA_BAD;
}
+
return self::METADATA_GOOD;
}
$gis[0] = $gis[1];
$gis[1] = $width;
}
+
return $gis;
}
}
$data = $file->getMetadata();
+
return $this->getRotationForExif( $data );
}
return 0;
}
}
+
return 0;
}
}
* @since 1.23 the class extends ContextSource and various formerly-public internal methods are private
*/
class FormatMetadata extends ContextSource {
-
/**
* Only output a single language for multi-language fields
* @var boolean
if ( $context ) {
$obj->setContext( $context );
}
+
return $obj->makeFormattedData( $tags );
}
foreach ( $vals as &$val ) {
switch ( $tag ) {
- case 'Compression':
- switch ( $val ) {
- case 1: case 2: case 3: case 4:
- case 5: case 6: case 7: case 8:
- case 32773: case 32946: case 34712:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'Compression':
+ switch ( $val ) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 32773:
+ case 32946:
+ case 34712:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'PhotometricInterpretation':
- switch ( $val ) {
- case 2: case 6:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'PhotometricInterpretation':
+ switch ( $val ) {
+ case 2:
+ case 6:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'Orientation':
- switch ( $val ) {
- case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'Orientation':
+ switch ( $val ) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'PlanarConfiguration':
- switch ( $val ) {
- case 1: case 2:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
- break;
- }
- break;
-
- // TODO: YCbCrSubSampling
- case 'YCbCrPositioning':
- switch ( $val ) {
- case 1:
- case 2:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'PlanarConfiguration':
+ switch ( $val ) {
+ case 1:
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
-
- case 'XResolution':
- case 'YResolution':
- switch ( $resolutionunit ) {
- case 2:
- $val = $this->exifMsg( 'XYResolution', 'i', $this->formatNum( $val ) );
- break;
- case 3:
- $val = $this->exifMsg( 'XYResolution', 'c', $this->formatNum( $val ) );
- break;
- default:
- /* If not recognized, display as is. */
- break;
- }
- break;
- // TODO: YCbCrCoefficients #p27 (see annex E)
- case 'ExifVersion': case 'FlashpixVersion':
- $val = "$val" / 100;
- break;
-
- case 'ColorSpace':
- switch ( $val ) {
- case 1: case 65535:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ // TODO: YCbCrSubSampling
+ case 'YCbCrPositioning':
+ switch ( $val ) {
+ case 1:
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'ComponentsConfiguration':
- switch ( $val ) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6:
- $val = $this->exifMsg( $tag, $val );
+ case 'XResolution':
+ case 'YResolution':
+ switch ( $resolutionunit ) {
+ case 2:
+ $val = $this->exifMsg( 'XYResolution', 'i', $this->formatNum( $val ) );
+ break;
+ case 3:
+ $val = $this->exifMsg( 'XYResolution', 'c', $this->formatNum( $val ) );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ // TODO: YCbCrCoefficients #p27 (see annex E)
+ case 'ExifVersion':
+ case 'FlashpixVersion':
+ $val = "$val" / 100;
break;
- }
- break;
-
- case 'DateTime':
- case 'DateTimeOriginal':
- case 'DateTimeDigitized':
- case 'DateTimeReleased':
- case 'DateTimeExpires':
- case 'GPSDateStamp':
- case 'dc-date':
- case 'DateTimeMetadata':
- if ( $val == '0000:00:00 00:00:00' || $val == ' : : : : ' ) {
- $val = $this->msg( 'exif-unknowndate' )->text();
- } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D', $val ) ) {
- // Full date.
- $time = wfTimestamp( TS_MW, $val );
- if ( $time && intval( $time ) > 0 ) {
- $val = $this->getLanguage()->timeanddate( $time );
- }
- } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) {
- // No second field. Still format the same
- // since timeanddate doesn't include seconds anyways,
- // but second still available in api
- $time = wfTimestamp( TS_MW, $val . ':00' );
- if ( $time && intval( $time ) > 0 ) {
- $val = $this->getLanguage()->timeanddate( $time );
- }
- } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) {
- // If only the date but not the time is filled in.
- $time = wfTimestamp( TS_MW, substr( $val, 0, 4 )
- . substr( $val, 5, 2 )
- . substr( $val, 8, 2 )
- . '000000' );
- if ( $time && intval( $time ) > 0 ) {
- $val = $this->getLanguage()->date( $time );
- }
- }
- // else it will just output $val without formatting it.
- break;
- case 'ExposureProgram':
- switch ( $val ) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
- $val = $this->exifMsg( $tag, $val );
+ case 'ColorSpace':
+ switch ( $val ) {
+ case 1:
+ case 65535:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'ComponentsConfiguration':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'SubjectDistance':
- $val = $this->exifMsg( $tag, '', $this->formatNum( $val ) );
- break;
+ case 'DateTime':
+ case 'DateTimeOriginal':
+ case 'DateTimeDigitized':
+ case 'DateTimeReleased':
+ case 'DateTimeExpires':
+ case 'GPSDateStamp':
+ case 'dc-date':
+ case 'DateTimeMetadata':
+ if ( $val == '0000:00:00 00:00:00' || $val == ' : : : : ' ) {
+ $val = $this->msg( 'exif-unknowndate' )->text();
+ } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D', $val ) ) {
+ // Full date.
+ $time = wfTimestamp( TS_MW, $val );
+ if ( $time && intval( $time ) > 0 ) {
+ $val = $this->getLanguage()->timeanddate( $time );
+ }
+ } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) {
+ // No second field. Still format the same
+ // since timeanddate doesn't include seconds anyways,
+ // but second still available in api
+ $time = wfTimestamp( TS_MW, $val . ':00' );
+ if ( $time && intval( $time ) > 0 ) {
+ $val = $this->getLanguage()->timeanddate( $time );
+ }
+ } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) {
+ // If only the date but not the time is filled in.
+ $time = wfTimestamp( TS_MW, substr( $val, 0, 4 )
+ . substr( $val, 5, 2 )
+ . substr( $val, 8, 2 )
+ . '000000' );
+ if ( $time && intval( $time ) > 0 ) {
+ $val = $this->getLanguage()->date( $time );
+ }
+ }
+ // else it will just output $val without formatting it.
+ break;
- case 'MeteringMode':
- switch ( $val ) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 255:
- $val = $this->exifMsg( $tag, $val );
+ case 'ExposureProgram':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'SubjectDistance':
+ $val = $this->exifMsg( $tag, '', $this->formatNum( $val ) );
break;
- }
- break;
-
- case 'LightSource':
- switch ( $val ) {
- case 0: case 1: case 2: case 3: case 4: case 9: case 10: case 11:
- case 12: case 13: case 14: case 15: case 17: case 18: case 19: case 20:
- case 21: case 22: case 23: case 24: case 255:
- $val = $this->exifMsg( $tag, $val );
+
+ case 'MeteringMode':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 255:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'LightSource':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 255:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
-
- case 'Flash':
- $flashDecode = array(
- 'fired' => $val & bindec( '00000001' ),
- 'return' => ( $val & bindec( '00000110' ) ) >> 1,
- 'mode' => ( $val & bindec( '00011000' ) ) >> 3,
- 'function' => ( $val & bindec( '00100000' ) ) >> 5,
- 'redeye' => ( $val & bindec( '01000000' ) ) >> 6,
+
+ case 'Flash':
+ $flashDecode = array(
+ 'fired' => $val & bindec( '00000001' ),
+ 'return' => ( $val & bindec( '00000110' ) ) >> 1,
+ 'mode' => ( $val & bindec( '00011000' ) ) >> 3,
+ 'function' => ( $val & bindec( '00100000' ) ) >> 5,
+ 'redeye' => ( $val & bindec( '01000000' ) ) >> 6,
// 'reserved' => ($val & bindec( '10000000' )) >> 7,
- );
- $flashMsgs = array();
- # We do not need to handle unknown values since all are used.
- foreach ( $flashDecode as $subTag => $subValue ) {
- # We do not need any message for zeroed values.
- if ( $subTag != 'fired' && $subValue == 0 ) {
- continue;
+ );
+ $flashMsgs = array();
+ # We do not need to handle unknown values since all are used.
+ foreach ( $flashDecode as $subTag => $subValue ) {
+ # We do not need any message for zeroed values.
+ if ( $subTag != 'fired' && $subValue == 0 ) {
+ continue;
+ }
+ $fullTag = $tag . '-' . $subTag;
+ $flashMsgs[] = $this->exifMsg( $fullTag, $subValue );
}
- $fullTag = $tag . '-' . $subTag;
- $flashMsgs[] = $this->exifMsg( $fullTag, $subValue );
- }
- $val = $this->getLanguage()->commaList( $flashMsgs );
- break;
-
- case 'FocalPlaneResolutionUnit':
- switch ( $val ) {
- case 2:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ $val = $this->getLanguage()->commaList( $flashMsgs );
break;
- }
- break;
- case 'SensingMethod':
- switch ( $val ) {
- case 1: case 2: case 3: case 4: case 5: case 7: case 8:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'FocalPlaneResolutionUnit':
+ switch ( $val ) {
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'FileSource':
- switch ( $val ) {
- case 3:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'SensingMethod':
+ switch ( $val ) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 8:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'SceneType':
- switch ( $val ) {
- case 1:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'FileSource':
+ switch ( $val ) {
+ case 3:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'CustomRendered':
- switch ( $val ) {
- case 0: case 1:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'SceneType':
+ switch ( $val ) {
+ case 1:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'ExposureMode':
- switch ( $val ) {
- case 0: case 1: case 2:
- $val = $this->exifMsg( $tag, $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'CustomRendered':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'WhiteBalance':
- switch ( $val ) {
- case 0: case 1:
- $val = $this->exifMsg( $tag, $val );
+ case 'ExposureMode':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'WhiteBalance':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'SceneCaptureType':
- switch ( $val ) {
- case 0: case 1: case 2: case 3:
- $val = $this->exifMsg( $tag, $val );
+ case 'SceneCaptureType':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'GainControl':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'GainControl':
- switch ( $val ) {
- case 0: case 1: case 2: case 3: case 4:
- $val = $this->exifMsg( $tag, $val );
+ case 'Contrast':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'Saturation':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'Contrast':
- switch ( $val ) {
- case 0: case 1: case 2:
- $val = $this->exifMsg( $tag, $val );
+ case 'Sharpness':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'SubjectDistanceRange':
+ switch ( $val ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'Saturation':
- switch ( $val ) {
- case 0: case 1: case 2:
- $val = $this->exifMsg( $tag, $val );
+ //The GPS...Ref values are kept for compatibility, probably won't be reached.
+ case 'GPSLatitudeRef':
+ case 'GPSDestLatitudeRef':
+ switch ( $val ) {
+ case 'N':
+ case 'S':
+ $val = $this->exifMsg( 'GPSLatitude', $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'GPSLongitudeRef':
+ case 'GPSDestLongitudeRef':
+ switch ( $val ) {
+ case 'E':
+ case 'W':
+ $val = $this->exifMsg( 'GPSLongitude', $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'Sharpness':
- switch ( $val ) {
- case 0: case 1: case 2:
- $val = $this->exifMsg( $tag, $val );
+ case 'GPSAltitude':
+ if ( $val < 0 ) {
+ $val = $this->exifMsg( 'GPSAltitude', 'below-sealevel', $this->formatNum( -$val, 3 ) );
+ } else {
+ $val = $this->exifMsg( 'GPSAltitude', 'above-sealevel', $this->formatNum( $val, 3 ) );
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'GPSStatus':
+ switch ( $val ) {
+ case 'A':
+ case 'V':
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'SubjectDistanceRange':
- switch ( $val ) {
- case 0: case 1: case 2: case 3:
- $val = $this->exifMsg( $tag, $val );
+ case 'GPSMeasureMode':
+ switch ( $val ) {
+ case 2:
+ case 3:
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'GPSTrackRef':
+ case 'GPSImgDirectionRef':
+ case 'GPSDestBearingRef':
+ switch ( $val ) {
+ case 'T':
+ case 'M':
+ $val = $this->exifMsg( 'GPSDirection', $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
-
- //The GPS...Ref values are kept for compatibility, probably won't be reached.
- case 'GPSLatitudeRef':
- case 'GPSDestLatitudeRef':
- switch ( $val ) {
- case 'N': case 'S':
- $val = $this->exifMsg( 'GPSLatitude', $val );
+
+ case 'GPSLatitude':
+ case 'GPSDestLatitude':
+ $val = $this->formatCoords( $val, 'latitude' );
break;
- default:
- /* If not recognized, display as is. */
+ case 'GPSLongitude':
+ case 'GPSDestLongitude':
+ $val = $this->formatCoords( $val, 'longitude' );
break;
- }
- break;
- case 'GPSLongitudeRef':
- case 'GPSDestLongitudeRef':
- switch ( $val ) {
- case 'E': case 'W':
- $val = $this->exifMsg( 'GPSLongitude', $val );
- break;
- default:
- /* If not recognized, display as is. */
+ case 'GPSSpeedRef':
+ switch ( $val ) {
+ case 'K':
+ case 'M':
+ case 'N':
+ $val = $this->exifMsg( 'GPSSpeed', $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
break;
- }
- break;
- case 'GPSAltitude':
- if ( $val < 0 ) {
- $val = $this->exifMsg( 'GPSAltitude', 'below-sealevel', $this->formatNum( -$val, 3 ) );
- } else {
- $val = $this->exifMsg( 'GPSAltitude', 'above-sealevel', $this->formatNum( $val, 3 ) );
- }
- break;
+ case 'GPSDestDistanceRef':
+ switch ( $val ) {
+ case 'K':
+ case 'M':
+ case 'N':
+ $val = $this->exifMsg( 'GPSDestDistance', $val );
+ break;
+ default:
+ /* If not recognized, display as is. */
+ break;
+ }
+ break;
- case 'GPSStatus':
- switch ( $val ) {
- case 'A': case 'V':
- $val = $this->exifMsg( $tag, $val );
+ case 'GPSDOP':
+ // See http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
+ if ( $val <= 2 ) {
+ $val = $this->exifMsg( $tag, 'excellent', $this->formatNum( $val ) );
+ } elseif ( $val <= 5 ) {
+ $val = $this->exifMsg( $tag, 'good', $this->formatNum( $val ) );
+ } elseif ( $val <= 10 ) {
+ $val = $this->exifMsg( $tag, 'moderate', $this->formatNum( $val ) );
+ } elseif ( $val <= 20 ) {
+ $val = $this->exifMsg( $tag, 'fair', $this->formatNum( $val ) );
+ } else {
+ $val = $this->exifMsg( $tag, 'poor', $this->formatNum( $val ) );
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ // This is not in the Exif standard, just a special
+ // case for our purposes which enables wikis to wikify
+ // the make, model and software name to link to their articles.
+ case 'Make':
+ case 'Model':
+ $val = $this->exifMsg( $tag, '', $val );
break;
- }
- break;
- case 'GPSMeasureMode':
- switch ( $val ) {
- case 2: case 3:
- $val = $this->exifMsg( $tag, $val );
+ case 'Software':
+ if ( is_array( $val ) ) {
+ //if its a software, version array.
+ $val = $this->msg( 'exif-software-version-value', $val[0], $val[1] )->text();
+ } else {
+ $val = $this->exifMsg( $tag, '', $val );
+ }
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'ExposureTime':
+ // Show the pretty fraction as well as decimal version
+ $val = $this->msg( 'exif-exposuretime-format',
+ $this->formatFraction( $val ), $this->formatNum( $val ) )->text();
break;
- }
- break;
-
- case 'GPSTrackRef':
- case 'GPSImgDirectionRef':
- case 'GPSDestBearingRef':
- switch ( $val ) {
- case 'T': case 'M':
- $val = $this->exifMsg( 'GPSDirection', $val );
+ case 'ISOSpeedRatings':
+ // If its = 65535 that means its at the
+ // limit of the size of Exif::short and
+ // is really higher.
+ if ( $val == '65535' ) {
+ $val = $this->exifMsg( $tag, 'overflow' );
+ } else {
+ $val = $this->formatNum( $val );
+ }
break;
- default:
- /* If not recognized, display as is. */
+ case 'FNumber':
+ $val = $this->msg( 'exif-fnumber-format',
+ $this->formatNum( $val ) )->text();
break;
- }
- break;
-
- case 'GPSLatitude':
- case 'GPSDestLatitude':
- $val = $this->formatCoords( $val, 'latitude' );
- break;
- case 'GPSLongitude':
- case 'GPSDestLongitude':
- $val = $this->formatCoords( $val, 'longitude' );
- break;
-
- case 'GPSSpeedRef':
- switch ( $val ) {
- case 'K': case 'M': case 'N':
- $val = $this->exifMsg( 'GPSSpeed', $val );
+
+ case 'FocalLength':
+ case 'FocalLengthIn35mmFilm':
+ $val = $this->msg( 'exif-focallength-format',
+ $this->formatNum( $val ) )->text();
break;
- default:
- /* If not recognized, display as is. */
+
+ case 'MaxApertureValue':
+ if ( strpos( $val, '/' ) !== false ) {
+ // need to expand this earlier to calculate fNumber
+ list( $n, $d ) = explode( '/', $val );
+ if ( is_numeric( $n ) && is_numeric( $d ) ) {
+ $val = $n / $d;
+ }
+ }
+ if ( is_numeric( $val ) ) {
+ $fNumber = pow( 2, $val / 2 );
+ if ( $fNumber !== false ) {
+ $val = $this->msg( 'exif-maxaperturevalue-value',
+ $this->formatNum( $val ),
+ $this->formatNum( $fNumber, 2 )
+ )->text();
+ }
+ }
break;
- }
- break;
- case 'GPSDestDistanceRef':
- switch ( $val ) {
- case 'K': case 'M': case 'N':
- $val = $this->exifMsg( 'GPSDestDistance', $val );
+ case 'iimCategory':
+ switch ( strtolower( $val ) ) {
+ // See pg 29 of IPTC photo
+ // metadata standard.
+ case 'ace':
+ case 'clj':
+ case 'dis':
+ case 'fin':
+ case 'edu':
+ case 'evn':
+ case 'hth':
+ case 'hum':
+ case 'lab':
+ case 'lif':
+ case 'pol':
+ case 'rel':
+ case 'sci':
+ case 'soi':
+ case 'spo':
+ case 'war':
+ case 'wea':
+ $val = $this->exifMsg(
+ 'iimcategory',
+ $val
+ );
+ }
break;
- default:
- /* If not recognized, display as is. */
+ case 'SubjectNewsCode':
+ // Essentially like iimCategory.
+ // 8 (numeric) digit hierarchical
+ // classification. We decode the
+ // first 2 digits, which provide
+ // a broad category.
+ $val = $this->convertNewsCode( $val );
break;
- }
- break;
-
- case 'GPSDOP':
- // See http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
- if ( $val <= 2 ) {
- $val = $this->exifMsg( $tag, 'excellent', $this->formatNum( $val ) );
- } elseif ( $val <= 5 ) {
- $val = $this->exifMsg( $tag, 'good', $this->formatNum( $val ) );
- } elseif ( $val <= 10 ) {
- $val = $this->exifMsg( $tag, 'moderate', $this->formatNum( $val ) );
- } elseif ( $val <= 20 ) {
- $val = $this->exifMsg( $tag, 'fair', $this->formatNum( $val ) );
- } else {
- $val = $this->exifMsg( $tag, 'poor', $this->formatNum( $val ) );
- }
- break;
-
- // This is not in the Exif standard, just a special
- // case for our purposes which enables wikis to wikify
- // the make, model and software name to link to their articles.
- case 'Make':
- case 'Model':
- $val = $this->exifMsg( $tag, '', $val );
- break;
-
- case 'Software':
- if ( is_array( $val ) ) {
- //if its a software, version array.
- $val = $this->msg( 'exif-software-version-value', $val[0], $val[1] )->text();
- } else {
- $val = $this->exifMsg( $tag, '', $val );
- }
- break;
-
- case 'ExposureTime':
- // Show the pretty fraction as well as decimal version
- $val = $this->msg( 'exif-exposuretime-format',
- $this->formatFraction( $val ), $this->formatNum( $val ) )->text();
- break;
- case 'ISOSpeedRatings':
- // If its = 65535 that means its at the
- // limit of the size of Exif::short and
- // is really higher.
- if ( $val == '65535' ) {
- $val = $this->exifMsg( $tag, 'overflow' );
- } else {
- $val = $this->formatNum( $val );
- }
- break;
- case 'FNumber':
- $val = $this->msg( 'exif-fnumber-format',
- $this->formatNum( $val ) )->text();
- break;
-
- case 'FocalLength': case 'FocalLengthIn35mmFilm':
- $val = $this->msg( 'exif-focallength-format',
- $this->formatNum( $val ) )->text();
- break;
-
- case 'MaxApertureValue':
- if ( strpos( $val, '/' ) !== false ) {
- // need to expand this earlier to calculate fNumber
- list( $n, $d ) = explode( '/', $val );
- if ( is_numeric( $n ) && is_numeric( $d ) ) {
- $val = $n / $d;
+ case 'Urgency':
+ // 1-8 with 1 being highest, 5 normal
+ // 0 is reserved, and 9 is 'user-defined'.
+ $urgency = '';
+ if ( $val == 0 || $val == 9 ) {
+ $urgency = 'other';
+ } elseif ( $val < 5 && $val > 1 ) {
+ $urgency = 'high';
+ } elseif ( $val == 5 ) {
+ $urgency = 'normal';
+ } elseif ( $val <= 8 && $val > 5 ) {
+ $urgency = 'low';
}
- }
- if ( is_numeric( $val ) ) {
- $fNumber = pow( 2, $val / 2 );
- if ( $fNumber !== false ) {
- $val = $this->msg( 'exif-maxaperturevalue-value',
- $this->formatNum( $val ),
- $this->formatNum( $fNumber, 2 )
- )->text();
- }
- }
- break;
-
- case 'iimCategory':
- switch ( strtolower( $val ) ) {
- // See pg 29 of IPTC photo
- // metadata standard.
- case 'ace': case 'clj':
- case 'dis': case 'fin':
- case 'edu': case 'evn':
- case 'hth': case 'hum':
- case 'lab': case 'lif':
- case 'pol': case 'rel':
- case 'sci': case 'soi':
- case 'spo': case 'war':
- case 'wea':
- $val = $this->exifMsg(
- 'iimcategory',
- $val
+
+ if ( $urgency !== '' ) {
+ $val = $this->exifMsg( 'urgency',
+ $urgency, $val
);
- }
- break;
- case 'SubjectNewsCode':
- // Essentially like iimCategory.
- // 8 (numeric) digit hierarchical
- // classification. We decode the
- // first 2 digits, which provide
- // a broad category.
- $val = $this->convertNewsCode( $val );
- break;
- case 'Urgency':
- // 1-8 with 1 being highest, 5 normal
- // 0 is reserved, and 9 is 'user-defined'.
- $urgency = '';
- if ( $val == 0 || $val == 9 ) {
- $urgency = 'other';
- } elseif ( $val < 5 && $val > 1 ) {
- $urgency = 'high';
- } elseif ( $val == 5 ) {
- $urgency = 'normal';
- } elseif ( $val <= 8 && $val > 5 ) {
- $urgency = 'low';
- }
+ }
+ break;
- if ( $urgency !== '' ) {
- $val = $this->exifMsg( 'urgency',
- $urgency, $val
- );
- }
- break;
-
- // Things that have a unit of pixels.
- case 'OriginalImageHeight':
- case 'OriginalImageWidth':
- case 'PixelXDimension':
- case 'PixelYDimension':
- case 'ImageWidth':
- case 'ImageLength':
- $val = $this->formatNum( $val ) . ' ' . $this->msg( 'unit-pixel' )->text();
- break;
-
- // Do not transform fields with pure text.
- // For some languages the formatNum()
- // conversion results to wrong output like
- // foo,bar@example,com or fooÙ«bar@exampleÙ«com.
- // Also some 'numeric' things like Scene codes
- // are included here as we really don't want
- // commas inserted.
- case 'ImageDescription':
- case 'Artist':
- case 'Copyright':
- case 'RelatedSoundFile':
- case 'ImageUniqueID':
- case 'SpectralSensitivity':
- case 'GPSSatellites':
- case 'GPSVersionID':
- case 'GPSMapDatum':
- case 'Keywords':
- case 'WorldRegionDest':
- case 'CountryDest':
- case 'CountryCodeDest':
- case 'ProvinceOrStateDest':
- case 'CityDest':
- case 'SublocationDest':
- case 'WorldRegionCreated':
- case 'CountryCreated':
- case 'CountryCodeCreated':
- case 'ProvinceOrStateCreated':
- case 'CityCreated':
- case 'SublocationCreated':
- case 'ObjectName':
- case 'SpecialInstructions':
- case 'Headline':
- case 'Credit':
- case 'Source':
- case 'EditStatus':
- case 'FixtureIdentifier':
- case 'LocationDest':
- case 'LocationDestCode':
- case 'Writer':
- case 'JPEGFileComment':
- case 'iimSupplementalCategory':
- case 'OriginalTransmissionRef':
- case 'Identifier':
- case 'dc-contributor':
- case 'dc-coverage':
- case 'dc-publisher':
- case 'dc-relation':
- case 'dc-rights':
- case 'dc-source':
- case 'dc-type':
- case 'Lens':
- case 'SerialNumber':
- case 'CameraOwnerName':
- case 'Label':
- case 'Nickname':
- case 'RightsCertificate':
- case 'CopyrightOwner':
- case 'UsageTerms':
- case 'WebStatement':
- case 'OriginalDocumentID':
- case 'LicenseUrl':
- case 'MorePermissionsUrl':
- case 'AttributionUrl':
- case 'PreferredAttributionName':
- case 'PNGFileComment':
- case 'Disclaimer':
- case 'ContentWarning':
- case 'GIFFileComment':
- case 'SceneCode':
- case 'IntellectualGenre':
- case 'Event':
- case 'OrginisationInImage':
- case 'PersonInImage':
-
- $val = htmlspecialchars( $val );
- break;
-
- case 'ObjectCycle':
- switch ( $val ) {
- case 'a': case 'p': case 'b':
- $val = $this->exifMsg( $tag, $val );
+ // Things that have a unit of pixels.
+ case 'OriginalImageHeight':
+ case 'OriginalImageWidth':
+ case 'PixelXDimension':
+ case 'PixelYDimension':
+ case 'ImageWidth':
+ case 'ImageLength':
+ $val = $this->formatNum( $val ) . ' ' . $this->msg( 'unit-pixel' )->text();
break;
- default:
+
+ // Do not transform fields with pure text.
+ // For some languages the formatNum()
+ // conversion results to wrong output like
+ // foo,bar@example,com or fooÙ«bar@exampleÙ«com.
+ // Also some 'numeric' things like Scene codes
+ // are included here as we really don't want
+ // commas inserted.
+ case 'ImageDescription':
+ case 'Artist':
+ case 'Copyright':
+ case 'RelatedSoundFile':
+ case 'ImageUniqueID':
+ case 'SpectralSensitivity':
+ case 'GPSSatellites':
+ case 'GPSVersionID':
+ case 'GPSMapDatum':
+ case 'Keywords':
+ case 'WorldRegionDest':
+ case 'CountryDest':
+ case 'CountryCodeDest':
+ case 'ProvinceOrStateDest':
+ case 'CityDest':
+ case 'SublocationDest':
+ case 'WorldRegionCreated':
+ case 'CountryCreated':
+ case 'CountryCodeCreated':
+ case 'ProvinceOrStateCreated':
+ case 'CityCreated':
+ case 'SublocationCreated':
+ case 'ObjectName':
+ case 'SpecialInstructions':
+ case 'Headline':
+ case 'Credit':
+ case 'Source':
+ case 'EditStatus':
+ case 'FixtureIdentifier':
+ case 'LocationDest':
+ case 'LocationDestCode':
+ case 'Writer':
+ case 'JPEGFileComment':
+ case 'iimSupplementalCategory':
+ case 'OriginalTransmissionRef':
+ case 'Identifier':
+ case 'dc-contributor':
+ case 'dc-coverage':
+ case 'dc-publisher':
+ case 'dc-relation':
+ case 'dc-rights':
+ case 'dc-source':
+ case 'dc-type':
+ case 'Lens':
+ case 'SerialNumber':
+ case 'CameraOwnerName':
+ case 'Label':
+ case 'Nickname':
+ case 'RightsCertificate':
+ case 'CopyrightOwner':
+ case 'UsageTerms':
+ case 'WebStatement':
+ case 'OriginalDocumentID':
+ case 'LicenseUrl':
+ case 'MorePermissionsUrl':
+ case 'AttributionUrl':
+ case 'PreferredAttributionName':
+ case 'PNGFileComment':
+ case 'Disclaimer':
+ case 'ContentWarning':
+ case 'GIFFileComment':
+ case 'SceneCode':
+ case 'IntellectualGenre':
+ case 'Event':
+ case 'OrginisationInImage':
+ case 'PersonInImage':
+
$val = htmlspecialchars( $val );
break;
- }
- break;
- case 'Copyrighted':
- switch ( $val ) {
- case 'True': case 'False':
- $val = $this->exifMsg( $tag, $val );
+
+ case 'ObjectCycle':
+ switch ( $val ) {
+ case 'a':
+ case 'p':
+ case 'b':
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ default:
+ $val = htmlspecialchars( $val );
+ break;
+ }
+ break;
+ case 'Copyrighted':
+ switch ( $val ) {
+ case 'True':
+ case 'False':
+ $val = $this->exifMsg( $tag, $val );
+ break;
+ }
+ break;
+ case 'Rating':
+ if ( $val == '-1' ) {
+ $val = $this->exifMsg( $tag, 'rejected' );
+ } else {
+ $val = $this->formatNum( $val );
+ }
break;
- }
- break;
- case 'Rating':
- if ( $val == '-1' ) {
- $val = $this->exifMsg( $tag, 'rejected' );
- } else {
- $val = $this->formatNum( $val );
- }
- break;
- case 'LanguageCode':
- $lang = Language::fetchLanguageName( strtolower( $val ), $this->getLanguage()->getCode() );
- if ( $lang ) {
- $val = htmlspecialchars( $lang );
- } else {
- $val = htmlspecialchars( $val );
- }
- break;
+ case 'LanguageCode':
+ $lang = Language::fetchLanguageName( strtolower( $val ), $this->getLanguage()->getCode() );
+ if ( $lang ) {
+ $val = htmlspecialchars( $lang );
+ } else {
+ $val = htmlspecialchars( $val );
+ }
+ break;
- default:
- $val = $this->formatNum( $val );
- break;
+ default:
+ $val = $this->formatNum( $val );
+ break;
}
}
// End formatting values, start flattening arrays.
$vals = $this->flattenArrayReal( $vals, $type );
-
}
+
return $tags;
}
$context = new DerivativeContext( $obj->getContext() );
$context->setLanguage( $wgContLang );
$obj->setContext( $context );
+
return $obj->flattenArrayReal( $vals, $type, $noHtml );
}
if ( $context ) {
$obj->setContext( $context );
}
+
return $obj->flattenArrayReal( $vals, $type, $noHtml );
}
if ( !is_array( $vals ) ) {
return $vals; // do nothing if not an array;
- }
- elseif ( count( $vals ) === 1 && $type !== 'lang' ) {
+ } elseif ( count( $vals ) === 1 && $type !== 'lang' ) {
return $vals[0];
- }
- elseif ( count( $vals ) === 0 ) {
+ } elseif ( count( $vals ) === 0 ) {
wfDebug( __METHOD__ . " metadata array with 0 elements!\n" );
+
return ""; // paranoia. This should never happen
- }
- /* @todo FIXME: This should hide some of the list entries if there are
- * say more than four. Especially if a field is translated into 20
- * languages, we don't want to show them all by default
- */
- else {
+ } else {
+ /* @todo FIXME: This should hide some of the list entries if there are
+ * say more than four. Especially if a field is translated into 20
+ * languages, we don't want to show them all by default
+ */
switch ( $type ) {
- case 'lang':
- // Display default, followed by ContLang,
- // followed by the rest in no particular
- // order.
-
- // Todo: hide some items if really long list.
-
- $content = '';
-
- $priorityLanguages = $this->getPriorityLanguages();
- $defaultItem = false;
- $defaultLang = false;
-
- // If default is set, save it for later,
- // as we don't know if it's equal to
- // one of the lang codes. (In xmp
- // you specify the language for a
- // default property by having both
- // a default prop, and one in the language
- // that are identical)
- if ( isset( $vals['x-default'] ) ) {
- $defaultItem = $vals['x-default'];
- unset( $vals['x-default'] );
- }
- foreach ( $priorityLanguages as $pLang ) {
- if ( isset( $vals[$pLang] ) ) {
- $isDefault = false;
- if ( $vals[$pLang] === $defaultItem ) {
- $defaultItem = false;
- $isDefault = true;
+ case 'lang':
+ // Display default, followed by ContLang,
+ // followed by the rest in no particular
+ // order.
+
+ // Todo: hide some items if really long list.
+
+ $content = '';
+
+ $priorityLanguages = $this->getPriorityLanguages();
+ $defaultItem = false;
+ $defaultLang = false;
+
+ // If default is set, save it for later,
+ // as we don't know if it's equal to
+ // one of the lang codes. (In xmp
+ // you specify the language for a
+ // default property by having both
+ // a default prop, and one in the language
+ // that are identical)
+ if ( isset( $vals['x-default'] ) ) {
+ $defaultItem = $vals['x-default'];
+ unset( $vals['x-default'] );
+ }
+ foreach ( $priorityLanguages as $pLang ) {
+ if ( isset( $vals[$pLang] ) ) {
+ $isDefault = false;
+ if ( $vals[$pLang] === $defaultItem ) {
+ $defaultItem = false;
+ $isDefault = true;
+ }
+ $content .= $this->langItem(
+ $vals[$pLang], $pLang,
+ $isDefault, $noHtml );
+
+ unset( $vals[$pLang] );
+
+ if ( $this->singleLang ) {
+ return Html::rawElement( 'span',
+ array( 'lang' => $pLang ), $vals[$pLang] );
+ }
}
- $content .= $this->langItem(
- $vals[$pLang], $pLang,
- $isDefault, $noHtml );
-
- unset( $vals[$pLang] );
+ }
+ // Now do the rest.
+ foreach ( $vals as $lang => $item ) {
+ if ( $item === $defaultItem ) {
+ $defaultLang = $lang;
+ continue;
+ }
+ $content .= $this->langItem( $item,
+ $lang, false, $noHtml );
if ( $this->singleLang ) {
return Html::rawElement( 'span',
- array( 'lang' => $pLang ), $vals[$pLang] );
+ array( 'lang' => $lang ), $item );
}
}
- }
-
- // Now do the rest.
- foreach ( $vals as $lang => $item ) {
- if ( $item === $defaultItem ) {
- $defaultLang = $lang;
- continue;
- }
- $content .= $this->langItem( $item,
- $lang, false, $noHtml );
- if ( $this->singleLang ) {
- return Html::rawElement( 'span',
- array( 'lang' => $lang ), $item );
+ if ( $defaultItem !== false ) {
+ $content = $this->langItem( $defaultItem,
+ $defaultLang, true, $noHtml ) .
+ $content;
+ if ( $this->singleLang ) {
+ return $defaultItem;
+ }
}
- }
- if ( $defaultItem !== false ) {
- $content = $this->langItem( $defaultItem,
- $defaultLang, true, $noHtml ) .
- $content;
- if ( $this->singleLang ) {
- return $defaultItem;
+ if ( $noHtml ) {
+ return $content;
}
- }
- if ( $noHtml ) {
- return $content;
- }
- return '<ul class="metadata-langlist">' .
+
+ return '<ul class="metadata-langlist">' .
$content .
'</ul>';
- case 'ol':
- if ( $noHtml ) {
- return "\n#" . implode( "\n#", $vals );
- }
- return "<ol><li>" . implode( "</li>\n<li>", $vals ) . '</li></ol>';
- case 'ul':
- default:
- if ( $noHtml ) {
- return "\n*" . implode( "\n*", $vals );
- }
- return "<ul><li>" . implode( "</li>\n<li>", $vals ) . '</li></ul>';
+ case 'ol':
+ if ( $noHtml ) {
+ return "\n#" . implode( "\n#", $vals );
+ }
+
+ return "<ol><li>" . implode( "</li>\n<li>", $vals ) . '</li></ol>';
+ case 'ul':
+ default:
+ if ( $noHtml ) {
+ return "\n*" . implode( "\n*", $vals );
+ }
+
+ return "<ul><li>" . implode( "</li>\n<li>", $vals ) . '</li></ul>';
}
}
}
if ( $noHtml ) {
return $msg->text() . "\n\n";
} /* else */
+
return '<li class="mw-metadata-lang-default">'
. $msg->text()
. "</li>\n";
$item .= '" lang="' . $lang . '">';
$item .= $msg->text();
$item .= "</li>\n";
+
return $item;
}
if ( $val === '' ) {
$val = 'value';
}
+
return $this->msg( $wgContLang->lc( "exif-$tag-$val" ), $arg, $arg2 )->text();
}
foreach ( $num as $number ) {
$out[] = $this->formatNum( $number );
}
+
return $this->getLanguage()->commaList( $out );
}
if ( preg_match( '/^(-?\d+)\/(\d+)$/', $num, $m ) ) {
if ( is_numeric( $num ) && $round !== false ) {
$num = round( $num, $round );
}
+
return $this->getLanguage()->formatNum( $num );
}
}
return $this->formatNum( $numerator / $gcd ) . '/' . $this->formatNum( $denominator / $gcd );
}
}
+
return $this->formatNum( $num );
}
$a = $b;
$b = $remainder;
}
+
return $a;
}
$catMsg = $this->exifMsg( 'iimcategory', $cat );
$val = $this->exifMsg( 'subjectnewscode', '', $val, $catMsg );
}
+
return $val;
}
foreach ( $vals as &$val ) {
$val = htmlspecialchars( $val );
}
+
return $this->flattenArrayReal( $vals );
} else {
// We have a real ContactInfo field.
$emails[] = $finalEmail;
} else {
$emails[] = '[mailto:'
- . $finalEmail
- . ' <span class="email">'
- . $finalEmail
- . '</span>]';
+ . $finalEmail
+ . ' <span class="email">'
+ . $finalEmail
+ . '</span>]';
}
}
}
. htmlspecialchars( $vals['CiUrlWork'] )
. '</span>';
}
+
return $this->msg( 'exif-contact-value', $email, $url,
$street, $city, $region, $postal, $country,
$tel )->text();
}
}
$fields = array_map( 'strtolower', $fields );
+
return $fields;
}
// If revision deleted, exit immediately
if ( $file->isDeleted( File::DELETED_FILE ) ) {
wfProfileOut( __METHOD__ );
+
return array();
}
$cacheKey = wfMemcKey(
'getExtendedMetadata',
$this->getLanguage()->getCode(),
- (int) $this->singleLang,
+ (int)$this->singleLang,
$file->getSha1()
);
}
wfProfileOut( __METHOD__ );
+
return $extendedMetadata;
}
$name = $text;
}
- $fileMetadata[ 'ObjectName' ] = array(
+ $fileMetadata['ObjectName'] = array(
'value' => $name,
'source' => 'mediawiki-metadata',
);
}
wfProfileOut( __METHOD__ );
+
return $fileMetadata;
}
$visible = array_flip( self::getVisibleFields() );
foreach ( $extendedMetadata as $key => $value ) {
- if ( !isset( $visible[ strtolower( $key ) ] ) ) {
+ if ( !isset( $visible[strtolower( $key )] ) ) {
$extendedMetadata[$key]['hidden'] = '';
}
}
wfProfileOut( __METHOD__ );
+
return $extendedMetadata;
}
*/
protected function getPriorityLanguages() {
$priorityLanguages = Language::getFallbacksIncludingSiteLanguage( $this->getLanguage()->getCode() );
- $priorityLanguages = array_merge( (array) $this->getLanguage()->getCode(), $priorityLanguages[0], $priorityLanguages[1] );
+ $priorityLanguages = array_merge( (array)$this->getLanguage()->getCode(), $priorityLanguages[0], $priorityLanguages[1] );
+
return $priorityLanguages;
}
}
* @ingroup Media
*/
class GIFHandler extends BitmapHandler {
-
const BROKEN_FILE = '0'; // value to store in img_metadata if error extracting metadata.
function getMetadata( $image, $filename ) {
} catch ( Exception $e ) {
// Broken file?
wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
+
return self::BROKEN_FILE;
}
return array();
}
unset( $meta['metadata']['_MW_GIF_VERSION'] );
+
return $meta['metadata'];
}
$ser = $image->getMetadata();
if ( $ser ) {
$metadata = unserialize( $ser );
+
return $image->getWidth() * $image->getHeight() * $metadata['frameCount'];
} else {
return $image->getWidth() * $image->getHeight();
return true;
}
}
+
return false;
}
function canAnimateThumbnail( $file ) {
global $wgMaxAnimatedGifArea;
$answer = $this->getImageArea( $file ) <= $wgMaxAnimatedGifArea;
+
return $answer;
}
if ( !$data || !is_array( $data ) ) {
wfDebug( __METHOD__ . " invalid GIF metadata\n" );
+
return self::METADATA_BAD;
}
if ( !isset( $data['metadata']['_MW_GIF_VERSION'] )
- || $data['metadata']['_MW_GIF_VERSION'] != GIFMetadataExtractor::VERSION ) {
+ || $data['metadata']['_MW_GIF_VERSION'] != GIFMetadataExtractor::VERSION
+ ) {
wfDebug( __METHOD__ . " old but compatible GIF metadata\n" );
+
return self::METADATA_COMPATIBLE;
}
+
return self::METADATA_GOOD;
}
*/
class GIFMetadataExtractor {
static $gif_frame_sep;
+
static $gif_extension_sep;
+
static $gif_term;
const VERSION = 1;
// strip out trailer.
$xmp = substr( $xmp, 0, -257 );
-
} else {
// unrecognized extension block
fseek( $fh, -( $blockLength + 1 ), SEEK_CUR );
$data .= fread( $fh, ord( $subLength ) );
$subLength = fread( $fh, 1 );
}
+
return $data;
}
-
}
* @ingroup Media
*/
class IPTC {
-
/**
* This takes the results of iptcparse() and puts it into a
* form that can be handled by mediawiki. Generally called from
$parsed = iptcparse( $rawData );
$data = array();
if ( !is_array( $parsed ) ) {
- return $data;
+ return $data;
}
$c = '';
wfDebugLog( 'iptc', 'IPTC: '
. '2:04 too short. '
. 'Ignoring.' );
- break;
+ break;
}
$extracted = substr( $con[0], 4 );
$data['IntellectualGenre'] = $extracted;
break;
default:
- wfDebugLog( 'iptc', "Unsupported iptc tag: $tag. Value: " . implode( ',', $val ));
+ wfDebugLog( 'iptc', "Unsupported iptc tag: $tag. Value: " . implode( ',', $val ) );
break;
}
-
}
+
return $data;
}
// April, but the year and day is unknown. We don't process these
// types of incomplete dates atm.
wfDebugLog( 'iptc', "IPTC: invalid time ( $time ) or date ( $date )" );
+
return null;
}
- $unixTS = wfTimestamp( TS_UNIX, $date . substr( $time, 0, 6 ));
+ $unixTS = wfTimestamp( TS_UNIX, $date . substr( $time, 0, 6 ) );
if ( $unixTS === false ) {
wfDebugLog( 'iptc', "IPTC: can't convert date to TS_UNIX: $date $time." );
+
return null;
}
+ ( intval( substr( $time, 9, 2 ) ) * 60 );
if ( substr( $time, 6, 1 ) === '-' ) {
- $tz = - $tz;
+ $tz = -$tz;
}
$finalTimestamp = wfTimestamp( TS_EXIF, $unixTS + $tz );
if ( $finalTimestamp === false ) {
wfDebugLog( 'iptc', "IPTC: can't make final timestamp. Date: " . ( $unixTS + $tz ) );
+
return null;
}
if ( $dateOnly ) {
return $data;
}
+
/**
* Helper function of a helper function to convert charset for iptc values.
* @param $data Mixed String or Array: The iptc string
return self::convIPTCHelper( $oldData, 'Windows-1252' );
}
}
+
return trim( $data );
}
* @ingroup Media
*/
abstract class ImageHandler extends MediaHandler {
-
/**
* @param $file File
* @return bool
} else {
throw new MWException( 'No width specified to ' . __METHOD__ );
}
+
# Removed for ProofreadPage
#$width = intval( $width );
return "{$width}px";
}
if ( !$this->validateThumbParams( $params['physicalWidth'],
- $params['physicalHeight'], $srcWidth, $srcHeight, $mimeType ) ) {
+ $params['physicalHeight'], $srcWidth, $srcHeight, $mimeType )
+ ) {
return false;
}
+
return true;
}
# Sanity check $width
if ( $width <= 0 ) {
wfDebug( __METHOD__ . ": Invalid destination width: $width\n" );
+
return false;
}
if ( $srcWidth <= 0 ) {
wfDebug( __METHOD__ . ": Invalid source width: $srcWidth\n" );
+
return false;
}
# Force height to be at least 1 pixel
$height = 1;
}
+
return true;
}
wfSuppressWarnings();
$gis = getimagesize( $path );
wfRestoreWarnings();
+
return $gis;
}
+
/**
* Function that returns the number of pixels to be thumbnailed.
* Intended for animated GIFs to multiply by the number of frames.
if ( $pages === false || $pages <= 1 ) {
$msg = wfMessage( 'file-info-size' )->numParams( $file->getWidth(),
$file->getHeight() )->params( $size,
- $file->getMimeType() )->parse();
+ $file->getMimeType() )->parse();
} else {
$msg = wfMessage( 'file-info-size-pages' )->numParams( $file->getWidth(),
$file->getHeight() )->params( $size,
- $file->getMimeType() )->numParams( $pages )->parse();
+ $file->getMimeType() )->numParams( $pages )->parse();
}
+
return $msg;
}
* @ingroup Media
*/
class JpegHandler extends ExifBitmapHandler {
-
function getMetadata( $image, $filename ) {
try {
$meta = BitmapMetadataHandler::Jpeg( $filename );
throw new MWException( 'Metadata array is not an array' );
}
$meta['MEDIAWIKI_EXIF_VERSION'] = Exif::version();
+
return serialize( $meta );
- }
- catch ( MWException $e ) {
+ } catch ( MWException $e ) {
// BitmapMetadataHandler throws an exception in certain exceptional cases like if file does not exist.
wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
* Thus switch to using -1 to denote only a broken file, and use an array with only
* MEDIAWIKI_EXIF_VERSION to denote no props.
*/
+
return ExifBitmapHandler::BROKEN_FILE;
}
}
/**
* @param $file File
* @param array $params Rotate parameters.
- * 'rotation' clockwise rotation in degrees, allowed are multiples of 90
+ * 'rotation' clockwise rotation in degrees, allowed are multiples of 90
* @since 1.21
* @return bool
*/
wfProfileOut( 'jpegtran' );
if ( $retval !== 0 ) {
$this->logErrorForExternalProcess( $retval, $err, $cmd );
+
return new MediaTransformError( 'thumbnail_error', 0, 0, $err );
}
+
return false;
} else {
return parent::rotate( $file, $params );
}
}
-
}
* @ingroup Media
*/
class JpegMetadataExtractor {
-
const MAX_JPEG_SEGMENTS = 200;
+
// the max segment is a sanity check.
// A jpeg file should never even remotely have
// that many segments. Your average file has about 10.
} else {
wfDebug( __METHOD__ . " Ignoring JPEG comment as is garbage.\n" );
}
-
} elseif ( $buffer === "\xE1" ) {
// APP1 section (Exif, XMP, and XMP extended)
// only extract if XMP is enabled.
}
fseek( $fh, $size['int'] - 2, SEEK_CUR );
}
-
}
// shouldn't get here.
throw new MWException( "Reached end of jpeg file unexpectedly" );
if ( strlen( $segment ) !== $size['int'] - 2 ) {
throw new MWException( "Segment shorter than expected" );
}
+
return $segment;
}
$lenData['len']++;
}
$offset += $lenData['len'];
-
}
if ( !$realHash || !$recordedHash ) {
const METADATA_GOOD = true;
const METADATA_BAD = false;
const METADATA_COMPATIBLE = 2; // for old but backwards compatible.
+
/**
* Instance cache
*/
global $wgMediaHandlers;
if ( !isset( $wgMediaHandlers[$type] ) ) {
wfDebug( __METHOD__ . ": no handler found for $type.\n" );
+
return false;
}
$class = $wgMediaHandlers[$type];
self::$handlers[$class] = false;
}
}
+
return self::$handlers[$class];
}
static function getMetadataVersion() {
$version = array( '2' ); // core metadata version
wfRunHooks( 'GetMetadataVersion', array( &$version ) );
+
return implode( ';', $version );
}
wfSuppressWarnings();
$ret = unserialize( $metadata );
wfRestoreWarnings();
+
return $ret;
}
+
return $metadata;
}
$value
);
}
+
return $result;
}
*/
function getShortDesc( $file ) {
global $wgLang;
+
return htmlspecialchars( $wgLang->formatSize( $file->getSize() ) );
}
*/
function getLongDesc( $file ) {
global $wgLang;
+
return wfMessage( 'file-info', htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ),
$file->getMimeType() )->parse();
}
*/
static function getGeneralShortDesc( $file ) {
global $wgLang;
+
return $wgLang->formatSize( $file->getSize() );
}
*/
static function getGeneralLongDesc( $file ) {
global $wgLang;
+
return wfMessage( 'file-info', $wgLang->formatSize( $file->getSize() ),
$file->getMimeType() )->parse();
}
* @param Parser $parser
* @param File $file
*/
- function parserTransformHook( $parser, $file ) {}
+ function parserTransformHook( $parser, $file ) {
+ }
/**
* File validation hook called on upload.
sprintf( 'Removing bad %d-byte thumbnail "%s". unlink() failed',
$thumbstat['size'], $dstPath ) );
}
+
return true;
}
}
+
return false;
}
public function getRotation( $file ) {
return 0;
}
-
}
$be = $this->file->getRepo()->getBackend();
// The temp file will be process cached by FileBackend
$fsFile = $be->getLocalReference( array( 'src' => $this->path ) );
+
return $fsFile ? $fsFile->getPath() : false;
} else {
return $this->path; // may return false
return false;
} elseif ( FileBackend::isStoragePath( $this->path ) ) {
$be = $this->file->getRepo()->getBackend();
+
return $be->streamFile( array( 'src' => $this->path, 'headers' => $headers ) )->isOK();
} else { // FS-file
return StreamFile::stream( $this->getLocalCopyPath(), $headers );
if ( $title ) {
$attribs['title'] = $title;
}
+
return $attribs;
}
}
return $this->linkWrap( $linkAttribs, Xml::element( 'img', $attribs ) );
}
-
}
/**
* @ingroup Media
*/
class PNGHandler extends BitmapHandler {
-
const BROKEN_FILE = '0';
/**
} catch ( Exception $e ) {
// Broken file?
wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
+
return self::BROKEN_FILE;
}
return array();
}
unset( $meta['metadata']['_MW_PNG_VERSION'] );
+
return $meta['metadata'];
}
return true;
}
}
+
return false;
}
+
/**
* We do not support making APNG thumbnails, so always false
* @param $image File
if ( !$data || !is_array( $data ) ) {
wfDebug( __METHOD__ . " invalid png metadata\n" );
+
return self::METADATA_BAD;
}
if ( !isset( $data['metadata']['_MW_PNG_VERSION'] )
- || $data['metadata']['_MW_PNG_VERSION'] != PNGMetadataExtractor::VERSION ) {
+ || $data['metadata']['_MW_PNG_VERSION'] != PNGMetadataExtractor::VERSION
+ ) {
wfDebug( __METHOD__ . " old but compatible png metadata\n" );
+
return self::METADATA_COMPATIBLE;
}
+
return self::METADATA_GOOD;
}
return $wgLang->commaList( $info );
}
-
}
*/
class PNGMetadataExtractor {
static $png_sig;
+
static $CRC_size;
+
static $text_chunks;
const VERSION = 1;
# Artist is unofficial. Author is the recommended
# keyword in the PNG spec. However some people output
# Artist so support both.
- 'artist' => 'Artist',
- 'model' => 'Model',
- 'make' => 'Make',
- 'author' => 'Artist',
- 'comment' => 'PNGFileComment',
+ 'artist' => 'Artist',
+ 'model' => 'Model',
+ 'make' => 'Make',
+ 'author' => 'Artist',
+ 'comment' => 'PNGFileComment',
'description' => 'ImageDescription',
- 'title' => 'ObjectName',
- 'copyright' => 'Copyright',
+ 'title' => 'ObjectName',
+ 'copyright' => 'Copyright',
# Source as in original device used to make image
# not as in who gave you the image
- 'source' => 'Model',
- 'software' => 'Software',
- 'disclaimer' => 'Disclaimer',
- 'warning' => 'ContentWarning',
- 'url' => 'Identifier', # Not sure if this is best mapping. Maybe WebStatement.
- 'label' => 'Label',
+ 'source' => 'Model',
+ 'software' => 'Software',
+ 'disclaimer' => 'Disclaimer',
+ 'warning' => 'ContentWarning',
+ 'url' => 'Identifier', # Not sure if this is best mapping. Maybe WebStatement.
+ 'label' => 'Label',
'creation time' => 'DateTimeDigitized',
/* Other potentially useful things - Document */
);
fseek( $fh, self::$CRC_size, SEEK_CUR );
continue;
}
-
} else {
wfDebug( __METHOD__ . ' Skipping compressed png iTXt chunk due to lack of zlib,'
. " or potentially invalid compression method\n" );
$finalKeyword = self::$text_chunks[$items[1]];
$text[$finalKeyword][$items[3]] = $items[5];
$text[$finalKeyword]['_type'] = 'lang';
-
} else {
// Error reading iTXt chunk
throw new Exception( __METHOD__ . ": Read error on iTXt chunk" );
}
-
} elseif ( $chunk_type == 'tEXt' ) {
$buf = self::read( $fh, $chunk_size );
// Theoretically should be case-sensitive, but in practise...
$keyword = strtolower( $keyword );
- if ( !isset( self::$text_chunks[ $keyword ] ) ) {
+ if ( !isset( self::$text_chunks[$keyword] ) ) {
// Don't recognize chunk, so skip.
fseek( $fh, self::$CRC_size, SEEK_CUR );
continue;
$finalKeyword = self::$text_chunks[$keyword];
$text[$finalKeyword]['x-default'] = $content;
$text[$finalKeyword]['_type'] = 'lang';
-
} elseif ( $chunk_type == 'zTXt' ) {
if ( function_exists( 'gzuncompress' ) ) {
$buf = self::read( $fh, $chunk_size );
// Theoretically should be case-sensitive, but in practise...
$keyword = strtolower( $keyword );
- if ( !isset( self::$text_chunks[ $keyword ] ) ) {
+ if ( !isset( self::$text_chunks[$keyword] ) ) {
// Don't recognize chunk, so skip.
fseek( $fh, self::$CRC_size, SEEK_CUR );
continue;
$finalKeyword = self::$text_chunks[$keyword];
$text[$finalKeyword]['x-default'] = $content;
$text[$finalKeyword]['_type'] = 'lang';
-
} else {
wfDebug( __METHOD__ . " Cannot decompress zTXt chunk due to lack of zlib. Skipping.\n" );
fseek( $fh, $chunk_size, SEEK_CUR );
if ( $exifTime ) {
$text['DateTime'] = $exifTime;
}
-
} elseif ( $chunk_type == 'pHYs' ) {
// how big pixels are (dots per meter).
if ( $chunk_size !== 9 ) {
// 3 = dots per cm (from Exif).
}
}
-
} elseif ( $chunk_type == "IEND" ) {
break;
} else {
}
}
}
+
return array(
'frameCount' => $frameCount,
'loopCount' => $loopCount,
'bitDepth' => $bitDepth,
'colorType' => $colorType,
);
-
}
+
/**
* Read a chunk, checking to make sure its not too big.
*
throw new Exception( __METHOD__ . ': Chunk size of ' . $size .
' too big. Max size is: ' . self::MAX_CHUNK_SIZE );
}
+
return fread( $fh, $size );
}
}
global $wgSVGConverters, $wgSVGConverter;
if ( !isset( $wgSVGConverters[$wgSVGConverter] ) ) {
wfDebug( "\$wgSVGConverter is invalid, disabling SVG rendering.\n" );
+
return false;
} else {
return true;
return $metadata['animated'];
}
}
+
return false;
}
$params['physicalHeight'] = $wgSVGMaxSize;
}
}
+
return true;
}
$metadata = $this->unpackMetadata( $image->getMetadata() );
if ( isset( $metadata['error'] ) ) { // sanity check
$err = wfMessage( 'svg-long-error', $metadata['error']['message'] )->text();
+
return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, $err );
}
$removed = $this->removeBadFile( $dstPath, $retval );
if ( $retval != 0 || $removed ) {
wfDebugLog( 'thumbnail', sprintf( 'thumbnail failed on %s: error %d "%s" from "%s"',
- wfHostname(), $retval, trim( $err ), $cmd ) );
+ wfHostname(), $retval, trim( $err ), $cmd ) );
+
return new MediaTransformError( 'thumbnail_error', $width, $height, $err );
}
+
return true;
}
if ( isset( $metadata['width'] ) && isset( $metadata['height'] ) ) {
return array( $metadata['width'], $metadata['height'], 'SVG',
- "width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" );
+ "width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" );
} else { // error
return array( 0, 0, 'SVG', "width=\"0\" height=\"0\"" );
}
);
wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
}
+
return serialize( $metadata );
}
// Old but compatible
return self::METADATA_COMPATIBLE;
}
+
return self::METADATA_GOOD;
}
function visibleMetadataFields() {
$fields = array( 'objectname', 'imagedescription' );
+
return $fields;
}
$value
);
}
+
return $showMeta ? $result : false;
}
// Validate $code
if ( !Language::isValidBuiltinCode( $value ) ) {
wfDebug( "Invalid user language code\n" );
+
return false;
}
+
return true;
}
+
// Only lang, width and height are acceptable keys
return false;
}
if ( !isset( $params['width'] ) ) {
return false;
}
+
return "$lang{$params['width']}px";
}
$stdMetadata[$tag] = $value;
}
}
+
return $stdMetadata;
}
}
class SVGMetadataExtractor {
static function getMetadata( $filename ) {
$svg = new SVGReader( $filename );
+
return $svg->getMetadata();
}
}
const NS_SVG = 'http://www.w3.org/2000/svg';
private $reader = null;
+
private $mDebug = false;
+
private $metadata = array();
/**
$keepReading = $this->reader->read();
while ( $keepReading ) {
if ( $this->reader->localName == $name && $this->reader->depth <= $exitDepth
- && $this->reader->nodeType == XmlReader::END_ELEMENT ) {
+ && $this->reader->nodeType == XmlReader::END_ELEMENT
+ ) {
break;
} elseif ( $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::ELEMENT ) {
switch ( $this->reader->localName ) {
* http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
*
* @param string $length CSS/SVG length.
- * @param $viewportSize: Float optional scale for percentage units...
+ * @param $viewportSize : Float optional scale for percentage units...
* @return float: length in pixels
*/
static function scaleSVGUnit( $length, $viewportSize = 512 ) {
'em' => 16.0, // fake it?
'ex' => 12.0, // fake it?
'' => 1.0, // "User units" pixels by default
- );
+ );
$matches = array();
if ( preg_match( '/^\s*(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)\s*$/', $length, $matches ) ) {
$length = floatval( $matches[1] );
* @ingroup Media
*/
class TiffHandler extends ExifBitmapHandler {
-
/**
* Conversion to PNG for inline display can be disabled here...
* Note scaling should work with ImageMagick, but may not with GD scaling.
*/
function canRender( $file ) {
global $wgTiffThumbnailType;
+
return (bool)$wgTiffThumbnailType
|| $file->getRepo() instanceof ForeignAPIRepo;
}
*/
function getThumbType( $ext, $mime, $params = null ) {
global $wgTiffThumbnailType;
+
return $wgTiffThumbnailType;
}
throw new MWException( 'Metadata array is not an array' );
}
$meta['MEDIAWIKI_EXIF_VERSION'] = Exif::version();
+
return serialize( $meta );
- }
- catch ( MWException $e ) {
+ } catch ( MWException $e ) {
// BitmapMetadataHandler throws an exception in certain exceptional
// cases like if file does not exist.
wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
+
return ExifBitmapHandler::BROKEN_FILE;
}
} else {
* @ingroup Media
*/
class XCFHandler extends BitmapHandler {
-
/**
* @param $file
* @return bool
# (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
try {
$header = wfUnpack(
- "A9magic" . # A: space padded
+ "A9magic" . # A: space padded
"/a5version" . # a: zero padded
- "/Nwidth" . # \
- "/Nheight" . # N: unsigned long 32bit big endian
+ "/Nwidth" . # \
+ "/Nheight" . # N: unsigned long 32bit big endian
"/Nbase_type", # /
$binaryHeader
);
# Check values
if ( $header['magic'] !== 'gimp xcf' ) {
wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" );
+
return false;
}
# TODO: we might want to check for sane values of width and height
$metadata = array();
$metadata[0] = $header['width'];
$metadata[1] = $header['height'];
- $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
+ $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
$metadata[3] = sprintf(
'height="%s" width="%s"', $header['height'], $header['width']
);
$metadata['mime'] = 'image/x-xcf';
$metadata['channels'] = null;
- $metadata['bits'] = 8; # Always 8-bits per color
+ $metadata['bits'] = 8; # Always 8-bits per color
assert( '7 == count($metadata); # return array must contains 7 elements just like getimagesize() return' );
*
* The public methods one would call in this class are
* - parse( $content )
- * Reads in xmp content.
- * Can potentially be called multiple times with partial data each time.
+ * Reads in xmp content.
+ * Can potentially be called multiple times with partial data each time.
* - parseExtended( $content )
- * Reads XMPExtended blocks (jpeg files only).
+ * Reads XMPExtended blocks (jpeg files only).
* - getResults
- * Outputs a results array.
+ * Outputs a results array.
*
* Note XMP kind of looks like rdf. They are not the same thing - XMP is
* encoded as a specific subset of rdf. This class can read XMP. It cannot
*
*/
class XMPReader {
+ private $curItem = array(); // array to hold the current element (and previous element, and so on)
- private $curItem = array(); // array to hold the current element (and previous element, and so on)
- private $ancestorStruct = false; // the structure name when processing nested structures.
- private $charContent = false; // temporary holder for character data that appears in xmp doc.
- private $mode = array(); // stores the state the xmpreader is in (see MODE_FOO constants)
- private $results = array(); // array to hold results
- private $processingArray = false; // if we're doing a seq or bag.
- private $itemLang = false; // used for lang alts only
+ private $ancestorStruct = false; // the structure name when processing nested structures.
+
+ private $charContent = false; // temporary holder for character data that appears in xmp doc.
+
+ private $mode = array(); // stores the state the xmpreader is in (see MODE_FOO constants)
+
+ private $results = array(); // array to hold results
+
+ private $processingArray = false; // if we're doing a seq or bag.
+
+ private $itemLang = false; // used for lang alts only
private $xmlParser;
+
private $charset = false;
+
private $extendedXMPOffset = 0;
protected $items;
$this->items = XMPInfo::getItems();
$this->resetXMLParser();
-
}
+
/**
* Main use is if a single item has multiple xmp documents describing it.
* For example in jpeg's with extendedXMP
* the array, and transform any metadata that is special-cased.
*
* @return Array array of results as an array of arrays suitable for
- * FormatMetadata::getFormattedData().
+ * FormatMetadata::getFormattedData().
*/
public function getResults() {
// xmp-special is for metadata that affects how stuff
} catch ( MWException $e ) {
wfDebugLog( 'XMP', 'XMP parse error: ' . $e );
$this->results = array();
+
return false;
}
+
return true;
}
// or programs that make such files..
$guid = substr( $content, 0, 32 );
if ( !isset( $this->results['xmp-special']['HasExtendedXMP'] )
- || $this->results['xmp-special']['HasExtendedXMP'] !== $guid ) {
+ || $this->results['xmp-special']['HasExtendedXMP'] !== $guid
+ ) {
wfDebugLog( 'XMP', __METHOD__ . " Ignoring XMPExtended block due to wrong guid (guid= '$guid')" );
+
return false;
}
$len = unpack( 'Nlength/Noffset', substr( $content, 32, 8 ) );
if ( !$len || $len['length'] < 4 || $len['offset'] < 0 || $len['offset'] > $len['length'] ) {
wfDebugLog( 'XMP', __METHOD__ . 'Error reading extended XMP block, invalid length or offset.' );
+
return false;
}
if ( $len['offset'] !== $this->extendedXMPOffset ) {
wfDebugLog( 'XMP', __METHOD__ . 'Ignoring XMPExtended block due to wrong order. (Offset was '
. $len['offset'] . ' but expected ' . $this->extendedXMPOffset . ')' );
+
return false;
}
}
wfDebugLog( 'XMP', __METHOD__ . 'Parsing a XMPExtended block' );
+
return $this->parse( $actualContent, $atEnd );
}
} else {
$this->charContent .= $data;
}
-
}
/** When we hit a closing element in MODE_IGNORE
}
array_shift( $this->curItem );
array_shift( $this->mode );
-
}
/**
if ( !isset( $this->results['xmp-' . $info['map_group']][$finalName] ) ) {
// This can happen if all the members of the struct failed validation.
wfDebugLog( 'XMP', __METHOD__ . " <$ns:$tag> has no valid members." );
-
} elseif ( is_callable( $validate ) ) {
$val =& $this->results['xmp-' . $info['map_group']][$finalName];
call_user_func_array( $validate, array( $info, &$val, false ) );
if ( !isset( $this->results['xmp-' . $info['map_group']][$finalName] ) ) {
wfDebugLog( 'XMP', __METHOD__ . " Empty compund element $finalName." );
+
return;
}
if ( $info['mode'] === self::MODE_LANG ) {
$this->results['xmp-' . $info['map_group']][$finalName]['_type'] = 'lang';
}
-
} else {
throw new MWException( __METHOD__ . " expected </rdf:seq> or </rdf:bag> but instead got $elm." );
}
if ( $elm === self::NS_RDF . ' value' ) {
list( $ns, $tag ) = explode( ' ', $this->curItem[0], 2 );
$this->saveValue( $ns, $tag, $this->charContent );
+
return;
} else {
array_shift( $this->mode );
// that forgets the namespace on some things.
// (Luckily they are unimportant things).
wfDebugLog( 'XMP', __METHOD__ . " Encountered </$elm> which has no namespace. Skipping." );
+
return;
}
} else {
throw new MWException( "Expected <rdf:Bag> but got $elm." );
}
-
}
/**
} else {
throw new MWException( "Expected <rdf:Seq> but got $elm." );
}
-
}
/**
} else {
throw new MWException( "Expected <rdf:Seq> but got $elm." );
}
-
}
/**
} elseif ( $elm === self::NS_RDF . ' value' ) {
// This should not be here.
throw new MWException( __METHOD__ . ' Encountered <rdf:value> where it was unexpected.' );
-
} else {
// something else we don't recognize, like a qualifier maybe.
wfDebugLog( 'XMP', __METHOD__ . " Encountered element <$elm> where only expecting character data as value of " . $this->curItem[0] );
array_unshift( $this->mode, self::MODE_IGNORE );
array_unshift( $this->curItem, $elm );
-
}
-
}
/**
array_unshift( $this->mode, self::MODE_IGNORE );
array_unshift( $this->curItem, $ns . ' ' . $tag );
+
return;
}
$mode = $this->items[$ns][$tag]['mode'];
wfDebugLog( 'XMP', __METHOD__ . " Ignoring unrecognized element <$ns:$tag>." );
array_unshift( $this->mode, self::MODE_IGNORE );
array_unshift( $this->curItem, $ns . ' ' . $tag );
+
return;
}
-
}
// process attributes
$this->doAttribs( $attribs );
} else {
array_unshift( $this->mode, self::MODE_IGNORE );
array_unshift( $this->curItem, $elm );
+
return;
}
-
}
if ( $ns === self::NS_RDF && $tag === 'Description' ) {
? $this->items[$curNS][$curTag]['map_name'] : $curTag;
$this->doAttribs( $attribs );
-
} else {
// Normal BAG or SEQ containing simple values.
array_unshift( $this->mode, self::MODE_SIMPLE );
array_unshift( $this->curItem, $this->curItem[0] );
$this->processingArray = true;
}
-
}
/**
if ( strpos( $elm, ' ' ) === false ) {
// This probably shouldn't happen.
wfDebugLog( 'XMP', __METHOD__ . " Encountered <$elm> which has no namespace. Skipping." );
+
return;
}
// is to be consistent between here and validating structures.
if ( is_null( $val ) ) {
wfDebugLog( 'XMP', __METHOD__ . " <$ns:$tag> failed validation." );
+
return;
}
} else {
* extract.
*/
class XMPInfo {
-
/** get the items array
* @return Array XMP item configuration array.
*/
wfRunHooks( 'XMPGetInfo', array( &self::$items ) );
self::$ranHooks = true; // Only want to do this once.
}
+
return self::$items;
}
* * 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.
+ * * 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.
+ * * 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
*/
'http://ns.adobe.com/exif/1.0/' => array(
'ApertureValue' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'BrightnessValue' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'CompressedBitsPerPixel' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'DigitalZoomRatio' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'ExposureBiasValue' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'ExposureIndex' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'ExposureTime' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'FlashEnergy' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
),
'FNumber' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'FocalLength' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'FocalPlaneXResolution' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'FocalPlaneYResolution' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'GPSAltitude' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
),
'GPSDestBearing' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'GPSDestDistance' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'GPSDOP' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'GPSImgDirection' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'GPSSpeed' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'GPSTrack' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
- 'MaxApertureValue' => array(
+ 'MaxApertureValue' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
'ShutterSpeedValue' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
- 'SubjectDistance' => array(
+ 'SubjectDistance' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational'
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational'
),
/* Flash */
- 'Flash' => array(
- 'mode' => XMPReader::MODE_STRUCT,
- 'children' => array(
- 'Fired' => true,
- 'Function' => true,
- 'Mode' => true,
+ 'Flash' => array(
+ 'mode' => XMPReader::MODE_STRUCT,
+ 'children' => array(
+ 'Fired' => true,
+ 'Function' => true,
+ 'Mode' => true,
'RedEyeMode' => true,
- 'Return' => true,
+ 'Return' => true,
),
- 'validate' => 'validateFlash',
+ 'validate' => 'validateFlash',
'map_group' => 'exif',
),
- 'Fired' => array(
+ 'Fired' => array(
'map_group' => 'exif',
- 'validate' => 'validateBoolean',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'validate' => 'validateBoolean',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
- 'Function' => array(
+ 'Function' => array(
'map_group' => 'exif',
- 'validate' => 'validateBoolean',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'validate' => 'validateBoolean',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
- 'Mode' => array(
+ 'Mode' => array(
'map_group' => 'exif',
- 'validate' => 'validateClosed',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'choices' => array( '0' => true, '1' => true,
- '2' => true, '3' => true ),
- 'structPart'=> true,
+ 'validate' => 'validateClosed',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'choices' => array( '0' => true, '1' => true,
+ '2' => true, '3' => true ),
+ 'structPart' => true,
),
- 'Return' => array(
+ 'Return' => array(
'map_group' => 'exif',
- 'validate' => 'validateClosed',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'choices' => array( '0' => true,
- '2' => true, '3' => true ),
- 'structPart'=> true,
+ 'validate' => 'validateClosed',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'choices' => array( '0' => true,
+ '2' => true, '3' => true ),
+ 'structPart' => true,
),
- 'RedEyeMode' => array(
+ 'RedEyeMode' => array(
'map_group' => 'exif',
- 'validate' => 'validateBoolean',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'validate' => 'validateBoolean',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
/* End Flash */
- 'ISOSpeedRatings' => array(
+ 'ISOSpeedRatings' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateInteger'
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger'
),
/* end rational things */
- 'ColorSpace' => array(
+ 'ColorSpace' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '1' => true, '65535' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '65535' => true ),
),
- 'ComponentsConfiguration' => array(
+ '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 )
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true, '3' => true, '4' => true,
+ '5' => true, '6' => true )
),
- 'Contrast' => array(
+ 'Contrast' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '0' => true, '1' => true, '2' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true, '2' => true )
),
- 'CustomRendered' => array(
+ 'CustomRendered' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '0' => true, '1' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true )
),
- 'DateTimeOriginal' => array(
+ 'DateTimeOriginal' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateDate',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
),
'DateTimeDigitized' => array( /* xmp:CreateDate */
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateDate',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
),
/* todo: there might be interesting information in
* exif:DeviceSettingDescription, but need to find an
* example
*/
- 'ExifVersion' => array(
+ 'ExifVersion' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'ExposureMode' => array(
+ 'ExposureMode' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 2,
),
- 'ExposureProgram' => array(
+ 'ExposureProgram' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 8,
),
- 'FileSource' => array(
+ 'FileSource' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '3' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '3' => true )
),
- 'FlashpixVersion' => array(
+ 'FlashpixVersion' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'FocalLengthIn35mmFilm' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
),
'FocalPlaneResolutionUnit' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '2' => true, '3' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '3' => true ),
),
- 'GainControl' => array(
+ 'GainControl' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 4,
),
/* this value is post-processed out later */
- 'GPSAltitudeRef' => array(
+ 'GPSAltitudeRef' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '0' => true, '1' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true ),
),
'GPSAreaInformation' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'GPSDestBearingRef' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( 'T' => true, 'M' => true ),
+ '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 ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'K' => true, 'M' => true,
+ 'N' => true ),
),
- 'GPSDestLatitude' => array(
+ 'GPSDestLatitude' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateGPS',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
),
- 'GPSDestLongitude' => array(
+ 'GPSDestLongitude' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateGPS',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
),
- 'GPSDifferential' => array(
+ 'GPSDifferential' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '0' => true, '1' => true ),
+ '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 ),
+ 'map_group' => 'exif',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'T' => true, 'M' => true ),
),
- 'GPSLatitude' => array(
+ 'GPSLatitude' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateGPS',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
),
- 'GPSLongitude' => array(
+ 'GPSLongitude' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateGPS',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateGPS',
),
- 'GPSMapDatum' => array(
+ 'GPSMapDatum' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'GPSMeasureMode' => array(
+ 'GPSMeasureMode' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '2' => true, '3' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '3' => true )
),
'GPSProcessingMethod' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'GPSSatellites' => array(
+ 'GPSSatellites' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'GPSSpeedRef' => array(
+ 'GPSSpeedRef' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( 'K' => true, 'M' => true,
- 'N' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'K' => true, 'M' => true,
+ 'N' => true ),
),
- 'GPSStatus' => array(
+ 'GPSStatus' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( 'A' => true, 'V' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'A' => true, 'V' => true )
),
- 'GPSTimeStamp' => array(
+ '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',
+ 'map_name' => 'GPSDateStamp',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
),
- 'GPSTrackRef' => array(
+ 'GPSTrackRef' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( 'T' => true, 'M' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( 'T' => true, 'M' => true )
),
- 'GPSVersionID' => array(
+ 'GPSVersionID' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'ImageUniqueID' => array(
+ 'ImageUniqueID' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'LightSource' => array(
+ 'LightSource' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
/* can't use a range, as it skips... */
- 'choices' => array( '0' => true, '1' => true,
+ 'choices' => array( '0' => true, '1' => true,
'2' => true, '3' => true, '4' => true,
'9' => true, '10' => true, '11' => true,
'12' => true, '13' => true,
'255' => true,
),
),
- 'MeteringMode' => array(
+ 'MeteringMode' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 6,
- 'choices' => array( '255' => true ),
+ 'choices' => array( '255' => true ),
),
/* Pixel(X|Y)Dimension are rather useless, but for
* completeness since we do it with exif.
*/
- 'PixelXDimension' => array(
+ 'PixelXDimension' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
),
- 'PixelYDimension' => array(
+ 'PixelYDimension' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
),
- 'Saturation' => array(
+ 'Saturation' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 2,
),
- 'SceneCaptureType' => array(
+ 'SceneCaptureType' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 3,
),
- 'SceneType' => array(
+ 'SceneType' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '1' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true ),
),
// Note, 6 is not valid SensingMethod.
- 'SensingMethod' => array(
+ 'SensingMethod' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 1,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 1,
'rangeHigh' => 5,
- 'choices' => array( '7' => true, 8 => true ),
+ 'choices' => array( '7' => true, 8 => true ),
),
- 'Sharpness' => array(
+ 'Sharpness' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 2,
),
'SpectralSensitivity' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
// This tag should perhaps be displayed to user better.
- 'SubjectArea' => array(
+ 'SubjectArea' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger',
),
'SubjectDistanceRange' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'rangeLow' => 0,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'rangeLow' => 0,
'rangeHigh' => 3,
),
- 'SubjectLocation' => array(
+ 'SubjectLocation' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger',
),
- 'UserComment' => array(
+ 'UserComment' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_LANG,
+ 'mode' => XMPReader::MODE_LANG,
),
- 'WhiteBalance' => array(
+ 'WhiteBalance' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '0' => true, '1' => true )
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '0' => true, '1' => true )
),
),
'http://ns.adobe.com/tiff/1.0/' => array(
- 'Artist' => array(
+ 'Artist' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'BitsPerSample' => array(
+ 'BitsPerSample' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateInteger',
),
- 'Compression' => array(
+ 'Compression' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '1' => true, '6' => true ),
+ '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(
+ 'Copyright' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_LANG,
+ 'mode' => XMPReader::MODE_LANG,
),
- 'DateTime' => array( /* proper prop is xmp:ModifyDate */
+ 'DateTime' => array( /* proper prop is xmp:ModifyDate */
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateDate',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateDate',
),
- 'ImageDescription' => array( /* proper one is dc:description */
+ 'ImageDescription' => array( /* proper one is dc:description */
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_LANG,
+ 'mode' => XMPReader::MODE_LANG,
),
- 'ImageLength' => array(
+ 'ImageLength' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
),
- 'ImageWidth' => array(
+ 'ImageWidth' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
),
- 'Make' => array(
+ 'Make' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'Model' => array(
+ 'Model' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ '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 ),
+ * '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 ),
+ '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 ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true ),
),
'PrimaryChromaticities' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
),
'ReferenceBlackWhite' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
),
- 'ResolutionUnit' => array(
+ 'ResolutionUnit' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '2' => true, '3' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '2' => true, '3' => true ),
),
- 'SamplesPerPixel' => array(
+ 'SamplesPerPixel' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
),
- 'Software' => array( /* see xmp:CreatorTool */
+ 'Software' => array( /* see xmp:CreatorTool */
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
/* ignore TransferFunction */
- 'WhitePoint' => array(
+ 'WhitePoint' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
),
- 'XResolution' => array(
+ 'XResolution' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
),
- 'YResolution' => array(
+ 'YResolution' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateRational',
),
'YCbCrCoefficients' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SEQ,
- 'validate' => 'validateRational',
+ 'mode' => XMPReader::MODE_SEQ,
+ 'validate' => 'validateRational',
),
- 'YCbCrPositioning' => array(
+ 'YCbCrPositioning' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateClosed',
- 'choices' => array( '1' => true, '2' => true ),
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateClosed',
+ 'choices' => array( '1' => true, '2' => true ),
),
/********
* Disable extracting this property (bug 31944)
* just disable this prop for now, until such
* XMPReader is more graceful (bug 32172)
* 'YCbCrSubSampling' => array(
- * 'map_group' => 'exif',
- * 'mode' => XMPReader::MODE_SEQ,
- * 'validate' => 'validateClosed',
- * 'choices' => array( '1' => true, '2' => true ),
+ * '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(
+ 'Lens' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'SerialNumber' => array(
+ 'SerialNumber' => array(
'map_group' => 'exif',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'OwnerName' => array(
+ 'OwnerName' => array(
'map_group' => 'exif',
- 'map_name' => 'CameraOwnerName',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CameraOwnerName',
+ 'mode' => XMPReader::MODE_SIMPLE,
),
),
'http://purl.org/dc/elements/1.1/' => array(
- 'title' => array(
+ 'title' => array(
'map_group' => 'general',
- 'map_name' => 'ObjectName',
- 'mode' => XMPReader::MODE_LANG
+ 'map_name' => 'ObjectName',
+ 'mode' => XMPReader::MODE_LANG
),
- 'description' => array(
+ 'description' => array(
'map_group' => 'general',
- 'map_name' => 'ImageDescription',
- 'mode' => XMPReader::MODE_LANG
+ 'map_name' => 'ImageDescription',
+ 'mode' => XMPReader::MODE_LANG
),
- 'contributor' => array(
+ 'contributor' => array(
'map_group' => 'general',
- 'map_name' => 'dc-contributor',
- 'mode' => XMPReader::MODE_BAG
+ 'map_name' => 'dc-contributor',
+ 'mode' => XMPReader::MODE_BAG
),
- 'coverage' => array(
+ 'coverage' => array(
'map_group' => 'general',
- 'map_name' => 'dc-coverage',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'dc-coverage',
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'creator' => array(
+ 'creator' => array(
'map_group' => 'general',
- 'map_name' => 'Artist', //map with exif Artist, iptc byline (2:80)
- 'mode' => XMPReader::MODE_SEQ,
+ 'map_name' => 'Artist', //map with exif Artist, iptc byline (2:80)
+ 'mode' => XMPReader::MODE_SEQ,
),
- 'date' => array(
+ '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',
+ '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(
+ 'identifier' => array(
'map_group' => 'deprecated',
- 'map_name' => 'Identifier',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'Identifier',
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'language' => array(
+ 'language' => array(
'map_group' => 'general',
- 'map_name' => 'LanguageCode', /* mapped with iptc 2:135 */
- 'mode' => XMPReader::MODE_BAG,
- 'validate' => 'validateLangCode',
+ 'map_name' => 'LanguageCode', /* mapped with iptc 2:135 */
+ 'mode' => XMPReader::MODE_BAG,
+ 'validate' => 'validateLangCode',
),
- 'publisher' => array(
+ 'publisher' => array(
'map_group' => 'general',
- 'map_name' => 'dc-publisher',
- 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'dc-publisher',
+ 'mode' => XMPReader::MODE_BAG,
),
// for related images/resources
- 'relation' => array(
+ 'relation' => array(
'map_group' => 'general',
- 'map_name' => 'dc-relation',
- 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'dc-relation',
+ 'mode' => XMPReader::MODE_BAG,
),
- 'rights' => array(
+ 'rights' => array(
'map_group' => 'general',
- 'map_name' => 'Copyright',
- 'mode' => XMPReader::MODE_LANG,
+ '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(
+ 'source' => array(
'map_group' => 'general',
- 'map_name' => 'dc-source',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'dc-source',
+ 'mode' => XMPReader::MODE_SIMPLE,
),
- 'subject' => array(
+ 'subject' => array(
'map_group' => 'general',
- 'map_name' => 'Keywords', /* maps to iptc 2:25 */
- 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'Keywords', /* maps to iptc 2:25 */
+ 'mode' => XMPReader::MODE_BAG,
),
- 'type' => array(
+ 'type' => array(
'map_group' => 'general',
- 'map_name' => 'dc-type',
- 'mode' => XMPReader::MODE_BAG,
+ '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,
+ 'mode' => XMPReader::MODE_SIMPLE,
'validate' => 'validateDate',
),
'CreatorTool' => array(
'map_group' => 'general',
- 'map_name' => 'Software',
- 'mode' => XMPReader::MODE_SIMPLE
+ 'map_name' => 'Software',
+ 'mode' => XMPReader::MODE_SIMPLE
),
'Identifier' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_BAG,
+ 'mode' => XMPReader::MODE_BAG,
),
'Label' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'ModifyDate' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'DateTime',
- 'validate' => 'validateDate',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'DateTime',
+ 'validate' => 'validateDate',
),
'MetadataDate' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
// map_name to be consistent with other date names.
- 'map_name' => 'DateTimeMetadata',
- 'validate' => 'validateDate',
+ 'map_name' => 'DateTimeMetadata',
+ 'validate' => 'validateDate',
),
'Nickname' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'Rating' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateRating',
+ '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,
+ 'map_name' => 'RightsCertificate',
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'Marked' => array(
'map_group' => 'general',
- 'map_name' => 'Copyrighted',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateBoolean',
+ 'map_name' => 'Copyrighted',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateBoolean',
),
'Owner' => array(
'map_group' => 'general',
- 'map_name' => 'CopyrightOwner',
- 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'CopyrightOwner',
+ 'mode' => XMPReader::MODE_BAG,
),
// this seems similar to dc:rights.
'UsageTerms' => array(
// as well do this too.
'OriginalDocumentID' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
// It might also be useful to do xmpMM:LastURL
// and xmpMM:DerivedFrom as you can potentially,
),
'http://creativecommons.org/ns#' => array(
'license' => array(
- 'map_name' => 'LicenseUrl',
+ 'map_name' => 'LicenseUrl',
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'morePermissions' => array(
- 'map_name' => 'MorePermissionsUrl',
+ 'map_name' => 'MorePermissionsUrl',
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'attributionURL' => array(
'map_group' => 'general',
- 'map_name' => 'AttributionUrl',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'AttributionUrl',
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'attributionName' => array(
'map_group' => 'general',
- 'map_name' => 'PreferredAttributionName',
- 'mode' => XMPReader::MODE_SIMPLE,
+ '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,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
),
/* Note, in iptc schemas, the legacy properties are denoted
'http://ns.adobe.com/photoshop/1.0/' => array(
'City' => array(
'map_group' => 'deprecated',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'CityDest',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CityDest',
),
'Country' => array(
'map_group' => 'deprecated',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'CountryDest',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CountryDest',
),
'State' => array(
'map_group' => 'deprecated',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'ProvinceOrStateDest',
+ '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',
+ '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',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'Writer',
),
'Instructions' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'SpecialInstructions',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'SpecialInstructions',
),
'TransmissionReference' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'OriginalTransmissionRef',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'OriginalTransmissionRef',
),
'AuthorsPosition' => array(
/* This corresponds with 2:85
* handled weirdly to correspond
* with iptc/exif. */
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE
+ 'mode' => XMPReader::MODE_SIMPLE
),
'Credit' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'Source' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'Urgency' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ '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',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'iimCategory',
),
'SupplementalCategories' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_BAG,
- 'map_name' => 'iimSupplementalCategory',
+ 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'iimSupplementalCategory',
),
'Headline' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE
+ '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',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'CountryCodeDest',
),
'IntellectualGenre' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
// Note, this is a six digit code.
// See: http://cv.iptc.org/newscodes/scene/
// we just show the number.
'Scene' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_BAG,
- 'validate' => 'validateInteger',
- 'map_name' => 'SceneCode',
+ '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,
*/
'SubjectCode' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_BAG,
- 'map_name' => 'SubjectNewsCode',
- 'validate' => 'validateInteger'
+ 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'SubjectNewsCode',
+ 'validate' => 'validateInteger'
),
'Location' => array(
'map_group' => 'deprecated',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'map_name' => 'SublocationDest',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'map_name' => 'SublocationDest',
),
'CreatorContactInfo' => array(
/* Note this maps to 2:118 in iim
* is more structured.
*/
'map_group' => 'general',
- 'mode' => XMPReader::MODE_STRUCT,
- 'map_name' => 'Contact',
- 'children' => array(
+ 'mode' => XMPReader::MODE_STRUCT,
+ 'map_name' => 'Contact',
+ 'children' => array(
'CiAdrExtadr' => true,
- 'CiAdrCity' => true,
- 'CiAdrCtry' => true,
+ 'CiAdrCity' => true,
+ 'CiAdrCtry' => true,
'CiEmailWork' => true,
- 'CiTelWork' => true,
- 'CiAdrPcode' => true,
+ 'CiTelWork' => true,
+ 'CiAdrPcode' => true,
'CiAdrRegion' => true,
- 'CiUrlWork' => true,
+ 'CiUrlWork' => true,
),
),
'CiAdrExtadr' => array( /* address */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiAdrCity' => array( /* city */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiAdrCtry' => array( /* country */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiEmailWork' => array( /* email (possibly separated by ',') */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiTelWork' => array( /* telephone */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiAdrPcode' => array( /* postal code */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiAdrRegion' => array( /* province/state */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CiUrlWork' => array( /* url. Multiple may be separated by comma. */
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ '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,
+ 'mode' => XMPReader::MODE_SIMPLE,
),
'OrganisationInImageName' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_BAG,
- 'map_name' => 'OrganisationInImage'
+ 'mode' => XMPReader::MODE_BAG,
+ 'map_name' => 'OrganisationInImage'
),
'PersonInImage' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_BAG,
+ 'mode' => XMPReader::MODE_BAG,
),
'MaxAvailHeight' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
- 'map_name' => 'OriginalImageHeight',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'validate' => 'validateInteger',
+ 'map_name' => 'OriginalImageHeight',
),
'MaxAvailWidth' => array(
'map_group' => 'general',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'validate' => 'validateInteger',
- 'map_name' => 'OriginalImageWidth',
+ '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(
+ 'mode' => XMPReader::MODE_BAGSTRUCT,
+ 'children' => array(
'WorldRegion' => true,
'CountryCode' => true, /* iso code */
'CountryName' => true,
),
'LocationCreated' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_BAGSTRUCT,
- 'children' => array(
+ 'mode' => XMPReader::MODE_BAGSTRUCT,
+ 'children' => array(
'WorldRegion' => true,
'CountryCode' => true, /* iso code */
'CountryName' => true,
),
'WorldRegion' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CountryCode' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'CountryName' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
- 'map_name' => 'Country',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
+ 'map_name' => 'Country',
),
'ProvinceState' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
- 'map_name' => 'ProvinceOrState',
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
+ 'map_name' => 'ProvinceOrState',
),
'City' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
'Sublocation' => array(
'map_group' => 'special',
- 'mode' => XMPReader::MODE_SIMPLE,
- 'structPart'=> true,
+ 'mode' => XMPReader::MODE_SIMPLE,
+ 'structPart' => true,
),
/* Other props that might be interesting but
* Each of these functions take the same parameters
* * an info array which is a subset of the XMPInfo::items array
* * A value (passed as reference) to validate. This can be either a
- * simple value or an array
+ * simple value or an array
* * A boolean to determine if this is validating a simple or complex values
*
* It should be noted that when an array is being validated, typically the validation
wfDebugLog( 'XMP', __METHOD__ . " Expected True or False but got $val" );
$val = null;
}
-
}
/**
wfDebugLog( 'XMP', __METHOD__ . " Expected rational but got $val" );
$val = null;
}
-
}
/**
) {
wfDebugLog( 'XMP', __METHOD__ . " Expected rating but got $val" );
$val = null;
+
return;
} else {
$nVal = (float)$val;
// as -1 is meant as a special reject rating.
wfDebugLog( 'XMP', __METHOD__ . " Rating too low, setting to -1 (Rejected)" );
$val = '-1';
+
return;
}
if ( $nVal > 5 ) {
wfDebugLog( 'XMP', __METHOD__ . " Rating too high, setting to 5" );
$val = '5';
+
return;
}
}
wfDebugLog( 'XMP', __METHOD__ . " Expected integer but got $val" );
$val = null;
}
-
}
/**
wfDebugLog( 'XMP', __METHOD__ . " Expected Lang code but got $val" );
$val = null;
}
-
}
/**
*
* @param array $info information about current property
* @param &$val Mixed current value to validate. Converts to TS_EXIF as a side-effect.
- * in cases where there's only a partial date, it will give things like
- * 2011:04.
+ * in cases where there's only a partial date, it will give things like
+ * 2011:04.
* @param $standalone Boolean if this is a simple property or array
*/
public static function validateDate( $info, &$val, $standalone ) {
if ( $res[1] === '0000' ) {
wfDebugLog( 'XMP', __METHOD__ . " Invalid date (year 0): $val" );
$val = null;
+
return;
}
if ( isset( $res[3] ) ) {
$val .= ':' . $res[3];
}
+
return;
}
if ( isset( $res[6] ) && $res[6] !== '' ) {
$val .= ':' . $res[6];
}
+
return;
}
$val = substr( $val, 0, -3 );
}
}
-
}
/** function to validate, and more importantly
$coord = -$coord;
}
$val = $coord;
+
return;
} elseif ( preg_match(
'/(\d{1,3}),(\d{1,2}(?:.\d*)?)([NWSE])/D',
$coord = -$coord;
}
$val = $coord;
- return;
+ return;
} else {
wfDebugLog( 'XMP', __METHOD__
. " Expected GPSCoordinate, but got $val." );
$val = null;
+
return;
}
}