1: | <?php |
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | |
21: | |
22: | |
23: | |
24: | |
25: | |
26: | |
27: | |
28: | |
29: | |
30: | |
31: | |
32: | |
33: | |
34: | |
35: | |
36: | |
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; |
50: | |
51: | |
52: | $header['identifier'] = 'BM'; |
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); |
73: | } |
74: | |
75: | |
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); |
86: | } else { |
87: | foreach ($header as $h) { |
88: | echo $h; |
89: | } |
90: | |
91: | |
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: | |
108: | $pos = 0; |
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']; |
129: | $wid2 = ceil(($bps/8 * $header['width']) / 4) * 4; |
130: | $colors = $header['colors']; |
131: | |
132: | |
133: | |
134: | $header['height'] = abs($header['height']); |
135: | |
136: | $wid = $header['width']; |
137: | $hei = $header['height']; |
138: | |
139: | $img = imagecreatetruecolor($header['width'], $header['height']); |
140: | if (!$img) { |
141: | return false; |
142: | } |
143: | |
144: | $palette = []; |
145: | |
146: | if ($bps < 9) { |
147: | |
148: | if (isset($header['colors']) && $header['colors'] > 0) { |
149: | |
150: | |
151: | $colors = min($header['colors'], $colors); |
152: | } |
153: | for ($i = 0; $i < $colors; $i++) { |
154: | $palette[] = self::undword(substr($data, $pos, 4)); |
155: | $pos += 4; |
156: | } |
157: | } else { |
158: | if ($bps == 32) { |
159: | imagealphablending($img, false); |
160: | imagesavealpha($img, true); |
161: | } |
162: | |
163: | $palette = array(); |
164: | } |
165: | |
166: | |
167: | for ($y = $hei-1; $y >= 0; $y--) { |
168: | $row = substr($data, $pos, $wid2); |
169: | $pos += $wid2; |
170: | $pixels = self::str_split2($row, $bps, $palette); |
171: | |
172: | for ($x = 0; $x < $wid; $x++) { |
173: | self::makepixel($img, $x, $y, $pixels[$x], $bps); |
174: | } |
175: | } |
176: | |
177: | return $img; |
178: | } |
179: | |
180: | public static function imagecreatefrombmp($filename) |
181: | { |
182: | return self::imagecreatefromstring(file_get_contents($filename)); |
183: | } |
184: | |
185: | private static function str_split2($row, $bps, $palette) |
186: | { |
187: | switch ($bps) { |
188: | case 32: |
189: | case 24: return str_split($row, $bps / 8); |
190: | case 8: $out = array(); |
191: | $count = strlen($row); |
192: | |
193: | for ($i = 0; $i < $count; $i++) { |
194: | $out[] = $palette[ ord($row[$i]) ]; |
195: | } |
196: | |
197: | return $out; |
198: | case 4: $out = array(); |
199: | $count = strlen($row); |
200: | |
201: | for ($i = 0; $i < $count; $i++) { |
202: | $roww = ord($row[$i]); |
203: | $out[] = $palette[ ($roww & 240) >> 4 ]; |
204: | $out[] = $palette[ ($roww & 15) ]; |
205: | } |
206: | |
207: | return $out; |
208: | case 1: $out = array(); |
209: | $count = strlen($row); |
210: | |
211: | for ($i = 0; $i < $count; $i++) { |
212: | $roww = ord($row[$i]); |
213: | $out[] = $palette[ ($roww & 128) >> 7 ]; |
214: | $out[] = $palette[ ($roww & 64) >> 6 ]; |
215: | $out[] = $palette[ ($roww & 32) >> 5 ]; |
216: | $out[] = $palette[ ($roww & 16) >> 4 ]; |
217: | $out[] = $palette[ ($roww & 8) >> 3 ]; |
218: | $out[] = $palette[ ($roww & 4) >> 2 ]; |
219: | $out[] = $palette[ ($roww & 2) >> 1 ]; |
220: | $out[] = $palette[ ($roww & 1) ]; |
221: | } |
222: | |
223: | return $out; |
224: | } |
225: | } |
226: | |
227: | private static function makepixel($img, $x, $y, $str, $bps) |
228: | { |
229: | switch ($bps) { |
230: | case 32 : $a = ord($str[0]); |
231: | $b = ord($str[1]); |
232: | $c = ord($str[2]); |
233: | $d = 256 - ord($str[3]); |
234: | $pixel = $d*256*256*256 + $c*256*256 + $b*256 + $a; |
235: | imagesetpixel($img, $x, $y, $pixel); |
236: | break; |
237: | case 24 : $a = ord($str[0]); |
238: | $b = ord($str[1]); |
239: | $c = ord($str[2]); |
240: | $pixel = $c*256*256 + $b*256 + $a; |
241: | imagesetpixel($img, $x, $y, $pixel); |
242: | break; |
243: | case 8 : |
244: | case 4 : |
245: | case 1 : imagesetpixel($img, $x, $y, $str); |
246: | break; |
247: | } |
248: | } |
249: | |
250: | private static function byte3($n) |
251: | { |
252: | return chr($n & 255) . chr(($n >> 8) & 255) . chr(($n >> 16) & 255); |
253: | } |
254: | |
255: | private static function undword($n) |
256: | { |
257: | $r = unpack("V", $n); |
258: | return $r[1]; |
259: | } |
260: | |
261: | private static function dword($n) |
262: | { |
263: | return pack("V", $n); |
264: | } |
265: | |
266: | private static function word($n) |
267: | { |
268: | return pack("v", $n); |
269: | } |
270: | } |
271: | |