PluginProbe
Imsanity / 2.5.0
Imsanity v2.5.0
2.9.4 2.9.3 2.9.2 trunk 2.4.3 2.5.0 2.6.0 2.7.0 2.7.2 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.9.0 2.9.1
imsanity / libs / imagecreatefrombmp.php

imagecreatefrombmp.php in Imsanity 2.5.0, at libs/imagecreatefrombmp.php

316 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The imagecreatefrombmp function converts a bmp to an image resource
4 *
5 * @author http://www.programmierer-forum.de/function-imagecreatefrombmp-laeuft-mit-allen-bitraten-t143137.htm
6 * @package Imsanity
7 */
8
9 if ( ! function_exists( 'imagecreatefrombmp' ) ) {
10
11 /**
12 * Converts a bitmap (BMP) image into an image resource.
13 *
14 * @param string $filename The name of the image file.
15 * @return bool|object False, or a GD image resource.
16 */
17 function imagecreatefrombmp( $filename ) {
18 // version 1.1.
19 if ( ! is_readable( $filename ) ) {
20 /* translators: %s: the image filename */
21 trigger_error( sprintf( __( 'imagecreatefrombmp: Can not open %s!', 'imsanity' ), $filename ), E_USER_WARNING );
22 return false;
23 }
24 $fh = fopen( $filename, 'rb' );
25 if ( ! $fh ) {
26 /* translators: %s: the image filename */
27 trigger_error( sprintf( __( 'imagecreatefrombmp: Can not open %s!', 'imsanity' ), $filename ), E_USER_WARNING );
28 return false;
29 }
30 // read file header.
31 $meta = unpack( 'vtype/Vfilesize/Vreserved/Voffset', fread( $fh, 14 ) );
32 // check for bitmap.
33 if ( 19778 !== (int) $meta['type'] ) {
34 /* translators: %s: the image filename */
35 trigger_error( sprintf( __( 'imagecreatefrombmp: %s is not a bitmap!', 'imsanity' ), $filename ), E_USER_WARNING );
36 return false;
37 }
38 // read image header.
39 $meta += unpack( 'Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread( $fh, 40 ) );
40 $bytes_read = 40;
41
42 // read additional bitfield header.
43 if ( 3 === (int) $meta['compression'] ) {
44 $meta += unpack( 'VrMask/VgMask/VbMask', fread( $fh, 12 ) );
45 $bytes_read += 12;
46 }
47
48 // set bytes and padding.
49 $meta['bytes'] = $meta['bits'] / 8;
50 $meta['decal'] = 4 - ( 4 * ( ( $meta['width'] * $meta['bytes'] / 4 ) - floor( $meta['width'] * $meta['bytes'] / 4 ) ) );
51 if ( 4 === (int) $meta['decal'] ) {
52 $meta['decal'] = 0;
53 }
54
55 // obtain imagesize.
56 if ( $meta['imagesize'] < 1 ) {
57 $meta['imagesize'] = $meta['filesize'] - $meta['offset'];
58 // in rare cases filesize is equal to offset so we need to read physical size.
59 if ( $meta['imagesize'] < 1 ) {
60 $meta['imagesize'] = filesize( $filename ) - $meta['offset'];
61 if ( $meta['imagesize'] < 1 ) {
62 /* translators: %s: the image filename */
63 trigger_error( sprintf( __( 'imagecreatefrombmp: Cannot obtain filesize of %s !', 'imsanity' ), $filename ), E_USER_WARNING );
64 return false;
65 }
66 }
67 }
68
69 // calculate colors.
70 $meta['colors'] = ! $meta['colors'] ? pow( 2, $meta['bits'] ) : $meta['colors'];
71
72 // read color palette.
73 $palette = array();
74 if ( $meta['bits'] < 16 ) {
75 $palette = unpack( 'l' . $meta['colors'], fread( $fh, $meta['colors'] * 4 ) );
76 // in rare cases the color value is signed.
77 if ( $palette[1] < 0 ) {
78 foreach ( $palette as $i => $color ) {
79 $palette[ $i ] = $color + 16777216;
80 }
81 }
82 }
83
84 // ignore extra bitmap headers.
85 if ( $meta['headersize'] > $bytes_read ) {
86 fread( $fh, $meta['headersize'] - $bytes_read );
87 }
88
89 // create gd image.
90 $im = imagecreatetruecolor( $meta['width'], $meta['height'] );
91 $data = fread( $fh, $meta['imagesize'] );
92
93 // uncompress data.
94 switch ( $meta['compression'] ) {
95 case 1:
96 $data = rle8_decode( $data, $meta['width'] );
97 break;
98 case 2:
99 $data = rle4_decode( $data, $meta['width'] );
100 break;
101 }
102
103 $p = 0;
104 $vide = chr( 0 );
105 $y = $meta['height'] - 1;
106 /* translators: %s: the image filename */
107 $error = sprintf( __( 'imagecreatefrombmp: %s has not enough data!', 'imsanity' ), $filename );
108 // loop through the image data beginning with the lower left corner.
109 while ( $y >= 0 ) {
110 $x = 0;
111 while ( $x < $meta['width'] ) {
112 switch ( $meta['bits'] ) {
113 case 32:
114 case 24:
115 $part = substr( $data, $p, 3 );
116 if ( ! $part ) {
117 trigger_error( $error, E_USER_WARNING );
118 return $im;
119 }
120 $color = unpack( 'V', $part . $vide );
121 break;
122 case 16:
123 $part = substr( $data, $p, 2 );
124 if ( ! $part ) {
125 trigger_error( $error, E_USER_WARNING );
126 return $im;
127 }
128 $color = unpack( 'v', $part );
129 if ( empty( $meta['rMask'] ) || 0xf800 !== (int) $meta['rMask'] ) {
130 $color[1] = ( ( $color[1] & 0x7c00 ) >> 7 ) * 65536 + ( ( $color[1] & 0x03e0 ) >> 2 ) * 256 + ( ( $color[1] & 0x001f ) << 3 ); // 555.
131 } else {
132 $color[1] = ( ( $color[1] & 0xf800 ) >> 8 ) * 65536 + ( ( $color[1] & 0x07e0 ) >> 3 ) * 256 + ( ( $color[1] & 0x001f ) << 3 ); // 565.
133 }
134 break;
135 case 8:
136 $color = unpack( 'n', $vide . substr( $data, $p, 1 ) );
137 $color[1] = $palette[ $color[1] + 1 ];
138 break;
139 case 4:
140 $color = unpack( 'n', $vide . substr( $data, floor( $p ), 1 ) );
141 $color[1] = 0 === ( $p * 2 ) % 2 ? $color[1] >> 4 : $color[1] & 0x0F;
142 $color[1] = $palette[ $color[1] + 1 ];
143 break;
144 case 1:
145 $color = unpack( 'n', $vide . substr( $data, floor( $p ), 1 ) );
146 switch ( ( $p * 8 ) % 8 ) {
147 case 0:
148 $color[1] = $color[1] >> 7;
149 break;
150 case 1:
151 $color[1] = ( $color[1] & 0x40 ) >> 6;
152 break;
153 case 2:
154 $color[1] = ( $color[1] & 0x20 ) >> 5;
155 break;
156 case 3:
157 $color[1] = ( $color[1] & 0x10 ) >> 4;
158 break;
159 case 4:
160 $color[1] = ( $color[1] & 0x8 ) >> 3;
161 break;
162 case 5:
163 $color[1] = ( $color[1] & 0x4 ) >> 2;
164 break;
165 case 6:
166 $color[1] = ( $color[1] & 0x2 ) >> 1;
167 break;
168 case 7:
169 $color[1] = ( $color[1] & 0x1 );
170 break;
171 }
172 $color[1] = $palette[ $color[1] + 1 ];
173 break;
174 default:
175 /* translators: 1: the image filename 2: bitrate of image */
176 trigger_error( sprintf( __( 'imagecreatefrombmp: %1$s has %2$d bits and this is not supported!', 'imsanity' ), $filename, $meta['bits'] ), E_USER_WARNING );
177 return false;
178 }
179 imagesetpixel( $im, $x, $y, $color[1] );
180 $x++;
181 $p += $meta['bytes'];
182 }
183 $y--;
184 $p += $meta['decal'];
185 }
186 fclose( $fh );
187 return $im;
188 }
189 /**
190 * The original source for these functions no longer exists, but it appears to come from
191 * MSDN and has proliferated across many projects with only the stale link which now
192 * points to https://docs.microsoft.com/en-us/windows/desktop/gdi/bitmap-compression.
193 */
194 /**
195 * Decoder for RLE8 compression in windows bitmaps.
196 *
197 * @param string $str Data to decode.
198 * @param integer $width Image width.
199 *
200 * @return string
201 */
202 function rle8_decode( $str, $width ) {
203 $linewidth = $width + ( 3 - ( $width - 1 ) % 4 );
204 $out = '';
205 $cnt = strlen( $str );
206
207 for ( $i = 0; $i < $cnt; $i++ ) {
208 $o = ord( $str[ $i ] );
209 switch ( $o ) {
210 case 0: // ESCAPE.
211 $i++;
212 switch ( ord( $str[ $i ] ) ) {
213 case 0: // NEW LINE.
214 $padcnt = $linewidth - strlen( $out ) % $linewidth;
215 if ( $padcnt < $linewidth ) {
216 $out .= str_repeat( chr( 0 ), $padcnt ); // pad line.
217 }
218 break;
219 case 1: // END OF FILE.
220 $padcnt = $linewidth - strlen( $out ) % $linewidth;
221 if ( $padcnt < $linewidth ) {
222 $out .= str_repeat( chr( 0 ), $padcnt ); // pad line.
223 }
224 break 3;
225 case 2: // DELTA.
226 $i += 2;
227 break;
228 default: // ABSOLUTE MODE.
229 $num = ord( $str[ $i ] );
230 for ( $j = 0; $j < $num; $j++ ) {
231 $out .= $str[ ++$i ];
232 }
233 if ( $num % 2 ) {
234 $i++;
235 }
236 }
237 break;
238 default:
239 $out .= str_repeat( $str[ ++$i ], $o );
240 }
241 }
242 return $out;
243 }
244
245 /**
246 * Decoder for RLE4 compression in windows bitmaps.
247 *
248 * @param string $str Data to decode.
249 * @param integer $width Image width.
250 * @return string
251 */
252 function rle4_decode( $str, $width ) {
253 $w = floor( $width / 2 ) + ( $width % 2 );
254 $linewidth = $w + ( 3 - ( ( $width - 1 ) / 2 ) % 4 );
255 $pixels = array();
256 $cnt = strlen( $str );
257 $c = 0;
258
259 for ( $i = 0; $i < $cnt; $i++ ) {
260 $o = ord( $str[ $i ] );
261 switch ( $o ) {
262 case 0: // ESCAPE.
263 $i++;
264 switch ( ord( $str[ $i ] ) ) {
265 case 0: // NEW LINE.
266 while ( 0 !== count( $pixels ) % $linewidth ) {
267 $pixels[] = 0;
268 }
269 break;
270 case 1: // END OF FILE.
271 while ( 0 !== count( $pixels ) % $linewidth ) {
272 $pixels[] = 0;
273 }
274 break 3;
275 case 2: // DELTA.
276 $i += 2;
277 break;
278 default: // ABSOLUTE MODE.
279 $num = ord( $str[ $i ] );
280 for ( $j = 0; $j < $num; $j++ ) {
281 if ( 0 === $j % 2 ) {
282 $c = ord( $str[ ++$i ] );
283 $pixels[] = ( $c & 240 ) >> 4;
284 } else {
285 $pixels[] = $c & 15;
286 }
287 }
288
289 if ( 0 === $num % 2 ) {
290 $i++;
291 }
292 }
293 break;
294 default:
295 $c = ord( $str[ ++$i ] );
296 for ( $j = 0; $j < $o; $j++ ) {
297 $pixels[] = ( 0 === $j % 2 ? ( $c & 240 ) >> 4 : $c & 15 );
298 }
299 }
300 }
301
302 $out = '';
303 if ( count( $pixels ) % 2 ) {
304 $pixels[] = 0;
305 }
306
307 $cnt = count( $pixels ) / 2;
308
309 for ( $i = 0; $i < $cnt; $i++ ) {
310 $out .= chr( 16 * $pixels[ 2 * $i ] + $pixels[ 2 * $i + 1 ] );
311 }
312
313 return $out;
314 }
315 }
316