Test Failed
Push — master ( 398493...d4ef72 )
by Michael
11:04
created

phpthumb_bmp::BigEndian2Bin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
371
						// no padding byte
372
					} else {
373
						$paletteoffset++; // padding byte
374
					}
375
					$thisfile_bmp['palette'][$i] = (($red << 16) | ($green << 8) | ($blue));
376
				}
377
			}
378
		}
379
380
		if ($ExtractData) {
381
			$RowByteLength = ceil(($thisfile_bmp_header_raw['width'] * ($thisfile_bmp_header_raw['bits_per_pixel'] / 8)) / 4) * 4; // round up to nearest DWORD boundary
382
383
			$BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], $thisfile_bmp_header_raw['height'] * $RowByteLength);
0 ignored issues
show
Bug introduced by
$thisfile_bmp_header_raw...ight'] * $RowByteLength of type double is incompatible with the type integer expected by parameter $length of substr(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

383
			$BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], /** @scrutinizer ignore-type */ $thisfile_bmp_header_raw['height'] * $RowByteLength);
Loading history...
384
			$overalloffset = $thisfile_bmp_header_raw['data_offset'] + ($thisfile_bmp_header_raw['height'] * $RowByteLength);
0 ignored issues
show
Unused Code introduced by
The assignment to $overalloffset is dead and can be removed.
Loading history...
385
386
			$pixeldataoffset = 0;
387
			switch (@$thisfile_bmp_header_raw['compression']) {
388
389
				case 0: // BI_RGB
390
					switch ($thisfile_bmp_header_raw['bits_per_pixel']) {
391
						case 1:
392
							for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
393
								for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) {
394
									$paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++});
395
									for ($i = 7; $i >= 0; $i--) {
396
										$paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i;
397
										$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
398
										$col++;
399
									}
400
								}
401
								while (($pixeldataoffset % 4) != 0) {
402
									// lines are padded to nearest DWORD
403
									$pixeldataoffset++;
404
								}
405
							}
406
							break;
407
408
						case 4:
409
							for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
410
								for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) {
411
									$paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++});
412
									for ($i = 1; $i >= 0; $i--) {
413
										$paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i);
414
										$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
415
										$col++;
416
									}
417
								}
418
								while (($pixeldataoffset % 4) != 0) {
419
									// lines are padded to nearest DWORD
420
									$pixeldataoffset++;
421
								}
422
							}
423
							break;
424
425
						case 8:
426
							for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
427
								for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
428
									$paletteindex = ord($BMPpixelData{$pixeldataoffset++});
429
									$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
430
								}
431
								while (($pixeldataoffset % 4) != 0) {
432
									// lines are padded to nearest DWORD
433
									$pixeldataoffset++;
434
								}
435
							}
436
							break;
437
438
						case 24:
439
							for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
440
								for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
441
									$thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset});
442
									$pixeldataoffset += 3;
443
								}
444
								while (($pixeldataoffset % 4) != 0) {
445
									// lines are padded to nearest DWORD
446
									$pixeldataoffset++;
447
								}
448
							}
449
							break;
450
451
						case 32:
452
							for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
453
								for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
454
									$thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset});
455
									$pixeldataoffset += 4;
456
								}
457
								while (($pixeldataoffset % 4) != 0) {
458
									// lines are padded to nearest DWORD
459
									$pixeldataoffset++;
460
								}
461
							}
462
							break;
463
464
						case 16:
465
							// ?
466
							break;
467
468
						default:
469
							$ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data';
470
							break;
471
					}
472
					break;
473
474
475
				case 1: // BI_RLE8 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp
