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