MediaWiki  REL1_22
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 }