BMP颜色替换器:填充算法不起作用

时间:2015-02-10 21:25:54

标签: c bitmap padding bmp

我正在构建一个功能,用另一种目标颜色替换BMP图像中的颜色。 只要我不尝试替换需要填充的图像中的颜色,它就可以工作。 但是,我几乎可以肯定我的帐户填充方式是正确的。所以对我来说这是一个完全的谜。


enter image description here


330 x 250(248 054 bytes)Hi-color 24bit bitmap


这是功能:

union
{
    unsigned long ulColor;
    unsigned char byteColor[4];
} oldColor;
union
{
    unsigned long ulColor;
    unsigned char byteColor[4];
} newColor;

typedef unsigned char           BYTE;
typedef unsigned short int      WORD;
typedef unsigned long int       DWORD;
typedef unsigned long long int  DDWORD;

DDWORD
bitfox_color_replace_data
(BYTE *buff, BYTE old_r, BYTE old_g, BYTE old_b, BYTE new_r, BYTE new_g, BYTE new_b)
{
    #define OFFSET_OF_SIZE      0x2
    #define OFFSET_OF_PIXELS    0xA
    #define OFFSET_OF_WIDTH     0x12
    #define OFFSET_OF_HEIGHT    0x16

    DWORD* buffSize     = (DWORD*)&buff[OFFSET_OF_SIZE];
    DWORD* buffPixels   = (DWORD*)&buff[OFFSET_OF_PIXELS];
    DWORD* buffWidth    = (DWORD*)&buff[OFFSET_OF_WIDTH];
    DWORD  buffHeight   = 0;

    BYTE pad            = 0;

    DDWORD pixels_replaced = 0;
    DDWORD i;

    oldColor.byteColor[0] = old_b;  newColor.byteColor[0] = new_b;
    oldColor.byteColor[1] = old_g;  newColor.byteColor[1] = new_g;
    oldColor.byteColor[2] = old_r;  newColor.byteColor[2] = new_r;

    for(i = (*buffPixels); i < (*buffSize); i += 3)
    {
        if( i == ((*buffPixels) + (((*buffWidth) * 3) + pad) * (buffHeight + 1)) )
        {
            pad = ((*buffWidth) % 4);
            buffHeight++;
            i += pad;
        }

        if(!memcmp(buff + i, oldColor.byteColor, 3))
        {
            memcpy(buff + i, newColor.byteColor, 3);

            pixels_replaced++;
        }

    }
    return pixels_replaced;
}

我可能做错了什么?

1 个答案:

答案 0 :(得分:3)

处理位图时,您需要知道三个参数:高度,宽度和步幅。宽度和高度都很明显。 stride是每行的字节数,包括填充。

这是计算stride的一种方法。请注意,stride必须是4的倍数。

int stride = ((width * 3) + 3) >> 2;
stride *= 4;

第一行计算可容纳一行的最小4字节值。第二行将stride转换为字节数。

本文末尾的代码演示了如何使用步幅。该代码假定输入文件包含24bpp RGB图像。文件头已经被读取,只留下像素数据,这些数据被读入buffer。代码写入输出文件,假设输出图像与输入图像的大小相同,并且已经写入任何标题。

重要的是

size = height * stride;           // total number of bytes in the image, including padding

offset = (y * stride) + (x * 3);  // 'y * stride' is the offset to the beginning of a line
                                  // 'x * 3' computes the byte offset of a particular pixel

for ( x=width*3; x<stride; x++ )  // outputs the padding bytes, if needed,
    fputc( 0, fpout );  

unsigned char *buffer = NULL;

int height = bmpinfo.biHeight;
int width  = bmpinfo.biWidth;

// stride = (width * 3), rounded up to a multiple of 4
int stride = ((width * 3) + 3) >> 2;    
stride *= 4;

// size of the pixel data, including padding
size_t size = height * stride;         

// allocate memory for the pixel data
if ( (buffer = malloc( size )) == NULL )
    error( "Insufficient memory" );

// read the pixel data from the file
if ( fread( buffer, 1, size, fpin ) != size )
    error( "Unable to read image data" );

// process pixels by row and column
for ( y = 0; y < height; y++ )
{
    for ( x = 0; x < width; x++ )
    {
        // get the RGB values from the buffer
        offset = (y * stride) + (x * 3);
        blue  = buffer[offset];
        green = buffer[offset+1];
        red   = buffer[offset+2];

        // mess around with the RGB value here

        // write the new RGB values to the file
        fputc( (int)blue , fpout );
        fputc( (int)green, fpout );
        fputc( (int)red  , fpout );
    }

    // write the padding bytes to the file
    for ( x = width*3; x < stride; x++ )
        fputc( 0, fpout );
}