111 $resolutionunit = !isset( $tags[
'ResolutionUnit'] ) || $tags[
'ResolutionUnit'] == 2 ? 2 : 3;
112 unset( $tags[
'ResolutionUnit'] );
115 unset( $tags[
'HasExtendedXMP'] );
116 unset( $tags[
'AuthorsPosition'] );
117 unset( $tags[
'LocationCreated'] );
118 unset( $tags[
'LocationShown'] );
119 unset( $tags[
'GPSAltitudeRef'] );
121 foreach ( $tags as $tag => &$vals ) {
124 if ( !is_array( $vals ) ) {
129 if ( isset( $vals[
'_type'] ) ) {
130 $type = $vals[
'_type'];
131 unset( $vals[
'_type'] );
138 if ( isset( $tags[$tag][
'_formatted'] ) ) {
140 $tags[$tag][
'_formatted'], $type
146 if ( $tag ===
'GPSTimeStamp' && count( $vals ) === 3 ) {
149 $h = explode(
'/', $vals[0], 2 );
150 $m = explode(
'/', $vals[1], 2 );
151 $s = explode(
'/', $vals[2], 2 );
166 $vals = str_pad( (
string)( (
int)$h[0] / (
int)$h[1] ), 2,
'0', STR_PAD_LEFT )
167 .
':' . str_pad( (
string)( (
int)$m[0] / (
int)$m[1] ), 2,
'0', STR_PAD_LEFT )
168 .
':' . str_pad( (
string)( (
int)$s[0] / (
int)$s[1] ), 2,
'0', STR_PAD_LEFT );
170 $time =
wfTimestamp( TS_MW,
'1971:01:01 ' . $vals );
172 if ( $time && (
int)$time > 0 ) {
181 if ( $tag ===
'Contact' || $tag ===
'CreatorContactInfo' ) {
186 foreach ( $vals as &$val ) {
201 $val = $this->exifMsg( $tag, $val );
210 case 'PhotometricInterpretation':
224 $val = $this->exifMsg( $tag, $val );
243 $val = $this->exifMsg( $tag, $val );
252 case 'PlanarConfiguration':
256 $val = $this->exifMsg( $tag, $val );
266 case 'YCbCrPositioning':
270 $val = $this->exifMsg( $tag, $val );
281 switch ( $resolutionunit ) {
283 $val = $this->exifMsg(
'XYResolution',
'i', $this->formatNum( $val ) );
286 $val = $this->exifMsg(
'XYResolution',
'c', $this->formatNum( $val ) );
302 case 'FlashPixVersion':
305 case 'FlashpixVersion':
306 $val = $this->
literal( (
int)$val / 100 );
313 $val = $this->exifMsg( $tag, $val );
322 case 'ComponentsConfiguration':
331 $val = $this->exifMsg( $tag, $val );
341 case 'DateTimeOriginal':
342 case 'DateTimeDigitized':
343 case 'DateTimeReleased':
344 case 'DateTimeExpires':
347 case 'DateTimeMetadata':
348 case 'FirstPhotoDate':
349 case 'LastPhotoDate':
350 if ( $val ===
'0000:00:00 00:00:00' || $val ===
' : : : : ' ) {
351 $val = $this->
msg(
'exif-unknowndate' )->text();
355 '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D',
360 if ( $time && (
int)$time > 0 ) {
364 } elseif ( preg_match(
'/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) {
369 if ( $time && (
int)$time > 0 ) {
373 } elseif ( preg_match(
'/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) {
376 . substr( $val, 5, 2 )
377 . substr( $val, 8, 2 )
379 if ( $time && (
int)$time > 0 ) {
388 case 'ExposureProgram':
399 $val = $this->exifMsg( $tag, $val );
408 case 'SubjectDistance':
409 $val = $this->exifMsg( $tag,
'', $this->formatNum( $val ) );
423 $val = $this->exifMsg( $tag, $val );
455 $val = $this->exifMsg( $tag, $val );
469 'fired' => $val & 0b00000001,
470 'return' => ( $val & 0b00000110 ) >> 1,
471 'mode' => ( $val & 0b00011000 ) >> 3,
472 'function' => ( $val & 0b00100000 ) >> 5,
473 'redeye' => ( $val & 0b01000000 ) >> 6,
477 # We do not need to handle unknown values since all are used.
478 foreach ( $flashDecode as $subTag => $subValue ) {
479 # We do not need any message for zeroed values.
480 if ( $subTag !==
'fired' && $subValue === 0 ) {
483 $fullTag = $tag .
'-' . $subTag;
484 $flashMsgs[] = $this->exifMsg( $fullTag, $subValue );
486 $val = $this->
getLanguage()->commaList( $flashMsgs );
489 case 'FocalPlaneResolutionUnit':
492 $val = $this->exifMsg( $tag, $val );
501 case 'SensingMethod':
510 $val = $this->exifMsg( $tag, $val );
522 $val = $this->exifMsg( $tag, $val );
534 $val = $this->exifMsg( $tag, $val );
543 case 'CustomRendered':
555 $val = $this->exifMsg( $tag, $val );
569 $val = $this->exifMsg( $tag, $val );
581 $val = $this->exifMsg( $tag, $val );
590 case 'SceneCaptureType':
596 $val = $this->exifMsg( $tag, $val );
612 $val = $this->exifMsg( $tag, $val );
626 $val = $this->exifMsg( $tag, $val );
640 $val = $this->exifMsg( $tag, $val );
654 $val = $this->exifMsg( $tag, $val );
663 case 'SubjectDistanceRange':
669 $val = $this->exifMsg( $tag, $val );
679 case 'GPSLatitudeRef':
680 case 'GPSDestLatitudeRef':
684 $val = $this->exifMsg(
'GPSLatitude', $val );
693 case 'GPSLongitudeRef':
694 case 'GPSDestLongitudeRef':
698 $val = $this->exifMsg(
'GPSLongitude', $val );
709 $val = $this->exifMsg(
'GPSAltitude',
'below-sealevel', $this->formatNum( -$val, 3 ) );
711 $val = $this->exifMsg(
'GPSAltitude',
'above-sealevel', $this->formatNum( $val, 3 ) );
719 $val = $this->exifMsg( $tag, $val );
728 case 'GPSMeasureMode':
732 $val = $this->exifMsg( $tag, $val );
742 case 'GPSImgDirectionRef':
743 case 'GPSDestBearingRef':
747 $val = $this->exifMsg(
'GPSDirection', $val );
757 case 'GPSDestLatitude':
758 $val = $this->formatCoords( $val,
'latitude' );
761 case 'GPSDestLongitude':
762 $val = $this->formatCoords( $val,
'longitude' );
770 $val = $this->exifMsg(
'GPSSpeed', $val );
779 case 'GPSDestDistanceRef':
784 $val = $this->exifMsg(
'GPSDestDistance', $val );
796 $val = $this->exifMsg( $tag,
'excellent', $this->formatNum( $val ) );
797 } elseif ( $val <= 5 ) {
798 $val = $this->exifMsg( $tag,
'good', $this->formatNum( $val ) );
799 } elseif ( $val <= 10 ) {
800 $val = $this->exifMsg( $tag,
'moderate', $this->formatNum( $val ) );
801 } elseif ( $val <= 20 ) {
802 $val = $this->exifMsg( $tag,
'fair', $this->formatNum( $val ) );
804 $val = $this->exifMsg( $tag,
'poor', $this->formatNum( $val ) );
813 $val = $this->exifMsg( $tag,
'', $this->
literal( $val ) );
817 if ( is_array( $val ) ) {
818 if ( count( $val ) > 1 ) {
821 'exif-software-version-value',
827 $val = $this->exifMsg( $tag,
'', $this->
literal( $val[0] ) );
830 $val = $this->exifMsg( $tag,
'', $this->
literal( $val ) );
836 $val = $this->
msg(
'exif-exposuretime-format',
837 $this->formatFraction( $val ), $this->formatNum( $val ) )->text();
839 case 'ISOSpeedRatings':
843 if ( $val ===
'65535' ) {
844 $val = $this->exifMsg( $tag,
'overflow' );
846 $val = $this->formatNum( $val );
850 $val = $this->
msg(
'exif-fnumber-format',
851 $this->formatNum( $val ) )->text();
855 case 'FocalLengthIn35mmFilm':
856 $val = $this->
msg(
'exif-focallength-format',
857 $this->formatNum( $val ) )->text();
860 case 'MaxApertureValue':
861 if ( strpos( $val,
'/' ) !==
false ) {
863 [ $n, $d ] = explode(
'/', $val, 2 );
864 if ( is_numeric( $n ) && is_numeric( $d ) ) {
865 $val = (int)$n / (
int)$d;
868 if ( is_numeric( $val ) ) {
869 $fNumber = 2 ** ( $val / 2 );
870 if ( is_finite( $fNumber ) ) {
871 $val = $this->
msg(
'exif-maxaperturevalue-value',
872 $this->formatNum( $val ),
873 $this->formatNum( $fNumber, 2 )
882 switch ( strtolower( $val ) ) {
902 $val = $this->exifMsg(
911 case 'SubjectNewsCode':
917 $val = $this->convertNewsCode( $val );
923 if ( $val === 0 || $val === 9 ) {
925 } elseif ( $val < 5 && $val > 1 ) {
927 } elseif ( $val === 5 ) {
929 } elseif ( $val <= 8 && $val > 5 ) {
933 if ( $urgency !==
'' ) {
934 $val = $this->exifMsg(
'urgency',
935 $urgency, $this->
literal( $val )
943 case 'OriginalImageHeight':
944 case 'OriginalImageWidth':
945 case 'PixelXDimension':
946 case 'PixelYDimension':
949 $val = $this->formatNum( $val ) .
' ' . $this->
msg(
'unit-pixel' )->text();
959 case 'ImageDescription':
963 case 'RelatedSoundFile':
964 case 'ImageUniqueID':
965 case 'SpectralSensitivity':
966 case 'GPSSatellites':
970 case 'WorldRegionDest':
972 case 'CountryCodeDest':
973 case 'ProvinceOrStateDest':
975 case 'SublocationDest':
976 case 'WorldRegionCreated':
977 case 'CountryCreated':
978 case 'CountryCodeCreated':
979 case 'ProvinceOrStateCreated':
981 case 'SublocationCreated':
983 case 'SpecialInstructions':
988 case 'FixtureIdentifier':
990 case 'LocationDestCode':
992 case 'JPEGFileComment':
993 case 'iimSupplementalCategory':
994 case 'OriginalTransmissionRef':
996 case 'dc-contributor':
1004 case 'SerialNumber':
1005 case 'CameraOwnerName':
1008 case 'RightsCertificate':
1009 case 'CopyrightOwner':
1011 case 'WebStatement':
1012 case 'OriginalDocumentID':
1014 case 'MorePermissionsUrl':
1015 case 'AttributionUrl':
1016 case 'PreferredAttributionName':
1017 case 'PNGFileComment':
1019 case 'ContentWarning':
1020 case 'GIFFileComment':
1022 case 'IntellectualGenre':
1024 case 'OrganisationInImage':
1025 case 'PersonInImage':
1026 case 'CaptureSoftware':
1027 case 'GPSAreaInformation':
1028 case 'GPSProcessingMethod':
1029 case 'StitchingSoftware':
1031 case 'SubSecTimeOriginal':
1032 case 'SubSecTimeDigitized':
1033 $val = $this->
literal( $val );
1036 case 'ProjectionType':
1038 case 'equirectangular':
1039 $val = $this->exifMsg( $tag, $val );
1042 $val = $this->
literal( $val );
1051 $val = $this->exifMsg( $tag, $val );
1054 $val = $this->
literal( $val );
1059 case 'UsePanoramaViewer':
1060 case 'ExposureLockUsed':
1064 $val = $this->exifMsg( $tag, $val );
1067 $val = $this->
literal( $val );
1072 if ( $val ===
'-1' ) {
1073 $val = $this->exifMsg( $tag,
'rejected' );
1075 $val = $this->formatNum( $val );
1079 case 'LanguageCode':
1080 $lang = MediaWikiServices::getInstance()
1081 ->getLanguageNameUtils()
1082 ->getLanguageName( strtolower( $val ), $this->
getLanguage()->getCode() );
1083 $val = $this->
literal( $lang ?: $val );
1087 $val = $this->formatNum( $val,
false, $tag );