C读取bmp文件 [英] C reading bmp files

查看:122
本文介绍了C读取bmp文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将bmp文件读入程序,但遇到了一些问题.读完文件后,如果我告诉它打印pBmp-> header.fileSize,它说16,但是如果我在十六进制编辑器中查看它,如果我将值修改为正确的文件大小,则文件大小部分为F6 7A 10 00在十六进制中会说F6 7A F6 7A 10 00,但这正在运行到resv1中,应该始终为零.我知道这仅读取1个像素的数据,我遇到的另一个问题是当我尝试使用while循环读取像素直到文件结束时出现分段错误.我花了数小时在谷歌上努力想办法解决这个问题,但是我运气不怎么好.

I'm trying to read in a bmp file to my program and I'm having some issues. After reading in the file if i tell it to print the pBmp->header.fileSize it says 16 but if i look at it in a hex editor the file size portion has F6 7A 10 00 if I modify the value to the correct file size in the hex it will say F6 7A F6 7A 10 00 but that is running into the resv1 which should always be zero. I know that this is only reading in 1 pixel of data another issue I have is when I try to use a while loop to read in the pixels until the end of file I get a segmentation fault. I've literally spent hours googling trying to figure this out but I'm not having much luck.

// The BMPHEADER structure.
typedef struct {
    byte        sigB;
    byte        sigM;
    int32_t     fileSize;
    int16_t     resv1;
    int16_t     resv2;
    int32_t     pixelOffset;
} tBmpHeader;

// The BMPINFOHEADER structure.
typedef struct {
    int32_t     size;
    int32_t     width;
    int32_t     height;
    int16_t     colorPlanes;
    int16_t     bitsPerPixel;
    byte        zeros[24];
} tBmpInfoHeader;

typedef uint8_t byte;

typedef struct {
    byte blue;
    byte green;
    byte red;
} tPixel;

// A BMP image consists of the BMPHEADER and BMPINFOHEADER structures, and the 2D pixel array.
typedef struct {
    tBmpHeader      header;
    tBmpInfoHeader  infoHeader;
    tPixel          **pixel;
} tBmp;

tPixel **BmpPixelAlloc(int pWidth, int pHeight)
{
    tPixel **pixels = (tPixel **)malloc (pHeight * sizeof(tPixel *));
    for (int row = 0; row < pHeight; ++row)
    {
        pixels[row] = (tPixel *)malloc(pWidth * sizeof(tPixel));
    }

    printf("pixelAlloc\n"); 

    return pixels;
}

pBmp->pixel = BmpPixelAlloc(pBmp->infoHeader.width, pBmp->infoHeader.height);
if(FileRead(file, &pBmp->pixel, sizeof(tPixel), 1)!=0)
{ 
    errorCode = ErrorFileRead;
}

推荐答案

检查标题的结构填充.您可能会发现编译器已将struct中的fileSize值对齐到结构内的4字节边界.如果您放入一些结构元素地址的调试printf,就可以看到这一点.

Check the padding of the structure for the header. You may find that the compiler has aligned the fileSize value in the struct to a 4-byte boundary within the structure. You can see this if you put in some debug printf's of the structure element addresses.

我在这里使用您的struct进行了示例:

I ran an example using your struct here:

typedef struct {
    byte        sigB;
    byte        sigM;
    int32_t     fileSize;
    int16_t     resv1;
    int16_t     resv2;
    int32_t     pixelOffset;
} tBmpHeader;

tBmpHeader hdr;

int main(int argc, char *argv[])
{
    printf("%d\n", sizeof(tBmpHeader) );
    printf("%p hdr\n", &hdr);
    printf("%p sigB\n", &hdr.sigB);
    printf("%p sigM\n", &hdr.sigM);
    printf("%p fileSize\n", &hdr.fileSize);
    printf("%p resv1\n", &hdr.resv1);
    printf("%p resv2\n", &hdr.resv2);
    printf("%p pixelOffset\n", &hdr.pixelOffset);
}

输出:

16
0x8049788 hdr
0x8049788 sigB
0x8049789 sigM
0x804978c fileSize
0x8049790 resv1
0x8049792 resv2
0x8049794 pixelOffset

hdr的开头和fileSize元素之间有4个字节的偏移量,因此在fileSize之前有两个填充字节.

There is a 4-byte offset between the beginning of hdr and the fileSize element, so there are two bytes of padding before fileSize.

要做的是一次读取标头和日期项.您可以通过将读取结果封装在一个函数中(例如"readBmpHeader(...)")来维护代码的某些结构".您可以保留struct,但分别读取每个字段.因此,您可以这样做(为清楚起见,我省去了返回值检查):

The thing to do is read the header a date item at a time. You can maintain some "structure" to the code by encapsulating the reads in a single function (e.g., "readBmpHeader(...)"). You can keep the struct but read each field separately. So, you would do (I leave off the return value checks for clarity of example):

FileRead(file, &pBmp->header.sigB, sizeof(byte), 1)
FileRead(file, &pBmp->header.sigB, sizeof(byte), 1)
FileRead(file, &pBmp->header.fileSize, sizeof(int32_t), 1)
FileRead(file, &pBmp->header.resv1, sizeof(int16_t), 1)
FileRead(file, &pBmp->header.resv2, sizeof(int16_t), 1)
FileRead(file, &pBmp->header.pixelOffset, sizeof(int32_t), 1)

这篇关于C读取bmp文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