开发者

flip a 1bpp .bmp image horizontally

I am trying to write a progr开发者_StackOverflow社区am containing two source files: main program written in C and assembly(x86 32 and 64) module callable from C. The C declaration for the assembly routine looks like this: void mirrorbmp1(void *img, int width, int height)

The task involves Mirror/flipping a 1 bpp .BMP image horizontally while Handling any image width properly, not only multiples of 8.

I am new to assembly programming and have very little idea about how i should do the ask.

Any help would be appreciated.


The solution should be based on shift and rotate instructions in assembler. If you know how to program with macros, you can make a smart macro which will generate you 8 versions of the routine for each width of image (0 to 7 bits in last byte).

Example for basic situation where width is a multiple of 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

Example for width not being multiple of 8:

repeat 3x:
shr al
rol bl

lodsb

repeat 5x:
shr al
rol bl

mov [edi],bl
dec edi

I hope these short examples can guide you enough so you can make the complete solution on your own. Good luck.


If the image is a .BMP, then each line is alighed on DWORD boundary, so at least the beginning of each line is alighed at byte boundary.

To mirror the image you have to reverse the order of bits in each byte, and also to reverse the byte order. They can be combined easily:

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

It's not optimized, but explains the idea. Note that you have to be very good at assembly to be able to beat C compiler, so measure!


I don't know how a .bmp file is stored in memory, but at first approach I would do something similar to (pseudocode):

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