Cleanup debug and comments of r68324
[lhc/web/wiklou.git] / includes / media / PNGMetadataExtractor.php
1 <?php
2 /**
3 * PNG frame counter.
4 * Slightly derived from GIFMetadataExtractor.php
5 * Deliberately not using MWExceptions to avoid external dependencies, encouraging
6 * redistribution.
7 */
8
9 class PNGMetadataExtractor {
10 static $png_sig;
11 static $CRC_size;
12
13 static function getMetadata( $filename ) {
14 self::$png_sig = pack( "C8", 137, 80, 78, 71, 13, 10, 26, 10 );
15 self::$CRC_size = 4;
16
17 $frameCount = 0;
18 $loopCount = 1;
19 $duration = 0.0;
20
21 if (!$filename)
22 throw new Exception( __METHOD__ . ": No file name specified" );
23 elseif ( !file_exists($filename) || is_dir($filename) )
24 throw new Exception( __METHOD__ . ": File $filename does not exist" );
25
26 $fh = fopen( $filename, 'r' );
27
28 if (!$fh)
29 throw new Exception( __METHOD__ . ": Unable to open file $filename" );
30
31 // Check for the PNG header
32 $buf = fread( $fh, 8 );
33 if ( !($buf == self::$png_sig) ) {
34 throw new Exception( __METHOD__ . ": Not a valid PNG file; header: $buf" );
35 }
36
37 // Read chunks
38 while( !feof( $fh ) ) {
39 $buf = fread( $fh, 4 );
40 if( !$buf ) { throw new Exception( __METHOD__ . ": Read error" ); return; }
41 $chunk_size = unpack( "N", $buf);
42 $chunk_size = $chunk_size[1];
43
44 $chunk_type = fread( $fh, 4 );
45 if( !$chunk_type ) { throw new Exception( __METHOD__ . ": Read error" ); return; }
46
47 if ( $chunk_type == "acTL" ) {
48 $buf = fread( $fh, $chunk_size );
49 if( !$buf ) { throw new Exception( __METHOD__ . ": Read error" ); return; }
50
51 $actl = unpack( "Nframes/Nplays", $buf );
52 $frameCount = $actl['frames'];
53 $loopCount = $actl['plays'];
54 } elseif ( $chunk_type == "fcTL" ) {
55 $buf = fread( $fh, $chunk_size );
56 if( !$buf ) { throw new Exception( __METHOD__ . ": Read error" ); return; }
57 $buf = substr( $buf, 20 );
58
59 $fctldur = unpack( "ndelay_num/ndelay_den", $buf );
60 if( $fctldur['delay_den'] == 0 ) $fctldur['delay_den'] = 100;
61 if( $fctldur['delay_num'] ) {
62 $duration += $fctldur['delay_num'] / $fctldur['delay_den'];
63 }
64 } elseif ( ( $chunk_type == "IDAT" || $chunk_type == "IEND" ) && $frameCount == 0 ) {
65 // Not a valid animated image. No point in continuing.
66 break;
67 } elseif ( $chunk_type == "IEND" ) {
68 break;
69 } else {
70 fseek( $fh, $chunk_size, SEEK_CUR );
71 }
72 fseek( $fh, self::$CRC_size, SEEK_CUR );
73 }
74 fclose( $fh );
75
76 if( $loopCount > 1 ) {
77 $duration *= $loopCount;
78 }
79
80 return array(
81 'frameCount' => $frameCount,
82 'loopCount' => $loopCount,
83 'duration' => $duration
84 );
85
86 }
87 }