美文网首页嵌入式单片机学习嵌入式开发
热敏打印头打印原理和C实现黑白位图的放大

热敏打印头打印原理和C实现黑白位图的放大

作者: 桂慧要努力当个攻城师 | 来源:发表于2016-10-22 12:26 被阅读940次

    最近的项目中需要实现单片机控制热敏打印机打印图片和文字的功能,但是所选用的字库IC最多支持32*32的中文点阵和32*16的英文点阵。如果需要显示更大的字体,就需要自己用代码实现将原本的32*32位图放大成64*64的点阵,因为如果放大超过2倍出现明显的锯齿边缘。所以代码中只实现了两倍的放大。

    热敏打印机打印原理

    热敏打印机,每一次加热一行点阵数据,就此项目所用的热敏打印机一行共有384个加热点,所以每一行总共有384/8=48个字节的点阵数据。

    #define MAX_WIDTH 48 //每一行最大打印显示的点阵数量的字节表达
    

    每一个字节共有八位加热数据位,1 最终加热打印成黑色,0则不加热,根据加热数据不同。最终显示不同的加热效果。
    把需要打印的字符串规格,转换成相应的字符串点阵缓冲。这里需要注意的是,每一行最多打印48字节的点阵数据,需要处理好每一个字符点阵在这个缓冲中的横竖排列。然后每一次向热敏打印机传送48字节的点阵数据。当加热完一行后,控制步进电机转动,实现送纸功能。

    加热一行点阵数据后控制步进电机的转动步数:
    步进电机转动步数 = 加热点高度/步进电机转动一步的出纸长度
    当遇到结尾遇到换行需要打印空白行时控制步进电机的转动步数:
    步进电机转动步数 = 加热点高度/步进电机转动一步的出纸长度*字符高度*行距

    当打印图片时,需要提前将图片处理成二进制黑白位图,且宽度控制在48字节之内(如果热敏打印机一行的加热点为48字节),然后将位图数据逐行传送给热敏打印头,每加热一行控制步进电机转动相应的步数。直至需要打印显示的黑白图片的位图数据全部传送打印完。

    多灰度色阶的图片打印实现方式(推理猜想)

    如果需要让打印出来的图片,呈现出黑灰白更丰富色阶变化时。可以在图片处理时,将图片进行灰度值处理,这时每一行位图所占的字节数应当为:

    一行位图所占字节数 = 热敏打印机一行加热点字节数*灰度值色阶

    然后根据色阶数对一行进行循环加热,属于当前色阶的则进行加热,不属于的点,则不加热,每个色阶的加热时间按最小灰度值到最大灰度值依次递增。

    伪代码

    for(色阶数)
    {
      for(MAX_WIDTH)
      {
         if(当前点位图数据 == 当前色阶) 
              热敏打印头加热行当前点传1
        else
              热敏打印头加热行当前点传0
      }
      打印头加热数据行(最低加热时间*色阶等级)
    }
    

    位图放大原理

    当需要把位图放大两倍时,整个图片数据就增加了四倍,属于一点对四点。既是源位图中的第一行第一个点,对应了放大后的位图中的第一行第一第二个点以及第二行第一第二个点。源位图中的一个点实际上对应了放大后位图的2*2个点。

    代码解析

    1.扫描源位图的每一行

    for (uint16_t i = 0;i < srcHigh;i++)
    

    srcHigh为源位图的高度即需要放大的行数

    2.扫描一行中需要放大的字节宽度

        for (uint16_t j = 0;j < srcWidth;j++)
    

    srcWidth为源位图的宽度单位字节

    3.扫描每一个字节中的每个位,进行放大处理赋值给目标位图缓冲的相应位

    srcData = 0x80;
    for (uint8_t k = 0; k < 8;k++)
    {
           if ((src[i][j]&srcData) != 0)
           {
                dst[i*multiple][j*multiple+((k*multiple)/8)] |= temp;
            }
        temp = temp >> 2; if (temp == 0x00) temp = 0xC0;  
        srcData = srcData >> 1;
    }
    

    首先判断一个字节的最高位是否为1,如果是为1,则目标位图的对应的字节的两个相邻位就会被赋值成1;
    [j*multiple+((k*multiple)/8)是用来计算字节偏移量的,j*multiple计算出目标位图缓冲对应源位图当前放大字节的初始偏移字节。((k*multiple)/8)则是计算后续偏移量。当计算结果大于等于1时,则偏移一个字节,存放新的放大数据。
    temp = temp >> 2; if (temp == 0x00) temp = 0xC0; 二进制11000000转换成十六进制就是0xC0,当高位判断结束后,判断更低一位时,则需要将temp再右移两个位,才能实现对目标位图字节的更低两位赋值。
    srcData = srcData >> 1;源位图字节位判断参考值。

    完整的实现代码

    void bitmapMagnify(uint8_t src[][MAX_WIDTH],uint8_t dst[][MAX_WIDTH],
        uint8_t multiple,uint16_t srcWidth, uint16_t srcHigh )
    {
        uint8_t temp = 0xC0;
        uint8_t srcData = 0x80;
        
        switch (multiple)
        {
            case 0x02:
                for (uint16_t i = 0;i < srcHigh;i++)
                {
                    for (uint16_t j = 0;j < srcWidth;j++)
                    {
                        srcData = 0x80;
                        
                        for (uint8_t k = 0; k < 8;k++)
                        {
                            if ((src[i][j]&srcData) != 0)
                            {
                                dst[i*multiple][j*multiple+((k*multiple)/8)] |= temp;
                            }
                            temp = temp >> 2; if (temp == 0x00) temp = 0xC0;  
                            srcData = srcData >> 1;
                        }
                    }
                    for (uint8_t a = 0; a < multiple; a++)
                    {
                        for (uint16_t b = 0; b < multiple*srcWidth;b++)
                            dst[i*multiple+a][b] = dst[i*multiple][b];
                    }
                }
                break;
            case 0x04:
                break;
            case 0x08:
                break;
            default :
                break;
        }
    }
    /****************************************************
    

    相关文章

      网友评论

        本文标题:热敏打印头打印原理和C实现黑白位图的放大

        本文链接:https://www.haomeiwen.com/subject/jkzcuttx.html