476
					switch ($thisfile_bmp_header_raw['bits_per_pixel']) {
477
						case 8:
478
							$pixelcounter = 0;
479
							while ($pixeldataoffset < strlen($BMPpixelData)) {
480
								$firstbyte  = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
481
								$secondbyte = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
482
								if ($firstbyte == 0) {
483
484
									// escaped/absolute mode - the first byte of the pair can be set to zero to
485
									// indicate an escape character that denotes the end of a line, the end of
486
									// a bitmap, or a delta, depending on the value of the second byte.
487
									switch ($secondbyte) {
488
										case 0:
489
											// end of line
490
											// no need for special processing, just ignore
491
											break;
492
493
										case 1:
494
											// end of bitmap
495
											$pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case
496
											break;
497
498
										case 2:
499
											// delta - The 2 bytes following the escape contain unsigned values
500
											// indicating the horizontal and vertical offsets of the next pixel
501
											// from the current position.
502
											$colincrement = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
503
											$rowincrement = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
504
											$col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement;
505
											$row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement;
506
											$pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col;
507
											break;
508
509
										default:
510
											// In absolute mode, the first byte is zero and the second byte is a
511
											// value in the range 03H through FFH. The second byte represents the
512
											// number of bytes that follow, each of which contains the color index
513
											// of a single pixel. Each run must be aligned on a word boundary.
514
											for ($i = 0; $i < $secondbyte; $i++) {
515
												$paletteindex = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
516
												$col = $pixelcounter % $thisfile_bmp_header_raw['width'];
517
												$row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']);
518
												$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
519
												$pixelcounter++;
520
											}
521
											while (($pixeldataoffset % 2) != 0) {
522
												// Each run must be aligned on a word boundary.
523
												$pixeldataoffset++;
524
											}
525
											break;
526
									}
527
528
								} else {
529
530
									// encoded mode - the first byte specifies the number of consecutive pixels
531
									// to be drawn using the color index contained in the second byte.
532
									for ($i = 0; $i < $firstbyte; $i++) {
533
										$col = $pixelcounter % $thisfile_bmp_header_raw['width'];
534
										$row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']);
535
										$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$secondbyte];
536
										$pixelcounter++;
537
									}
538
539
								}
540
							}
541
							break;
542
543
						default:
544
							$ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data';
545
							break;
546
					}
547
					break;
548
549
550
551
				case 2: // BI_RLE4 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp
552
					switch ($thisfile_bmp_header_raw['bits_per_pixel']) {
553
						case 4:
554
							$pixelcounter = 0;
555
							while ($pixeldataoffset < strlen($BMPpixelData)) {
556
								$firstbyte  = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
557
								$secondbyte = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
558
								if ($firstbyte == 0) {
559
560
									// escaped/absolute mode - the first byte of the pair can be set to zero to
561
									// indicate an escape character that denotes the end of a line, the end of
562
									// a bitmap, or a delta, depending on the value of the second byte.
563
									switch ($secondbyte) {
564
										case 0:
565
											// end of line
566
											// no need for special processing, just ignore
567
											break;
568
569
										case 1:
570
											// end of bitmap
571
											$pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case
572
											break;
573
574
										case 2:
575
											// delta - The 2 bytes following the escape contain unsigned values
576
											// indicating the horizontal and vertical offsets of the next pixel
577
											// from the current position.
578
											$colincrement = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
579
											$rowincrement = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
580
											$col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement;
581
											$row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement;
582
											$pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col;
583
											break;
584
585
										default:
586
											// In absolute mode, the first byte is zero. The second byte contains the number
587
											// of color indexes that follow. Subsequent bytes contain color indexes in their
588
											// high- and low-order 4 bits, one color index for each pixel. In absolute mode,
589
											// each run must be aligned on a word boundary.
590
											$paletteindexes = array();
591
											for ($i = 0, $iMax = ceil($secondbyte / 2); $i < $iMax; $i++) {
592
												$paletteindexbyte = $this->LittleEndian2Int($BMPpixelData[ $pixeldataoffset++ ]);
593
												$paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4;
594
												$paletteindexes[] = ($paletteindexbyte & 0x0F);
595
											}
596
											while (($pixeldataoffset % 2) != 0) {
597
												// Each run must be aligned on a word boundary.
598
												$pixeldataoffset++;
599
											}
600
601
											foreach ($paletteindexes as $dummy => $paletteindex) {
602
												$col = $pixelcounter % $thisfile_bmp_header_raw['width'];
603
												$row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']);
604
												$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
605
												$pixelcounter++;
606
											}
607
											break;
608
									}
609
610
								} else {
611
612
									// encoded mode - the first byte of the pair contains the number of pixels to be
613
									// drawn using the color indexes in the second byte. The second byte contains two
614
									// color indexes, one in its high-order 4 bits and one in its low-order 4 bits.
615
									// The first of the pixels is drawn using the color specified by the high-order
616
									// 4 bits, the second is drawn using the color in the low-order 4 bits, the third
617
									// is drawn using the color in the high-order 4 bits, and so on, until all the
618
									// pixels specified by the first byte have been drawn.
619
									$paletteindexes[0] = ($secondbyte & 0xF0) >> 4;
620
									$paletteindexes[1] = ($secondbyte & 0x0F);
621
									for ($i = 0; $i < $firstbyte; $i++) {
622
										$col = $pixelcounter % $thisfile_bmp_header_raw['width'];
623
										$row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']);
624
										$thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindexes[($i % 2)]];
625
										$pixelcounter++;
626
									}
627
628
								}
629
							}
630
							break;
631
632
						default:
633
							$ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data';
634
							break;
635
					}
636
					break;
637
638
639
				case 3: // BI_BITFIELDS
