Brian Brown
Brian Brown

Reputation: 4311

Reading/writing a bmp file

I wrote a code to simply read/write (copy) a *.bmp file. But something is wrong my program runs over and over and over again ... I mean it looks like there is a while(true) loop inside or something. Heres my code:

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

Upvotes: 1

Views: 14092

Answers (3)

Tarek Eldeeb
Tarek Eldeeb

Reputation: 606

You need to skip copying the Pix pointer, it works for me within a single structure as you wanted.

fread(&source_info, (sizeof(BitMap) - sizeof(struct Pix*)),1,fp);

By the way, the code produces smaller file sizes if you defined the Pix as

typedef struct Pix
{
  unsigned char R;
  unsigned char G;
  unsigned char B;
}Pix;

Upvotes: 0

Bernd Elkemann
Bernd Elkemann

Reputation: 23550

The number of pixels you read (S) is 3762821376 for a sample image i tried. That is obviously far too large.

Have a look at the BMP-spec whether the struct BitMap you are using is correct.

EDIT 1:

Change these:

fread(&source_info, (sizeof(long)*3 + sizeof(short)),1,fp);
...
fwrite(&source_info,  (sizeof(long)*3 + sizeof(short)),1,Dfp);

to

fread(&source_info, sizeof(source_info),1,fp);
...
fwrite(&source_info, sizeof(source_info),1,Dfp);

It now copies my test .bmp fine.

EDIT 2:

I think the color-switching problem on your machine comes because you do source_info.pixels = .... You should use your own pointer Pix* pixels = malloc... and in the loops change source_info.pixels to pixels. Just dont assign your malloc into the source_info struct and it should be fine

Upvotes: 3

Davide Berra
Davide Berra

Reputation: 6568

You're accessing to the source_info.Width and source_info.Height data that's not inited because when you fread the header data of the file, you just stop after the first 4 fields.

Thus the other field of source_info could contain junk data. (expecially width and height cause they affect the next loops)

Ensure to read the full header changing

fread(&source_info, (sizeof(long)*3 + sizeof(short)),1,fp);

with

fread(&source_info, sizeof(BitMap),1,fp);

then ensure to dump it correctly for the same reason, chainging

fwrite(&source_info,  (sizeof(long)*3 + sizeof(short)),1,Dfp);

with

fwrite(&source_info, sizeof(BitMap),1,Dfp);

Upvotes: 1

Related Questions