Index: branches/img_metadata/phase3/includes/media/PNGMetadataExtractor.php |
— | — | @@ -40,7 +40,8 @@ |
41 | 41 | 'warning' => 'ContentWarning', |
42 | 42 | 'url' => 'Identifier', # Not sure if this is best mapping. Maybe WebStatement. |
43 | 43 | 'label' => 'Label', |
44 | | - /* Other potentially useful things - Creation Time, Document */ |
| 44 | + 'creation time' => 'DateTimeDigitized', |
| 45 | + /* Other potentially useful things - Document */ |
45 | 46 | ); |
46 | 47 | |
47 | 48 | $showXMP = function_exists( 'xml_parser_create_ns' ); |
— | — | @@ -94,7 +95,7 @@ |
95 | 96 | $duration += $fctldur['delay_num'] / $fctldur['delay_den']; |
96 | 97 | } |
97 | 98 | } elseif ( $chunk_type == "iTXt" ) { |
98 | | - // Extracts iTXt chunks, uncompressing if neccesary. |
| 99 | + // Extracts iTXt chunks, uncompressing if necessary. |
99 | 100 | $buf = fread( $fh, $chunk_size ); |
100 | 101 | $items = array(); |
101 | 102 | if ( preg_match( |
— | — | @@ -237,7 +238,42 @@ |
238 | 239 | wfDebug( __METHOD__ . " Cannot decompress zTXt chunk due to lack of zlib. Skipping." ); |
239 | 240 | fseek( $fh, $chunk_size, SEEK_CUR ); |
240 | 241 | } |
| 242 | + } elseif ( $chunk_type == 'tIME' ) { |
| 243 | + // last mod timestamp. |
| 244 | + if( $chunk_size !== 7 ) { throw new Exception( __METHOD__ . ": tIME wrong size" ); return; } |
| 245 | + $buf = fread( $fh, $chunk_size ); |
| 246 | + if( !$buf ) { throw new Exception( __METHOD__ . ": Read error" ); return; } |
241 | 247 | |
| 248 | + // Note: spec says this should be UTC. |
| 249 | + $t = unpack( "ny/Cm/Cd/Ch/Cmin/Cs", $buf ); |
| 250 | + $strTime = sprintf( "%04d%02d%02d%02d%02d%02d", |
| 251 | + $t['y'], $t['m'], $t['d'], $t['h'], |
| 252 | + $t['min'], $t['s'] ); |
| 253 | + |
| 254 | + $exifTime = wfTimestamp( TS_EXIF, $strTime ); |
| 255 | + |
| 256 | + if ( $exifTime ) { |
| 257 | + $text['DateTime'] = $exifTime; |
| 258 | + } |
| 259 | + |
| 260 | + } elseif ( $chunk_type == 'pHYs' ) { |
| 261 | + // how big pixels are (dots per meter). |
| 262 | + if( $chunk_size !== 9 ) { throw new Exception( __METHOD__ . ": pHYs wrong size" ); return; } |
| 263 | + $buf = fread( $fh, $chunk_size ); |
| 264 | + if( !$buf ) { throw new Exception( __METHOD__ . ": Read error" ); return; } |
| 265 | + |
| 266 | + $dim = unpack( "Nwidth/Nheight/Cunit", $buf ); |
| 267 | + if ( $dim['unit'] == 1 ) { |
| 268 | + // unit is meters |
| 269 | + // (as opposed to 0 = undefined ) |
| 270 | + $text['XResolution'] = $dim['width'] |
| 271 | + . '/100'; |
| 272 | + $text['YResolution'] = $dim['height'] |
| 273 | + . '/100'; |
| 274 | + $text['ResolutionUnit'] = 3; |
| 275 | + // 3 = dots per cm (from Exif). |
| 276 | + } |
| 277 | + |
242 | 278 | } elseif ( $chunk_type == "IEND" ) { |
243 | 279 | break; |
244 | 280 | } else { |
— | — | @@ -251,6 +287,32 @@ |
252 | 288 | $duration *= $loopCount; |
253 | 289 | } |
254 | 290 | |
| 291 | + if ( isset( $text['DateTimeDigitized'] ) ) { |
| 292 | + // Convert date format from rfc2822 to exif. |
| 293 | + foreach ( $text['DateTimeDigitized'] as $name => &$value ) { |
| 294 | + if ( $name === '_type' ) { |
| 295 | + continue; |
| 296 | + } |
| 297 | + |
| 298 | + // fixme: currently timezones are ignored. |
| 299 | + // possibly should be wfTimestamp's |
| 300 | + // responsibility. (at least for numeric TZ) |
| 301 | + $formatted = wfTimestamp( TS_EXIF, $value ); |
| 302 | + if ( $formatted ) { |
| 303 | + // Only change if we could convert the |
| 304 | + // date. |
| 305 | + // The png standard says it should be |
| 306 | + // in rfc2822 format, but not required. |
| 307 | + // In general for the exif stuff we |
| 308 | + // prettify the date if we can, but we |
| 309 | + // display as-is if we cannot or if |
| 310 | + // it is invalid. |
| 311 | + // So do the same here. |
| 312 | + |
| 313 | + $value = $formatted; |
| 314 | + } |
| 315 | + } |
| 316 | + } |
255 | 317 | return array( |
256 | 318 | 'frameCount' => $frameCount, |
257 | 319 | 'loopCount' => $loopCount, |