From: Antoine Musso Date: Thu, 5 Jan 2012 14:48:55 +0000 (+0000) Subject: rewrite getXCFMetaData() to get ride of im identify X-Git-Tag: 1.31.0-rc.0~25510 X-Git-Url: http://git.cyclocoop.org/%24self?a=commitdiff_plain;h=1b82b6dc2384fe49903c480ea0a1f9427ce94e10;p=lhc%2Fweb%2Fwiklou.git rewrite getXCFMetaData() to get ride of im identify By reading the file header and unpacking the data, we can avoid shelling out to imagemagick 'identify'. Save up some CPU cycles :D An XCF is made of a canvas of a given width / height, the various layers are applied to it which must fit in the canvas. So we just use the canvas size :-) I do not think we have any usage for channels count, so I have just skip that part. I am not sure it makes any sense when the picture can be made of several layers each using different channels count. Bits per color is always 8 per definition. Grayscale is 0 - 255 and indexed palette is 256 colors at most. XCF spec: http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup pack() / unpack() is familiar to perl monkeys Fully reimplements r107351 --- diff --git a/includes/media/XCF.php b/includes/media/XCF.php index 837c8554dd..c72927b9b8 100644 --- a/includes/media/XCF.php +++ b/includes/media/XCF.php @@ -42,55 +42,75 @@ class XCFHandler extends BitmapHandler { 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 $filename String Full path to a XCF file + * @return false|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" ); - - /* 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; + # 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) + $header = unpack( + "A9magic" # A: space padded + . "/a5version" # a: zero padded + . "/Nwidth" # \ + . "/Nheight" # N: unsigned long 32bit big endian + . "/Nbase_type" # / + , $binaryHeader + ); - # 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]; - } - } - /* } */ + # Check values + if( $header['magic'] !== 'gimp xcf' ) { + var_dump( $header ); + wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" ); + 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; }