MediaWiki  REL1_20
ExifBitmap.php
Go to the documentation of this file.
00001 <?php
00030 class ExifBitmapHandler extends BitmapHandler {
00031 
00032         const BROKEN_FILE = '-1'; // error extracting metadata
00033         const OLD_BROKEN_FILE = '0'; // outdated error extracting metadata.
00034 
00035         function convertMetadataVersion( $metadata, $version = 1 ) {
00036                 // basically flattens arrays.
00037                 $version = explode(';', $version, 2);
00038                 $version = intval($version[0]);
00039                 if ( $version < 1 || $version >= 2 ) {
00040                         return $metadata;
00041                 }
00042 
00043                 $avoidHtml = true;
00044 
00045                 if ( !is_array( $metadata ) ) {
00046                         $metadata = unserialize( $metadata );
00047                 }
00048                 if ( !isset( $metadata['MEDIAWIKI_EXIF_VERSION'] ) || $metadata['MEDIAWIKI_EXIF_VERSION'] != 2 ) {
00049                         return $metadata;
00050                 }
00051 
00052                 // Treat Software as a special case because in can contain
00053                 // an array of (SoftwareName, Version).
00054                 if (isset( $metadata['Software'] )
00055                         && is_array( $metadata['Software'] )
00056                         && is_array( $metadata['Software'][0])
00057                         && isset( $metadata['Software'][0][0] )
00058                         && isset( $metadata['Software'][0][1])
00059                  ) {
00060                         $metadata['Software'] = $metadata['Software'][0][0] . ' (Version '
00061                                 . $metadata['Software'][0][1] . ')';
00062                 }
00063 
00064                 // ContactInfo also has to be dealt with specially
00065                 if ( isset( $metadata['Contact'] ) ) {
00066                         $metadata['Contact'] =
00067                                 FormatMetadata::collapseContactInfo(
00068                                         $metadata['Contact'] );
00069                 }
00070 
00071                 foreach ( $metadata as &$val ) {
00072                         if ( is_array( $val ) ) {
00073                                 $val = FormatMetadata::flattenArray( $val, 'ul', $avoidHtml );
00074                         }
00075                 }
00076                 $metadata['MEDIAWIKI_EXIF_VERSION'] = 1;
00077                 return $metadata;
00078         }
00079 
00080         function isMetadataValid( $image, $metadata ) {
00081                 global $wgShowEXIF;
00082                 if ( !$wgShowEXIF ) {
00083                         # Metadata disabled and so an empty field is expected
00084                         return self::METADATA_GOOD;
00085                 }
00086                 if ( $metadata === self::OLD_BROKEN_FILE ) {
00087                         # Old special value indicating that there is no EXIF data in the file.
00088                         # or that there was an error well extracting the metadata.
00089                         wfDebug( __METHOD__ . ": back-compat version\n");
00090                         return self::METADATA_COMPATIBLE;
00091                 }
00092                 if ( $metadata === self::BROKEN_FILE ) {
00093                         return self::METADATA_GOOD;
00094                 }
00095                 wfSuppressWarnings();
00096                 $exif = unserialize( $metadata );
00097                 wfRestoreWarnings();
00098                 if ( !isset( $exif['MEDIAWIKI_EXIF_VERSION'] ) ||
00099                         $exif['MEDIAWIKI_EXIF_VERSION'] != Exif::version() )
00100                 {
00101                         if ( isset( $exif['MEDIAWIKI_EXIF_VERSION'] ) &&
00102                                 $exif['MEDIAWIKI_EXIF_VERSION'] == 1 )
00103                         {
00104                                 //back-compatible but old
00105                                 wfDebug( __METHOD__.": back-compat version\n" );
00106                                 return self::METADATA_COMPATIBLE;
00107                         }
00108                         # Wrong (non-compatible) version
00109                         wfDebug( __METHOD__.": wrong version\n" );
00110                         return self::METADATA_BAD;
00111                 }
00112                 return self::METADATA_GOOD;
00113         }
00114 
00119         function formatMetadata( $image ) {
00120                 $metadata = $image->getMetadata();
00121                 if ( $metadata === self::OLD_BROKEN_FILE ||
00122                         $metadata === self::BROKEN_FILE ||
00123                         $this->isMetadataValid( $image, $metadata ) === self::METADATA_BAD )
00124                 {
00125                         // So we don't try and display metadata from PagedTiffHandler
00126                         // for example when using InstantCommons.
00127                         return false;
00128                 }
00129 
00130                 $exif = unserialize( $metadata );
00131                 if ( !$exif ) {
00132                         return false;
00133                 }
00134                 unset( $exif['MEDIAWIKI_EXIF_VERSION'] );
00135                 if ( count( $exif ) == 0 ) {
00136                         return false;
00137                 }
00138                 return $this->formatMetadataHelper( $exif );
00139         }
00140 
00141         function getMetadataType( $image ) {
00142                 return 'exif';
00143         }
00144 
00153         function getImageSize( $image, $path ) {
00154                 global $wgEnableAutoRotation;
00155                 $gis = parent::getImageSize( $image, $path );
00156 
00157                 // Don't just call $image->getMetadata(); FSFile::getPropsFromPath() calls us with a bogus object.
00158                 // This may mean we read EXIF data twice on initial upload.
00159                 if ( $wgEnableAutoRotation ) {
00160                         $meta = $this->getMetadata( $image, $path );
00161                         $rotation = $this->getRotationForExif( $meta );
00162                 } else {
00163                         $rotation = 0;
00164                 }
00165 
00166                 if ($rotation == 90 || $rotation == 270) {
00167                         $width = $gis[0];
00168                         $gis[0] = $gis[1];
00169                         $gis[1] = $width;
00170                 }
00171                 return $gis;
00172         }
00173 
00186         public function getRotation( $file ) {
00187                 global $wgEnableAutoRotation;
00188                 if ( !$wgEnableAutoRotation ) {
00189                         return 0;
00190                 }
00191 
00192                 $data = $file->getMetadata();
00193                 return $this->getRotationForExif( $data );
00194         }
00195 
00205         protected function getRotationForExif( $data ) {
00206                 if ( !$data ) {
00207                         return 0;
00208                 }
00209                 wfSuppressWarnings();
00210                 $data = unserialize( $data );
00211                 wfRestoreWarnings();
00212                 if ( isset( $data['Orientation'] ) ) {
00213                         # See http://sylvana.net/jpegcrop/exif_orientation.html
00214                         switch ( $data['Orientation'] ) {
00215                                 case 8:
00216                                         return 90;
00217                                 case 3:
00218                                         return 180;
00219                                 case 6:
00220                                         return 270;
00221                                 default:
00222                                         return 0;
00223                         }
00224                 }
00225                 return 0;
00226         }
00227 }
00228