«
使用php GD库生成bmp格式的图片(imagebmp)

时间:2008-5-31    作者:Deri    分类: 分享


   <p>  GD库里没有生成bmp图片的函数,所以自己写了一个,这个函数尚有一个压缩算法没有写,不过已经够用了。需要的同学可以看看。</p><p>  int imagebmp ( resource image [, string filename [, int $bit [, int compression]]] )</p><p>  $im: 图像资源</p><p>  $filename: 如果要另存为文件,请指定文件名,为空则直接在浏览器输出</p><p>  $bit: 图像质量(1、4、8、16、24、32位)</p><p>  $compression: 压缩方式,0为不压缩,1使用RLE8压缩算法进行压缩</p><p>  注意:这个函数仍然需要GD库的支持。</p><p>  Demo:</p><code>$im = imagecreatefrompng("test.png");<br />imagebmp($im);<br />imagedestroy($im);<br />Source:<br />/**<br />* 创建bmp格式图片<br />*<br />* @author: legend(legendsky@hotmail.com)<br />* @link: http://www.ugia.cn/?p=96<br />* @description: create Bitmap-File with GD library<br />* @version: 0.1<br />*<br />* @param resource $im     图像资源<br />* @param string  $filename  如果要另存为文件,请指定文件名,为空则直接在浏览器输出<br />* @param integer $bit     图像质量(1、4、8、16、24、32位)<br />* @param integer $compression 压缩方式,0为不压缩,1使用RLE8压缩算法进行压缩<br />*<br />* @return integer<br />*/<br />function imagebmp(&$im, $filename = '', $bit = 8, $compression = 0)<br />{<br />  if (!in_array($bit, array(1, 4, 8, 16, 24, 32)))<br />  {<br />    $bit = 8;<br />  }<br />  else if ($bit == 32) // todo:32 bit<br />  {<br />    $bit = 24;<br />  }<br /> <br />  $bits = pow(2, $bit);<br />  <br />  // 调整调色板<br />  imagetruecolortopalette($im, true, $bits);<br />  $width = imagesx($im);<br />  $height = imagesy($im);<br />  $colors_num = imagecolorstotal($im);<br />  <br />  if ($bit <= 8)<br />  {<br />    // 颜色索引<br />    $rgb_quad = '';<br />    for ($i = 0; $i < $colors_num; $i ++)<br />    {<br />      $colors = imagecolorsforindex($im, $i);<br />      $rgb_quad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "";<br />    }<br />    <br />    // 位图数据<br />    $bmp_data = '';<br /> <br />    // 非压缩<br />    if ($compression == 0 || $bit < 8)<br />    {<br />      if (!in_array($bit, array(1, 4, 8)))<br />      {<br />        $bit = 8;<br />      }<br /> <br />      $compression = 0;<br />      <br />      // 每行字节数必须为4的倍数,补齐。<br />      $extra = '';<br />      $padding = 4 - ceil($width / (8 / $bit)) % 4;<br />      if ($padding % 4 != 0)<br />      {<br />        $extra = str_repeat("", $padding);<br />      }<br />      <br />      for ($j = $height - 1; $j >= 0; $j --)<br />      {<br />        $i = 0;<br />        while ($i < $width)<br />        {<br />          $bin = 0;<br />          $limit = $width - $i < 8 / $bit ? (8 / $bit - $width + $i) * $bit : 0;<br /> <br />          for ($k = 8 - $bit; $k >= $limit; $k -= $bit)<br />          {<br />            $index = imagecolorat($im, $i, $j);<br />            $bin |= $index << $k;<br />            $i ++;<br />          }<br /> <br />          $bmp_data .= chr($bin);<br />        }<br />        <br />        $bmp_data .= $extra;<br />      }<br />    }<br />    // RLE8 压缩<br />    else if ($compression == 1 && $bit == 8)<br />    {<br />      for ($j = $height - 1; $j >= 0; $j --)<br />      {<br />        $last_index = "";<br />        $same_num  = 0;<br />        for ($i = 0; $i <= $width; $i ++)<br />        {<br />          $index = imagecolorat($im, $i, $j);<br />          if ($index !== $last_index || $same_num > 255)<br />          {<br />            if ($same_num != 0)<br />            {<br />              $bmp_data .= chr($same_num) . chr($last_index);<br />            }<br /> <br />            $last_index = $index;<br />            $same_num = 1;<br />          }<br />          else<br />          {<br />            $same_num ++;<br />          }<br />        }<br /> <br />        $bmp_data .= "";<br />      }<br />      <br />      $bmp_data .= "1";<br />    }<br /> <br />    $size_quad = strlen($rgb_quad);<br />    $size_data = strlen($bmp_data);<br />  }<br />  else<br />  {<br />    // 每行字节数必须为4的倍数,补齐。<br />    $extra = '';<br />    $padding = 4 - ($width * ($bit / 8)) % 4;<br />    if ($padding % 4 != 0)<br />    {<br />      $extra = str_repeat("", $padding);<br />    }<br /> <br />    // 位图数据<br />    $bmp_data = '';<br /> <br />    for ($j = $height - 1; $j >= 0; $j --)<br />    {<br />      for ($i = 0; $i < $width; $i ++)<br />      {<br />        $index = imagecolorat($im, $i, $j);<br />        $colors = imagecolorsforindex($im, $index);<br />        <br />        if ($bit == 16)<br />        {<br />          $bin = 0 << $bit;<br /> <br />          $bin |= ($colors['red'] >> 3) << 10;<br />          $bin |= ($colors['green'] >> 3) << 5;<br />          $bin |= $colors['blue'] >> 3;<br /> <br />          $bmp_data .= pack("v", $bin);<br />        }<br />        else<br />        {<br />          $bmp_data .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);<br />        }<br />        <br />        // todo: 32bit;<br />      }<br /> <br />      $bmp_data .= $extra;<br />    }<br /> <br />    $size_quad = 0;<br />    $size_data = strlen($bmp_data);<br />    $colors_num = 0;<br />  }<br /> <br />  // 位图文件头<br />  $file_header = "BM" . pack("V3", 54 + $size_quad + $size_data, 0, 54 + $size_quad);<br /> <br />  // 位图信息头<br />  $info_header = pack("V3v2V*", 0x28, $width, $height, 1, $bit, $compression, $size_data, 0, 0, $colors_num, 0);<br />  <br />  // 写入文件<br />  if ($filename != '')<br />  {<br />    $fp = fopen("test.bmp", "wb");<br /> <br />    fwrite($fp, $file_header);<br />    fwrite($fp, $info_header);<br />    fwrite($fp, $rgb_quad);<br />    fwrite($fp, $bmp_data);<br />    fclose($fp);<br /> <br />    return 1;<br />  }<br />  <br />  // 浏览器输出<br />  header("Content-Type: image/bmp");<br />  echo $file_header . $info_header;<br />  echo $rgb_quad;<br />  echo $bmp_data;<br />  <br />  return 1;<br />}</code><p>  参考资料:BMP文件格式分析 (出处没有找到…)</p>