0

我有一个 C 头文件,其中包含 2x12 数组中的 10x12 像素位图字体字符(对于单色 lcd)。这浪费了每个其他字节的低 6 位,更不用说因为必须跳过填充而更难渲染。

将其转换为没有填充位的简单序列化位的最简单方法是什么?

我看到的解决方案有很多复杂的问题。有没有一种简单的方法来执行此操作?

0x00,0x00,  /*  ................  */
0x30,0x00,  /*  ..@@............  */
0x78,0x00,  /*  .@@@@...........  */
0x48,0x00,  /*  .@..@...........  */
0xCC,0x00,  /*  @@..@@..........  */
0xCC,0x00,  /*  @@..@@..........  */
0xCC,0x00,  /*  @@..@@..........  */
0xFC,0x00,  /*  @@@@@@..........  */
0xCC,0x00,  /*  @@..@@..........  */
0xCC,0x00,  /*  @@..@@..........  */
0x00,0x00,  /*  ................  */
0x00,0x00   /*  ................  */
4

5 回答 5

2

你所拥有的本质上是一个 8x15稀疏矩阵

有一个 boost 库 - uBLAS - 可以帮助您处理稀疏矩阵。例如,如果您的字体尺寸发生变化,这将有所帮助。

这个问题也可能有帮助。

于 2012-09-25T23:47:44.333 回答
2

至于“复杂的位碰撞”......是的,它很复杂,但如果你写下你的打包字节和索引到它们来自的解包数组中,很容易弄清楚如何构造每个值...

|........|........|........|........|........|
|00000000|11222222|22334444|44445566|66666677|

上述循环重复3次。

char a[24] = {
    0x00,0x00,  /*  ................  */
    0x30,0x00,  /*  ..@@............  */
    0x78,0x00,  /*  .@@@@...........  */
    0x48,0x00,  /*  .@..@...........  */
    0xCC,0x00,  /*  @@..@@..........  */
    0xCC,0x00,  /*  @@..@@..........  */
    0xCC,0x00,  /*  @@..@@..........  */
    0xFC,0x00,  /*  @@@@@@..........  */
    0xCC,0x00,  /*  @@..@@..........  */
    0xCC,0x00,  /*  @@..@@..........  */
    0x00,0x00,  /*  ................  */
    0x00,0x00   /*  ................  */
};

void pack( char ap[15], const char a[24] )
{
    ap[0] = a[0];
    ap[1] = a[1] | (a[2] >> 2 );
    ap[2] = (a[2] << 6) | (a[3] >> 2 ) | (a[4] >> 4);
    ap[3] = (a[4] << 4) | (a[5] >> 4) | (a[6] >> 6);
    ap[4] = (a[6] << 2) | (a[7] >> 6);
    ap[5] = a[8];
    ap[6] = a[9] | (a[10] >> 2 );
    ap[7] = (a[10] << 6) | (a[11] >> 2 ) | (a[12] >> 4);
    ap[8] = (a[12] << 4) | (a[13] >> 4) | (a[14] >> 6);
    ap[9] = (a[14] << 2) | (a[15] >> 6);
    ap[10] = a[16];
    ap[11] = a[17] | (a[18] >> 2 );
    ap[12] = (a[18] << 6) | (a[19] >> 2 ) | (a[20] >> 4);
    ap[13] = (a[20] << 4) | (a[21] >> 4) | (a[22] >> 6);
    ap[14] = (a[22] << 2) | (a[23] >> 6);
}

如果您愿意,您可以在一个小循环中执行上述操作,以减少犯错的范围......只需从 0 循环到 2,并相应地推进您的数组。你知道,有点像这样(除非你需要正确的指针):

for( int i = 0; i < 3; i++ ) {
    ap[0] = a[0];
    ap[1] = a[1] | (a[2] >> 2 );
    ap[2] = (a[2] << 6) | (a[3] >> 2 ) | (a[4] >> 4);
    ap[3] = (a[4] << 4) | (a[5] >> 4) | (a[6] >> 6);
    ap[4] = (a[6] << 2) | (a[7] >> 6);
    ap += 5;
    a += 8;
}

我希望我把所有这些转变都做对了=)

于 2012-09-25T23:58:41.650 回答
2

嗯,10 × 12 = 120,你可以在 15 个字节中存储 120 个像素。每 5 个字节编码 4 行像素。

于 2012-09-25T22:58:35.290 回答
1

这当然正是JBIG CODEC旨在处理的那种问题——但会涉及大量的位碰撞。

使用运行长度为的字典编码算法,您可能还会获得不错的结果0

于 2012-09-26T13:48:56.533 回答
0

一个简化的版本可以创建一个生产者消费者,一次只做一点,这让一点点保持在一个理智的水平。这就是我最终做的事情:

#define CHAR_W 10
#define CHAR_H 12
#define NUM_CHARS 100
#define CEILING(x,y) (((x) + (y) - 1) / (y))
#define BYTES CEILING(CHAR_W, 8)
#define BIT(x, n) ( ((1 << n) & x) >> n )
#define COPYBIT(b,x,n) (((0x1 & b) << n) | x)
#define CHAR_BYTES CEILING(CHAR_H * CHAR_W, 8)
#define OUTBYTES NUM_CHARS * CHAR_BYTES

int main()
{
    int totinbit = 0;
    int locinbit = 0;
    int locoutbit = 7;  // start with msb 
    int totoutbit = 0;
    int bytes = BYTES;

    unsigned char c = 0;
    unsigned char o = 0;
    unsigned char buf[OUTBYTES];

    while (totoutbit < NUM_CHARS * CHAR_H * CHAR_W)
    {
        c = fontArray[totinbit / 8];
        locinbit = 7 - totinbit % 8;

        o = COPYBIT(BIT(c,locinbit),o,locoutbit);

        // reset out counter, full byte produced
        if (--locoutbit < 0)
        {
            locoutbit = 7;
            buf[totoutbit  / 8] = o;
            o = 0;
        }

        // skip over the padding bits
        if ((totoutbit % CHAR_W) == (CHAR_W - 1))
            totinbit =  CEILING(totinbit,8) * 8 - 1;

        totinbit++;     
        // character boundary
        if ( (totinbit % (bytes * 8 * CHAR_H)) == 0 && totinbit > 0)
        {
                            // pad the last byte in the character if necessary
            if (locoutbit != 7)
                    locoutbit = 7;
        }

        totoutbit++;


        }
 // at this point buf contains the converted bitmap array
}
于 2012-09-26T17:21:21.190 回答