php转换图片为.bin文件

[我的另外一个博客地址:http://www.ncmacker.cc,那边排版会比较好点。]

公司的打印机最近新添加一个打印图片的功能,具体是用户在后台设置他的logo,服务器接收到图片文件,转换单色的bmp文件(热敏打印机),再由php将单色bmp图片转换成bin文件,里面包含了图片的头信息和数据。做这么个小功能还花了我不少时间,走了很多弯路,各位看官请容我一一讲述吧。

思路1:使用PHP扩展用c语言来完成这个操作

最开始的时候,认为这个操作php语言无法胜任,于是选用了php extension。可是作为菜鸟的我,何曾玩过这么高大上的技能?没办法了,只好现学现卖了,最开始我以为是只要用c语言将转换的功能实现了,然后封装下就可以给php调用,做到后面才发现很多c语言的函数都不能直接使用,要么是被阉割掉了,要么就是被zend重写了,只有遵循zend_api才能够做出一个有用的php扩展。网上搜索了很多关于php extension的资料,发现中文资料还是相对较少。虽然有那么几个稍微系统点的资料:

PHP扩展开发及内核应用

这本书的是翻译的一本国外一个大牛的扩展开发的书籍,翻译的还是比较有水准的,这个翻译项目的发起人也是大牛,其中最为知名的应该是鸟哥,如果连鸟哥都不知道的话,你这php程序员估计也是白当了。

还有极客学院也有一份这本书,与上面介绍的差不多。还有这本深入理解php内核:Thinking In PHP Int ernals也不错。还有一些国外牛人整理的一些资料,先不再这里罗嗦,待会放在结尾当福利发送哈。

我的php extension第一步是先搭建环境,我也把搭建环境的步骤也讲下吧,这样也方便其他需要使用到扩展的童鞋。

1.下载php的完整版源码,我的是php-5.4.41版本的,因为公司的服务器就是使用的5.4.41的,不然版本不对,扩展就算开发好了,后面也是无法添加到php里的(可以兼容老版本的,但是开发版本不能比服务器版本高)。

2.将下载好的php源码解压放在某个地方,我的是放在主文件夹里(就是ubuntu的个人文件夹里)。

然后用cd命令跳转到php-5.4.41/ext目录下:

cd /home/pchangl/php-5.4.41/ext

然后在主文件夹下创建一个extension_def的目录(这个目录不是必须的,只是我为了方便管理.def的文件才建立的),在这个文件夹下建立一个叫做pchangl.def的文件(def的文件是扩展方法的签名)。

这个时候建立好了def的文件,我们就开始使用php/ext目录下的ext_skel小工具为我们的扩展生成框架。

root@pchangl:/home/pchangl/php-5.4.41/ext #ext_skel --extname=pchangl --proto=/home/pchangl/php-extension/pchangl.def

这个时候就给我们生成了扩展的框架:

这个时候我们的框架已经生成了,我们先把config.m4文件修改下,删除掉第16,17,18行前的dnl注释

这个时候我们就可以修改pchangl.c的代码了,这个文件里的代码就是我们自己的程序代码。

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_pchangl.h"

static int le_pchangl;
const zend_function_entry pchangl_functions[] = {
    PHP_FE(confirm_pchangl_compiled,    NULL)       /* For testing, remove later. */
    PHP_FE_END  /* Must be the last line in pchangl_functions[] */
};
zend_module_entry pchangl_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    "pchangl",
    pchangl_functions,
    PHP_MINIT(pchangl),
    PHP_MSHUTDOWN(pchangl),
    PHP_RINIT(pchangl),     /* Replace with NULL if there's nothing to do at request start */
    PHP_RSHUTDOWN(pchangl), /* Replace with NULL if there's nothing to do at request end */
    PHP_MINFO(pchangl),
#if ZEND_MODULE_API_NO >= 20010901
    PHP_PCHANGL_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_PCHANGL
ZEND_GET_MODULE(pchangl)
#endif
PHP_MINIT_FUNCTION(pchangl)
{
    return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(pchangl)
{
    return SUCCESS;
}
PHP_RINIT_FUNCTION(pchangl)
{
    return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(pchangl)
{
    return SUCCESS;
}
PHP_MINFO_FUNCTION(pchangl)
{
    php_info_print_table_start();
    php_info_print_table_header(2, "pchangl support", "enabled");
    php_info_print_table_end();
}
PHP_FUNCTION(confirm_pchangl_compiled)
{
    char *arg = NULL;
    int arg_len, len;
    char *strg;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
        return;
    }
    len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "pchangl", arg);
    RETURN_STRINGL(strg, len, 0);
}

上面的这个代码是ext_skel工具生成的框架,你写的扩展也要按照他的标准来写,由于代码长度的原因,我删除掉了一部分生成的注释,如果想看的话,你可以自己编写个框架看看注视,下面我就讲解下几个比较重要的部分吧。

PHP_MINIT_FUNCTION(pchangl)
{
    return SUCCESS;
}

这个方法随着php在apache或者nginx中启动而诞生内存的时候,就会执行,可以把这个方法当成初始化的方法吧。


PHP_RINIT_FUNCTION(pchangl)
{
    return SUCCESS;
}

这个方法会在每一个页面请求到来的时候执行。


PHP_RSHUTDOWN_FUNCTION(pchangl)
{
    return SUCCESS;
}

RINIT_FUNCTION方法执行玩后,请求也处理的差不多了,这个时候就会进入这个方法,启动回收程序来收拾烂摊子。


PHP_MSHUTDOWN_FUNCTION(pchangl)
{
    return SUCCESS;
}

前面该启动的也启动了,该结束的也结束了,现在该apache老人家休息的时候,当apache通知php自己要stop的时候,就会进入这个方法。给扩展下最后通碟,如果有未了的心愿,就放在这个方法里,这可是最后的机会哦


PHP_FUNCTION(function name)
{
    //实现
}

这个方法就是我们扩展方法的主体了。

pchangl.c这个文件就介绍到这里了,其他的内容就到我推荐的几个资料中查询吧,都有的。我也就不一一讲解了。

介绍完了环境的搭建,我就开始写自己的扩展,我们的bmp转bin的c代码是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

//调试开关
#define PRINTF_DEBUG 0

//四个字节对齐  进1制处理
#define WIDTHBYTES(bits)    (((bits)+31)/32*4)  //每一行的像素宽度必须是4的倍数,否则补0补齐。

/*定义BYTE为无符号一个字节的类型*/
typedef unsigned char   BYTE;
/*定义WORD为无符号两个字节的类型*/
typedef unsigned short  WORD;
/*定义DWORD为无符号四个字节的类型*/
typedef unsigned long   DWORD;

#pragma pack(1)

/*位图文件头*/
typedef struct BMP_FILE_HEADER
{
    WORD    bType;              /* 文件标识符 */
    DWORD   bSize;              /* 文件的大小 */
    WORD    bReserved1;         /* 保留值,必须设置为0 */
    WORD    bReserved2;         /* 保留值,必须设置为0 */
    DWORD   bOffset;            /* 文件头的最后到图像数据位开始的偏移量 */
} BMPFILEHEADER;

/*位图信息头*/
typedef struct BMP_INFO
{
    DWORD   bInfoSize;          /* 信息头的大小 */
    DWORD   bWidth;             /* 图像的宽度 */
    DWORD   bHeight;            /* 图像的高度 */
    WORD    bPlanes;            /* 图像的位面数 */
    WORD    bBitCount;          /* 每个像素的位数 */
    DWORD   bCompression;       /* 压缩类型 */
    DWORD   bmpImageSize;       /* 图像的大小,以字节为单位 */
    DWORD   bXPelsPerMeter;     /* 水平分辨率 */
    DWORD   bYPelsPerMeter;     /* 垂直分辨率 */
    DWORD   bClrUsed;           /* 使用的色彩数 */
    DWORD   bClrImportant;      /* 重要的颜色数 */
} BMPINF;

typedef struct tagRGBQUAD
{
    BYTE    rgbBlue;            //蓝色的亮度(值范围为0-255)
    BYTE    rgbGreen;           //绿色的亮度(值范围为0-255)
    BYTE    rgbRed;             //红色的亮度(值范围为0-255)
    BYTE    rgbReserved;        //保留,必须为0
} RGBQUAD;

#pragma pack()

int main()
{
    FILE *fpin = NULL;
    FILE *fpout = NULL;
    BMPFILEHEADER fileHeader = { 0, 0 };
    BMPINF infoHeader = { 0, 0 };
    RGBQUAD imgHeader[256 * 4] = { 0, 0 };
    DWORD offset = 0, width = 0, height = 0, bitCount = 0;
    DWORD l_width = 0, bmp_width = 0, bmp_height = 0;
    DWORD i = 0, j = 0, m = 0;
    BYTE *bmpDataTmp = NULL;
    BYTE *bmpPixelTmp = NULL;
    BYTE bmp_start[8] = "ICONTOP";
    BYTE bmp_end[8] = "ICONEND";

    //打开文件
    if((fpin = fopen("logo.bmp", "rb")) == NULL)
    {
        printf("\r\nCann't open the file!\r\n");
#if PRINTF_DEBUG

        while(1);

#endif
        return 1; //错误,返回1
    }

    //把fpin指针移动到文件开头
    fseek(fpin, 0, 0);
    //获取文件头数据
    fread(&fileHeader, sizeof(fileHeader), 1, fpin);
    //获取信息头数据
    fread(&infoHeader, sizeof(infoHeader), 1, fpin);
    //计算并输出位图数据的偏移量,图像的宽度和高度,每个像素的位数
    offset = fileHeader.bOffset;
    width = infoHeader.bWidth;
    height = infoHeader.bHeight;
    bitCount = infoHeader.bBitCount;
#if PRINTF_DEBUG
    printf("\r\noffset=%d, width=%d, height=%d, bitCount=%d\r\n", offset, width, height, bitCount);
#endif
    l_width = WIDTHBYTES(width * bitCount); //每一行的像素宽度必须是4的倍数,否则补0补齐。

    //图象限制:单色位图,宽48字节内,尺寸1024 * 20字节内。
    if((bitCount == 1) && (((l_width + bitCount - 1) / bitCount) * bitCount / bitCount <= 48) && (((l_width + bitCount - 1) / bitCount) * bitCount / bitCount * height <= 1024 * 20))
    {
        if((bmpPixelTmp = (unsigned char *)malloc(sizeof(char) * (((l_width + bitCount - 1) / bitCount) * bitCount * height))) == NULL)
        {
            printf("\r\nData allocation failed!\r\n");
#if PRINTF_DEBUG

            while(1);

#endif
            return 1; //错误,返回1
        }

        memset(bmpPixelTmp, 0, sizeof(char) * (((l_width + bitCount - 1) / bitCount) * bitCount * height));
        //获取其他数据
        fread(imgHeader, sizeof(char), (offset - 54), fpin);
        //获取图像数据
        fread(bmpPixelTmp, sizeof(char), (l_width * height), fpin);
        //关闭文件
        fclose(fpin);

        if((bmpDataTmp = (unsigned char *)malloc(sizeof(char) * (((l_width + bitCount - 1) / bitCount) * bitCount * height / bitCount))) == NULL)
        {
            printf("\r\nData allocation failed!\r\n");
#if PRINTF_DEBUG

            while(1);

#endif
            return 1; //错误,返回1
        }

        memset(bmpDataTmp, 0, sizeof(char) * (((l_width + bitCount - 1) / bitCount) * bitCount * height / bitCount));

        /*********************************************图像数据纠正*********************************************/
        for(m = 0, i = 0; i < height; i++)
        {
            for(j = 0; j < l_width; j = j + 1)
            {
                bmpDataTmp[m] =  ~bmpPixelTmp[(height - i - 1) * l_width + j + 0]; //图像纠正
                m = m + 1;
            }
        }

        /**********************************************结  束**********************************************/
        /*********************************************图像数据填充*********************************************/
        for(m = 0, i = 0; i < height; i++)
        {
#if PRINTF_DEBUG
            printf("\r\n");
#endif

            for(j = 0; j < (((l_width + bitCount - 1) / bitCount)*bitCount / bitCount); j = j + 1)
            {
                if(j == width / 8)
                {
                    bmpDataTmp[m] = (bmpDataTmp[m]) & (~(0xff >> (width - width / 8 * 8))); //多余位填白
                }
                else if(j > width / 8)
                {
                    bmpDataTmp[m] = 0x00; //多余字节填白
                }
                else
                {
                    bmpDataTmp[m] =  bmpDataTmp[m]; //不处理
                }

#if PRINTF_DEBUG
                printf("%d%d%d%d%d%d%d%d", (bmpDataTmp[m] & 0x80) >> 7, (bmpDataTmp[m] & 0x40) >> 6, (bmpDataTmp[m] & 0x20) >> 5, (bmpDataTmp[m] & 0x10) >> 4, (bmpDataTmp[m] & 0x08) >> 3, (bmpDataTmp[m] & 0x04) >> 2, (bmpDataTmp[m] & 0x02) >> 1, (bmpDataTmp[m] & 0x01) >> 0);
#endif
                m = m + 1;
            }
        }

        /**********************************************结  束**********************************************/
        /*****************************************数据写入BIN文件******************************************/
        //第01~07字节:命令头"ICONTOP"
        //第08~09字节:图片高bmp_height
        //第10~11字节:图片宽bmp_width
        //   其他字节:图像数据
        //最后7个字节:命令尾"ICONEND"
        /**************************************************************************************************/
        //打开文件
        if((fpout = fopen("logo.bin", "wb+")) == NULL)
        {
            printf("\r\nCann't open the file!\r\n");
#if PRINTF_DEBUG

            while(1);

#endif
            return 1; //错误,返回1
        }

        //把fpout指针移动到文件开头
        fseek(fpout, 0, 0);
        bmp_height = height;
        bmp_width = ((l_width + bitCount - 1) / bitCount) * bitCount / bitCount;
        //写入命令头"ICONTOP"
        fwrite(&bmp_start, 7, 1, fpout);
        //写入图片高
        fwrite(&bmp_height, 2, 1, fpout);
        //写入图片宽
        fwrite(&bmp_width, 2, 1, fpout);
        //写入图像数据
        fwrite(bmpDataTmp, (bmp_height * bmp_width), 1, fpout);
        //写入命令尾"ICONEND"
        fwrite(&bmp_end, 7, 1, fpout);
        //关闭文件
        fclose(fpout);
        /**********************************************结  束**********************************************/
        free(bmpDataTmp);
        bmpDataTmp = NULL;
        free(bmpPixelTmp);
        bmpPixelTmp = NULL;
    }
    else
    {
        //关闭文件
        fclose(fpin);
        printf("\r\nIt has high resolution for this picture!\r\n");
#if PRINTF_DEBUG

        while(1);

#endif
        return 1; //错误,返回1
    }

#if PRINTF_DEBUG

    while(1);

#endif
    return 0; //正确,返回0
}

上面的代码就不详细讲解了,注释挺清楚的。可是发现有很多c的函数在扩展开发的时候是不能使用的,于是就开始了最为苦逼的工作,翻看zend文档,把能用的方法找出来,实在是没有,就自己重写。这段工程实在是复杂,就不列出代码了。后面因为太费时间了,还没写完就放弃了。换了一种思路来实现:

PHP_FUNCTION(Convert_pchangl)
{
    FILE *fi,*fo;
    char *fromurl = NULL;
    char *tourl = NULL;
    int argc = ZEND_NUM_ARGS();
    int fromurl_len;
    int tourl_len;

    int ch,i=0,j=0;


    //check the parameters
    if (zend_parse_parameters(argc TSRMLS_CC, "ss", &fromurl, &fromurl_len, &tourl, &tourl_len) == FAILURE)
        return;

    fi = fopen(fromurl,"r");
    fo = fopen(tourl,"w+");
    if(fi == NULL ||fo == NULL)
    {
            php_error(E_WARNING, "Convert_pchangl: not yet implemented");
            char *str="Open the file Error!";
            RETURN_STRINGL(str, sizeof(str), 0);
    }else{
        //char *str="Open the file Success!";
        //RETURN_STRINGL(str, sizeof(str), 0);
    }

    //php_printf("Hello, PHP v5.2.5 - 2008-3-28");
    //一直读取,直到bmp文件结束(EOF)
  //注意,在我读取时,有时16进制为“1A”时会被读成EOF,所以我用UltraEdit把“0A”改成了“0B”
  while((ch = fgetc(fi)) != EOF)
  {
      php_printf("0x%02x,",ch);
            //php_printf("0x"+ch+"2x");
      //bmpinf[j] =ch;//把图像同时保存在全局变量里
            //php_printf("There are %u million cars in %s.",123,"str:");
      i++;
      if(i == 263)//输出到文件时,16个数据为一行
      {
          php_printf("<br>");
          i = 0;
      }
      j++;
  }
  //php_printf("\n};");
  //php_printf("bmp size : %d",j);
  //return j;//返回数据长度
    //RETURN_STRINGL(fromurl,fromurl_len,0);
    //php_error(E_WARNING, "Convert_pchangl: not yet implemented");
}

这段就是php_function的代码,刚实现了把bmp所有的数据读出来,并且输出到了浏览器中。这时候脑子一抽筋,就去翻看了一下php中其他图片格式的代码转换成bmp的代码:

/*
int imagebmp ( resource image [, string filename [, int $bit [, int compression]]] )

$im: 图像资源
$filename: 如果要另存为文件,请指定文件名,为空则直接在浏览器输出
$bit: 图像质量(1、4、8、16、24、32位)
$compression: 压缩方式,0为不压缩,1使用RLE8压缩算法进行压缩

注意:这个函数仍然需要GD库的支持。

Demo:

$filename="9.jpg";
$extension=get_extension($filename);
exit;
switch(extension){
    case 'jpg':
        $im = imagecreatefromjpeg($filename);
        echo "jpeg";
        break;
    case 'png':
        $im = imagecreatefrompng($filename);
        echo "png";
        break;
    default:
        echo "只能上传jpg和png图片!";
        end;
        break;
}
$im = imagecreatefrompng('3.png');
//$im=imagecreatefromjpeg("1417743927755.jpg");
ImageToBlackAndWhite($im);
imagebmp($im,"9.bmp",'8');
imagedestroy($im);
Source:
echo "<img src='9.bmp' />";

*/



/**

* 取图片后缀
*/
function get_extension($file)
{
    return @end(explode('.', $file));
}


/**

* 将图片转换成黑白色
* @author:pchangl,Amed(stack overflow)
* @link:http://tingm.cc
* @version: 0.1
* @param resource $im       图像资源
*/
function ImageToBlackAndWhite($im,$level) {

    for ($x = imagesx($im); $x--;) {
        for ($y = imagesy($im); $y--;) {
            $rgb = imagecolorat($im, $x, $y);
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8 ) & 0xFF;
            $b = $rgb & 0xFF;
            $gray = ($r + $g + $b)/ $level;
            if ($gray < 0xFF) {

                imagesetpixel($im, $x, $y, 0xFFFFFF);
            }else
                imagesetpixel($im, $x, $y, 0x000000);
        }
    }

    imagefilter($im, IMG_FILTER_NEGATE);

}

