0

2x12の配列に10x12ピクセルのビットマップフォント文字を含むCヘッダーファイルがあります(単色液晶の場合)。これにより、パディングをスキップする必要があるためにレンダリングが難しくなることは言うまでもなく、1バイトおきに下位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

ええと、10×12 = 120で、正確に15バイトで120ピクセルを保存できます。5バイトごとに4行のピクセルがエンコードされます。

于 2012-09-25T22:58:35.290 に答える
2

あなたが持っているのは本質的に8x15のスパース行列です。

スパース行列の処理に役立つブーストライブラリ(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 に答える
1

もちろん、これはまさにJBIG CODECが処理するように設計されている種類の問題ですが、膨大な量のビットバンギングが関係します。

ランレングスでも動作する辞書エンコーディングアルゴリズムを使用すると、おそらく適切な結果が得0られます。

于 2012-09-26T13:48:56.533 に答える
0

簡略化されたバージョンでは、プロデューサーのコンシューマーを一度に1ビットずつ作成して、ビットを正常なレベルに保つことができます。これが私がやったことです:

#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 に答える