перевернуть 1bpp .bmp изображение по горизонтали - PullRequest
0 голосов
/ 15 января 2011

Я пытаюсь написать программу, содержащую два исходных файла: основную программу, написанную на C, и модуль сборки (x86 32 и 64), вызываемый из C. Объявление C для процедуры сборки выглядит следующим образом: void mirrorbmp1 (void * img), int width, int height)

Задача состоит в том, чтобы отразить / перевернуть изображение размером 1 bpp .BMP по горизонтали при правильной обработке любой ширины изображения, а не только кратно 8.

Я новичок в сборкепрограммирование и я очень мало знаю о том, как я должен делать запрос.

Любая помощь будет оценена.

Ответы [ 3 ]

1 голос
/ 15 января 2011

Решение должно основываться на инструкциях по сдвигу и повороту в ассемблере. Если вы знаете, как программировать с помощью макросов, вы можете создать умный макрос, который будет генерировать вам 8 версий подпрограммы для каждой ширины изображения (от 0 до 7 бит в последнем байте).

Пример для базовой ситуации, когда ширина кратна 8:

;al ... byte from input
;bl ... for output

;load from [esi] to al and move to next byte:
lodsb

repeat 8x:
shr al
rol bl

;store bl do [edi] and move to previous byte:
mov [edi],bl
dec edi

Пример ширины, не кратной 8:

repeat 3x:
shr al
rol bl

lodsb

repeat 5x:
shr al
rol bl

mov [edi],bl
dec edi

Я надеюсь, что эти короткие примеры помогут вам в этом, и вы сможете самостоятельно составить полное решение. Удачи.

0 голосов
/ 15 января 2011

Я не знаю, как файл .bmp хранится в памяти, но при первом подходе я сделал бы что-то похожее (псевдокод):

for y = 1 to row_num
    for x = 1 to col_num / 2
        swap pixel(x, y) with pixel(col_num - x, y);
    next x
next y
0 голосов
/ 15 января 2011

Если изображение является .BMP, то каждая строка выравнивается по границе DWORD, поэтому по крайней мере начало каждой строки выравнивается по границе байта.

Чтобы отразить изображение, необходимо изменить порядок битов в каждом байте, а также изменить порядок байтов. Их можно легко комбинировать:

void rev_line(unsigned char* line, unsigned char* tmp_buff, int line_sz){
    unsigned char* line2 = line + line_sz/8 - 1; // last complete byte of the input buffer
    int bit_delta = line_sz % 8; // number of unaligned bits. 
    // special case for bit_delta == 0 :
    if (!bit_delta){ // just reverse the input
        while (line < line2){
            unsigned char c = reverse(*line);
            *line++ = reverse(*line2);
            *line2-- = c;
        };
        if (line == line2) // odd number of bytes, so we'll just reverse it.
            *line = reverse(*line);
        return;
    };
    // now we have to take bit_delta bits from 
    for (; line2 >= line; line2--)
        *tmp_buff++ = (reverse(line2[1]) >> (8 - bit_delta) | // not sure about endianness here!
                      (reverse(line2[0]) << bit_delta;
    memcpy(line, tmp_buff, (line_sz + 7) / 8);
};

Это не оптимизировано, но объясняет идею. Обратите внимание, что вы должны быть очень хороши в сборке, чтобы иметь возможность побеждать компилятор C, так что измерьте!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...