C读取bmp文件
我正在尝试将bmp文件读入我的程序,但遇到了一些问题。读入文件后,如果我告诉它打印pBmp->header.fileSize,它会显示16,但如果我在十六进制编辑器中查看,文件大小部分有F6 7A 10 00如果我将值修改为十六进制中的正确文件大小,它会显示F6 7A F6 7A 10 00,但这会运行到resv1中,它应该始终为零。我知道这只是读取1个像素的数据。我遇到的另一个问题是,当我尝试使用while循环来读取像素,直到文件结束时,我得到了一个分割错误。我真的花了几个小时在谷歌上寻找答案,但我运气不太好C读取bmp文件,c,bmp,C,Bmp,我正在尝试将bmp文件读入我的程序,但遇到了一些问题。读入文件后,如果我告诉它打印pBmp->header.fileSize,它会显示16,但如果我在十六进制编辑器中查看,文件大小部分有F6 7A 10 00如果我将值修改为十六进制中的正确文件大小,它会显示F6 7A F6 7A 10 00,但这会运行到resv1中,它应该始终为零。我知道这只是读取1个像素的数据。我遇到的另一个问题是,当我尝试使用while循环来读取像素,直到文件结束时,我得到了一个分割错误。我真的花了几个小时在谷歌上寻找答案
// 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;
}
//BMPHEADER结构。
类型定义结构{
字节sigB;
字节sigM;
int32_t文件大小;
int16_t resv1;
int16_t resv2;
int32_t像素偏移;
}tBmpHeader;
//BMPINFOHEADER结构。
类型定义结构{
int32_t大小;
int32_t宽度;
int32_t高度;
int16色平面;
int16_t Bitsperpix;
字节零[24];
}tBmpInfoHeader;
typedef uint8_t字节;
类型定义结构{
字节蓝色;
字节绿色;
字节红色;
}tPixel;
//BMP图像由BMPHEADER和BMPINFOHEADER结构以及2D像素阵列组成。
类型定义结构{
掘进机割台;
tBmpInfoHeader信息头;
t像素**像素;
}tBmp;
t像素**bmppixellalloc(内宽、内宽)
{
tPixel**像素=(tPixel**)malloc(pHeight*sizeof(tPixel*);
用于(int行=0;行pixel=bmppixellalloc(pBmp->infoHeader.width,pBmp->infoHeader.height);
if(FileRead(file,&pBmp->pixel,sizeof(tPixel),1)!=0)
{
errorCode=ErrorFileRead;
}
您不应该对结构使用直接I/O:仅仅因为您以与BMP头相同的顺序声明了您的结构,就不能保证您的编译器具有端到端的字段,其间没有任何内容
编译器经常遵守平台的对齐限制,这可能会导致它们在字段之间添加填充字节,以确保大字段的起始地址对齐
您需要使用特定于编译器的魔法强制结构“打包”,或者逐字节地将I/O输入到结构中。检查结构的填充以获取标题。您可能会发现编译器已将struct
中的fileSize
值与结构中的4字节边界对齐。如果您输入一些结构元素地址的debugprintf
,就可以看到这一点
我在这里使用您的struct
运行了一个示例:
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
之前有两个字节的填充
要做的事情是一次读取一个日期项的标题。您可以通过将读取封装在单个函数中(例如,“readBmpHeader(…)”)来维护代码的某些“结构”。您可以保留结构
,但可以分别读取每个字段。因此,您可以这样做(为了示例的清晰性,我省略了返回值检查):
你能显示完整的代码吗?你没有main,没有定义FileRead,没有显示检查头的位置。FileSize,没有显示tBmpHeader,等等。看起来你是对的,但我不知道该怎么办。啊,现在可以了,你认为这就是为什么我也有循环的问题吗?@Covertpyro你需要分割你的像素行读取,因为你单独的malloc
地址不会在连续的内存中。是的,我以前得到的第一个像素的像素数据是正确的,但是现在头工作了,第一个像素是错误的。一位导师告诉我使用while(!feof)循环来填充数组,但这给了我一个分段错误。请参阅代码示例。您确实需要读入保留值才能通过它们。由于像素数据不连续,while(!feof(…)
可能会使您失败。因此,您将覆盖未分配的内存。此外,您不能将tPixel
作为结构来读取。一次需要一个字节,就像标头一样。您可能需要更新代码并发布新问题。:)
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)