Как да конвертирате растерен шрифт от C формат на заглавка в необработени битове

Имам C заглавен файл, който съдържа 10x12 пикселни растерни шрифтови знаци в масив от 2x12 (за монохромен цветен 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   /*  ................  */

person MandoMando    schedule 25.09.2012    source източник
comment
Не, няма начин да се сериализират битове без много битови удари. И бих си помислил, че допълнителната подложка ще направи кода по-прост, а не по-труден.   -  person Mark Ransom    schedule 26.09.2012


Отговори (5)


Е, 10 12 = 120 и можете да съхраните 120 пиксела в 15 байта, точно. Всеки 5 байта кодират 4 реда от пиксели.

person Kerrek SB    schedule 25.09.2012
comment
Наистина ли? два пъти за посочване на аритметика и без истински отговор? - person MandoMando; 26.09.2012

Това, което имате, е по същество 8x15 разредена матрица.

Има библиотека за повишаване - uBLAS - за да ви помогне да се справите с разредени матрици. Би помогнало, например, ако размерите на шрифта ви се променят.

Този въпрос също може да е от полза.

person Carl    schedule 25.09.2012

Що се отнася до „сложното разбиване на битове“... Да, сложно е, но ако запишете опакованите си байтове и индекса в неопакования масив, откъдето идват, е достатъчно лесно да разберете как да конструирате всяка стойност ...

|........|........|........|........|........|
|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;
}

Надявам се, че направих всички тези смени правилно =)

person paddy    schedule 25.09.2012
comment
благодаря, че публикувахте това. Надявах се на нещо малко по-общо, което да работи и с други размери на символи. Все пак дава представа. - person MandoMando; 26.09.2012
comment
О, добре... Е, вижте операциите, които направих, и ги комбинирайте с начина, по който написах тези индекси. Ще бъде объркващо, но единственият истински трик е последният байт (ако ширината на знака не е кратна на 8 бита). Това е моментът, в който „отклонявате“ вашите bitshifts. - person paddy; 27.09.2012
comment
Да, в крайна сметка изскачах по един бит и добавях към dst масив. Идеята за преместване на няколко бита на променливи места в общо решение ми създаваше главоболие. Дрейфът наистина влиза в действие, публикуваното от мен решение има малък проблем, когато WxH не е кратно на 8, но 8 дели остатъка. Така отклонението се сумира и подравнява към границата на байта. Както и да е, благодаря за вдъхновението! - person MandoMando; 27.09.2012

Това, разбира се, е точно видът проблем, с който JBIG CODEC е предназначен да се справи - но ще да бъде включено чудовищно количество битови удари.

Вероятно ще получите и прилични резултати с алгоритми за кодиране на речници, работещи и върху дължини на изпълнение на 0.

person marko    schedule 26.09.2012

Една опростена версия може да създаде потребител на производител, който върви един по един, което поддържа битовото натоварване на разумно ниво. Ето какво в крайна сметка направих:

#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
}
person MandoMando    schedule 26.09.2012