Passed
Push — master ( b5dddf...91d417 )
by Richard
09:12
created

BMP::dword()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
	/**
4
##DOC-SIGNATURE##
5
6
    This file is part of WideImage.
7
8
    WideImage is free software; you can redistribute it and/or modify
9
    it under the terms of the GNU Lesser General Public License as published by
10
    the Free Software Foundation; either version 2.1 of the License, or
11
    (at your option) any later version.
12
13
    WideImage is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU Lesser General Public License for more details.
17
18
    You should have received a copy of the GNU Lesser General Public License
19
    along with WideImage; if not, write to the Free Software
20
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22
    * @package Internal/Mappers
23
  **/
24
25
/**
26
 * External code for BMP
27
 *
28
 * Adapted for use in WideImage. Code used with permission from the original author de77.
29
 * http://de77.com/php/read-and-write-bmp-in-php-imagecreatefrombmp-imagebmp
30
 *
31
 * @author de77
32
 * @license MIT
33
 * @url de77.com
34
 * @version 21.08.2010
35
 *
36
 * @package Internal/Mappers
37
 */
38
39
namespace WideImage\vendor\de77;
40
41
class BMP
42
{
43
	public static function imagebmp(&$img, $filename = false)
44
	{
45
		$wid     = imagesx($img);
46
		$hei     = imagesy($img);
47
		$wid_pad = str_pad('', $wid % 4, "\0");
48
49
		$size = 54 + ($wid + $wid_pad) * $hei * 3; //fixed
50
51
		//prepare & save header
52
		$header['identifier']		= 'BM';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$header was never initialized. Although not strictly required by PHP, it is generally a good practice to add $header = array(); before regardless.
Loading history...
53
		$header['file_size']		= self::dword($size);
54
		$header['reserved']			= self::dword(0);
55
		$header['bitmap_data']		= self::dword(54);
56
		$header['header_size']		= self::dword(40);
57
		$header['width']			= self::dword($wid);
58
		$header['height']			= self::dword($hei);
59
		$header['planes']			= self::word(1);
60
		$header['bits_per_pixel']	= self::word(24);
61
		$header['compression']		= self::dword(0);
62
		$header['data_size']		= self::dword(0);
63
		$header['h_resolution']		= self::dword(0);
64
		$header['v_resolution']		= self::dword(0);
65
		$header['colors']			= self::dword(0);
66
		$header['important_colors']	= self::dword(0);
67
68
		if ($filename) {
69
		    $f = fopen($filename, "wb");
70
71
		    foreach ($header as $h) {
72
		    	fwrite($f, $h);
0 ignored issues
show
Bug introduced by
It seems like $f can also be of type false; however, parameter $handle of fwrite() 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

72
		    	fwrite(/** @scrutinizer ignore-type */ $f, $h);
Loading history...
73
		    }
74
75
			//save pixels
76
			for ($y = $hei-1; $y >= 0; $y--) {
77
				for ($x = 0; $x < $wid; $x++) {
78
					$rgb = imagecolorat($img, $x, $y);
79
					fwrite($f, self::byte3($rgb));
80
				}
81
82
				fwrite($f, $wid_pad);
83
			}
84
85
			fclose($f);
0 ignored issues
show
Bug introduced by
It seems like $f can also be of type false; however, parameter $handle of fclose() 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

85
			fclose(/** @scrutinizer ignore-type */ $f);
Loading history...
86
		} else {
87
		    foreach ($header as $h) {
88
		    	echo $h;
89
		    }
90
91
			//save pixels
92
			for ($y = $hei-1; $y >= 0; $y--) {
93
				for ($x = 0; $x < $wid; $x++) {
94
					$rgb = imagecolorat($img, $x, $y);
95
					echo self::byte3($rgb);
96
				}
97
98
				echo $wid_pad;
99
			}
100
		}
101
102
		return true;
103
	}
104
105
	public static function imagecreatefromstring($data)
106
	{
107
		//read header
108
		$pos    = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $pos is dead and can be removed.
Loading history...
109
		$header = substr($data, 0, 54);
110
		$pos    = 54;
111
112
		if (strlen($header) < 54) {
113
			return false;
114
		}
115
116
	    $header = unpack(	'c2identifier/Vfile_size/Vreserved/Vbitmap_data/Vheader_size/' .
117
							'Vwidth/Vheight/vplanes/vbits_per_pixel/Vcompression/Vdata_size/'.
118
							'Vh_resolution/Vv_resolution/Vcolors/Vimportant_colors', $header);
119
120
	    if ($header['identifier1'] != 66 or $header['identifier2'] != 77) {
121
	    	return false;
122
	    }
123
124
	    if (!in_array($header['bits_per_pixel'], array(24, 32, 8, 4, 1))) {
125
	    	return false;
126
	    }
127
128
		$bps    = $header['bits_per_pixel']; //bits per pixel
129
	    $wid2   = ceil(($bps/8 * $header['width']) / 4) * 4;
130
		$colors = $header['colors'];
131
132
	    $wid = $header['width'];
133
	    $hei = $header['height'];
134
135
	    $img = imagecreatetruecolor($header['width'], $header['height']);
136
137
		//read palette
138
		if ($bps < 9) {
139
			for ($i = 0; $i < $colors; $i++) {
140
				$palette[] = self::undword(substr($data, $pos, 4));
141
				$pos += 4;
142
			}
143
		} else {
144
			if ($bps == 32) {
145
				imagealphablending($img, false);
146
				imagesavealpha($img, true);
147
			}
148
149
			$palette = array();
150
		}
151
152
		//read pixels
153
	    for ($y = $hei-1; $y >= 0; $y--) {
154
			$row    = substr($data, $pos, $wid2);
0 ignored issues
show
Bug introduced by
$wid2 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

154
			$row    = substr($data, $pos, /** @scrutinizer ignore-type */ $wid2);
Loading history...
155
			$pos   += $wid2;
156
			$pixels = self::str_split2($row, $bps, $palette);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $palette does not seem to be defined for all execution paths leading up to this point.
Loading history...
157
158
	    	for ($x = 0; $x < $wid; $x++) {
159
	    		self::makepixel($img, $x, $y, $pixels[$x], $bps);
160
	    	}
161
	    }
162
163
		return $img;
164
	}
165
166
	public static function imagecreatefrombmp($filename)
167
	{
168
		return self::imagecreatefromstring(file_get_contents($filename));
169
	}
170
171
	private static function str_split2($row, $bps, $palette)
172
	{
173
		switch ($bps) {
174
			case 32:
175
			case 24:	return str_split($row, $bps / 8);
176
			case  8:	$out   = array();
177
						$count = strlen($row);
178
179
						for ($i = 0; $i < $count; $i++) {
180
							$out[] = $palette[	ord($row[$i])		];
181
						}
182
183
						return $out;
184
			case  4:	$out   = array();
185
						$count = strlen($row);
186
187
						for ($i = 0; $i < $count; $i++) {
188
							$roww  = ord($row[$i]);
189
							$out[] = $palette[	($roww & 240) >> 4	];
190
							$out[] = $palette[	($roww & 15) 		];
191
						}
192
193
						return $out;
194
			case  1:	$out   = array();
195
						$count = strlen($row);
196
197
						for ($i = 0; $i < $count; $i++) {
198
							$roww  = ord($row[$i]);
199
							$out[] = $palette[	($roww & 128) >> 7	];
200
							$out[] = $palette[	($roww & 64) >> 6	];
201
							$out[] = $palette[	($roww & 32) >> 5	];
202
							$out[] = $palette[	($roww & 16) >> 4	];
203
							$out[] = $palette[	($roww & 8) >> 3	];
204
							$out[] = $palette[	($roww & 4) >> 2	];
205
							$out[] = $palette[	($roww & 2) >> 1	];
206
							$out[] = $palette[	($roww & 1)			];
207
						}
208
209
						return $out;
210
		}
211
	}
212
213
	private static function makepixel($img, $x, $y, $str, $bps)
214
	{
215
		switch ($bps) {
216
			case 32 :	$a = ord($str[0]);
217
						$b = ord($str[1]);
218
						$c = ord($str[2]);
219
						$d = 256 - ord($str[3]); //TODO: gives imperfect results
220
						$pixel = $d*256*256*256 + $c*256*256 + $b*256 + $a;
221
						imagesetpixel($img, $x, $y, $pixel);
222
						break;
223
			case 24 :	$a = ord($str[0]);
224
						$b = ord($str[1]);
225
						$c = ord($str[2]);
226
						$pixel = $c*256*256 + $b*256 + $a;
227
						imagesetpixel($img, $x, $y, $pixel);
228
						break;
229
			case 8 :
230
			case 4 :
231
			case 1 :	imagesetpixel($img, $x, $y, $str);
232
						break;
233
		}
234
	}
235
236
	private static function byte3($n)
237
	{
238
		return chr($n & 255) . chr(($n >> 8) & 255) . chr(($n >> 16) & 255);
239
	}
240
241
	private static function undword($n)
242
	{
243
		$r = unpack("V", $n);
244
		return $r[1];
245
	}
246
247
	private static function dword($n)
248
	{
249
		return pack("V", $n);
250
	}
251
252
	private static function word($n)
253
	{
254
		return pack("v", $n);
255
	}
256
}
257