Index: branches/img_metadata/phase3/includes/Exif.php |
— | — | @@ -918,7 +918,10 @@ |
919 | 919 | $val = wfMsg( 'exif-unknowndate' ); |
920 | 920 | } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/', $val ) ) { |
921 | 921 | $val = $wgLang->timeanddate( wfTimestamp( TS_MW, $val ) ); |
| 922 | + } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d)$/', $val ) ) { |
| 923 | + $val = $wgLang->date( wfTimestamp( TS_MW, $val . ' 00:00:00' ) ); |
922 | 924 | } |
| 925 | + // else it will just output $val without formatting it. |
923 | 926 | break; |
924 | 927 | |
925 | 928 | case 'ExposureProgram': |
Index: branches/img_metadata/phase3/includes/media/IPTC.php |
— | — | @@ -19,7 +19,6 @@ |
20 | 20 | * @return Array iptc metadata array |
21 | 21 | */ |
22 | 22 | static function parse( $rawData ) { |
23 | | - // TODO: This is nowhere near complete yet. |
24 | 23 | $parsed = iptcparse( $rawData ); |
25 | 24 | $data = Array(); |
26 | 25 | if (!is_array($parsed)) { |
— | — | @@ -153,6 +152,40 @@ |
154 | 153 | case '2#135': /* lang code */ |
155 | 154 | $data['LanguageCode'] = self::convIPTC( $val, $c ); |
156 | 155 | break; |
| 156 | + |
| 157 | + // Start date stuff. |
| 158 | + // It doesn't accept incomplete dates even though they are valid |
| 159 | + // according to spec. |
| 160 | + // Should potentially store timezone as well. |
| 161 | + case '2#055': |
| 162 | + //Date created (not date digitized). |
| 163 | + //Maps to exif DateTimeOriginal |
| 164 | + if ( isset( $parsed['2#060'] ) ) { |
| 165 | + $time = $parsed['2#060']; |
| 166 | + } else { |
| 167 | + $time = Array(); |
| 168 | + } |
| 169 | + $timestamp = self::timeHelper( $val, $time, $c ); |
| 170 | + if ($timestamp) { |
| 171 | + $data['DateTimeOriginal'] = $timestamp; |
| 172 | + } |
| 173 | + break; |
| 174 | + |
| 175 | + case '2#062': |
| 176 | + //Date converted to digital representation. |
| 177 | + //Maps to exif DateTimeDigitized |
| 178 | + if ( isset( $parsed['2#063'] ) ) { |
| 179 | + $time = $parsed['2#063']; |
| 180 | + } else { |
| 181 | + $time = Array(); |
| 182 | + } |
| 183 | + $timestamp = self::timeHelper( $val, $time, $c ); |
| 184 | + if ($timestamp) { |
| 185 | + $data['DateTimeDigitized'] = $timestamp; |
| 186 | + } |
| 187 | + break; |
| 188 | + |
| 189 | + |
157 | 190 | case '2#000': /* iim version */ |
158 | 191 | // unlike other tags, this is a 2-byte binary number. |
159 | 192 | //technically this is required if there is iptc data |
— | — | @@ -176,6 +209,12 @@ |
177 | 210 | // 2:200, 2:201, 2:202 |
178 | 211 | // or the audio stuff (2:150 to 2:154) |
179 | 212 | |
| 213 | + case '2#070': |
| 214 | + case '2#060': |
| 215 | + case '2#063': |
| 216 | + //ignore. Handled elsewhere. |
| 217 | + break; |
| 218 | + |
180 | 219 | default: |
181 | 220 | wfDebugLog( 'iptc', "Unsupported iptc tag: $tag. Value: " . implode( ',', $val )); |
182 | 221 | break; |
— | — | @@ -186,6 +225,71 @@ |
187 | 226 | } |
188 | 227 | |
189 | 228 | /** |
| 229 | + * Convert an iptc date and time tags into the exif format |
| 230 | + * |
| 231 | + * @todo Potentially this should also capture the timezone offset. |
| 232 | + * @param Array $date The date tag |
| 233 | + * @param Array $time The time tag |
| 234 | + * @return String Date in exif format. |
| 235 | + */ |
| 236 | + private static function timeHelper( $date, $time, $c ) { |
| 237 | + if ( count( $date ) === 1 ) { |
| 238 | + //the standard says this should always be 1 |
| 239 | + //just double checking. |
| 240 | + list($date) = self::convIPTC( $date, $c ); |
| 241 | + } else { |
| 242 | + return null; |
| 243 | + } |
| 244 | + |
| 245 | + if ( count( $time ) === 1 ) { |
| 246 | + list($time) = self::convIPTC( $time, $c ); |
| 247 | + $dateOnly = false; |
| 248 | + } else { |
| 249 | + $time = '000000+0000'; //placeholder |
| 250 | + $dateOnly = true; |
| 251 | + } |
| 252 | + |
| 253 | + if ( ! ( preg_match('/\d\d\d\d\d\d[-+]\d\d\d\d/', $time) |
| 254 | + && preg_match('/\d\d\d\d\d\d\d\d/', $date) |
| 255 | + && substr($date, 0, 4) !== '0000' |
| 256 | + && substr($date, 4, 2) !== '00' |
| 257 | + && substr($date, 6, 2) !== '00' |
| 258 | + ) ) { |
| 259 | + //something wrong. |
| 260 | + // Note, this rejects some valid dates according to iptc spec |
| 261 | + // for example: the date 00000400 means the photo was taken in |
| 262 | + // april, but the year and day is unknown. We don't process these |
| 263 | + // types of incomplete dates atm. |
| 264 | + wfDebugLog( 'iptc', "IPTC: invalid time ( $time ) or date ( $date )"); |
| 265 | + return null; |
| 266 | + } |
| 267 | + |
| 268 | + if ( substr($date, 0, 4) < "1902" ) { |
| 269 | + //We run into the reverse y2k38 bug. |
| 270 | + //might do something better later... |
| 271 | + wfDebugLog( 'iptc', "IPTC: date is too early (reverse y2k38 bug) ( $date )"); |
| 272 | + return null; |
| 273 | + } |
| 274 | + |
| 275 | + $unixTS = wfTimestamp( TS_UNIX, $date . substr( $time, 0, 6 )); |
| 276 | + $tz = ( intval( substr( $time, 7, 2 ) ) *60*60 ) |
| 277 | + + ( intval( substr( $time, 9, 2 ) ) * 60 ); |
| 278 | + |
| 279 | + if ( substr( $time, 6, 1 ) === '-' ) { |
| 280 | + $tz = - $tz; |
| 281 | + } |
| 282 | + |
| 283 | + $finalTimestamp = wfTimestamp( TS_EXIF, $unixTS + $tz ); |
| 284 | + if ( $dateOnly ) { |
| 285 | + //return the date only |
| 286 | + return substr( $finalTimestamp, 0, 10 ); |
| 287 | + } else { |
| 288 | + return $finalTimestamp; |
| 289 | + } |
| 290 | + |
| 291 | + } |
| 292 | + |
| 293 | + /** |
190 | 294 | * Helper function to convert charset for iptc values. |
191 | 295 | * @param $data Mixed String or Array: The iptc string |
192 | 296 | * @param $charset String: The charset |