/**

* 创建bmp格式图片
*

* @author: legend(legendsky@hotmail.com)
* @link: http://www.ugia.cn/?p=96
* @description: create Bitmap-File with GD library
* @version: 0.1
*

* @param resource $im          图像资源
* @param string   $filename    如果要另存为文件,请指定文件名,为空则直接在浏览器输出
* @param integer  $bit         图像质量(1、4、8、16、24、32位)
* @param integer  $compression 压缩方式,0为不压缩,1使用RLE8压缩算法进行压缩
*

* @return integer
*/
function imagebmp(&$im, $filename = '', $bit = 8, $compression = 0)
{
    if (!in_array($bit, array(1, 4, 8, 16, 24, 32)))
    {
        $bit = 8;
    }
    else if ($bit == 32) // todo:32 bit
    {
        $bit = 24;
    }
    $bits = pow(2, $bit);

    // 调整调色板
    imagetruecolortopalette($im, true, $bits);
    $width  = imagesx($im);
    $height = imagesy($im);
    $colors_num = imagecolorstotal($im);

    if ($bit <= 8)
    {
        // 颜色索引
        $rgb_quad = '';
        for ($i = 0; $i < $colors_num; $i ++)
        {
            $colors = imagecolorsforindex($im, $i);
            $rgb_quad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0";
        }

        // 位图数据
        $bmp_data = '';

        // 非压缩
        if ($compression == 0 || $bit < 8)
        {
            if (!in_array($bit, array(1, 4, 8)))
            {
            $bit = 8;
            }
            $compression = 0;

            // 每行字节数必须为4的倍数,补齐。
            $extra = '';
            $padding = 4 - ceil($width / (8 / $bit)) % 4;
            if ($padding % 4 != 0)
            {
            $extra = str_repeat("\0", $padding);
            }

            for ($j = $height - 1; $j >= 0; $j --)
            {
                $i = 0;
                while ($i < $width)
                {
                    $bin = 0;
                    $limit = $width - $i < 8 / $bit ? (8 / $bit - $width + $i) * $bit : 0;

                    for ($k = 8 - $bit; $k >= $limit; $k -= $bit)
                    {
                        $index = imagecolorat($im, $i, $j);
                        $bin |= $index << $k;
                        $i ++;
                    }

                    $bmp_data .= chr($bin);
                }

                $bmp_data .= $extra;
            }
        }
        // RLE8 压缩
        else if ($compression == 1 && $bit == 8)
        {
            for ($j = $height - 1; $j >= 0; $j --)
            {
                $last_index = "\0";
                $same_num   = 0;
                for ($i = 0; $i <= $width; $i ++)
                {
                    $index = imagecolorat($im, $i, $j);
                    if ($index !== $last_index || $same_num > 255)
                    {
                        if ($same_num != 0)
                        {
                            $bmp_data .= chr($same_num) . chr($last_index);
                        }

                        $last_index = $index;
                        $same_num = 1;
                    }
                    else
                    {
                    $same_num ++;
                    }
                }

                $bmp_data .= "\0\0";
            }

            $bmp_data .= "\0\1";
        }
        $size_quad = strlen($rgb_quad);
        $size_data = strlen($bmp_data);
    }
    else
    {
    // 每行字节数必须为4的倍数,补齐。
        $extra = '';
        $padding = 4 - ($width * ($bit / 8)) % 4;
        if ($padding % 4 != 0)
        {
            $extra = str_repeat("\0", $padding);
        }
        // 位图数据
        $bmp_data = '';
        for ($j = $height - 1; $j >= 0; $j --)
        {
            for ($i = 0; $i < $width; $i ++)
            {
                $index  = imagecolorat($im, $i, $j);
                $colors = imagecolorsforindex($im, $index);
                if ($bit == 16)
                {
                    $bin = 0 << $bit;

                    $bin |= ($colors['red'] >> 3) << 10;
                    $bin |= ($colors['green'] >> 3) << 5;
                    $bin |= $colors['blue'] >> 3;

                    $bmp_data .= pack("v", $bin);
                }
                else
                {
                    $bmp_data .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);
                }

                // todo: 32bit;
            }
            $bmp_data .= $extra;
        }
        $size_quad = 0;
        $size_data = strlen($bmp_data);
        $colors_num = 0;
    }

    // 位图文件头
    $file_header = "BM" . pack("V3", 54 + $size_quad + $size_data, 0, 54 + $size_quad);

    // 位图信息头
    $info_header = pack("V3v2V*", 0x28, $width, $height, 1, $bit, $compression, $size_data, 0, 0, $colors_num, 0);

    // 写入文件
    if ($filename != '')
    {
        $fp = fopen($filename, "wb");
        fwrite($fp, $file_header);
        fwrite($fp, $info_header);
        fwrite($fp, $rgb_quad);
        fwrite($fp, $bmp_data);
        fclose($fp);
        return true;
    }

    // 浏览器输出
    header("Content-Type: image/bmp");
    echo $file_header . $info_header;
    echo $rgb_quad;
    echo $bmp_data;
    return true;
}

这个时候才想到,其实我已经拿到了bmp图片的数据,为什么还要去用c来解码bmp尼?真是脑子抽筋了,发现在这个代码了,其实已经拿到了数据了,于是在写到文件这部分稍微修改下,把bmp的信息保存到文件中就好了:

    $fp=fopen($filename,"wb");
    fwrite($fp,"ICONTOP");
    fwrite($fp,$pack("v1",$height));
    fwrite($fp,$pack("v1",(int)(($width+31)/32)*4));
    fwrite($fp,$bmp_data);
    fwrite($fp,"ICONEND");

这个函数的调用是这样的:

imagebmp($im,$filename.".bin",'1');

到这里就好了,把生成的bin文件拿到打印机那边去测试,发现完美打印:

接下来就是把打印机交互的接口完善了就好了。

——————小编菜鸟一只,讲的不好的地方,欢迎批评,邮箱:pchangl@163.com ,如果有什么不明白的也可以随时骚扰。只要我能解答,绝不藏私。

www.ncmacker.cc

posted @ 2015-11-04 22:35  彭长霖  阅读(310)  评论(0编辑  收藏  举报