【问题标题】:BMP color replacer: Algorithm for padding doesn't workBMP 颜色替换器:填充算法不起作用
【发布时间】:2015-04-11 02:25:28
【问题描述】:

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



330 x 250(248 054 字节)高彩 24 位位图


这是函数:

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

我可能做错了什么?

【问题讨论】:

  • 如果您提供了一种读取文件的方法,以便可以单步执行代码,则可能更容易发现错误。我看到的问题静态地围绕着用于输入pad = 语句的条件语句。我不明白你选择条件的标准:if( i == ((*buffPixels) + (((*buffWidth) * 3) + pad) * (buffHeight + 1)) )
  • @ryyker 尝试找出一种方法来考虑在此特定函数中进行填充,您最终可能也会得到类似的结果。 i 也到达了填充,因此它需要包含在确定 i 是否位于一行像素末尾的公式中。
  • 你能用y 计数器的高度和x 计数器的宽度将指针混乱重写为例程吗?我怀疑如果你这样做并且仍然考虑填充,问题就会神秘地消失。

标签: c bitmap padding bmp


【解决方案1】:

在处理位图时,需要了解三个参数:高度、宽度和步幅。宽度和高度是显而易见的。 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 );
}

【讨论】:

  • 嗯嗯..我不知道该说什么。这和我的问题有什么关系?这与内存缓冲 bmp 的直接颜色替换有什么关系?此外,我的功能显然是要快速的。
  • @AlanSalios 我刚刚回答了标题“BMP 颜色替换器:填充算法”中的问题。我向您展示了如何正确计算位图图像中的填充。请注意,如果它不起作用,快速是没有意义的,premature optimization is the root of all evil
  • 我知道如何计算填充。我已经构建了创建、读取、否定 bmp 文件的函数,它们无疑都可以快速运行。但我遇到的并发症在于该功能。我的确定填充的算法应该可以工作。问题也不在标题中。它在问题的正文中。我想知道为什么我的算法没有按预期工作。
  • 好吧,我什么也不想说,但是当我阅读你的代码时,我无法理解它。 (根据 cmets,我不是唯一一个。)然后我建议您编辑问题,试图向人们解释您的代码应该如何工作。那么也许有人能发现这个缺陷。
  • 我认为这很明显。我也举了一个例子。它很简单,它将旧颜色替换为新颜色。当我尝试替换填充图像中的颜色时,图像会失真,因为图片举例说明..我不知道还能说什么..有一行算法可以考虑填充,但它不起作用..什么更多..
猜你喜欢
  • 2017-02-06
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多