108 $resolutionunit = !isset( $tags[
'ResolutionUnit'] ) || $tags[
'ResolutionUnit'] == 2 ? 2 : 3;
109 unset( $tags[
'ResolutionUnit'] );
112 unset( $tags[
'HasExtendedXMP'] );
113 unset( $tags[
'AuthorsPosition'] );
114 unset( $tags[
'LocationCreated'] );
115 unset( $tags[
'LocationShown'] );
116 unset( $tags[
'GPSAltitudeRef'] );
118 foreach ( $tags as $tag => &$vals ) {
121 if ( !is_array( $vals ) ) {
126 if ( isset( $vals[
'_type'] ) ) {
127 $type = $vals[
'_type'];
128 unset( $vals[
'_type'] );
135 if ( isset( $tags[$tag][
'_formatted'] ) ) {
137 $tags[$tag][
'_formatted'],
$type
143 if ( $tag ==
'GPSTimeStamp' && count( $vals ) === 3 ) {
146 $h = explode(
'/', $vals[0], 2 );
147 $m = explode(
'/', $vals[1], 2 );
148 $s = explode(
'/', $vals[2], 2 );
163 $vals = str_pad( (
string)( (
int)$h[0] / (
int)$h[1] ), 2,
'0', STR_PAD_LEFT )
164 .
':' . str_pad( (
string)( (
int)$m[0] / (
int)$m[1] ), 2,
'0', STR_PAD_LEFT )
165 .
':' . str_pad( (
string)( (
int)
$s[0] / (
int)
$s[1] ), 2,
'0', STR_PAD_LEFT );
168 $time =
wfTimestamp( TS_MW,
'1971:01:01 ' . $vals );
170 if ( $time && intval( $time ) > 0 ) {
173 }
catch ( TimestampException $e ) {
184 if ( $tag ===
'Contact' || $tag ===
'CreatorContactInfo' ) {
189 foreach ( $vals as &$val ) {
204 $val = $this->exifMsg( $tag, $val );
213 case 'PhotometricInterpretation':
227 $val = $this->exifMsg( $tag, $val );
246 $val = $this->exifMsg( $tag, $val );
255 case 'PlanarConfiguration':
259 $val = $this->exifMsg( $tag, $val );
269 case 'YCbCrPositioning':
273 $val = $this->exifMsg( $tag, $val );
284 switch ( $resolutionunit ) {
286 $val = $this->exifMsg(
'XYResolution',
'i', $this->formatNum( $val ) );
289 $val = $this->exifMsg(
'XYResolution',
'c', $this->formatNum( $val ) );
305 case 'FlashPixVersion':
308 case 'FlashpixVersion':
309 $val = $this->
literal( (
int)$val / 100 );
316 $val = $this->exifMsg( $tag, $val );
325 case 'ComponentsConfiguration':
334 $val = $this->exifMsg( $tag, $val );
344 case 'DateTimeOriginal':
345 case 'DateTimeDigitized':
346 case 'DateTimeReleased':
347 case 'DateTimeExpires':
350 case 'DateTimeMetadata':
351 case 'FirstPhotoDate':
352 case 'LastPhotoDate':
353 if ( $val ==
'0000:00:00 00:00:00' || $val ==
' : : : : ' ) {
354 $val = $this->
msg(
'exif-unknowndate' )->text();
356 } elseif ( preg_match(
357 '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D',
362 if ( $time && intval( $time ) > 0 ) {
366 } elseif ( preg_match(
'/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) {
371 if ( $time && intval( $time ) > 0 ) {
375 } elseif ( preg_match(
'/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) {
378 . substr( $val, 5, 2 )
379 . substr( $val, 8, 2 )
381 if ( $time && intval( $time ) > 0 ) {
390 case 'ExposureProgram':
401 $val = $this->exifMsg( $tag, $val );
410 case 'SubjectDistance':
411 $val = $this->exifMsg( $tag,
'', $this->formatNum( $val ) );
425 $val = $this->exifMsg( $tag, $val );
457 $val = $this->exifMsg( $tag, $val );
468 'fired' => $val & 0b00000001,
469 'return' => ( $val & 0b00000110 ) >> 1,
470 'mode' => ( $val & 0b00011000 ) >> 3,
471 'function' => ( $val & 0b00100000 ) >> 5,
472 'redeye' => ( $val & 0b01000000 ) >> 6,
476 # We do not need to handle unknown values since all are used.
477 foreach ( $flashDecode as $subTag => $subValue ) {
478 # We do not need any message for zeroed values.
479 if ( $subTag !=
'fired' && $subValue == 0 ) {
482 $fullTag = $tag .
'-' . $subTag;
483 $flashMsgs[] = $this->exifMsg( $fullTag, $subValue );
485 $val = $this->
getLanguage()->commaList( $flashMsgs );
488 case 'FocalPlaneResolutionUnit':
491 $val = $this->exifMsg( $tag, $val );
500 case 'SensingMethod':
509 $val = $this->exifMsg( $tag, $val );
521 $val = $this->exifMsg( $tag, $val );
533 $val = $this->exifMsg( $tag, $val );
542 case 'CustomRendered':
554 $val = $this->exifMsg( $tag, $val );
568 $val = $this->exifMsg( $tag, $val );
580 $val = $this->exifMsg( $tag, $val );
589 case 'SceneCaptureType':
595 $val = $this->exifMsg( $tag, $val );
611 $val = $this->exifMsg( $tag, $val );
625 $val = $this->exifMsg( $tag, $val );
639 $val = $this->exifMsg( $tag, $val );
653 $val = $this->exifMsg( $tag, $val );
662 case 'SubjectDistanceRange':
668 $val = $this->exifMsg( $tag, $val );
678 case 'GPSLatitudeRef':
679 case 'GPSDestLatitudeRef':
683 $val = $this->exifMsg(
'GPSLatitude', $val );
692 case 'GPSLongitudeRef':
693 case 'GPSDestLongitudeRef':
697 $val = $this->exifMsg(
'GPSLongitude', $val );
708 $val = $this->exifMsg(
'GPSAltitude',
'below-sealevel', $this->formatNum( -$val, 3 ) );
710 $val = $this->exifMsg(
'GPSAltitude',
'above-sealevel', $this->formatNum( $val, 3 ) );
718 $val = $this->exifMsg( $tag, $val );
727 case 'GPSMeasureMode':
731 $val = $this->exifMsg( $tag, $val );
741 case 'GPSImgDirectionRef':
742 case 'GPSDestBearingRef':
746 $val = $this->exifMsg(
'GPSDirection', $val );
756 case 'GPSDestLatitude':
757 $val = $this->formatCoords( $val,
'latitude' );
760 case 'GPSDestLongitude':
761 $val = $this->formatCoords( $val,
'longitude' );
769 $val = $this->exifMsg(
'GPSSpeed', $val );
778 case 'GPSDestDistanceRef':
783 $val = $this->exifMsg(
'GPSDestDistance', $val );
795 $val = $this->exifMsg( $tag,
'excellent', $this->formatNum( $val ) );
796 } elseif ( $val <= 5 ) {
797 $val = $this->exifMsg( $tag,
'good', $this->formatNum( $val ) );
798 } elseif ( $val <= 10 ) {
799 $val = $this->exifMsg( $tag,
'moderate', $this->formatNum( $val ) );
800 } elseif ( $val <= 20 ) {
801 $val = $this->exifMsg( $tag,
'fair', $this->formatNum( $val ) );
803 $val = $this->exifMsg( $tag,
'poor', $this->formatNum( $val ) );
812 $val = $this->exifMsg( $tag,
'', $this->
literal( $val ) );
816 if ( is_array( $val ) ) {
817 if ( count( $val ) > 1 ) {
820 'exif-software-version-value',
826 $val = $this->exifMsg( $tag,
'', $this->
literal( $val[0] ) );
829 $val = $this->exifMsg( $tag,
'', $this->
literal( $val ) );
835 $val = $this->
msg(
'exif-exposuretime-format',
836 $this->formatFraction( $val ), $this->formatNum( $val ) )->text();
838 case 'ISOSpeedRatings':
842 if ( $val ==
'65535' ) {
843 $val = $this->exifMsg( $tag,
'overflow' );
845 $val = $this->formatNum( $val );
849 $val = $this->
msg(
'exif-fnumber-format',
850 $this->formatNum( $val ) )->text();
854 case 'FocalLengthIn35mmFilm':
855 $val = $this->
msg(
'exif-focallength-format',
856 $this->formatNum( $val ) )->text();
859 case 'MaxApertureValue':
860 if ( strpos( $val,
'/' ) !==
false ) {
862 list( $n, $d ) = explode(
'/', $val, 2 );
863 if ( is_numeric( $n ) && is_numeric( $d ) ) {
864 $val = (int)$n / (
int)$d;
867 if ( is_numeric( $val ) ) {
868 $fNumber = 2 ** ( $val / 2 );
869 if ( is_finite( $fNumber ) ) {
870 $val = $this->
msg(
'exif-maxaperturevalue-value',
871 $this->formatNum( $val ),
872 $this->formatNum( $fNumber, 2 )
881 switch ( strtolower( $val ) ) {
901 $val = $this->exifMsg(
910 case 'SubjectNewsCode':
916 $val = $this->convertNewsCode( $val );
922 if ( $val == 0 || $val == 9 ) {
924 } elseif ( $val < 5 && $val > 1 ) {
926 } elseif ( $val == 5 ) {
928 } elseif ( $val <= 8 && $val > 5 ) {
932 if ( $urgency !==
'' ) {
933 $val = $this->exifMsg(
'urgency',
934 $urgency, $this->
literal( $val )
942 case 'OriginalImageHeight':
943 case 'OriginalImageWidth':
944 case 'PixelXDimension':
945 case 'PixelYDimension':
948 $val = $this->formatNum( $val ) .
' ' . $this->
msg(
'unit-pixel' )->text();
958 case 'ImageDescription':
962 case 'RelatedSoundFile':
963 case 'ImageUniqueID':
964 case 'SpectralSensitivity':
965 case 'GPSSatellites':
969 case 'WorldRegionDest':
971 case 'CountryCodeDest':
972 case 'ProvinceOrStateDest':
974 case 'SublocationDest':
975 case 'WorldRegionCreated':
976 case 'CountryCreated':
977 case 'CountryCodeCreated':
978 case 'ProvinceOrStateCreated':
980 case 'SublocationCreated':
982 case 'SpecialInstructions':
987 case 'FixtureIdentifier':
989 case 'LocationDestCode':
991 case 'JPEGFileComment':
992 case 'iimSupplementalCategory':
993 case 'OriginalTransmissionRef':
995 case 'dc-contributor':
1003 case 'SerialNumber':
1004 case 'CameraOwnerName':
1007 case 'RightsCertificate':
1008 case 'CopyrightOwner':
1010 case 'WebStatement':
1011 case 'OriginalDocumentID':
1013 case 'MorePermissionsUrl':
1014 case 'AttributionUrl':
1015 case 'PreferredAttributionName':
1016 case 'PNGFileComment':
1018 case 'ContentWarning':
1019 case 'GIFFileComment':
1021 case 'IntellectualGenre':
1023 case 'OrganisationInImage':
1024 case 'PersonInImage':
1025 case 'CaptureSoftware':
1026 case 'GPSAreaInformation':
1027 case 'GPSProcessingMethod':
1028 case 'StitchingSoftware':
1030 case 'SubSecTimeOriginal':
1031 case 'SubSecTimeDigitized':
1032 $val = $this->
literal( $val );
1035 case 'ProjectionType':
1037 case 'equirectangular':
1038 $val = $this->exifMsg( $tag, $val );
1041 $val = $this->
literal( $val );
1050 $val = $this->exifMsg( $tag, $val );
1053 $val = $this->
literal( $val );
1058 case 'UsePanoramaViewer':
1059 case 'ExposureLockUsed':
1063 $val = $this->exifMsg( $tag, $val );
1066 $val = $this->
literal( $val );
1071 if ( $val ==
'-1' ) {
1072 $val = $this->exifMsg( $tag,
'rejected' );
1074 $val = $this->formatNum( $val );
1078 case 'LanguageCode':
1079 $lang = MediaWikiServices::getInstance()
1080 ->getLanguageNameUtils()
1081 ->getLanguageName( strtolower( $val ), $this->
getLanguage()->getCode() );
1086 $val = $this->formatNum( $val,
false, $tag );