PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Helpers.php

https://gitlab.com/oritadeu/dompdf
PHP | 733 lines | 571 code | 61 blank | 101 comment | 71 complexity | f9516cad7660b92b990814135e4ae580 MD5 | raw file
  1. <?php
  2. namespace Dompdf;
  3. class Helpers
  4. {
  5. /**
  6. * print_r wrapper for html/cli output
  7. *
  8. * Wraps print_r() output in < pre > tags if the current sapi is not 'cli'.
  9. * Returns the output string instead of displaying it if $return is true.
  10. *
  11. * @param mixed $mixed variable or expression to display
  12. * @param bool $return
  13. *
  14. * @return string
  15. */
  16. public static function pre_r($mixed, $return = false)
  17. {
  18. if ($return) {
  19. return "<pre>" . print_r($mixed, true) . "</pre>";
  20. }
  21. if (php_sapi_name() !== "cli") {
  22. echo "<pre>";
  23. }
  24. print_r($mixed);
  25. if (php_sapi_name() !== "cli") {
  26. echo "</pre>";
  27. } else {
  28. echo "\n";
  29. }
  30. flush();
  31. }
  32. /**
  33. * builds a full url given a protocol, hostname, base path and url
  34. *
  35. * @param string $protocol
  36. * @param string $host
  37. * @param string $base_path
  38. * @param string $url
  39. * @return string
  40. *
  41. * Initially the trailing slash of $base_path was optional, and conditionally appended.
  42. * However on dynamically created sites, where the page is given as url parameter,
  43. * the base path might not end with an url.
  44. * Therefore do not append a slash, and **require** the $base_url to ending in a slash
  45. * when needed.
  46. * Vice versa, on using the local file system path of a file, make sure that the slash
  47. * is appended (o.k. also for Windows)
  48. */
  49. public static function build_url($protocol, $host, $base_path, $url)
  50. {
  51. $protocol = mb_strtolower($protocol);
  52. if (strlen($url) == 0) {
  53. //return $protocol . $host . rtrim($base_path, "/\\") . "/";
  54. return $protocol . $host . $base_path;
  55. }
  56. // Is the url already fully qualified, a Data URI, or a reference to a named anchor?
  57. if (mb_strpos($url, "://") !== false || mb_substr($url, 0, 1) === "#" || mb_strpos($url, "data:") === 0 || mb_strpos($url, "mailto:") === 0) {
  58. return $url;
  59. }
  60. $ret = $protocol;
  61. if (!in_array(mb_strtolower($protocol), array("http://", "https://", "ftp://", "ftps://"))) {
  62. //On Windows local file, an abs path can begin also with a '\' or a drive letter and colon
  63. //drive: followed by a relative path would be a drive specific default folder.
  64. //not known in php app code, treat as abs path
  65. //($url[1] !== ':' || ($url[2]!=='\\' && $url[2]!=='/'))
  66. if ($url[0] !== '/' && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' || ($url[0] !== '\\' && $url[1] !== ':'))) {
  67. // For rel path and local acess we ignore the host, and run the path through realpath()
  68. $ret .= realpath($base_path) . '/';
  69. }
  70. $ret .= $url;
  71. $ret = preg_replace('/\?(.*)$/', "", $ret);
  72. return $ret;
  73. }
  74. // Protocol relative urls (e.g. "//example.org/style.css")
  75. if (strpos($url, '//') === 0) {
  76. $ret .= substr($url, 2);
  77. //remote urls with backslash in html/css are not really correct, but lets be genereous
  78. } elseif ($url[0] === '/' || $url[0] === '\\') {
  79. // Absolute path
  80. $ret .= $host . $url;
  81. } else {
  82. // Relative path
  83. //$base_path = $base_path !== "" ? rtrim($base_path, "/\\") . "/" : "";
  84. $ret .= $host . $base_path . $url;
  85. }
  86. return $ret;
  87. }
  88. /**
  89. * Converts decimal numbers to roman numerals
  90. *
  91. * @param int $num
  92. *
  93. * @throws Exception
  94. * @return string
  95. */
  96. public static function dec2roman($num)
  97. {
  98. static $ones = array("", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix");
  99. static $tens = array("", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc");
  100. static $hund = array("", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm");
  101. static $thou = array("", "m", "mm", "mmm");
  102. if (!is_numeric($num)) {
  103. throw new Exception("dec2roman() requires a numeric argument.");
  104. }
  105. if ($num > 4000 || $num < 0) {
  106. return "(out of range)";
  107. }
  108. $num = strrev((string)$num);
  109. $ret = "";
  110. switch (mb_strlen($num)) {
  111. case 4:
  112. $ret .= $thou[$num[3]];
  113. case 3:
  114. $ret .= $hund[$num[2]];
  115. case 2:
  116. $ret .= $tens[$num[1]];
  117. case 1:
  118. $ret .= $ones[$num[0]];
  119. default:
  120. break;
  121. }
  122. return $ret;
  123. }
  124. /**
  125. * Determines whether $value is a percentage or not
  126. *
  127. * @param float $value
  128. *
  129. * @return bool
  130. */
  131. public static function is_percent($value)
  132. {
  133. return false !== mb_strpos($value, "%");
  134. }
  135. /**
  136. * Parses a data URI scheme
  137. * http://en.wikipedia.org/wiki/Data_URI_scheme
  138. *
  139. * @param string $data_uri The data URI to parse
  140. *
  141. * @return array The result with charset, mime type and decoded data
  142. */
  143. public static function parse_data_uri($data_uri)
  144. {
  145. if (!preg_match('/^data:(?P<mime>[a-z0-9\/+-.]+)(;charset=(?P<charset>[a-z0-9-])+)?(?P<base64>;base64)?\,(?P<data>.*)?/is', $data_uri, $match)) {
  146. return false;
  147. }
  148. $match['data'] = rawurldecode($match['data']);
  149. $result = array(
  150. 'charset' => $match['charset'] ? $match['charset'] : 'US-ASCII',
  151. 'mime' => $match['mime'] ? $match['mime'] : 'text/plain',
  152. 'data' => $match['base64'] ? base64_decode($match['data']) : $match['data'],
  153. );
  154. return $result;
  155. }
  156. /**
  157. * Decoder for RLE8 compression in windows bitmaps
  158. * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
  159. *
  160. * @param string $str Data to decode
  161. * @param integer $width Image width
  162. *
  163. * @return string
  164. */
  165. public static function rle8_decode($str, $width)
  166. {
  167. $lineWidth = $width + (3 - ($width - 1) % 4);
  168. $out = '';
  169. $cnt = strlen($str);
  170. for ($i = 0; $i < $cnt; $i++) {
  171. $o = ord($str[$i]);
  172. switch ($o) {
  173. case 0: # ESCAPE
  174. $i++;
  175. switch (ord($str[$i])) {
  176. case 0: # NEW LINE
  177. $padCnt = $lineWidth - strlen($out) % $lineWidth;
  178. if ($padCnt < $lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
  179. break;
  180. case 1: # END OF FILE
  181. $padCnt = $lineWidth - strlen($out) % $lineWidth;
  182. if ($padCnt < $lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
  183. break 3;
  184. case 2: # DELTA
  185. $i += 2;
  186. break;
  187. default: # ABSOLUTE MODE
  188. $num = ord($str[$i]);
  189. for ($j = 0; $j < $num; $j++)
  190. $out .= $str[++$i];
  191. if ($num % 2) $i++;
  192. }
  193. break;
  194. default:
  195. $out .= str_repeat($str[++$i], $o);
  196. }
  197. }
  198. return $out;
  199. }
  200. /**
  201. * Decoder for RLE4 compression in windows bitmaps
  202. * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
  203. *
  204. * @param string $str Data to decode
  205. * @param integer $width Image width
  206. *
  207. * @return string
  208. */
  209. public static function rle4_decode($str, $width)
  210. {
  211. $w = floor($width / 2) + ($width % 2);
  212. $lineWidth = $w + (3 - (($width - 1) / 2) % 4);
  213. $pixels = array();
  214. $cnt = strlen($str);
  215. $c = 0;
  216. for ($i = 0; $i < $cnt; $i++) {
  217. $o = ord($str[$i]);
  218. switch ($o) {
  219. case 0: # ESCAPE
  220. $i++;
  221. switch (ord($str[$i])) {
  222. case 0: # NEW LINE
  223. while (count($pixels) % $lineWidth != 0) {
  224. $pixels[] = 0;
  225. }
  226. break;
  227. case 1: # END OF FILE
  228. while (count($pixels) % $lineWidth != 0) {
  229. $pixels[] = 0;
  230. }
  231. break 3;
  232. case 2: # DELTA
  233. $i += 2;
  234. break;
  235. default: # ABSOLUTE MODE
  236. $num = ord($str[$i]);
  237. for ($j = 0; $j < $num; $j++) {
  238. if ($j % 2 == 0) {
  239. $c = ord($str[++$i]);
  240. $pixels[] = ($c & 240) >> 4;
  241. } else {
  242. $pixels[] = $c & 15;
  243. }
  244. }
  245. if ($num % 2 == 0) {
  246. $i++;
  247. }
  248. }
  249. break;
  250. default:
  251. $c = ord($str[++$i]);
  252. for ($j = 0; $j < $o; $j++) {
  253. $pixels[] = ($j % 2 == 0 ? ($c & 240) >> 4 : $c & 15);
  254. }
  255. }
  256. }
  257. $out = '';
  258. if (count($pixels) % 2) {
  259. $pixels[] = 0;
  260. }
  261. $cnt = count($pixels) / 2;
  262. for ($i = 0; $i < $cnt; $i++) {
  263. $out .= chr(16 * $pixels[2 * $i] + $pixels[2 * $i + 1]);
  264. }
  265. return $out;
  266. }
  267. /**
  268. * parse a full url or pathname and return an array(protocol, host, path,
  269. * file + query + fragment)
  270. *
  271. * @param string $url
  272. * @return array
  273. */
  274. public static function explode_url($url)
  275. {
  276. $protocol = "";
  277. $host = "";
  278. $path = "";
  279. $file = "";
  280. $arr = parse_url($url);
  281. if ( isset($arr["scheme"]) ) {
  282. $arr["scheme"] = mb_strtolower($arr["scheme"]);
  283. }
  284. // Exclude windows drive letters...
  285. if (isset($arr["scheme"]) && $arr["scheme"] !== "file" && strlen($arr["scheme"]) > 1) {
  286. $protocol = $arr["scheme"] . "://";
  287. if (isset($arr["user"])) {
  288. $host .= $arr["user"];
  289. if (isset($arr["pass"])) {
  290. $host .= ":" . $arr["pass"];
  291. }
  292. $host .= "@";
  293. }
  294. if (isset($arr["host"])) {
  295. $host .= $arr["host"];
  296. }
  297. if (isset($arr["port"])) {
  298. $host .= ":" . $arr["port"];
  299. }
  300. if (isset($arr["path"]) && $arr["path"] !== "") {
  301. // Do we have a trailing slash?
  302. if ($arr["path"][mb_strlen($arr["path"]) - 1] === "/") {
  303. $path = $arr["path"];
  304. $file = "";
  305. } else {
  306. $path = rtrim(dirname($arr["path"]), '/\\') . "/";
  307. $file = basename($arr["path"]);
  308. }
  309. }
  310. if (isset($arr["query"])) {
  311. $file .= "?" . $arr["query"];
  312. }
  313. if (isset($arr["fragment"])) {
  314. $file .= "#" . $arr["fragment"];
  315. }
  316. } else {
  317. $i = mb_stripos($url, "file://");
  318. if ($i !== false) {
  319. $url = mb_substr($url, $i + 7);
  320. }
  321. $protocol = ""; // "file://"; ? why doesn't this work... It's because of
  322. // network filenames like //COMPU/SHARENAME
  323. $host = ""; // localhost, really
  324. $file = basename($url);
  325. $path = dirname($url);
  326. // Check that the path exists
  327. if ($path !== false) {
  328. $path .= '/';
  329. } else {
  330. // generate a url to access the file if no real path found.
  331. $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
  332. $host = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : php_uname("n");
  333. if (substr($arr["path"], 0, 1) === '/') {
  334. $path = dirname($arr["path"]);
  335. } else {
  336. $path = '/' . rtrim(dirname($_SERVER["SCRIPT_NAME"]), '/') . '/' . $arr["path"];
  337. }
  338. }
  339. }
  340. $ret = array($protocol, $host, $path, $file,
  341. "protocol" => $protocol,
  342. "host" => $host,
  343. "path" => $path,
  344. "file" => $file);
  345. return $ret;
  346. }
  347. /**
  348. * Print debug messages
  349. *
  350. * @param string $type The type of debug messages to print
  351. * @param string $msg The message to show
  352. */
  353. public static function dompdf_debug($type, $msg)
  354. {
  355. global $_DOMPDF_DEBUG_TYPES, $_dompdf_show_warnings, $_dompdf_debug;
  356. if (isset($_DOMPDF_DEBUG_TYPES[$type]) && ($_dompdf_show_warnings || $_dompdf_debug)) {
  357. $arr = debug_backtrace();
  358. echo basename($arr[0]["file"]) . " (" . $arr[0]["line"] . "): " . $arr[1]["function"] . ": ";
  359. Helpers::pre_r($msg);
  360. }
  361. }
  362. /**
  363. * Stores warnings in an array for display later
  364. * This function allows warnings generated by the DomDocument parser
  365. * and CSS loader ({@link Stylesheet}) to be captured and displayed
  366. * later. Without this function, errors are displayed immediately and
  367. * PDF streaming is impossible.
  368. * @see http://www.php.net/manual/en/function.set-error_handler.php
  369. *
  370. * @param int $errno
  371. * @param string $errstr
  372. * @param string $errfile
  373. * @param string $errline
  374. *
  375. * @throws Exception
  376. */
  377. public static function record_warnings($errno, $errstr, $errfile, $errline)
  378. {
  379. // Not a warning or notice
  380. if (!($errno & (E_WARNING | E_NOTICE | E_USER_NOTICE | E_USER_WARNING))) {
  381. throw new Exception($errstr . " $errno");
  382. }
  383. global $_dompdf_warnings;
  384. global $_dompdf_show_warnings;
  385. if ($_dompdf_show_warnings) {
  386. echo $errstr . "\n";
  387. }
  388. $_dompdf_warnings[] = $errstr;
  389. }
  390. /**
  391. * @param $c
  392. * @return bool|string
  393. */
  394. public static function unichr($c)
  395. {
  396. if ($c <= 0x7F) {
  397. return chr($c);
  398. } else if ($c <= 0x7FF) {
  399. return chr(0xC0 | $c >> 6) . chr(0x80 | $c & 0x3F);
  400. } else if ($c <= 0xFFFF) {
  401. return chr(0xE0 | $c >> 12) . chr(0x80 | $c >> 6 & 0x3F)
  402. . chr(0x80 | $c & 0x3F);
  403. } else if ($c <= 0x10FFFF) {
  404. return chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F)
  405. . chr(0x80 | $c >> 6 & 0x3F)
  406. . chr(0x80 | $c & 0x3F);
  407. }
  408. return false;
  409. }
  410. /**
  411. * Converts a CMYK color to RGB
  412. *
  413. * @param float|float[] $c
  414. * @param float $m
  415. * @param float $y
  416. * @param float $k
  417. *
  418. * @return float[]
  419. */
  420. public static function cmyk_to_rgb($c, $m = null, $y = null, $k = null)
  421. {
  422. if (is_array($c)) {
  423. list($c, $m, $y, $k) = $c;
  424. }
  425. $c *= 255;
  426. $m *= 255;
  427. $y *= 255;
  428. $k *= 255;
  429. $r = (1 - round(2.55 * ($c + $k)));
  430. $g = (1 - round(2.55 * ($m + $k)));
  431. $b = (1 - round(2.55 * ($y + $k)));
  432. if ($r < 0) $r = 0;
  433. if ($g < 0) $g = 0;
  434. if ($b < 0) $b = 0;
  435. return array(
  436. $r, $g, $b,
  437. "r" => $r, "g" => $g, "b" => $b
  438. );
  439. }
  440. /**
  441. * getimagesize doesn't give a good size for 32bit BMP image v5
  442. *
  443. * @param string $filename
  444. * @return array The same format as getimagesize($filename)
  445. */
  446. public static function dompdf_getimagesize($filename, $context = null)
  447. {
  448. static $cache = array();
  449. if (isset($cache[$filename])) {
  450. return $cache[$filename];
  451. }
  452. list($width, $height, $type) = getimagesize($filename);
  453. // Custom types
  454. $types = array(
  455. IMAGETYPE_JPEG => "jpeg",
  456. IMAGETYPE_GIF => "gif",
  457. IMAGETYPE_BMP => "bmp",
  458. IMAGETYPE_PNG => "png",
  459. );
  460. $type = isset($types[$type]) ? $types[$type] : null;
  461. if ($width == null || $height == null) {
  462. $data = file_get_contents($filename, null, $context, 0, 26);
  463. if (substr($data, 0, 2) === "BM") {
  464. $meta = unpack('vtype/Vfilesize/Vreserved/Voffset/Vheadersize/Vwidth/Vheight', $data);
  465. $width = (int)$meta['width'];
  466. $height = (int)$meta['height'];
  467. $type = "bmp";
  468. }
  469. else {
  470. if (strpos(file_get_contents($filename), "<svg") !== false) {
  471. $doc = new \Svg\Document();
  472. $doc->loadFile($filename);
  473. list($width, $height) = $doc->getDimensions();
  474. $type = "svg";
  475. }
  476. }
  477. }
  478. return $cache[$filename] = array($width, $height, $type);
  479. }
  480. /**
  481. * Credit goes to mgutt
  482. * http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm
  483. * Modified by Fabien Menager to support RGB555 BMP format
  484. */
  485. public static function imagecreatefrombmp($filename, $context = null)
  486. {
  487. if (!function_exists("imagecreatetruecolor")) {
  488. trigger_error("The PHP GD extension is required, but is not installed.", E_ERROR);
  489. return false;
  490. }
  491. // version 1.00
  492. if (!($fh = fopen($filename, 'rb'))) {
  493. trigger_error('imagecreatefrombmp: Can not open ' . $filename, E_USER_WARNING);
  494. return false;
  495. }
  496. $bytes_read = 0;
  497. // read file header
  498. $meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14));
  499. // check for bitmap
  500. if ($meta['type'] != 19778) {
  501. trigger_error('imagecreatefrombmp: ' . $filename . ' is not a bitmap!', E_USER_WARNING);
  502. return false;
  503. }
  504. // read image header
  505. $meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread($fh, 40));
  506. $bytes_read += 40;
  507. // read additional bitfield header
  508. if ($meta['compression'] == 3) {
  509. $meta += unpack('VrMask/VgMask/VbMask', fread($fh, 12));
  510. $bytes_read += 12;
  511. }
  512. // set bytes and padding
  513. $meta['bytes'] = $meta['bits'] / 8;
  514. $meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4) - floor($meta['width'] * $meta['bytes'] / 4)));
  515. if ($meta['decal'] == 4) {
  516. $meta['decal'] = 0;
  517. }
  518. // obtain imagesize
  519. if ($meta['imagesize'] < 1) {
  520. $meta['imagesize'] = $meta['filesize'] - $meta['offset'];
  521. // in rare cases filesize is equal to offset so we need to read physical size
  522. if ($meta['imagesize'] < 1) {
  523. $meta['imagesize'] = @filesize($filename) - $meta['offset'];
  524. if ($meta['imagesize'] < 1) {
  525. trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING);
  526. return false;
  527. }
  528. }
  529. }
  530. // calculate colors
  531. $meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors'];
  532. // read color palette
  533. $palette = array();
  534. if ($meta['bits'] < 16) {
  535. $palette = unpack('l' . $meta['colors'], fread($fh, $meta['colors'] * 4));
  536. // in rare cases the color value is signed
  537. if ($palette[1] < 0) {
  538. foreach ($palette as $i => $color) {
  539. $palette[$i] = $color + 16777216;
  540. }
  541. }
  542. }
  543. // ignore extra bitmap headers
  544. if ($meta['headersize'] > $bytes_read) {
  545. fread($fh, $meta['headersize'] - $bytes_read);
  546. }
  547. // create gd image
  548. $im = imagecreatetruecolor($meta['width'], $meta['height']);
  549. $data = fread($fh, $meta['imagesize']);
  550. // uncompress data
  551. switch ($meta['compression']) {
  552. case 1:
  553. $data = Helpers::rle8_decode($data, $meta['width']);
  554. break;
  555. case 2:
  556. $data = Helpers::rle4_decode($data, $meta['width']);
  557. break;
  558. }
  559. $p = 0;
  560. $vide = chr(0);
  561. $y = $meta['height'] - 1;
  562. $error = 'imagecreatefrombmp: ' . $filename . ' has not enough data!';
  563. // loop through the image data beginning with the lower left corner
  564. while ($y >= 0) {
  565. $x = 0;
  566. while ($x < $meta['width']) {
  567. switch ($meta['bits']) {
  568. case 32:
  569. case 24:
  570. if (!($part = substr($data, $p, 3 /*$meta['bytes']*/))) {
  571. trigger_error($error, E_USER_WARNING);
  572. return $im;
  573. }
  574. $color = unpack('V', $part . $vide);
  575. break;
  576. case 16:
  577. if (!($part = substr($data, $p, 2 /*$meta['bytes']*/))) {
  578. trigger_error($error, E_USER_WARNING);
  579. return $im;
  580. }
  581. $color = unpack('v', $part);
  582. if (empty($meta['rMask']) || $meta['rMask'] != 0xf800) {
  583. $color[1] = (($color[1] & 0x7c00) >> 7) * 65536 + (($color[1] & 0x03e0) >> 2) * 256 + (($color[1] & 0x001f) << 3); // 555
  584. } else {
  585. $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3); // 565
  586. }
  587. break;
  588. case 8:
  589. $color = unpack('n', $vide . substr($data, $p, 1));
  590. $color[1] = $palette[$color[1] + 1];
  591. break;
  592. case 4:
  593. $color = unpack('n', $vide . substr($data, floor($p), 1));
  594. $color[1] = ($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F;
  595. $color[1] = $palette[$color[1] + 1];
  596. break;
  597. case 1:
  598. $color = unpack('n', $vide . substr($data, floor($p), 1));
  599. switch (($p * 8) % 8) {
  600. case 0:
  601. $color[1] = $color[1] >> 7;
  602. break;
  603. case 1:
  604. $color[1] = ($color[1] & 0x40) >> 6;
  605. break;
  606. case 2:
  607. $color[1] = ($color[1] & 0x20) >> 5;
  608. break;
  609. case 3:
  610. $color[1] = ($color[1] & 0x10) >> 4;
  611. break;
  612. case 4:
  613. $color[1] = ($color[1] & 0x8) >> 3;
  614. break;
  615. case 5:
  616. $color[1] = ($color[1] & 0x4) >> 2;
  617. break;
  618. case 6:
  619. $color[1] = ($color[1] & 0x2) >> 1;
  620. break;
  621. case 7:
  622. $color[1] = ($color[1] & 0x1);
  623. break;
  624. }
  625. $color[1] = $palette[$color[1] + 1];
  626. break;
  627. default:
  628. trigger_error('imagecreatefrombmp: ' . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', E_USER_WARNING);
  629. return false;
  630. }
  631. imagesetpixel($im, $x, $y, $color[1]);
  632. $x++;
  633. $p += $meta['bytes'];
  634. }
  635. $y--;
  636. $p += $meta['decal'];
  637. }
  638. fclose($fh);
  639. return $im;
  640. }
  641. }