r69162 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r69161‎ | r69162 | r69163 >
Date:22:54, 7 July 2010
Author:bawolff
Status:ok
Tags:
Comment:
Fix up handling of Exif::UNDEFINED values. Handle the ones we can, and more explicitly
reject the values we don't.
Modified paths:
  • /branches/img_metadata/phase3/includes/Exif.php (modified) (history)

Diff [purge]

Index: branches/img_metadata/phase3/includes/Exif.php
@@ -37,6 +37,7 @@
3838 const UNDEFINED = 7; //!< An 8-bit byte that can take any value depending on the field definition
3939 const SLONG = 9; //!< A 32-bit (4-byte) signed integer (2's complement notation),
4040 const SRATIONAL = 10; //!< Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
 41+ const IGNORE = -1; // A fake value for things we don't want or don't support.
4142
4243 //@{
4344 /* @var array
@@ -96,9 +97,7 @@
9798 *
9899 * @param $file String: filename.
99100 * @fixme the following are broke:
100 - * SubjectArea, ExifVersion, Flashpix Version (probably any Exif:Undefined with non 1 count)
101 - * SceneType, FileSource, MakerNote (we really don't want makerNote though),
102 - * ComponenentsConfiguration, and possibly others pending better testing.
 101+ * SubjectArea, GPSAltitudeRef, possibly more, need more testing.
103102 *
104103 * DigitalZoomRatio = 0/0 is rejected. need to determine if thats valid.
105104 * possibly should treat 0/0 = 0. need to read exif spec on that.
@@ -107,6 +106,9 @@
108107 /**
109108 * Page numbers here refer to pages in the EXIF 2.2 standard
110109 *
 110+ * Note, Exif::UNDEFINED is treated as a string, not as an array of bytes
 111+ * so don't put a count parameter for any UNDEFINED values.
 112+ *
111113 * @link http://exif.org/Exif2-2.PDF The Exif 2.2 specification
112114 */
113115 $this->mExifTags = array(
@@ -157,20 +159,20 @@
158160 'EXIF' => array(
159161 # TODO: NOTE: Nonexistence of this field is taken to mean nonconformance
160162 # to the EXIF 2.1 AND 2.2 standards
161 - 'ExifVersion' => array( Exif::UNDEFINED, 4 ), # Exif version
162 - 'FlashPixVersion' => array( Exif::UNDEFINED, 4 ), # Supported Flashpix version #p32
 163+ 'ExifVersion' => Exif::UNDEFINED, # Exif version
 164+ 'FlashPixVersion' => Exif::UNDEFINED, # Supported Flashpix version #p32
163165
164166 # Tags relating to Image Data Characteristics
165167 'ColorSpace' => Exif::SHORT, # Color space information #p32
166168
167169 # Tags relating to image configuration
168 - 'ComponentsConfiguration' => array( Exif::UNDEFINED, 1), # Meaning of each component #p33
 170+ 'ComponentsConfiguration' => Exif::UNDEFINED, # Meaning of each component #p33
169171 'CompressedBitsPerPixel' => Exif::RATIONAL, # Image compression mode
170172 'PixelYDimension' => Exif::SHORT.','.Exif::LONG, # Valid image width
171173 'PixelXDimension' => Exif::SHORT.','.Exif::LONG, # Valid image height
172174
173175 # Tags relating to related user information
174 - 'MakerNote' => Exif::UNDEFINED, # Manufacturer notes
 176+ 'MakerNote' => Exif::IGNORE, # Manufacturer notes
175177 'UserComment' => Exif::UNDEFINED, # User comments #p34
176178
177179 # Tags relating to related file information
@@ -189,7 +191,7 @@
190192 'ExposureProgram' => Exif::SHORT, # Exposure Program #p38
191193 'SpectralSensitivity' => Exif::ASCII, # Spectral sensitivity
192194 'ISOSpeedRatings' => Exif::SHORT, # ISO speed rating
193 - 'OECF' => Exif::UNDEFINED, # Optoelectronic conversion factor
 195+ 'OECF' => Exif::IGNORE, # Optoelectronic conversion factor. Note: We don't have support for this atm.
194196 'ShutterSpeedValue' => Exif::SRATIONAL, # Shutter speed
195197 'ApertureValue' => Exif::RATIONAL, # Aperture
196198 'BrightnessValue' => Exif::SRATIONAL, # Brightness
@@ -202,7 +204,7 @@
203205 'FocalLength' => Exif::RATIONAL, # Lens focal length
204206 'SubjectArea' => array( Exif::SHORT, 4 ), # Subject area
205207 'FlashEnergy' => Exif::RATIONAL, # Flash energy
206 - 'SpatialFrequencyResponse' => Exif::UNDEFINED, # Spatial frequency response
 208+ 'SpatialFrequencyResponse' => Exif::IGNORE, # Spatial frequency response. Not supported atm.
207209 'FocalPlaneXResolution' => Exif::RATIONAL, # Focal plane X resolution
208210 'FocalPlaneYResolution' => Exif::RATIONAL, # Focal plane Y resolution
209211 'FocalPlaneResolutionUnit' => Exif::SHORT, # Focal plane resolution unit #p46
@@ -211,7 +213,7 @@
212214 'SensingMethod' => Exif::SHORT, # Sensing method #p46
213215 'FileSource' => Exif::UNDEFINED, # File source #p47
214216 'SceneType' => Exif::UNDEFINED, # Scene type #p47
215 - 'CFAPattern' => Exif::UNDEFINED, # CFA pattern
 217+ 'CFAPattern' => Exif::IGNORE, # CFA pattern. not supported atm.
216218 'CustomRendered' => Exif::SHORT, # Custom image processing #p48
217219 'ExposureMode' => Exif::SHORT, # Exposure mode #p48
218220 'WhiteBalance' => Exif::SHORT, # White Balance #p49
@@ -222,7 +224,7 @@
223225 'Contrast' => Exif::SHORT, # Contrast #p50
224226 'Saturation' => Exif::SHORT, # Saturation #p50
225227 'Sharpness' => Exif::SHORT, # Sharpness #p50
226 - 'DeviceSettingDescription' => Exif::UNDEFINED, # Desice settings description
 228+ 'DeviceSettingDescription' => Exif::IGNORE, # Desice settings description. FIXME: this could maybe be supported.
227229 'SubjectDistanceRange' => Exif::SHORT, # Subject distance range #p51
228230
229231 'ImageUniqueID' => Exif::ASCII, # Unique image ID
@@ -346,8 +348,90 @@
347349 unset( $this->mFilteredExifData );
348350 }
349351
 352+ $this->toHex( 'FileSource', true );
 353+ $this->toHex( 'SceneType', true );
 354+
 355+ $this->charCodeString( 'UserComment' );
 356+ $this->charCodeString( 'GPSProcessingMethod');
 357+ $this->charCodeString( 'GPSAreaInformation' );
 358+
 359+ //ComponentsConfiguration should really be an array instead of a string...
 360+ if ( isset ( $this->mFilteredExifData['ComponentsConfiguration'] ) ) {
 361+ $val = $this->mFilteredExifData['ComponentsConfiguration'];
 362+ $ccVals = array();
 363+ for ($i = 0; $i < strlen($val); $i++) {
 364+ $ccVals[$i] = ord( substr($val, $i, 1) );
 365+ }
 366+ $ccVals['_type'] = 'ol'; //this is for formatting later.
 367+ $this->mFilteredExifData['ComponentsConfiguration'] = $ccVals;
 368+ }
 369+
350370 }
351371 /**
 372+ * do userComment and similar. pg. 34 of exif standard.
 373+ * basically first 8 bytes is charset, rest is value.
 374+ * Needs more testing, as its unclear from exif standard if they mean
 375+ * utf-8, utf-16, or something else by 'unicode'.
 376+ * @param $prop String prop name.
 377+ * @todo this is in need of testing.
 378+ */
 379+ function charCodeString ( $prop ) {
 380+ if ( isset( $this->mFilteredExifData[$prop] ) ) {
 381+
 382+ if ( strlen($this->mFilteredExifData[$prop]) <= 8 ) {
 383+ //invalid. Must be at least 9 bytes long.
 384+
 385+ $this->debug( $this->mFilteredExifData[$prop] , __FUNCTION__, false );
 386+ unset($this->mFilteredExifData[$prop]);
 387+ return;
 388+ }
 389+
 390+ $charCode = substr( $this->mFilteredExifData[$prop], 0, 8);
 391+ $val = substr( $this->mFilteredExifData[$prop], 8);
 392+
 393+
 394+ switch ($charCode) {
 395+ case "\x4A\x49\x53\x00\x00\x00\x00\x00":
 396+ //JIS
 397+ $val = iconv("Shift-JIS", "UTF-8//IGNORE", $val);
 398+ break;
 399+ default: //unicode or undefined. leave as is.
 400+ break;
 401+ }
 402+
 403+ //trim and check to make sure not only whitespace.
 404+ $val = trim($val);
 405+ if ( strlen( $val ) === 0 ) {
 406+ //only whitespace.
 407+ $this->debug( $this->mFilteredExifData[$prop] , __FUNCTION__, "$prop: Is only whitespace" );
 408+ unset($this->mFilteredExifData[$prop]);
 409+ return;
 410+ }
 411+
 412+ //all's good.
 413+ $this->mFilteredData[$prop] = $val;
 414+ }
 415+ }
 416+ /**
 417+ * Convert an Exif::UNDEFINED from a raw binary string
 418+ * to a hex string. This is sometimes needed depending on
 419+ * the type of UNDEFINED field
 420+ * @param $prop String name of property
 421+ * @param $stripLeadingZero boolean should it strip first leading zero
 422+ * if present on result (bit of a hack).
 423+ */
 424+ function toHex ( $prop, $stripLeadingZero = false ) {
 425+ if ( isset( $this->mFilteredExifData[$prop] ) ) {
 426+ $val = bin2hex( $this->mFilteredExifData[$prop] );
 427+ if ( $stripLeadingZero ) {
 428+ if (substr( $val, 0, 1) === '0') {
 429+ $val = substr( $val, 1);
 430+ }
 431+ }
 432+ $this->mFilteredExifData[$prop] = $val;
 433+ }
 434+ }
 435+ /**
352436 * Convert gps in exif form to a single floating point number
353437 * for example 10 degress 20`40`` S -> -10.34444
354438 * @param String $prop a gps coordinate exif tag name (like GPSLongitude)
@@ -498,6 +582,13 @@
499583 }
500584
501585 function isUndefined( $in ) {
 586+
 587+ $this->debug( $in, __FUNCTION__, true );
 588+ return true;
 589+
 590+ /* Exif::UNDEFINED means string of bytes
 591+ so this validation does not make sense.
 592+ comment out for now.
502593 if ( !is_array( $in ) && preg_match( '/^\d{4}$/', $in ) ) { // Allow ExifVersion and FlashpixVersion
503594 $this->debug( $in, __FUNCTION__, true );
504595 return true;
@@ -505,6 +596,7 @@
506597 $this->debug( $in, __FUNCTION__, false );
507598 return false;
508599 }
 600+ */
509601 }
510602
511603 function isSlong( $in ) {
@@ -589,6 +681,9 @@
590682 case (string)Exif::SHORT.','.Exif::LONG:
591683 $this->debug( $val, __FUNCTION__, $debug );
592684 return $this->isShort( $val ) || $this->isLong( $val );
 685+ case (string)Exif::IGNORE:
 686+ $this->debug( $val, __FUNCTION__, $debug );
 687+ return false;
593688 default:
594689 $this->debug( $val, __FUNCTION__, "The tag '$tag' is unknown" );
595690 return false;

Status & tagging log