【问题标题】:Reading the BGR colors from a bitmap in C从 C 中的位图中读取 BGR 颜色
【发布时间】:2011-07-18 13:25:48
【问题描述】:

我试图从 24 位 BMP 文件中获取 RGB 值。我使用的图像是一个很小的图像,全是红色的,所以所有像素 BGR 配置应该是B:0 G:0 R:255。我这样做:

int main(int argc, char **argv)
{
    principal();
    return 0;
}

typedef struct {
    unsigned char blue;
    unsigned char green;
    unsigned char red;
} rgb;

typedef struct {
    int ancho, alto;
    rgb *pixeles[MAX_COORD][MAX_COORD];
} tBitmapData;

void principal()
{

    FILE *fichero;
    tBitmapData *bmpdata = (tBitmapData *) malloc(sizeof(tBitmapData));
    rgb *pixel;
    int i, j, num_bytes;
    unsigned char *buffer_imag;
    char nombre[] = "imagen.bmp";
    fichero = fopen(nombre, "r");
    if (fichero == NULL)
            puts("No encontrado\n");
    else {
            fseek(fichero, 18, SEEK_SET);
            fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);
            printf("Ancho: %d\n", bmpdata->ancho);
            fseek(fichero, 22, SEEK_SET);
            fread(&(bmpdata->alto), sizeof((bmpdata->alto)), 4, fichero);
            printf("Alto: %d\n", bmpdata->alto);
    }

    num_bytes = (bmpdata->alto * bmpdata->ancho * 3);
    fseek(fichero, 54, SEEK_SET);
    for (j = 0; j < bmpdata->alto; j++) {
            printf("R   G   B Fila %d\n", j + 1);
            for (i = 0; i < bmpdata->ancho; i++) {
                    pixel =
                        (rgb *) malloc(sizeof(rgb) * bmpdata->alto *
                                       bmpdata->ancho * 3);
                    fread(pixel, 1, sizeof(rgb), fichero);
                    printf("Pixel %d: B: %3d G: %d R: %d \n", i + 1,
                           pixel->blue, pixel->green, pixel->red);
            }
    }
    fclose(fichero);
}

问题是当我打印它们时,第一个像素很好,B:0 G:0 R:255,但随后它们开始变为B:0 G:255 R:0,然后变为B:255 G:0 R:0。如果宽度为 10 像素,则每 10 像素更改一次。

【问题讨论】:

  • 这可能不是您的问题的原因,但您是否意识到您正在分配 三倍 保存整个图像所需的内存 i>,对于每个像素,并泄漏所有像素?如果您要单独使用fread 每个像素,则可以使用在堆栈上分配的rgb 结构。
  • 另外,如果您可以上传一个显示问题的图像文件,我们可以找到它,这将很有帮助。
  • 简单的解释就是bitmap的像素格式是32bpp。你不检查它,那是一个错误。您也忽略了步幅,在 24bpp 格式上是致命的。不要自己写这段代码,知道如何读取任意格式的图像文件的库很多。

标签: c bitmap pixel bgr


【解决方案1】:

我认为您的fread(3) 调用是错误的:

        fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);

这要求将4*sizeof((bmpdata-&gt;ancho)) 字节读入int。我假设sizeof((bmpdata-&gt;ancho)) 返回4,所以我认为你在用这两个调用在不相关的内存上乱写。将4 更改为1——您只阅读了一项。

你从不使用num_bytes;删除它。未使用的代码使思考已使用的代码变得更加困难。 :)

您分配的内存是您需要的三倍:

                pixel =
                    (rgb *) malloc(sizeof(rgb) * bmpdata->alto *
                                   bmpdata->ancho * 3);

3 看起来像是尝试在您的 rgb 结构中解释红色、绿色、蓝色中的每一个,但 sizeof(rgb) 已经知道结构的正确大小。 (这可能是 4 字节,以便于 32 位 CPU 对齐,或者它可能是 12 字节,再次对齐(每个 char 在其自己的 4 字节边界上),甚至可能是 @987654341 @bytes 在 64 位系统上真正喜欢处理在 8 字节边界上对齐的数据。)

我要注意的最后一件事:

                fread(pixel, 1, sizeof(rgb), fichero);

因为允许 C 编译器在结构中插入孔,所以您不能假设磁盘格式与您的内存结构定义相匹配。您需要使用GNU C extension __packed__ 属性,或者您需要使用为bmp 格式设计的库或结构从其中读取数据。如果这对您来说是一个有趣的项目,那么一定要尝试__packed__ 路线:如果有效,很好,如果无效,希望您能了解为什么不这样做,并重新编写代码以加载手动构造。如果您只是想获得可以正确解析位图的东西,那么您可能想尝试找到一些已经正确解析图像的预先编写的库。

(是的,正确解析图像非常重要CVE has a list of malformed image exploits 允许攻击者控制程序,其中许多是可远程利用的。)

【讨论】:

    【解决方案2】:

    BMP file format 中,每行像素数据都可以进行填充,以便四舍五入为 4 字节的倍数。

    如果您有 10 个 24 位像素,则为 30 个字节,然后是 2 个字节的填充。您的代码不会跳过填充。

    【讨论】:

      猜你喜欢
      • 2013-03-18
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 2016-03-31
      相关资源
      最近更新 更多