读/写 bmp 文件
Posted
技术标签:
【中文标题】读/写 bmp 文件【英文标题】:Reading/writing a bmp file 【发布时间】:2013-02-22 11:16:17 【问题描述】:我编写了一个代码来简单地读/写(复制)一个 *.bmp 文件。但是有问题我的程序一遍又一遍地运行......我的意思是看起来里面有一个while(true)循环或其他东西。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#pragma pack(push, 1)
typedef struct Pix
unsigned char R;
unsigned char G;
unsigned char B;
unsigned char L;
int BW;
Pix;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct BitMap
short Signature;
long Reserved1;
long Reserved2;
long DataOffSet;
long Size;
long Width;
long Height;
short Planes;
short BitsPerPixel;
long Compression;
long SizeImage;
long XPixelsPreMeter;
long YPixelsPreMeter;
long ColorsUsed;
long ColorsImportant;
struct Pix *pixels
BitMap;
#pragma pack(pop)
int main(int argc, char **argv)
unsigned long int i=0;//to count pixels readed
unsigned long int S=0;//number of pixcels to read
struct BitMap source_info;//to store bitmap info header
struct Pix source_pix;// to store pixcels
FILE *fp;//file pointer for source file
FILE *Dfp;//file ponter for distenation file
if(!(fp=fopen("in.bmp","rb")))//open in binery read mode
printf(" can not open file");//prind and exit if file open error
exit(-1);
Dfp=fopen("out.bmp","wb");//opne in binery write mode
//read the headers to souirce file
fread(&source_info, (sizeof(long)*3 + sizeof(short)),1,fp);
//calucate the number of pix to read
S=source_info.Width*source_info.Height;
source_info.pixels = (struct Pix *) malloc(sizeof(struct Pix)*S);
//read pixcels
for(i=1;i<=S;i++)
//read pixcel form source file
fread(&source_pix,sizeof(struct Pix),1,fp);
source_info.pixels[i-1] = source_pix;
// write header to dest file
fwrite(&source_info, (sizeof(long)*3 + sizeof(short)),1,Dfp);
// write pixels to dest file
for(i=1;i<=S;i++)
fwrite(&source_info.pixels[i-1],sizeof(struct Pix),1,Dfp);
//close all fiels
fclose(fp);
fclose(Dfp);
return 0;
【问题讨论】:
你不应该使用FILE*
来读/写二进制文件,而应该使用读/写系统调用。
@BrianBrown 扩展了我的答案。
关于各种可能性的参考信息可以存储在所谓的 bmp 文件中:en.wikipedia.org/wiki/BMP_file_format
您发布的结构 BitMap
仅适用于 long
大小为 32 位的系统。
【参考方案1】:
对于我尝试的示例图像,您读取的像素数 (S) 是 3762821376。这显然太大了。
查看 BMP 规范,您使用的 struct BitMap
是否正确。
编辑 1:
改变这些:
fread(&source_info, (sizeof(long)*3 + sizeof(short)),1,fp);
...
fwrite(&source_info, (sizeof(long)*3 + sizeof(short)),1,Dfp);
到
fread(&source_info, sizeof(source_info),1,fp);
...
fwrite(&source_info, sizeof(source_info),1,Dfp);
它现在可以很好地复制我的测试 .bmp。
编辑 2:
我认为您机器上的颜色切换问题是因为您使用source_info.pixels = ...
。您应该使用自己的指针Pix* pixels = malloc...
,并在循环中将source_info.pixels
更改为pixels
。只是不要将你的 malloc 分配到 source_info 结构中,它应该没问题
【讨论】:
在你写的时候改变了它,但现在出现了不同的问题。它复制了一个 bmp 图像,但也改变了它的颜色:/ 查看此示例图像的代码:imageshack.us/photo/my-images/208/39057820.png 很奇怪,因为我的有,看看:imageshack.us/photo/my-images/266/ouuut.png 这是我的输出图像,out.bmp 我认为您机器上的颜色切换问题是因为您使用source_info.pixels = ...
。您应该使用自己的指针Pix* pixels = malloc...
,并在循环中将source_info.pixels
更改为pixels
。只需不要将你的 malloc 分配到 source_info 结构中,它应该没问题。
帮助了,谢谢!但不幸的是,我需要在一个结构中使用 BitMap。如何制作?
你总是可以在它周围包裹另一个结构:typedef struct BitMap header; void* pixels; HeaderAndPixels;
。顺便说一句:您的位图标题结构不完整!它遗漏了一些字段,请参见此处:en.wikipedia.org/wiki/BMP_file_format【参考方案2】:
您正在访问未初始化的source_info.Width
和source_info.Height
数据,因为当您fread
文件的标头数据时,您只是在第一个4 fields
之后停止。
因此 source_info 的其他字段可能包含垃圾数据。 (特别是 width
和 height
因为它们会影响下一个循环)
确保阅读完整的标题变化
fread(&source_info, (sizeof(long)*3 + sizeof(short)),1,fp);
与
fread(&source_info, sizeof(BitMap),1,fp);
然后确保出于同样的原因正确转储它,链接
fwrite(&source_info, (sizeof(long)*3 + sizeof(short)),1,Dfp);
与
fwrite(&source_info, sizeof(BitMap),1,Dfp);
【讨论】:
【参考方案3】:您需要跳过复制 Pix 指针,它可以在您想要的单个结构中为我工作。
fread(&source_info, (sizeof(BitMap) - sizeof(struct Pix*)),1,fp);
顺便说一句,如果您将 Pix 定义为,代码会产生更小的文件大小
typedef struct Pix
unsigned char R;
unsigned char G;
unsigned char B;
Pix;
【讨论】:
以上是关于读/写 bmp 文件的主要内容,如果未能解决你的问题,请参考以下文章