640
					switch ($thisfile_bmp_header_raw['bits_per_pixel']) {
641
						case 16:
642
						case 32:
643
							$redshift   = 0;
644
							$greenshift = 0;
645
							$blueshift  = 0;
646
							if (!$thisfile_bmp_header_raw['red_mask'] || !$thisfile_bmp_header_raw['green_mask'] || !$thisfile_bmp_header_raw['blue_mask']) {
647
								$ThisFileInfo['error'][] = 'missing $thisfile_bmp_header_raw[(red|green|blue)_mask]';
648
								return false;
649
							}
650
							while ((($thisfile_bmp_header_raw['red_mask'] >> $redshift) & 0x01) == 0) {
651
								$redshift++;
652
							}
653
							while ((($thisfile_bmp_header_raw['green_mask'] >> $greenshift) & 0x01) == 0) {
654
								$greenshift++;
655
							}
656
							while ((($thisfile_bmp_header_raw['blue_mask'] >> $blueshift) & 0x01) == 0) {
657
								$blueshift++;
658
							}
659
							for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
660
								for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
661
									$pixelvalue = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset, $thisfile_bmp_header_raw['bits_per_pixel'] / 8));
662
									$pixeldataoffset += $thisfile_bmp_header_raw['bits_per_pixel'] / 8;
663
664
									$red   = (int) round(((($pixelvalue & $thisfile_bmp_header_raw[ 'red_mask'])   >> $redshift)   / ($thisfile_bmp_header_raw[ 'red_mask']   >> $redshift))   * 255);
665
									$green = (int) round(((($pixelvalue & $thisfile_bmp_header_raw[ 'green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw[ 'green_mask'] >> $greenshift)) * 255);
666
									$blue  = (int) round(((($pixelvalue & $thisfile_bmp_header_raw[ 'blue_mask'])  >> $blueshift)  / ($thisfile_bmp_header_raw[ 'blue_mask']  >> $blueshift))  * 255);
667
									$thisfile_bmp['data'][$row][$col] = (($red << 16) | ($green << 8) | ($blue));
668
								}
669
								while (($pixeldataoffset % 4) != 0) {
670
									// lines are padded to nearest DWORD
671
									$pixeldataoffset++;
672
								}
673
							}
674
							break;
675
676
						default:
677
							$ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data';
678
							break;
679
					}
680
					break;
681
682
683
				default: // unhandled compression type
684
					$ThisFileInfo['error'][] = 'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw['compression'].') - cannot decompress pixel data';
685
					break;
686
			}
687
		}
688
689
		return true;
690
	}
691
692
	public function IntColor2RGB($color) {
693
		$red   = ($color & 0x00FF0000) >> 16;
694
		$green = ($color & 0x0000FF00) >> 8;
695
		$blue  = ($color & 0x000000FF);
696
		return array($red, $green, $blue);
697
	}
698
699
	public function PlotPixelsGD(&$BMPdata, $truecolor=true) {
700
		$imagewidth  = $BMPdata['header']['raw']['width'];
701
		$imageheight = $BMPdata['header']['raw']['height'];
702
703
		if ($truecolor) {
704
705
			$gd = @imagecreatetruecolor($imagewidth, $imageheight);
706
707
		} else {
708
709
			$gd = @imagecreate($imagewidth, $imageheight);
710
			if (!empty($BMPdata['palette'])) {
711
				// create GD palette from BMP palette
712
				foreach ($BMPdata['palette'] as $dummy => $color) {
713
					list($r, $g, $b) = $this->IntColor2RGB($color);
714
					imagecolorallocate($gd, $r, $g, $b);
715
				}
716
			} else {
717
				// create 216-color websafe palette
718
				for ($r = 0x00; $r <= 0xFF; $r += 0x33) {
719
					for ($g = 0x00; $g <= 0xFF; $g += 0x33) {
720
						for ($b = 0x00; $b <= 0xFF; $b += 0x33) {
721
							imagecolorallocate($gd, $r, $g, $b);
722
						}
723
					}
724
				}
725
			}
726
727
		}
728
		if (!is_resource($gd)) {
729
			return false;
730
		}
731
732
		foreach ($BMPdata['data'] as $row => $colarray) {
733
			if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
734
				set_time_limit(30);
735
			}
736
			foreach ($colarray as $col => $color) {
737
				list($red, $green, $blue) = $this->IntColor2RGB($color);
738
				if ($truecolor) {
739
					$pixelcolor = imagecolorallocate($gd, $red, $green, $blue);
740
				} else {
741
					$pixelcolor = imagecolorclosest($gd, $red, $green, $blue);
742
				}
743
				imagesetpixel($gd, $col, $row, $pixelcolor);
744
			}
745
		}
746
		return $gd;
747
	}
