MediaWiki  REL1_24
XCF.php
Go to the documentation of this file.
00001 <?php
00035 class XCFHandler extends BitmapHandler {
00040     function mustRender( $file ) {
00041         return true;
00042     }
00043 
00052     function getThumbType( $ext, $mime, $params = null ) {
00053         return array( 'png', 'image/png' );
00054     }
00055 
00063     function getImageSize( $image, $filename ) {
00064         $header = self::getXCFMetaData( $filename );
00065         if ( !$header ) {
00066             return false;
00067         }
00068 
00069         # Forge a return array containing metadata information just like getimagesize()
00070         # See PHP documentation at: http://www.php.net/getimagesize
00071         $metadata = array();
00072         $metadata[0] = $header['width'];
00073         $metadata[1] = $header['height'];
00074         $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
00075         $metadata[3] = sprintf(
00076             'height="%s" width="%s"', $header['height'], $header['width']
00077         );
00078         $metadata['mime'] = 'image/x-xcf';
00079         $metadata['channels'] = null;
00080         $metadata['bits'] = 8; # Always 8-bits per color
00081 
00082         assert( '7 == count($metadata); ' .
00083             '# return array must contains 7 elements just like getimagesize() return' );
00084 
00085         return $metadata;
00086     }
00087 
00098     static function getXCFMetaData( $filename ) {
00099         # Decode master structure
00100         $f = fopen( $filename, 'rb' );
00101         if ( !$f ) {
00102             return false;
00103         }
00104         # The image structure always starts at offset 0 in the XCF file.
00105         # So we just read it :-)
00106         $binaryHeader = fread( $f, 26 );
00107         fclose( $f );
00108 
00109         # Master image structure:
00110         #
00111         # byte[9] "gimp xcf "  File type magic
00112         # byte[4] version      XCF version
00113         #                        "file" - version 0
00114         #                        "v001" - version 1
00115         #                        "v002" - version 2
00116         # byte    0            Zero-terminator for version tag
00117         # uint32  width        With of canvas
00118         # uint32  height       Height of canvas
00119         # uint32  base_type    Color mode of the image; one of
00120         #                         0: RGB color
00121         #                         1: Grayscale
00122         #                         2: Indexed color
00123         #        (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
00124         try {
00125             $header = wfUnpack(
00126                 "A9magic" . # A: space padded
00127                     "/a5version" . # a: zero padded
00128                     "/Nwidth" . # \
00129                     "/Nheight" . # N: unsigned long 32bit big endian
00130                     "/Nbase_type", # /
00131                 $binaryHeader
00132             );
00133         } catch ( MWException $mwe ) {
00134             return false;
00135         }
00136 
00137         # Check values
00138         if ( $header['magic'] !== 'gimp xcf' ) {
00139             wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" );
00140 
00141             return false;
00142         }
00143         # TODO: we might want to check for sane values of width and height
00144 
00145         wfDebug( __METHOD__ .
00146             ": canvas size of '$filename' is {$header['width']} x {$header['height']} px\n" );
00147 
00148         return $header;
00149     }
00150 
00161     public function getMetadata( $file, $filename ) {
00162         $header = self::getXCFMetadata( $filename );
00163         $metadata = array();
00164         if ( $header ) {
00165             // Try to be consistent with the names used by PNG files.
00166             // Unclear from base media type if it has an alpha layer,
00167             // so just assume that it does since it "potentially" could.
00168             switch ( $header['base_type'] ) {
00169             case 0:
00170                 $metadata['colorType'] = 'truecolour-alpha';
00171                 break;
00172             case 1:
00173                 $metadata['colorType'] = 'greyscale-alpha';
00174                 break;
00175             case 2:
00176                 $metadata['colorType'] = 'index-coloured';
00177                 break;
00178             default:
00179                 $metadata['colorType'] = 'unknown';
00180 
00181             }
00182         } else {
00183             // Marker to prevent repeated attempted extraction
00184             $metadata['error'] = true;
00185         }
00186         return serialize( $metadata );
00187     }
00188 
00196     public function isMetadataValid( $file, $metadata ) {
00197         if ( !$metadata ) {
00198             // Old metadata when we just put an empty string in there
00199             return self::METADATA_BAD;
00200         } else {
00201             return self::METADATA_GOOD;
00202         }
00203     }
00204 
00212     protected function getScalerType( $dstPath, $checkDstPath = true ) {
00213         return "im";
00214     }
00215 
00224     public function canRender( $file ) {
00225         wfSuppressWarnings();
00226         $xcfMeta = unserialize( $file->getMetadata() );
00227         wfRestoreWarnings();
00228         if ( isset( $xcfMeta['colorType'] ) && $xcfMeta['colorType'] === 'index-coloured' ) {
00229             return false;
00230         }
00231         return parent::canRender( $file );
00232     }
00233 }