Index: branches/img_metadata/phase3/maintenance/language/messages.inc |
— | — | @@ -2880,8 +2880,8 @@ |
2881 | 2881 | 'exif-gpslongitude-w', |
2882 | 2882 | ), |
2883 | 2883 | 'exif-altituderef' => array( |
2884 | | - 'exif-exif-gpsaltitude-0', |
2885 | | - 'exif-exif-gpsaltitude-1', |
| 2884 | + 'exif-gpsaltitude-above-sealevel', |
| 2885 | + 'exif-gpsaltitude-below-sealevel', |
2886 | 2886 | ), |
2887 | 2887 | 'exif-gpsstatus' => array( |
2888 | 2888 | 'exif-gpsstatus-a', |
Index: branches/img_metadata/phase3/maintenance/language/messageTypes.inc |
— | — | @@ -584,8 +584,8 @@ |
585 | 585 | 'exif-gpslatitude-s', |
586 | 586 | 'exif-gpslongitude-e', |
587 | 587 | 'exif-gpslongitude-w', |
588 | | - 'exif-gpsaltitude-0', |
589 | | - 'exif-gpsaltitude-1', |
| 588 | + 'exif-gpsaltitude-above-sealevel', |
| 589 | + 'exif-gpsaltitude-below-sealevel', |
590 | 590 | 'exif-gpsstatus-a', |
591 | 591 | 'exif-gpsstatus-v', |
592 | 592 | 'exif-gpsmeasuremode-2', |
Index: branches/img_metadata/phase3/includes/Exif.php |
— | — | @@ -97,7 +97,7 @@ |
98 | 98 | * |
99 | 99 | * @param $file String: filename. |
100 | 100 | * @fixme the following are broke: |
101 | | - * SubjectArea, GPSAltitudeRef, possibly more, need more testing. |
| 101 | + * SubjectArea. Need to test the more obscure tags. |
102 | 102 | * |
103 | 103 | * DigitalZoomRatio = 0/0 is rejected. need to determine if thats valid. |
104 | 104 | * possibly should treat 0/0 = 0. need to read exif spec on that. |
— | — | @@ -232,12 +232,12 @@ |
233 | 233 | |
234 | 234 | # GPS Attribute Information (p52) |
235 | 235 | 'GPS' => array( |
236 | | - 'GPSVersionID' => array( Exif::BYTE, 4 ), # GPS tag version |
| 236 | + 'GPSVersion' => Exif::UNDEFINED, # array( Exif::BYTE, 4 ) GPS tag version. Note exif standard calls this GPSVersionID, but php doesn't like the id. also php thinks its wrong type |
237 | 237 | 'GPSLatitudeRef' => Exif::ASCII, # North or South Latitude #p52-53 |
238 | 238 | 'GPSLatitude' => array( Exif::RATIONAL, 3 ), # Latitude |
239 | 239 | 'GPSLongitudeRef' => Exif::ASCII, # East or West Longitude #p53 |
240 | 240 | 'GPSLongitude' => array( Exif::RATIONAL, 3), # Longitude |
241 | | - 'GPSAltitudeRef' => Exif::BYTE, # Altitude reference |
| 241 | + 'GPSAltitudeRef' => Exif::UNDEFINED, # Altitude reference. Note, the exif standard says this should be an EXIF::Byte, but php seems to disagree. |
242 | 242 | 'GPSAltitude' => Exif::RATIONAL, # Altitude |
243 | 243 | 'GPSTimeStamp' => array( Exif::RATIONAL, 3), # GPS time (atomic clock) |
244 | 244 | 'GPSSatellites' => Exif::ASCII, # Satellites used for measurement |
— | — | @@ -281,7 +281,6 @@ |
282 | 282 | $this->mRawExifData = $data ? $data : array(); |
283 | 283 | $this->makeFilteredData(); |
284 | 284 | $this->collapseData(); |
285 | | - $this->makeFormattedData(); |
286 | 285 | $this->debugFile( __FUNCTION__, false ); |
287 | 286 | } |
288 | 287 | |
— | — | @@ -342,20 +341,21 @@ |
343 | 342 | $this->exifGPStoNumber( 'GPSDestLongitude' ); |
344 | 343 | |
345 | 344 | if ( isset( $this->mFilteredExifData['GPSAltitude'] ) && isset( $this->mFilteredExifData['GPSAltitudeRef'] ) ) { |
346 | | - if ( $this->mFilteredExifData['GPSAltitudeRef'] === 1 ) { |
| 345 | + if ( $this->mFilteredExifData['GPSAltitudeRef'] === "\1" ) { |
347 | 346 | $this->mFilteredExifData['GPSAltitude'] *= - 1; |
348 | 347 | } |
349 | | - unset( $this->mFilteredExifData ); |
| 348 | + unset( $this->mFilteredExifData['GPSAltitudeRef'] ); |
350 | 349 | } |
351 | 350 | |
352 | | - $this->toHex( 'FileSource', true ); |
353 | | - $this->toHex( 'SceneType', true ); |
| 351 | + $this->getOrd( 'FileSource' ); |
| 352 | + $this->getOrd( 'SceneType' ); |
354 | 353 | |
355 | 354 | $this->charCodeString( 'UserComment' ); |
356 | 355 | $this->charCodeString( 'GPSProcessingMethod'); |
357 | 356 | $this->charCodeString( 'GPSAreaInformation' ); |
358 | 357 | |
359 | 358 | //ComponentsConfiguration should really be an array instead of a string... |
| 359 | + |
360 | 360 | if ( isset ( $this->mFilteredExifData['ComponentsConfiguration'] ) ) { |
361 | 361 | $val = $this->mFilteredExifData['ComponentsConfiguration']; |
362 | 362 | $ccVals = array(); |
— | — | @@ -365,6 +365,21 @@ |
366 | 366 | $ccVals['_type'] = 'ol'; //this is for formatting later. |
367 | 367 | $this->mFilteredExifData['ComponentsConfiguration'] = $ccVals; |
368 | 368 | } |
| 369 | + |
| 370 | + //GPSVersion(ID) is just very screwed up by php |
| 371 | + //put into a version string, and change the tag name. |
| 372 | + if ( isset ( $this->mFilteredExifData['GPSVersion'] ) ) { |
| 373 | + $val = $this->mFilteredExifData['GPSVersion']; |
| 374 | + $newVal = ''; |
| 375 | + for ($i = 0; $i < strlen($val); $i++) { |
| 376 | + if ( $i !== 0 ) { |
| 377 | + $newVal .= '.'; |
| 378 | + } |
| 379 | + $newVal .= ord( substr($val, strlen($val) - $i - 1, 1) ); |
| 380 | + } |
| 381 | + $this->mFilteredExifData['GPSVersionID'] = $newVal; |
| 382 | + unset( $this->mFilteredExifData['GPSVersion'] ); |
| 383 | + } |
369 | 384 | |
370 | 385 | } |
371 | 386 | /** |
— | — | @@ -375,7 +390,7 @@ |
376 | 391 | * @param $prop String prop name. |
377 | 392 | * @todo this is in need of testing. |
378 | 393 | */ |
379 | | - function charCodeString ( $prop ) { |
| 394 | + private function charCodeString ( $prop ) { |
380 | 395 | if ( isset( $this->mFilteredExifData[$prop] ) ) { |
381 | 396 | |
382 | 397 | if ( strlen($this->mFilteredExifData[$prop]) <= 8 ) { |
— | — | @@ -414,21 +429,13 @@ |
415 | 430 | } |
416 | 431 | /** |
417 | 432 | * Convert an Exif::UNDEFINED from a raw binary string |
418 | | - * to a hex string. This is sometimes needed depending on |
| 433 | + * to its value. This is sometimes needed depending on |
419 | 434 | * the type of UNDEFINED field |
420 | 435 | * @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 | 436 | */ |
424 | | - function toHex ( $prop, $stripLeadingZero = false ) { |
| 437 | + private function getOrd ( $prop ) { |
425 | 438 | 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; |
| 439 | + $this->mFilteredExifData[$prop] = ord( $this->mFilteredExifData[$prop] ); |
433 | 440 | } |
434 | 441 | } |
435 | 442 | /** |
— | — | @@ -436,7 +443,7 @@ |
437 | 444 | * for example 10 degress 20`40`` S -> -10.34444 |
438 | 445 | * @param String $prop a gps coordinate exif tag name (like GPSLongitude) |
439 | 446 | */ |
440 | | - function exifGPStoNumber ( $prop ) { |
| 447 | + private function exifGPStoNumber ( $prop ) { |
441 | 448 | $loc =& $this->mFilteredExifData[$prop]; |
442 | 449 | $dir =& $this->mFilteredExifData[$prop . 'Ref']; |
443 | 450 | $res = false; |
— | — | @@ -466,9 +473,10 @@ |
467 | 474 | } |
468 | 475 | |
469 | 476 | /** |
470 | | - * @todo document |
| 477 | + * Use FormatExif to create formatted values for display to user |
| 478 | + * (is this ever used?) |
471 | 479 | */ |
472 | | - function makeFormattedData( ) { |
| 480 | + private function makeFormattedData( ) { |
473 | 481 | $format = new FormatExif( $this->getFilteredData() ); |
474 | 482 | $this->mFormattedExifData = $format->getFormattedData(); |
475 | 483 | } |
— | — | @@ -495,6 +503,9 @@ |
496 | 504 | * Get $this->mFormattedExifData |
497 | 505 | */ |
498 | 506 | function getFormattedData() { |
| 507 | + if (!$this->mFormattedExifData) { |
| 508 | + $this->makeFormattedData(); |
| 509 | + } |
499 | 510 | return $this->mFormattedExifData; |
500 | 511 | } |
501 | 512 | /**#@-*/ |
— | — | @@ -523,7 +534,7 @@ |
524 | 535 | * @param $in Mixed: the input value to check |
525 | 536 | * @return bool |
526 | 537 | */ |
527 | | - function isByte( $in ) { |
| 538 | + private function isByte( $in ) { |
528 | 539 | if ( !is_array( $in ) && sprintf('%d', $in) == $in && $in >= 0 && $in <= 255 ) { |
529 | 540 | $this->debug( $in, __FUNCTION__, true ); |
530 | 541 | return true; |
— | — | @@ -533,7 +544,7 @@ |
534 | 545 | } |
535 | 546 | } |
536 | 547 | |
537 | | - function isASCII( $in ) { |
| 548 | + private function isASCII( $in ) { |
538 | 549 | if ( is_array( $in ) ) { |
539 | 550 | return false; |
540 | 551 | } |
— | — | @@ -551,7 +562,7 @@ |
552 | 563 | return true; |
553 | 564 | } |
554 | 565 | |
555 | | - function isShort( $in ) { |
| 566 | + private function isShort( $in ) { |
556 | 567 | if ( !is_array( $in ) && sprintf('%d', $in) == $in && $in >= 0 && $in <= 65536 ) { |
557 | 568 | $this->debug( $in, __FUNCTION__, true ); |
558 | 569 | return true; |
— | — | @@ -561,7 +572,7 @@ |
562 | 573 | } |
563 | 574 | } |
564 | 575 | |
565 | | - function isLong( $in ) { |
| 576 | + private function isLong( $in ) { |
566 | 577 | if ( !is_array( $in ) && sprintf('%d', $in) == $in && $in >= 0 && $in <= 4294967296 ) { |
567 | 578 | $this->debug( $in, __FUNCTION__, true ); |
568 | 579 | return true; |
— | — | @@ -571,7 +582,7 @@ |
572 | 583 | } |
573 | 584 | } |
574 | 585 | |
575 | | - function isRational( $in ) { |
| 586 | + private function isRational( $in ) { |
576 | 587 | $m = array(); |
577 | 588 | if ( !is_array( $in ) && @preg_match( '/^(\d+)\/(\d+[1-9]|[1-9]\d*)$/', $in, $m ) ) { # Avoid division by zero |
578 | 589 | return $this->isLong( $m[1] ) && $this->isLong( $m[2] ); |
— | — | @@ -581,7 +592,7 @@ |
582 | 593 | } |
583 | 594 | } |
584 | 595 | |
585 | | - function isUndefined( $in ) { |
| 596 | + private function isUndefined( $in ) { |
586 | 597 | |
587 | 598 | $this->debug( $in, __FUNCTION__, true ); |
588 | 599 | return true; |
— | — | @@ -599,7 +610,7 @@ |
600 | 611 | */ |
601 | 612 | } |
602 | 613 | |
603 | | - function isSlong( $in ) { |
| 614 | + private function isSlong( $in ) { |
604 | 615 | if ( $this->isLong( abs( $in ) ) ) { |
605 | 616 | $this->debug( $in, __FUNCTION__, true ); |
606 | 617 | return true; |
— | — | @@ -609,7 +620,7 @@ |
610 | 621 | } |
611 | 622 | } |
612 | 623 | |
613 | | - function isSrational( $in ) { |
| 624 | + private function isSrational( $in ) { |
614 | 625 | $m = array(); |
615 | 626 | if ( !is_array( $in ) && preg_match( '/^(\d+)\/(\d+[1-9]|[1-9]\d*)$/', $in, $m ) ) { # Avoid division by zero |
616 | 627 | return $this->isSlong( $m[0] ) && $this->isSlong( $m[1] ); |
— | — | @@ -630,7 +641,7 @@ |
631 | 642 | * @param $recursive Boolean: true if called recursively for array types. |
632 | 643 | * @return bool |
633 | 644 | */ |
634 | | - function validate( $section, $tag, $val, $recursive = false ) { |
| 645 | + private function validate( $section, $tag, $val, $recursive = false ) { |
635 | 646 | $debug = "tag is '$tag'"; |
636 | 647 | $etype = $this->mExifTags[$section][$tag]; |
637 | 648 | $ecount = 1; |
— | — | @@ -699,7 +710,7 @@ |
700 | 711 | * @param $fname String: |
701 | 712 | * @param $action Mixed: , default NULL. |
702 | 713 | */ |
703 | | - function debug( $in, $fname, $action = null ) { |
| 714 | + private function debug( $in, $fname, $action = null ) { |
704 | 715 | if ( !$this->log ) { |
705 | 716 | return; |
706 | 717 | } |
— | — | @@ -726,7 +737,7 @@ |
727 | 738 | * @param $fname String: the name of the function calling this function |
728 | 739 | * @param $io Boolean: Specify whether we're beginning or ending |
729 | 740 | */ |
730 | | - function debugFile( $fname, $io ) { |
| 741 | + private function debugFile( $fname, $io ) { |
731 | 742 | if ( !$this->log ) { |
732 | 743 | return; |
733 | 744 | } |
— | — | @@ -1126,6 +1137,14 @@ |
1127 | 1138 | } |
1128 | 1139 | break; |
1129 | 1140 | |
| 1141 | + case 'GPSAltitude': |
| 1142 | + if ( $val < 0 ) { |
| 1143 | + $val = $this->msg( 'GPSAltitude', 'below-sealevel', $this->formatNum( -$val ) ); |
| 1144 | + } else { |
| 1145 | + $val = $this->msg( 'GPSAltitude', 'above-sealevel', $this->formatNum( $val ) ); |
| 1146 | + } |
| 1147 | + break; |
| 1148 | + |
1130 | 1149 | case 'GPSStatus': |
1131 | 1150 | switch( $val ) { |
1132 | 1151 | case 'A': case 'V': |
— | — | @@ -1166,17 +1185,6 @@ |
1167 | 1186 | $val = $wgLang->date( substr( $val, 0, 4 ) . substr( $val, 5, 2 ) . substr( $val, 8, 2 ) . '000000' ); |
1168 | 1187 | break; |
1169 | 1188 | |
1170 | | - case 'GPSAltitudeRef': |
1171 | | - switch( $val ) { |
1172 | | - case 0: case 1: |
1173 | | - $tags[$tag] = $this->msg( 'GPSAltitude', $val ); |
1174 | | - break; |
1175 | | - default: |
1176 | | - $tags[$tag] = $val; |
1177 | | - break; |
1178 | | - } |
1179 | | - break; |
1180 | | - |
1181 | 1189 | case 'GPSLatitude': |
1182 | 1190 | case 'GPSDestLatitude': |
1183 | 1191 | $val = $this->formatCoords( $val, 'latitude' ); |
— | — | @@ -1240,6 +1248,7 @@ |
1241 | 1249 | case 'ImageDescription': |
1242 | 1250 | case 'Artist': |
1243 | 1251 | case 'Copyright': |
| 1252 | + case 'GPSVersionID': |
1244 | 1253 | $val = htmlspecialchars( $val ); |
1245 | 1254 | break; |
1246 | 1255 | |
— | — | @@ -1419,6 +1428,7 @@ |
1420 | 1429 | function formatCoords( $coord, $type ) { |
1421 | 1430 | $ref = ''; |
1422 | 1431 | if ( $coord < 0 ) { |
| 1432 | + $nCoord = -$coord; |
1423 | 1433 | if ( $type === 'latitude' ) { |
1424 | 1434 | $ref = 'S'; |
1425 | 1435 | } |
— | — | @@ -1427,6 +1437,7 @@ |
1428 | 1438 | } |
1429 | 1439 | } |
1430 | 1440 | else { |
| 1441 | + $nCoord = $coord; |
1431 | 1442 | if ( $type === 'latitude' ) { |
1432 | 1443 | $ref = 'N'; |
1433 | 1444 | } |
— | — | @@ -1435,9 +1446,9 @@ |
1436 | 1447 | } |
1437 | 1448 | } |
1438 | 1449 | |
1439 | | - $deg = floor( $coord ); |
1440 | | - $min = floor( ( $coord - $deg ) * 60.0 ); |
1441 | | - $sec = round( ( ( $coord - $deg ) - $min / 60 ) * 3600, 2 ); |
| 1450 | + $deg = floor( $nCoord ); |
| 1451 | + $min = floor( ( $nCoord - $deg ) * 60.0 ); |
| 1452 | + $sec = round( ( ( $nCoord - $deg ) - $min / 60 ) * 3600, 2 ); |
1442 | 1453 | |
1443 | 1454 | $deg = $this->formatNum( $deg ); |
1444 | 1455 | $min = $this->formatNum( $min ); |
Index: branches/img_metadata/phase3/languages/messages/MessagesEn.php |
— | — | @@ -3915,9 +3915,9 @@ |
3916 | 3916 | 'exif-gpslongitude-e' => 'East longitude', |
3917 | 3917 | 'exif-gpslongitude-w' => 'West longitude', |
3918 | 3918 | |
3919 | | -# Pseudotags used for GPSAltitudeRef |
3920 | | -'exif-gpsaltitude-0' => 'Metres above sea level', |
3921 | | -'exif-gpsaltitude-1' => 'Metres below sea level', |
| 3919 | +# Pseudotags used for GPSAltitude |
| 3920 | +'exif-gpsaltitude-above-sealevel' => '$1 Metres above sea level', |
| 3921 | +'exif-gpsaltitude-below-sealevel' => '$1 Metres below sea level', |
3922 | 3922 | |
3923 | 3923 | 'exif-gpsstatus-a' => 'Measurement in progress', |
3924 | 3924 | 'exif-gpsstatus-v' => 'Measurement interoperability', |