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 ===
null ) {
360 if ( $val ==
'0000:00:00 00:00:00' || $val ==
' : : : : ' ) {
361 $val = $this->
msg(
'exif-unknowndate' )->text();
363 } elseif ( preg_match(
364 '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D',
369 if ( $time && intval( $time ) > 0 ) {
373 } elseif ( preg_match(
'/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) {
378 if ( $time && intval( $time ) > 0 ) {
382 } elseif ( preg_match(
'/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) {
385 . substr( $val, 5, 2 )
386 . substr( $val, 8, 2 )
388 if ( $time && intval( $time ) > 0 ) {
397 case 'ExposureProgram':
408 $val = $this->exifMsg( $tag, $val );
417 case 'SubjectDistance':
418 $val = $this->exifMsg( $tag,
'', $this->formatNum( $val ) );
432 $val = $this->exifMsg( $tag, $val );
464 $val = $this->exifMsg( $tag, $val );
475 'fired' => $val & 0b00000001,
476 'return' => ( $val & 0b00000110 ) >> 1,
477 'mode' => ( $val & 0b00011000 ) >> 3,
478 'function' => ( $val & 0b00100000 ) >> 5,
479 'redeye' => ( $val & 0b01000000 ) >> 6,
483 # We do not need to handle unknown values since all are used.
484 foreach ( $flashDecode as $subTag => $subValue ) {
485 # We do not need any message for zeroed values.
486 if ( $subTag !=
'fired' && $subValue == 0 ) {
489 $fullTag = $tag .
'-' . $subTag;
490 $flashMsgs[] = $this->exifMsg( $fullTag, $subValue );
492 $val = $this->
getLanguage()->commaList( $flashMsgs );
495 case 'FocalPlaneResolutionUnit':
498 $val = $this->exifMsg( $tag, $val );
507 case 'SensingMethod':
516 $val = $this->exifMsg( $tag, $val );
528 $val = $this->exifMsg( $tag, $val );
540 $val = $this->exifMsg( $tag, $val );
549 case 'CustomRendered':
561 $val = $this->exifMsg( $tag, $val );
575 $val = $this->exifMsg( $tag, $val );
587 $val = $this->exifMsg( $tag, $val );
596 case 'SceneCaptureType':
602 $val = $this->exifMsg( $tag, $val );
618 $val = $this->exifMsg( $tag, $val );
632 $val = $this->exifMsg( $tag, $val );
646 $val = $this->exifMsg( $tag, $val );
660 $val = $this->exifMsg( $tag, $val );
669 case 'SubjectDistanceRange':
675 $val = $this->exifMsg( $tag, $val );
685 case 'GPSLatitudeRef':
686 case 'GPSDestLatitudeRef':
690 $val = $this->exifMsg(
'GPSLatitude', $val );
699 case 'GPSLongitudeRef':
700 case 'GPSDestLongitudeRef':
704 $val = $this->exifMsg(
'GPSLongitude', $val );
715 $val = $this->exifMsg(
'GPSAltitude',
'below-sealevel', $this->formatNum( -$val, 3 ) );
717 $val = $this->exifMsg(
'GPSAltitude',
'above-sealevel', $this->formatNum( $val, 3 ) );
725 $val = $this->exifMsg( $tag, $val );
734 case 'GPSMeasureMode':
738 $val = $this->exifMsg( $tag, $val );
748 case 'GPSImgDirectionRef':
749 case 'GPSDestBearingRef':
753 $val = $this->exifMsg(
'GPSDirection', $val );
763 case 'GPSDestLatitude':
764 $val = $this->formatCoords( $val,
'latitude' );
767 case 'GPSDestLongitude':
768 $val = $this->formatCoords( $val,
'longitude' );
776 $val = $this->exifMsg(
'GPSSpeed', $val );
785 case 'GPSDestDistanceRef':
790 $val = $this->exifMsg(
'GPSDestDistance', $val );
802 $val = $this->exifMsg( $tag,
'excellent', $this->formatNum( $val ) );
803 } elseif ( $val <= 5 ) {
804 $val = $this->exifMsg( $tag,
'good', $this->formatNum( $val ) );
805 } elseif ( $val <= 10 ) {
806 $val = $this->exifMsg( $tag,
'moderate', $this->formatNum( $val ) );
807 } elseif ( $val <= 20 ) {
808 $val = $this->exifMsg( $tag,
'fair', $this->formatNum( $val ) );
810 $val = $this->exifMsg( $tag,
'poor', $this->formatNum( $val ) );
819 $val = $this->exifMsg( $tag,
'', $this->
literal( $val ) );
823 if ( is_array( $val ) ) {
824 if ( count( $val ) > 1 ) {
827 'exif-software-version-value',
833 $val = $this->exifMsg( $tag,
'', $this->
literal( $val[0] ) );
836 $val = $this->exifMsg( $tag,
'', $this->
literal( $val ) );
842 $val = $this->
msg(
'exif-exposuretime-format',
843 $this->formatFraction( $val ), $this->formatNum( $val ) )->text();
845 case 'ISOSpeedRatings':
849 if ( $val ==
'65535' ) {
850 $val = $this->exifMsg( $tag,
'overflow' );
852 $val = $this->formatNum( $val );
856 $val = $this->
msg(
'exif-fnumber-format',
857 $this->formatNum( $val ) )->text();
861 case 'FocalLengthIn35mmFilm':
862 $val = $this->
msg(
'exif-focallength-format',
863 $this->formatNum( $val ) )->text();
866 case 'MaxApertureValue':
867 if ( strpos( $val,
'/' ) !==
false ) {
869 list( $n, $d ) = explode(
'/', $val, 2 );
870 if ( is_numeric( $n ) && is_numeric( $d ) ) {
871 $val = (int)$n / (
int)$d;
874 if ( is_numeric( $val ) ) {
875 $fNumber = 2 ** ( $val / 2 );
876 if ( is_finite( $fNumber ) ) {
877 $val = $this->
msg(
'exif-maxaperturevalue-value',
878 $this->formatNum( $val ),
879 $this->formatNum( $fNumber, 2 )
888 switch ( strtolower( $val ) ) {
908 $val = $this->exifMsg(
917 case 'SubjectNewsCode':
923 $val = $this->convertNewsCode( $val );
929 if ( $val == 0 || $val == 9 ) {
931 } elseif ( $val < 5 && $val > 1 ) {
933 } elseif ( $val == 5 ) {
935 } elseif ( $val <= 8 && $val > 5 ) {
939 if ( $urgency !==
'' ) {
940 $val = $this->exifMsg(
'urgency',
941 $urgency, $this->
literal( $val )
949 case 'OriginalImageHeight':
950 case 'OriginalImageWidth':
951 case 'PixelXDimension':
952 case 'PixelYDimension':
955 $val = $this->formatNum( $val ) .
' ' . $this->
msg(
'unit-pixel' )->text();
965 case 'ImageDescription':
969 case 'RelatedSoundFile':
970 case 'ImageUniqueID':
971 case 'SpectralSensitivity':
972 case 'GPSSatellites':
976 case 'WorldRegionDest':
978 case 'CountryCodeDest':
979 case 'ProvinceOrStateDest':
981 case 'SublocationDest':
982 case 'WorldRegionCreated':
983 case 'CountryCreated':
984 case 'CountryCodeCreated':
985 case 'ProvinceOrStateCreated':
987 case 'SublocationCreated':
989 case 'SpecialInstructions':
994 case 'FixtureIdentifier':
996 case 'LocationDestCode':
998 case 'JPEGFileComment':
999 case 'iimSupplementalCategory':
1000 case 'OriginalTransmissionRef':
1002 case 'dc-contributor':
1004 case 'dc-publisher':
1010 case 'SerialNumber':
1011 case 'CameraOwnerName':
1014 case 'RightsCertificate':
1015 case 'CopyrightOwner':
1017 case 'WebStatement':
1018 case 'OriginalDocumentID':
1020 case 'MorePermissionsUrl':
1021 case 'AttributionUrl':
1022 case 'PreferredAttributionName':
1023 case 'PNGFileComment':
1025 case 'ContentWarning':
1026 case 'GIFFileComment':
1028 case 'IntellectualGenre':
1030 case 'OrganisationInImage':
1031 case 'PersonInImage':
1032 case 'CaptureSoftware':
1033 case 'GPSAreaInformation':
1034 case 'GPSProcessingMethod':
1035 case 'StitchingSoftware':
1037 case 'SubSecTimeOriginal':
1038 case 'SubSecTimeDigitized':
1039 $val = $this->
literal( $val );
1042 case 'ProjectionType':
1044 case 'equirectangular':
1045 $val = $this->exifMsg( $tag, $val );
1048 $val = $this->
literal( $val );
1057 $val = $this->exifMsg( $tag, $val );
1060 $val = $this->
literal( $val );
1065 case 'UsePanoramaViewer':
1066 case 'ExposureLockUsed':
1070 $val = $this->exifMsg( $tag, $val );
1073 $val = $this->
literal( $val );
1078 if ( $val ==
'-1' ) {
1079 $val = $this->exifMsg( $tag,
'rejected' );
1081 $val = $this->formatNum( $val );
1085 case 'LanguageCode':
1086 $lang = MediaWikiServices::getInstance()
1087 ->getLanguageNameUtils()
1088 ->getLanguageName( strtolower( $val ), $this->
getLanguage()->getCode() );
1093 $val = $this->formatNum( $val,
false, $tag );