MediaWiki  master
ExifBitmapHandler.php
Go to the documentation of this file.
1 <?php
31  const BROKEN_FILE = '-1'; // error extracting metadata
32  const OLD_BROKEN_FILE = '0'; // outdated error extracting metadata.
33 
34  function convertMetadataVersion( $metadata, $version = 1 ) {
35  // basically flattens arrays.
36  $version = intval( explode( ';', $version, 2 )[0] );
37  if ( $version < 1 || $version >= 2 ) {
38  return $metadata;
39  }
40 
41  $avoidHtml = true;
42 
43  if ( !is_array( $metadata ) ) {
44  $metadata = unserialize( $metadata );
45  }
46  if ( !isset( $metadata['MEDIAWIKI_EXIF_VERSION'] ) || $metadata['MEDIAWIKI_EXIF_VERSION'] != 2 ) {
47  return $metadata;
48  }
49 
50  // Treat Software as a special case because in can contain
51  // an array of (SoftwareName, Version).
52  if ( isset( $metadata['Software'] )
53  && is_array( $metadata['Software'] )
54  && is_array( $metadata['Software'][0] )
55  && isset( $metadata['Software'][0][0] )
56  && isset( $metadata['Software'][0][1] )
57  ) {
58  $metadata['Software'] = $metadata['Software'][0][0] . ' (Version '
59  . $metadata['Software'][0][1] . ')';
60  }
61 
62  $formatter = new FormatMetadata;
63 
64  // ContactInfo also has to be dealt with specially
65  if ( isset( $metadata['Contact'] ) ) {
66  $metadata['Contact'] =
67  $formatter->collapseContactInfo(
68  $metadata['Contact'] );
69  }
70 
71  foreach ( $metadata as &$val ) {
72  if ( is_array( $val ) ) {
73  $val = $formatter->flattenArrayReal( $val, 'ul', $avoidHtml );
74  }
75  }
76  $metadata['MEDIAWIKI_EXIF_VERSION'] = 1;
77 
78  return $metadata;
79  }
80 
86  public function isMetadataValid( $image, $metadata ) {
87  global $wgShowEXIF;
88  if ( !$wgShowEXIF ) {
89  # Metadata disabled and so an empty field is expected
90  return self::METADATA_GOOD;
91  }
92  if ( $metadata === self::OLD_BROKEN_FILE ) {
93  # Old special value indicating that there is no Exif data in the file.
94  # or that there was an error well extracting the metadata.
95  wfDebug( __METHOD__ . ": back-compat version\n" );
96 
97  return self::METADATA_COMPATIBLE;
98  }
99  if ( $metadata === self::BROKEN_FILE ) {
100  return self::METADATA_GOOD;
101  }
102  Wikimedia\suppressWarnings();
103  $exif = unserialize( $metadata );
104  Wikimedia\restoreWarnings();
105  if ( !isset( $exif['MEDIAWIKI_EXIF_VERSION'] )
106  || $exif['MEDIAWIKI_EXIF_VERSION'] != Exif::version()
107  ) {
108  if ( isset( $exif['MEDIAWIKI_EXIF_VERSION'] )
109  && $exif['MEDIAWIKI_EXIF_VERSION'] == 1
110  ) {
111  // back-compatible but old
112  wfDebug( __METHOD__ . ": back-compat version\n" );
113 
114  return self::METADATA_COMPATIBLE;
115  }
116  # Wrong (non-compatible) version
117  wfDebug( __METHOD__ . ": wrong version\n" );
118 
119  return self::METADATA_BAD;
120  }
121 
122  return self::METADATA_GOOD;
123  }
124 
130  public function formatMetadata( $image, $context = false ) {
131  $meta = $this->getCommonMetaArray( $image );
132  if ( count( $meta ) === 0 ) {
133  return false;
134  }
135 
136  return $this->formatMetadataHelper( $meta, $context );
137  }
138 
139  public function getCommonMetaArray( File $file ) {
140  $metadata = $file->getMetadata();
141  if ( $metadata === self::OLD_BROKEN_FILE
142  || $metadata === self::BROKEN_FILE
143  || $this->isMetadataValid( $file, $metadata ) === self::METADATA_BAD
144  ) {
145  // So we don't try and display metadata from PagedTiffHandler
146  // for example when using InstantCommons.
147  return [];
148  }
149 
150  $exif = unserialize( $metadata );
151  if ( !$exif ) {
152  return [];
153  }
154  unset( $exif['MEDIAWIKI_EXIF_VERSION'] );
155 
156  return $exif;
157  }
158 
159  function getMetadataType( $image ) {
160  return 'exif';
161  }
162 
171  function getImageSize( $image, $path ) {
172  $gis = parent::getImageSize( $image, $path );
173 
174  // Don't just call $image->getMetadata(); FSFile::getPropsFromPath() calls us with a bogus object.
175  // This may mean we read EXIF data twice on initial upload.
176  if ( $this->autoRotateEnabled() ) {
177  $meta = $this->getMetadata( $image, $path );
178  $rotation = $this->getRotationForExif( $meta );
179  } else {
180  $rotation = 0;
181  }
182 
183  if ( $rotation == 90 || $rotation == 270 ) {
184  $width = $gis[0];
185  $gis[0] = $gis[1];
186  $gis[1] = $width;
187  }
188 
189  return $gis;
190  }
191 
204  public function getRotation( $file ) {
205  if ( !$this->autoRotateEnabled() ) {
206  return 0;
207  }
208 
209  $data = $file->getMetadata();
210 
211  return $this->getRotationForExif( $data );
212  }
213 
222  protected function getRotationForExif( $data ) {
223  if ( !$data ) {
224  return 0;
225  }
226  Wikimedia\suppressWarnings();
227  $data = unserialize( $data );
228  Wikimedia\restoreWarnings();
229  if ( isset( $data['Orientation'] ) ) {
230  # See http://sylvana.net/jpegcrop/exif_orientation.html
231  switch ( $data['Orientation'] ) {
232  case 8:
233  return 90;
234  case 3:
235  return 180;
236  case 6:
237  return 270;
238  default:
239  return 0;
240  }
241  }
242 
243  return 0;
244  }
245 }
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
getImageSize( $image, $path)
Wrapper for base classes ImageHandler::getImageSize() that checks for rotation reported from metadata...
$context
Definition: load.php:45
Format Image metadata values into a human readable form.
static version()
#-
Definition: Exif.php:582
formatMetadata( $image, $context=false)
$wgShowEXIF
Show Exif data, on by default if available.
getMetadata( $image, $path)
Get handler-specific metadata which will be saved in the img_metadata field.
getMetadata()
Get handler-specific metadata Overridden by LocalFile, UnregisteredLocalFile STUB.
Definition: File.php:663
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
getCommonMetaArray(File $file)
unserialize( $serialized)
Stuff specific to JPEG and (built-in) TIFF handler.
convertMetadataVersion( $metadata, $version=1)
getRotation( $file)
On supporting image formats, try to read out the low-level orientation of the file and return the ang...
Generic handler for bitmap images.
isMetadataValid( $image, $metadata)
formatMetadataHelper( $metadataArray, $context=false)
sorts the visible/invisible field.
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition: File.php:61
collapseContactInfo( $vals)
Format the contact info field into a single value.
getRotationForExif( $data)
Given a chunk of serialized Exif metadata, return the orientation as degrees of rotation.