748
749
	public function PlotBMP(&$BMPinfo) {
750
		$starttime = time();
751
		if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) {
752
			echo 'ERROR: no pixel data<BR>';
753
			return false;
754
		}
755
		if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
756
			set_time_limit((int) round($BMPinfo[ 'resolution_x'] * $BMPinfo[ 'resolution_y'] / 10000));
757
		}
758
		$im = $this->PlotPixelsGD($BMPinfo['bmp']);
759
		if (headers_sent()) {
760
			echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds<BR>';
761
			imagedestroy($im);
0 ignored issues
show
Bug introduced by
It seems like $im can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

761
			imagedestroy(/** @scrutinizer ignore-type */ $im);
Loading history...
762
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
763
		}
764
		header('Content-Type: image/png');
765
		imagepng($im);
0 ignored issues
show
Bug introduced by
It seems like $im can also be of type false; however, parameter $image of imagepng() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

765
		imagepng(/** @scrutinizer ignore-type */ $im);
Loading history...
766
		imagedestroy($im);
767
		return true;
768
	}
769
770
	public function BMPcompressionWindowsLookup($compressionid) {
771
		static $BMPcompressionWindowsLookup = array(
772
			0 => 'BI_RGB',
773
			1 => 'BI_RLE8',
774
			2 => 'BI_RLE4',
775
			3 => 'BI_BITFIELDS',
776
			4 => 'BI_JPEG',
777
			5 => 'BI_PNG'
778
		);
779
		return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid');
780
	}
781
782
	public function BMPcompressionOS2Lookup($compressionid) {
783
		static $BMPcompressionOS2Lookup = array(
784
			0 => 'BI_RGB',
785
			1 => 'BI_RLE8',
786
			2 => 'BI_RLE4',
787
			3 => 'Huffman 1D',
788
			4 => 'BI_RLE24',
789
		);
790
		return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] : 'invalid');
791
	}
792
793
794
	// from getid3.lib.php
795
796
	public function trunc($floatnumber) {
797
		// truncates a floating-point number at the decimal point
798
		// returns int (if possible, otherwise float)
799
		if ($floatnumber >= 1) {
800
			$truncatednumber = floor($floatnumber);
801
		} elseif ($floatnumber <= -1) {
802
			$truncatednumber = ceil($floatnumber);
803
		} else {
804
			$truncatednumber = 0;
805
		}
806
		if ($truncatednumber <= 1073741824) { // 2^30
807
			$truncatednumber = (int) $truncatednumber;
808
		}
809
		return $truncatednumber;
810
	}
811
812
	public function LittleEndian2Int($byteword) {
813
		$intvalue = 0;
814
		$byteword = strrev($byteword);
815
		$bytewordlen = strlen($byteword);
816
		for ($i = 0; $i < $bytewordlen; $i++) {
817
			$intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
818
		}
819
		return $intvalue;
820
	}
821
822
	public function BigEndian2Int($byteword) {
823
		return $this->LittleEndian2Int(strrev($byteword));
824
	}
825
826
	public function BigEndian2Bin($byteword) {
827
		$binvalue = '';
828
		$bytewordlen = strlen($byteword);
829
		for ($i = 0; $i < $bytewordlen; $i++) {
830
			$binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
831
		}
832
		return $binvalue;
833
	}
834
835
	public function FixedPoint2_30($rawdata) {
836
		$binarystring = $this->BigEndian2Bin($rawdata);
837
		return $this->Bin2Dec(substr($binarystring, 0, 2)) + (float) ($this->Bin2Dec(substr($binarystring, 2, 30)) / 1073741824);
838
	}
839
840
	public function Bin2Dec($binstring, $signed=false) {
841
		$signmult = 1;
842
		if ($signed) {
843
			if ($binstring{0} == '1') {
844
				$signmult = -1;
845
			}
846
			$binstring = substr($binstring, 1);
847
		}
848
		$decvalue = 0;
849
		for ($i = 0, $iMax = strlen($binstring); $i < $iMax; $i++) {
850
			$decvalue += ((int) $binstring[ strlen($binstring) - $i - 1 ]) * pow(2, $i);
851
		}
852
		return $this->CastAsInt($decvalue * $signmult);
853
	}
854
855
	public function CastAsInt($floatnum) {
856
		// convert to float if not already
857
		$floatnum = (float) $floatnum;
858
859
		// convert a float to type int, only if possible
860
		if ($this->trunc($floatnum) == $floatnum) {
861
			// it's not floating point
862
			if ($floatnum <= 1073741824) { // 2^30
863
				// it's within int range
864
				$floatnum = (int) $floatnum;
865
			}
866
		}
867
		return $floatnum;
868
	}
869
870
}
871