当前位置:Gxlcms > PHP教程 > PHP仿GD生成BMP图片

PHP仿GD生成BMP图片

时间:2021-07-01 10:21:17 帮助过:19人阅读

PHP仿GD生成BMP图片
  1. function imagebmp(&$im, $filename = '', $bit = 8, $compression = 0)
  2. {
  3. if (!in_array($bit, array(1, 4, 8, 16, 24, 32)))
  4. {
  5. $bit = 8;
  6. }
  7. else if ($bit == 32) // todo:32 bit
  8. {
  9. $bit = 24;
  10. }
  11. $bits = pow(2, $bit);
  12. // 调整调色板
  13. imagetruecolortopalette($im, true, $bits);
  14. $width = imagesx($im);
  15. $height = imagesy($im);
  16. $colors_num = imagecolorstotal($im);
  17. if ($bit <= 8)
  18. {
  19. // 颜色索引
  20. $rgb_quad = '';
  21. for ($i = 0; $i < $colors_num; $i ++)
  22. {
  23. $colors = imagecolorsforindex($im, $i);
  24. $rgb_quad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0";
  25. }
  26. // 位图数据
  27. $bmp_data = '';
  28. // 非压缩
  29. if ($compression == 0 || $bit < 8)
  30. {
  31. if (!in_array($bit, array(1, 4, 8)))
  32. {
  33. $bit = 8;
  34. }
  35. $compression = 0;
  36. // 每行字节数必须为4的倍数,补齐。
  37. $extra = '';
  38. $padding = 4 - ceil($width / (8 / $bit)) % 4;
  39. if ($padding % 4 != 0)
  40. {
  41. $extra = str_repeat("\0", $padding);
  42. }
  43. for ($j = $height - 1; $j >= 0; $j --)
  44. {
  45. $i = 0;
  46. while ($i < $width)
  47. {
  48. $bin = 0;
  49. $limit = $width - $i < 8 / $bit ? (8 / $bit - $width + $i) * $bit : 0;
  50. for ($k = 8 - $bit; $k >= $limit; $k -= $bit)
  51. {
  52. $index = imagecolorat($im, $i, $j);
  53. $bin |= $index << $k;
  54. $i ++;
  55. }
  56. $bmp_data .= chr($bin);
  57. }
  58. $bmp_data .= $extra;
  59. }
  60. }
  61. // RLE8 压缩
  62. else if ($compression == 1 && $bit == 8)
  63. {
  64. for ($j = $height - 1; $j >= 0; $j --)
  65. {
  66. $last_index = "\0";
  67. $same_num = 0;
  68. for ($i = 0; $i <= $width; $i ++)
  69. {
  70. $index = imagecolorat($im, $i, $j);
  71. if ($index !== $last_index || $same_num > 255)
  72. {
  73. if ($same_num != 0)
  74. {
  75. $bmp_data .= chr($same_num) . chr($last_index);
  76. }
  77. $last_index = $index;
  78. $same_num = 1;
  79. }
  80. else
  81. {
  82. $same_num ++;
  83. }
  84. }
  85. $bmp_data .= "\0\0";
  86. }
  87. $bmp_data .= "\0\1";
  88. }
  89. $size_quad = strlen($rgb_quad);
  90. $size_data = strlen($bmp_data);
  91. }
  92. else
  93. {
  94. // 每行字节数必须为4的倍数,补齐。
  95. $extra = '';
  96. $padding = 4 - ($width * ($bit / 8)) % 4;
  97. if ($padding % 4 != 0)
  98. {
  99. $extra = str_repeat("\0", $padding);
  100. }
  101. // 位图数据
  102. $bmp_data = '';
  103. for ($j = $height - 1; $j >= 0; $j --)
  104. {
  105. for ($i = 0; $i < $width; $i ++)
  106. {
  107. $index = imagecolorat($im, $i, $j);
  108. $colors = imagecolorsforindex($im, $index);
  109. if ($bit == 16)
  110. {
  111. $bin = 0 << $bit;
  112. $bin |= ($colors['red'] >> 3) << 10;
  113. $bin |= ($colors['green'] >> 3) << 5;
  114. $bin |= $colors['blue'] >> 3;
  115. $bmp_data .= pack("v", $bin);
  116. }
  117. else
  118. {
  119. $bmp_data .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);
  120. }
  121. // todo: 32bit;
  122. }
  123. $bmp_data .= $extra;
  124. }
  125. $size_quad = 0;
  126. $size_data = strlen($bmp_data);
  127. $colors_num = 0;
  128. }
  129. // 位图文件头
  130. $file_header = "BM" . pack("V3", 54 + $size_quad + $size_data, 0, 54 + $size_quad);
  131. // 位图信息头
  132. $info_header = pack("V3v2V*", 0x28, $width, $height, 1, $bit, $compression, $size_data, 0, 0, $colors_num, 0);
  133. // 写入文件
  134. if ($filename != '')
  135. {
  136. $fp = fopen($filename, "wb");
  137. fwrite($fp, $file_header);
  138. fwrite($fp, $info_header);
  139. fwrite($fp, $rgb_quad);
  140. fwrite($fp, $bmp_data);
  141. fclose($fp);
  142. return true;
  143. }
  144. // 浏览器输出
  145. header("Content-Type: image/bmp");
  146. echo $file_header . $info_header;
  147. echo $rgb_quad;
  148. echo $bmp_data;
  149. return true;
  150. }

人气教程排行