]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/media/XCF.php
MediaWiki 1.30.2-scripts2
[autoinstalls/mediawiki.git] / includes / media / XCF.php
1 <?php
2 /**
3  * Handler for the Gimp's native file format (XCF)
4  *
5  * Overview:
6  *   https://en.wikipedia.org/wiki/XCF_(file_format)
7  * Specification in Gnome repository:
8  *   http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  * http://www.gnu.org/copyleft/gpl.html
24  *
25  * @file
26  * @ingroup Media
27  */
28
29 /**
30  * Handler for the Gimp's native file format; getimagesize() doesn't
31  * support these files
32  *
33  * @ingroup Media
34  */
35 class XCFHandler extends BitmapHandler {
36         /**
37          * @param File $file
38          * @return bool
39          */
40         public function mustRender( $file ) {
41                 return true;
42         }
43
44         /**
45          * Render files as PNG
46          *
47          * @param string $ext
48          * @param string $mime
49          * @param array $params
50          * @return array
51          */
52         function getThumbType( $ext, $mime, $params = null ) {
53                 return [ 'png', 'image/png' ];
54         }
55
56         /**
57          * Get width and height from the XCF header.
58          *
59          * @param File|FSFile $image
60          * @param string $filename
61          * @return array
62          */
63         function getImageSize( $image, $filename ) {
64                 $header = self::getXCFMetaData( $filename );
65                 if ( !$header ) {
66                         return false;
67                 }
68
69                 # Forge a return array containing metadata information just like getimagesize()
70                 # See PHP documentation at: https://secure.php.net/getimagesize
71                 return [
72                         0 => $header['width'],
73                         1 => $header['height'],
74                         2 => null, # IMAGETYPE constant, none exist for XCF.
75                         3 => "height=\"{$header['height']}\" width=\"{$header['width']}\"",
76                         'mime' => 'image/x-xcf',
77                         'channels' => null,
78                         'bits' => 8, # Always 8-bits per color
79                 ];
80         }
81
82         /**
83          * Metadata for a given XCF file
84          *
85          * Will return false if file magic signature is not recognized
86          * @author Hexmode
87          * @author Hashar
88          *
89          * @param string $filename Full path to a XCF file
90          * @return bool|array Metadata Array just like PHP getimagesize()
91          */
92         static function getXCFMetaData( $filename ) {
93                 # Decode master structure
94                 $f = fopen( $filename, 'rb' );
95                 if ( !$f ) {
96                         return false;
97                 }
98                 # The image structure always starts at offset 0 in the XCF file.
99                 # So we just read it :-)
100                 $binaryHeader = fread( $f, 26 );
101                 fclose( $f );
102
103                 /**
104                  * Master image structure:
105                  *
106                  * byte[9] "gimp xcf "  File type magic
107                  * byte[4] version      XCF version
108                  *                        "file" - version 0
109                  *                        "v001" - version 1
110                  *                        "v002" - version 2
111                  * byte    0            Zero-terminator for version tag
112                  * uint32  width        With of canvas
113                  * uint32  height       Height of canvas
114                  * uint32  base_type    Color mode of the image; one of
115                  *                         0: RGB color
116                  *                         1: Grayscale
117                  *                         2: Indexed color
118                  *        (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
119                  */
120                 try {
121                         $header = wfUnpack(
122                                 "A9magic" . # A: space padded
123                                         "/a5version" . # a: zero padded
124                                         "/Nwidth" . # \
125                                         "/Nheight" . # N: unsigned long 32bit big endian
126                                         "/Nbase_type", # /
127                                 $binaryHeader
128                         );
129                 } catch ( Exception $mwe ) {
130                         return false;
131                 }
132
133                 # Check values
134                 if ( $header['magic'] !== 'gimp xcf' ) {
135                         wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" );
136
137                         return false;
138                 }
139                 # TODO: we might want to check for sane values of width and height
140
141                 wfDebug( __METHOD__ .
142                         ": canvas size of '$filename' is {$header['width']} x {$header['height']} px\n" );
143
144                 return $header;
145         }
146
147         /**
148          * Store the channel type
149          *
150          * Greyscale files need different command line options.
151          *
152          * @param File|FSFile $file The image object, or false if there isn't one.
153          *   Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!)
154          * @param string $filename The filename
155          * @return string
156          */
157         public function getMetadata( $file, $filename ) {
158                 $header = self::getXCFMetaData( $filename );
159                 $metadata = [];
160                 if ( $header ) {
161                         // Try to be consistent with the names used by PNG files.
162                         // Unclear from base media type if it has an alpha layer,
163                         // so just assume that it does since it "potentially" could.
164                         switch ( $header['base_type'] ) {
165                         case 0:
166                                 $metadata['colorType'] = 'truecolour-alpha';
167                                 break;
168                         case 1:
169                                 $metadata['colorType'] = 'greyscale-alpha';
170                                 break;
171                         case 2:
172                                 $metadata['colorType'] = 'index-coloured';
173                                 break;
174                         default:
175                                 $metadata['colorType'] = 'unknown';
176
177                         }
178                 } else {
179                         // Marker to prevent repeated attempted extraction
180                         $metadata['error'] = true;
181                 }
182                 return serialize( $metadata );
183         }
184
185         /**
186          * Should we refresh the metadata
187          *
188          * @param File $file The file object for the file in question
189          * @param string $metadata Serialized metadata
190          * @return bool One of the self::METADATA_(BAD|GOOD|COMPATIBLE) constants
191          */
192         public function isMetadataValid( $file, $metadata ) {
193                 if ( !$metadata ) {
194                         // Old metadata when we just put an empty string in there
195                         return self::METADATA_BAD;
196                 } else {
197                         return self::METADATA_GOOD;
198                 }
199         }
200
201         /**
202          * Must use "im" for XCF
203          *
204          * @param string $dstPath
205          * @param bool $checkDstPath
206          * @return string
207          */
208         protected function getScalerType( $dstPath, $checkDstPath = true ) {
209                 return "im";
210         }
211
212         /**
213          * Can we render this file?
214          *
215          * Image magick doesn't support indexed xcf files as of current
216          * writing (as of 6.8.9-3)
217          * @param File $file
218          * @return bool
219          */
220         public function canRender( $file ) {
221                 MediaWiki\suppressWarnings();
222                 $xcfMeta = unserialize( $file->getMetadata() );
223                 MediaWiki\restoreWarnings();
224                 if ( isset( $xcfMeta['colorType'] ) && $xcfMeta['colorType'] === 'index-coloured' ) {
225                         return false;
226                 }
227                 return parent::canRender( $file );
228         }
229 }