MagicWord: Fix an indent
[lhc/web/wiklou.git] / includes / media / XCF.php
index 837c855..41e6f03 100644 (file)
@@ -7,6 +7,21 @@
  * Specification in Gnome repository:
  *   http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup
  *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
  * @file
  * @ingroup Media
  */
  * @ingroup Media
  */
 class XCFHandler extends BitmapHandler {
+       /**
+        * @param File $file
+        * @return bool
+        */
+       function mustRender( $file ) {
+               return true;
+       }
 
        /**
         * Render files as PNG
         *
-        * @param $ext
-        * @param $mime
-        * @param $params
+        * @param string $ext
+        * @param string $mime
+        * @param array $params
         * @return array
         */
        function getThumbType( $ext, $mime, $params = null ) {
@@ -34,63 +56,89 @@ class XCFHandler extends BitmapHandler {
        /**
         * Get width and height from the XCF header.
         *
-        * @param $image
-        * @param $filename
+        * @param File $image
+        * @param string $filename
         * @return array
         */
        function getImageSize( $image, $filename ) {
                return self::getXCFMetaData( $filename );
        }
 
+       /**
+        * Metadata for a given XCF file
+        *
+        * Will return false if file magic signature is not recognized
+        * @author Hexmode
+        * @author Hashar
+        *
+        * @param string $filename Full path to a XCF file
+        * @return bool|array metadata array just like PHP getimagesize()
+        */
        static function getXCFMetaData( $filename ) {
-               global $wgImageMagickIdentifyCommand;
-
-               $cmd = wfEscapeShellArg( $wgImageMagickIdentifyCommand ) . ' -verbose ' . wfEscapeShellArg( $filename );
-               wfDebug( __METHOD__ . ": Running $cmd \n" );
-
-               $retval = null;
-               $return = wfShellExec( $cmd, $retval );
-               if( $retval !== 0 ) {
-                       wfDebug( __METHOD__ . ": error encountered while running $cmd\n" );
+               # Decode master structure
+               $f = fopen( $filename, 'rb' );
+               if ( !$f ) {
                        return false;
                }
+               # The image structure always starts at offset 0 in the XCF file.
+               # So we just read it :-)
+               $binaryHeader = fread( $f, 26 );
+               fclose( $f );
 
-               $colorspace = preg_match_all( '/ *Colorspace: RGB/', $return, $match );
-               $frameCount = preg_match_all( '/ *Geometry: ([0-9]+x[0-9]+)\+[+0-9]*/', $return, $match );
-               wfDebug( __METHOD__ . ": Got $frameCount matches\n" );
+               # Master image structure:
+               #
+               # byte[9] "gimp xcf "  File type magic
+               # byte[4] version      XCF version
+               #                        "file" - version 0
+               #                        "v001" - version 1
+               #                        "v002" - version 2
+               # byte    0            Zero-terminator for version tag
+               # uint32  width        With of canvas
+               # uint32  height       Height of canvas
+               # uint32  base_type    Color mode of the image; one of
+               #                         0: RGB color
+               #                         1: Grayscale
+               #                         2: Indexed color
+               #        (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
+               try {
+                       $header = wfUnpack(
+                               "A9magic" . # A: space padded
+                                       "/a5version" . # a: zero padded
+                                       "/Nwidth" . # \
+                                       "/Nheight" . # N: unsigned long 32bit big endian
+                                       "/Nbase_type", # /
+                               $binaryHeader
+                       );
+               } catch ( MWException $mwe ) {
+                       return false;
+               }
 
-               /* if( $frameCount == 1 ) { */
-               /*      preg_match( '/([0-9]+)x([0-9]+)/sm', $match[1][0], $m ); */
-               /*      $sizeX = $m[1]; */
-               /*      $sizeY = $m[2]; */
-               /* } else { */
-                       $sizeX = 0;
-                       $sizeY = 0;
+               # Check values
+               if ( $header['magic'] !== 'gimp xcf' ) {
+                       wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" );
 
-                       # Find out the largest width and height used in any frame
-                       foreach( $match[1] as $res ) {
-                               preg_match( '/([0-9]+)x([0-9]+)/sm', $res, $m );
-                               if( $m[1] > $sizeX ) {
-                                       $sizeX = $m[1];
-                               }
-                               if( $m[2] > $sizeY ) {
-                                       $sizeY = $m[2];
-                               }
-                       }
-               /* } */
+                       return false;
+               }
+               # TODO: we might want to check for sane values of width and height
 
-               wfDebug( __METHOD__ . ": Found $sizeX x $sizeY x $frameCount \n" );
+               wfDebug( __METHOD__ .
+                       ": canvas size of '$filename' is {$header['width']} x {$header['height']} px\n" );
 
                # Forge a return array containing metadata information just like getimagesize()
                # See PHP documentation at: http://www.php.net/getimagesize
                $metadata = array();
-               $metadata['frameCount'] = $frameCount;
-               $metadata[0] = $sizeX;
-               $metadata[1] = $sizeY;
-               $metadata[2] = null;
-               $metadata[3] = "height=\"$sizeY\" width=\"$sizeX\"";
+               $metadata[0] = $header['width'];
+               $metadata[1] = $header['height'];
+               $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
+               $metadata[3] = sprintf(
+                       'height="%s" width="%s"', $header['height'], $header['width']
+               );
                $metadata['mime'] = 'image/x-xcf';
-               $metadata['channels'] = $colorspace == 1 ? 3 : 4;
+               $metadata['channels'] = null;
+               $metadata['bits'] = 8; # Always 8-bits per color
+
+               assert( '7 == count($metadata); ' .
+                       '# return array must contains 7 elements just like getimagesize() return' );
 
                return $metadata;
        }
@@ -98,6 +146,8 @@ class XCFHandler extends BitmapHandler {
        /**
         * Must use "im" for XCF
         *
+        * @param string $dstPath
+        * @param bool $checkDstPath
         * @return string
         */
        protected static function getScalerType( $dstPath, $checkDstPath = true ) {