root/releases/elgg0.8rc2/lib/phpthumb/phpthumb.bmp.php

Revision 421, 36.5 kB (checked in by sven, 3 years ago)

icons: upgrade phpthumb to 1.7.2 and move it to lib/
change icons to be output through a function rather than the bundled phpThumb.php, to allow greater control over security

  • Property svn:eol-style set to native
Line 
1 <?php
2 /////////////////////////////////////////////////////////////////
3 /// getID3() by James Heinrich <info@getid3.org>               //
4 //  available at http://getid3.sourceforge.net                 //
5 //            or http://www.getid3.org                         //
6 /////////////////////////////////////////////////////////////////
7 // See readme.txt for more details                             //
8 /////////////////////////////////////////////////////////////////
9 //                                                             //
10 // module.graphic.bmp.php                                      //
11 // module for analyzing BMP Image files                        //
12 // dependencies: NONE                                          //
13 //                                                            ///
14 /////////////////////////////////////////////////////////////////
15 //                                                             //
16 // Modified for use in phpThumb() - James Heinrich 2004.07.27  //
17 //                                                             //
18 /////////////////////////////////////////////////////////////////
19
20
21 class phpthumb_bmp {
22
23     function phpthumb_bmp() {
24         return true;
25     }
26
27     function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) {
28         $ThisFileInfo = array();
29         if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) {
30             $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor);
31             return $gd;
32         }
33         return false;
34     }
35
36     function phpthumb_bmpfile2gd($filename, $truecolor=true) {
37         if ($fp = @fopen($filename, 'rb')) {
38             $BMPdata = fread($fp, filesize($filename));
39             fclose($fp);
40             return $this->phpthumb_bmp2gd($BMPdata, $truecolor);
41         }
42         return false;
43     }
44
45     function GD2BMPstring(&$gd_image) {
46         $imageX = ImageSX($gd_image);
47         $imageY = ImageSY($gd_image);
48
49         $BMP = '';
50         for ($y = ($imageY - 1); $y >= 0; $y--) {
51             $thisline = '';
52             for ($x = 0; $x < $imageX; $x++) {
53                 $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y);
54                 $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']);
55             }
56             while (strlen($thisline) % 4) {
57                 $thisline .= "\x00";
58             }
59             $BMP .= $thisline;
60         }
61
62         $bmpSize = strlen($BMP) + 14 + 40;
63         // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
64         $BITMAPFILEHEADER  = 'BM';                                                           // WORD    bfType;
65         $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD   bfSize;
66         $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String(       0, 2); // WORD    bfReserved1;
67         $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String(       0, 2); // WORD    bfReserved2;
68         $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String(      54, 4); // DWORD   bfOffBits;
69
70         // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
71         $BITMAPINFOHEADER  = phpthumb_functions::LittleEndian2String(      40, 4); // DWORD  biSize;
72         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG   biWidth;
73         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG   biHeight;
74         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(       1, 2); // WORD   biPlanes;
75         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(      24, 2); // WORD   biBitCount;
76         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(       0, 4); // DWORD  biCompression;
77         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(       0, 4); // DWORD  biSizeImage;
78         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(    2835, 4); // LONG   biXPelsPerMeter;
79         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(    2835, 4); // LONG   biYPelsPerMeter;
80         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(       0, 4); // DWORD  biClrUsed;
81         $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String(       0, 4); // DWORD  biClrImportant;
82
83         return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP;
84     }
85
86     function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) {
87
88         // shortcuts
89         $ThisFileInfo['bmp']['header']['raw'] = array();
90         $thisfile_bmp                         = &$ThisFileInfo['bmp'];
91         $thisfile_bmp_header                  = &$thisfile_bmp['header'];
92         $thisfile_bmp_header_raw              = &$thisfile_bmp_header['raw'];
93
94         // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
95         // all versions
96         // WORD    bfType;
97         // DWORD   bfSize;
98         // WORD    bfReserved1;
99         // WORD    bfReserved2;
100         // DWORD   bfOffBits;
101
102         $offset = 0;
103         $overalloffset = 0;
104         $BMPheader = substr($BMPdata, $overalloffset, 14 + 40);
105         $overalloffset += (14 + 40);
106
107         $thisfile_bmp_header_raw['identifier']  = substr($BMPheader, $offset, 2);
108         $offset += 2;
109
110         if ($thisfile_bmp_header_raw['identifier'] != 'BM') {
111             $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.intval(@$ThisFileInfo['avdataoffset']).', found "'.$thisfile_bmp_header_raw['identifier'].'"';
112             unset($ThisFileInfo['fileformat']);
113             unset($ThisFileInfo['bmp']);
114             return false;
115         }
116
117         $thisfile_bmp_header_raw['filesize']    = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
118         $offset += 4;
119         $thisfile_bmp_header_raw['reserved1']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
120         $offset += 2;
121         $thisfile_bmp_header_raw['reserved2']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
122         $offset += 2;
123         $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
124         $offset += 4;
125         $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
126         $offset += 4;
127
128
129         // check if the hardcoded-to-1 "planes" is at offset 22 or 26
130         $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2));
131         $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2));
132         if (($planes22 == 1) && ($planes26 != 1)) {
133             $thisfile_bmp['type_os']      = 'OS/2';
134             $thisfile_bmp['type_version'] = 1;
135         } elseif (($planes26 == 1) && ($planes22 != 1)) {
136             $thisfile_bmp['type_os']      = 'Windows';
137             $thisfile_bmp['type_version'] = 1;
138         } elseif ($thisfile_bmp_header_raw['header_size'] == 12) {
139             $thisfile_bmp['type_os']      = 'OS/2';
140             $thisfile_bmp['type_version'] = 1;
141         } elseif ($thisfile_bmp_header_raw['header_size'] == 40) {
142             $thisfile_bmp['type_os']      = 'Windows';
143             $thisfile_bmp['type_version'] = 1;
144         } elseif ($thisfile_bmp_header_raw['header_size'] == 84) {
145             $thisfile_bmp['type_os']      = 'Windows';
146             $thisfile_bmp['type_version'] = 4;
147         } elseif ($thisfile_bmp_header_raw['header_size'] == 100) {
148             $thisfile_bmp['type_os']      = 'Windows';
149             $thisfile_bmp['type_version'] = 5;
150         } else {
151             $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)';
152             unset($ThisFileInfo['fileformat']);
153             unset($ThisFileInfo['bmp']);
154             return false;
155         }
156
157         $ThisFileInfo['fileformat']                  = 'bmp';
158         $ThisFileInfo['video']['dataformat']         = 'bmp';
159         $ThisFileInfo['video']['lossless']           = true;
160         $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1;
161
162         if ($thisfile_bmp['type_os'] == 'OS/2') {
163
164             // OS/2-format BMP
165             // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm
166
167             // DWORD  Size;             /* Size of this structure in bytes */
168             // DWORD  Width;            /* Bitmap width in pixels */
169             // DWORD  Height;           /* Bitmap height in pixel */
170             // WORD   NumPlanes;        /* Number of bit planes (color depth) */
171             // WORD   BitsPerPixel;     /* Number of bits per pixel per plane */
172
173             $thisfile_bmp_header_raw['width']          = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
174             $offset += 2;
175             $thisfile_bmp_header_raw['height']         = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
176             $offset += 2;
177             $thisfile_bmp_header_raw['planes']         = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
178             $offset += 2;
179             $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
180             $offset += 2;
181
182             $ThisFileInfo['video']['resolution_x']    = $thisfile_bmp_header_raw['width'];
183             $ThisFileInfo['video']['resolution_y']    = $thisfile_bmp_header_raw['height'];
184             $ThisFileInfo['video']['codec']           = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit';
185             $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel'];
186
187             if ($thisfile_bmp['type_version'] >= 2) {
188                 // DWORD  Compression;      /* Bitmap compression scheme */
189                 // DWORD  ImageDataSize;    /* Size of bitmap data in bytes */
190                 // DWORD  XResolution;      /* X resolution of display device */
191                 // DWORD  YResolution;      /* Y resolution of display device */
192                 // DWORD  ColorsUsed;       /* Number of color table indices used */
193                 // DWORD  ColorsImportant;  /* Number of important color indices */
194                 // WORD   Units;            /* Type of units used to measure resolution */
195                 // WORD   Reserved;         /* Pad structure to 4-byte boundary */
196                 // WORD   Recording;        /* Recording algorithm */
197                 // WORD   Rendering;        /* Halftoning algorithm used */
198                 // DWORD  Size1;            /* Reserved for halftoning algorithm use */
199                 // DWORD  Size2;            /* Reserved for halftoning algorithm use */
200                 // DWORD  ColorEncoding;    /* Color model used in bitmap */
201                 // DWORD  Identifier;       /* Reserved for application use */
202
203                 $thisfile_bmp_header_raw['compression']      = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
204                 $offset += 4;
205                 $thisfile_bmp_header_raw['bmp_data_size']    = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
206                 $offset += 4;
207                 $thisfile_bmp_header_raw['resolution_h']     = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
208                 $offset += 4;
209                 $thisfile_bmp_header_raw['resolution_v']     = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
210                 $offset += 4;
211                 $thisfile_bmp_header_raw['colors_used']      = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
212                 $offset += 4;
213                 $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
214                 $offset += 4;
215                 $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
216                 $offset += 2;
217                 $thisfile_bmp_header_raw['reserved1']        = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
218                 $offset += 2;
219                 $thisfile_bmp_header_raw['recording']        = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
220                 $offset += 2;
221                 $thisfile_bmp_header_raw['rendering']        = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
222                 $offset += 2;
223                 $thisfile_bmp_header_raw['size1']            = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
224                 $offset += 4;
225                 $thisfile_bmp_header_raw['size2']            = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
226                 $offset += 4;
227                 $thisfile_bmp_header_raw['color_encoding']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
228                 $offset += 4;
229                 $thisfile_bmp_header_raw['identifier']       = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
230                 $offset += 4;
231
232                 $thisfile_bmp_header['compression']          = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']);
233
234                 $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit';
235             }
236
237         } elseif ($thisfile_bmp['type_os'] == 'Windows') {
238
239             // Windows-format BMP
240
241             // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
242             // all versions
243             // DWORD  biSize;
244             // LONG   biWidth;
245             // LONG   biHeight;
246             // WORD   biPlanes;
247             // WORD   biBitCount;
248             // DWORD  biCompression;
249             // DWORD  biSizeImage;
250             // LONG   biXPelsPerMeter;
251             // LONG   biYPelsPerMeter;
252             // DWORD  biClrUsed;
253             // DWORD  biClrImportant;
254
255             $thisfile_bmp_header_raw['width']            = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true);
256             $offset += 4;
257             $thisfile_bmp_header_raw['height']           = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true);
258             $offset += 4;
259             $thisfile_bmp_header_raw['planes']           = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
260             $offset += 2;
261             $thisfile_bmp_header_raw['bits_per_pixel']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 2));
262             $offset += 2;
263             $thisfile_bmp_header_raw['compression']      = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
264             $offset += 4;
265             $thisfile_bmp_header_raw['bmp_data_size']    = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
266             $offset += 4;
267             $thisfile_bmp_header_raw['resolution_h']     = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true);
268             $offset += 4;
269             $thisfile_bmp_header_raw['resolution_v']     = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true);
270             $offset += 4;
271             $thisfile_bmp_header_raw['colors_used']      = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
272             $offset += 4;
273             $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
274             $offset += 4;
275
276             $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']);
277             $ThisFileInfo['video']['resolution_x']    = $thisfile_bmp_header_raw['width'];
278             $ThisFileInfo['video']['resolution_y']    = $thisfile_bmp_header_raw['height'];
279             $ThisFileInfo['video']['codec']           = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit';
280             $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel'];
281
282             if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) {
283                 // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen
284                 $BMPheader .= substr($BMPdata, $overalloffset, 44);
285                 $overalloffset += 44;
286
287                 // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp
288                 // Win95+, WinNT4.0+
289                 // DWORD        bV4RedMask;
290                 // DWORD        bV4GreenMask;
291                 // DWORD        bV4BlueMask;
292                 // DWORD        bV4AlphaMask;
293                 // DWORD        bV4CSType;
294                 // CIEXYZTRIPLE bV4Endpoints;
295                 // DWORD        bV4GammaRed;
296                 // DWORD        bV4GammaGreen;
297                 // DWORD        bV4GammaBlue;
298                 $thisfile_bmp_header_raw['red_mask']     = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
299                 $offset += 4;
300                 $thisfile_bmp_header_raw['green_mask']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
301                 $offset += 4;
302                 $thisfile_bmp_header_raw['blue_mask']    = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
303                 $offset += 4;
304                 $thisfile_bmp_header_raw['alpha_mask']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
305                 $offset += 4;
306                 $thisfile_bmp_header_raw['cs_type']      = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
307                 $offset += 4;
308                 $thisfile_bmp_header_raw['ciexyz_red']   =                         substr($BMPheader, $offset, 4);
309                 $offset += 4;
310                 $thisfile_bmp_header_raw['ciexyz_green'] =                         substr($BMPheader, $offset, 4);
311                 $offset += 4;
312                 $thisfile_bmp_header_raw['ciexyz_blue']  =                         substr($BMPheader, $offset, 4);
313                 $offset += 4;
314                 $thisfile_bmp_header_raw['gamma_red']    = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
315                 $offset += 4;
316                 $thisfile_bmp_header_raw['gamma_green']  = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
317                 $offset += 4;
318                 $thisfile_bmp_header_raw['gamma_blue']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
319                 $offset += 4;
320
321                 $thisfile_bmp_header['ciexyz_red']   = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_red']));
322                 $thisfile_bmp_header['ciexyz_green'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_green']));
323                 $thisfile_bmp_header['ciexyz_blue']  = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_blue']));
324             }
325
326             if ($thisfile_bmp['type_version'] >= 5) {
327                 $BMPheader .= substr($BMPdata, $overalloffset, 16);
328                 $overalloffset += 16;
329
330                 // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp
331                 // Win98+, Win2000+
332                 // DWORD        bV5Intent;
333                 // DWORD        bV5ProfileData;
334                 // DWORD        bV5ProfileSize;
335                 // DWORD        bV5Reserved;
336                 $thisfile_bmp_header_raw['intent']              = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
337                 $offset += 4;
338                 $thisfile_bmp_header_raw['profile_data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));
339                 $offset += 4;
340                 $thisfile_bmp_header_raw['profile_data_size']   = $this->LittleEndian2Int(substr($BMPheader, $offset, 4));