水平翻转1bpp .bmp图像

时间:2011-01-15 18:21:41

标签: c assembly image-processing x86

我正在尝试编写一个包含两个源文件的程序:用C语言编写的主程序和从C调用的程序集(x86 32和64)模块。程序集例程的C语句如下所示: void mirrorbmp1(void * img,int width,int height)

该任务涉及水平镜像/翻转1 bpp .BMP图像,同时正确处理任何图像宽度,而不仅是8的倍数。

我是汇编编程的新手,对我应该怎么做这个问题一无所知。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:1)

解决方案应该基于汇编程序中的shift和rotate指令。如果您知道如何使用宏进行编程,则可以创建一个智能宏,它将为每个图像宽度生成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

我希望这些简短的例子可以为您提供足够的指导,以便您可以自己制作完整的解决方案。祝你好运。

答案 1 :(得分:0)

如果图像是.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编译器,所以要测量!

答案 2 :(得分:0)

我不知道.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