Link to home
Start Free TrialLog in
Avatar of alekhine_x9
alekhine_x9

asked on

Bitmap Write Function in C

Here is a BMP read function which  found here, what i want is to add a write BMP function, and a sample processing function (like negatife),
Can you please send a sample code?

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <alloc.h>

#define BMP_OK          0
#define BMP_OPEN     1
#define BMP_READ     2
#define BMP_INVALID     3
#define BMP_NOMEM     4

typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;

typedef struct tagBITMAP {
  dword width;
  dword height;
  byte *data;
}BITMAP;

typedef struct BMPHEADER {
  char type[2];
  dword size;
  dword reserved;
  dword offset;
  dword headersize;
  dword width;
  dword height;
  word planes;
  word bitsperpixel;
  dword compression;
  dword sizeimage;
  dword xpixelspermeter;
  dword ypixelspermeter;
  dword colorsused;
  dword colorsimportant;
} BmpHeader;

int bmp_load(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader);

/*********************************************************************/
/*********************************************************************/
int main()
{
  int i,x,y;
  int result;
  BmpHeader *bmpheader;
  BITMAP *bitmap;
  BITMAP bmp;
  char palette[768];
  char *filename;

  printf("Enter the name of bmp image");
  scanf("%s",filename);

  result=bmp_load(filename, bitmap, palette, bmpheader);
  if (result!=0)
  {
    printf("%d", result);
    printf("Error reading file in bmp_load\n");
    return(2);
  }

  printf("Bmp header (size=%i) contains the following informations:\n", sizeof(struct BMPHEADER));
  printf("Type of bitmap (BM)               :%c%c\n", bmpheader->type[0], bmpheader->type[1]);
  printf("Size of file                    :%lu\n", bmpheader->size);
  printf("Offset of data from this position     :%lu\n", bmpheader->offset);
  printf("Size of rest of header               :%lu\n", bmpheader->headersize);
  printf("Width of bitmap                    :%lu\n", bmpheader->width);
  printf("Height of bitmap               :%lu\n", bmpheader->height);
  printf("Planes of bitmap               :%u\n", bmpheader->planes);
  printf("Number of bits per pixel          :%u\n", bmpheader->bitsperpixel);
  printf("Type of compression (usu. 0)          :%lu\n", bmpheader->compression);
  printf("Size of image                    :%lu\n", bmpheader->sizeimage);
  printf("Number of pixel per meter (X)          :%lu\n", bmpheader->xpixelspermeter);
  printf("Number of pixel per meter (Y)          :%lu\n", bmpheader->ypixelspermeter);
  printf("Number of colors used               :%lu\n", bmpheader->colorsused);
  printf("Number of colors considered important     :%lu\n", bmpheader->colorsimportant);
  getch();

  for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
  {
    for(x=0;x<bitmap->width;x++)
      printf("%i-", bitmap->data[i+x]);
    printf("\n");
  }

  return(0);
}


/*********************************************************************/
/*********************************************************************/
int bmp_load(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader)
{
  FILE *fp;
  register int i,x;

  /***initialise***/
  bmpheader->type[0]=' ';

  /***open file***/
  if ((fp=fopen(filename, "rb"))==NULL)
  {
    return(BMP_OPEN);
  }

  /***check for valid bitmap format***/
  fread(&bmpheader->type, 2, 1, fp);     /*read 2 bytes from file referenced by fp**********/
                         /*fread can read several fixed size array elements*/
                         /*third argument gives no. of element to be read***/
  if ((bmpheader->type[0]!='B')||(bmpheader->type[1]!='M'))
  {
    fclose(fp);
    return(BMP_INVALID);
  }

  /***read header information***/
  if (fread(&bmpheader->size, 52, 1, fp)!=1)
  {
    fclose(fp);
    return(BMP_READ);
  }

  /***verify windows or OS/2 bitmap***/
  if (bmpheader->headersize!=40)
  {
    return(BMP_INVALID);
  }

  /***read image width, height information***/
  bitmap->width=bmpheader->width;
  bitmap->height=bmpheader->height;

  /***read palette information***/
  for(i=0;i<256;i++)
  {
    palette[i*3+2]=getc(fp)>>2;
    palette[i*3+1]=getc(fp)>>2;
    palette[i*3+0]=getc(fp)>>2;
    getc(fp);
  }

  /***allocate memory dynamically***/
  if((bitmap->data=(byte *)malloc(bitmap->width*bitmap->height))==NULL)
  {
    fclose(fp);
    return(BMP_NOMEM);
  }

  /***read in bitmap pixels***/
  for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
  {
    for(x=0;x<bitmap->width;x++)
      bitmap->data[i+x]=getc(fp);

    for(x=4;x>bitmap->width%4;x--)     /*adjust data if width not divisible by 4*/
      getc(fp);
  }

  /***close file***/
  fclose(fp);
  return(BMP_OK);
}
Avatar of dhyanesh
dhyanesh

Hi

You can easily write a BMP function.

You already have the format of a BMP.

In your above code in place of fread you will be using fwrite and in place of getc use putc to write.

However do not blindly subsitute fwrite in place of fread. I am just giving an overview of how you can do it.

Dhyanesh
Avatar of alekhine_x9

ASKER

dhyanesh if it is easy for you to write a BMP function can you send me the source code
the first link I posted has the source code for reading and writing a bmp !!!!
check the link
Hi

First of all there were a few errors in your main program.

You had not allocated space for :(in main)

filename, bmpheader and bitmap. I have done the required modifications in main.

Also I have written a write function which is very similar to your read function. I have tested it and it works.

The entire code would be something like:


#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <alloc.h>

#define BMP_OK          0
#define BMP_OPEN     1
#define BMP_READ     2
#define BMP_INVALID     3
#define BMP_NOMEM     4

typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;

typedef struct tagBITMAP {
 dword width;
 dword height;
 byte *data;
}BITMAP;

typedef struct BMPHEADER {
 char type[2];
 dword size;
 dword reserved;
 dword offset;
 dword headersize;
 dword width;
 dword height;
 word planes;
 word bitsperpixel;
 dword compression;
 dword sizeimage;
 dword xpixelspermeter;
 dword ypixelspermeter;
 dword colorsused;
 dword colorsimportant;
} BmpHeader;

int bmp_load(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader);
int bmp_write(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader);
/*********************************************************************/
/*********************************************************************/
int main()
{
 int i,x,y;
 int result;
 BmpHeader bmphead,*bmpheader;
 BITMAP *bitmap;
 BITMAP bmp;
 char palette[768];
 char filename[30];

 printf("Enter the name of bmp image\n");
 scanf("%s",filename);

 bitmap = &bmp;
 bmpheader = &bmphead;
 result=bmp_load(filename, bitmap, palette, bmpheader);
 if (result!=0)
 {
       printf("%d", result);
       printf("Error reading file in bmp_load\n");
       return(2);
 }

 printf("Bmp header (size=%i) contains the following informations:\n", sizeof(struct BMPHEADER));
 printf("Type of bitmap (BM)               :%c%c\n", bmpheader->type[0], bmpheader->type[1]);
 printf("Size of file                    :%lu\n", bmpheader->size);
 printf("Offset of data from this position     :%lu\n", bmpheader->offset);
 printf("Size of rest of header               :%lu\n", bmpheader->headersize);
 printf("Width of bitmap                    :%lu\n", bmpheader->width);
 printf("Height of bitmap               :%lu\n", bmpheader->height);
 printf("Planes of bitmap               :%u\n", bmpheader->planes);
 printf("Number of bits per pixel          :%u\n", bmpheader->bitsperpixel);
 printf("Type of compression (usu. 0)          :%lu\n", bmpheader->compression);
 printf("Size of image                    :%lu\n", bmpheader->sizeimage);
 printf("Number of pixel per meter (X)          :%lu\n", bmpheader->xpixelspermeter);
 printf("Number of pixel per meter (Y)          :%lu\n", bmpheader->ypixelspermeter);
 printf("Number of colors used               :%lu\n", bmpheader->colorsused);
 printf("Number of colors considered important     :%lu\n", bmpheader->colorsimportant);
 getch();

 for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
 {
       for(x=0;x<bitmap->width;x++)
             printf("%i-", bitmap->data[i+x]);
       printf("\n");
 }
 result=bmp_write("new.bmp", bitmap, palette, bmpheader);
 if (result != 0)
      printf("Error");
 return(0);
}


/*********************************************************************/
/*********************************************************************/
int bmp_load(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader)
{
 FILE *fp;
 register int i,x;

 /***initialise***/
 bmpheader->type[0]=' ';

 /***open file***/
 if ((fp=fopen(filename, "rb"))==NULL)
 {
       return(BMP_OPEN);
 }

 /***check for valid bitmap format***/
 fread(&bmpheader->type, 2, 1, fp);     /*read 2 bytes from file referenced by fp**********/
                                                                        /*fread can read several fixed size array elements*/
                                                                        /*third argument gives no. of element to be read***/
 if ((bmpheader->type[0]!='B')||(bmpheader->type[1]!='M'))
 {
       fclose(fp);
       return(BMP_INVALID);
 }

 /***read header information***/
 if (fread(&bmpheader->size, 52, 1, fp)!=1)
 {
       fclose(fp);
       return(BMP_READ);
 }

 /***verify windows or OS/2 bitmap***/
 if (bmpheader->headersize!=40)
 {
       return(BMP_INVALID);
 }

 /***read image width, height information***/
 bitmap->width=bmpheader->width;
 bitmap->height=bmpheader->height;

 /***read palette information***/
 for(i=0;i<256;i++)
 {
       palette[i*3+2]=getc(fp)>>2;
       palette[i*3+1]=getc(fp)>>2;
       palette[i*3+0]=getc(fp)>>2;
       getc(fp);
 }

 /***allocate memory dynamically***/
 if((bitmap->data=(byte *)malloc(bitmap->width*bitmap->height))==NULL)
 {
       fclose(fp);
       return(BMP_NOMEM);
 }

 /***read in bitmap pixels***/
 for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
 {
       for(x=0;x<bitmap->width;x++)
             bitmap->data[i+x]=getc(fp);

       for(x=4;x>bitmap->width%4;x--)     /*adjust data if width not divisible by 4*/
             getc(fp);
 }

 /***close file***/
 fclose(fp);
 return(BMP_OK);
}

int bmp_write(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader)
{
 FILE *fp;
 register int i,x;

      /***open file***/
 if ((fp=fopen(filename, "wb"))==NULL)
 {
       return(BMP_OPEN);
 }

 /***check for valid bitmap format***/
 fwrite(&bmpheader->type, 2, 1, fp);     /*write 2 bytes from file referenced by fp**********/
                                                                        /*fwrite can read several fixed size array elements*/
                                                                        /*third argument gives no. of element to be write***/
 if ((bmpheader->type[0]!='B')||(bmpheader->type[1]!='M'))
 {
       fclose(fp);
       return(BMP_INVALID);
 }

 /***write header information***/
 if (fwrite(&bmpheader->size, 52, 1, fp)!=1)
 {
       fclose(fp);
       return(BMP_READ);
 }


      /***write palette information***/
 for(i=0;i<256;i++)
 {
       putc(palette[i*3+2]<<2,fp);
       putc(palette[i*3+1]<<2,fp);
       putc(palette[i*3+0]<<2,fp);
       putc(0,fp);
 }


 /***write in bitmap pixels***/
 for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
 {
       for(x=0;x<bitmap->width;x++)
             putc(bitmap->data[i+x],fp);

       for(x=4;x>bitmap->width%4;x--)     /*adjust data if width not divisible by 4*/
             putc(0,fp);
 }

 /***close file***/
 fclose(fp);
 return(BMP_OK);
}


Dhyanesh
Hi dhyanesh,
thanks for your help but the written NEW.BMP file cannot be opened by any program, it is corrupted, i tried the code with a 100X100X24 bmp, what may cause the problem, and if possible can you write a small processing function?
thanks in advance
Hi

The program will not work for 24 bit bmp. This is because in the structure BITMAP data is represented as a byte. Hence only 8 bit is possible i.e. 256 colors.

For 24-bit the program will have to be modified.

Dhyanesh
Hi

Also there is a small correction in both the read and write functions. I had not noticed it earlier as I was assuming the read function was perfect. However it is not. The correction is same for read and write function.

This condition is added just before reading or writing the padding bits.

 if (bitmap->width%4 != 0)

The entire code now will be somewhat like:


#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <alloc.h>

#define BMP_OK          0
#define BMP_OPEN     1
#define BMP_READ     2
#define BMP_INVALID     3
#define BMP_NOMEM     4

typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;

typedef struct tagBITMAP {
dword width;
dword height;
byte *data;
}BITMAP;

typedef struct BMPHEADER {
char type[2];
dword size;
dword reserved;
dword offset;
dword headersize;
dword width;
dword height;
word planes;
word bitsperpixel;
dword compression;
dword sizeimage;
dword xpixelspermeter;
dword ypixelspermeter;
dword colorsused;
dword colorsimportant;
} BmpHeader;

int bmp_load(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader);
int bmp_write(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader);
/*********************************************************************/
/*********************************************************************/
int main()
{
int i,x,y;
int result;
BmpHeader bmphead,*bmpheader;
BITMAP *bitmap;
BITMAP bmp;
char palette[768];
char filename[30];

printf("Enter the name of bmp image\n");
scanf("%s",filename);

bitmap = &bmp;
bmpheader = &bmphead;
result=bmp_load(filename, bitmap, palette, bmpheader);
if (result!=0)
{
     printf("%d", result);
     printf("Error reading file in bmp_load\n");
     return(2);
}

printf("Bmp header (size=%i) contains the following informations:\n", sizeof(struct BMPHEADER));
printf("Type of bitmap (BM)               :%c%c\n", bmpheader->type[0], bmpheader->type[1]);
printf("Size of file                    :%lu\n", bmpheader->size);
printf("Offset of data from this position     :%lu\n", bmpheader->offset);
printf("Size of rest of header               :%lu\n", bmpheader->headersize);
printf("Width of bitmap                    :%lu\n", bmpheader->width);
printf("Height of bitmap               :%lu\n", bmpheader->height);
printf("Planes of bitmap               :%u\n", bmpheader->planes);
printf("Number of bits per pixel          :%u\n", bmpheader->bitsperpixel);
printf("Type of compression (usu. 0)          :%lu\n", bmpheader->compression);
printf("Size of image                    :%lu\n", bmpheader->sizeimage);
printf("Number of pixel per meter (X)          :%lu\n", bmpheader->xpixelspermeter);
printf("Number of pixel per meter (Y)          :%lu\n", bmpheader->ypixelspermeter);
printf("Number of colors used               :%lu\n", bmpheader->colorsused);
printf("Number of colors considered important     :%lu\n", bmpheader->colorsimportant);
getch();

for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
{
     for(x=0;x<bitmap->width;x++)
          printf("%i-", bitmap->data[i+x]);
     printf("\n");
}
result=bmp_write("new.bmp", bitmap, palette, bmpheader);
if (result != 0)
    printf("Error");
return(0);
}


/*********************************************************************/
/*********************************************************************/
int bmp_load(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader)
{
FILE *fp;
register int i,x;

/***initialise***/
bmpheader->type[0]=' ';

/***open file***/
if ((fp=fopen(filename, "rb"))==NULL)
{
     return(BMP_OPEN);
}

/***check for valid bitmap format***/
fread(&bmpheader->type, 2, 1, fp);     /*read 2 bytes from file referenced by fp**********/
                                                           /*fread can read several fixed size array elements*/
                                                           /*third argument gives no. of element to be read***/
if ((bmpheader->type[0]!='B')||(bmpheader->type[1]!='M'))
{
     fclose(fp);
     return(BMP_INVALID);
}

/***read header information***/
if (fread(&bmpheader->size, 52, 1, fp)!=1)
{
     fclose(fp);
     return(BMP_READ);
}

/***verify windows or OS/2 bitmap***/
if (bmpheader->headersize!=40)
{
     return(BMP_INVALID);
}

/***read image width, height information***/
bitmap->width=bmpheader->width;
bitmap->height=bmpheader->height;

/***read palette information***/
for(i=0;i<256;i++)
{
     palette[i*3+2]=getc(fp)>>2;
     palette[i*3+1]=getc(fp)>>2;
     palette[i*3+0]=getc(fp)>>2;
     getc(fp);
}

/***allocate memory dynamically***/
if((bitmap->data=(byte *)malloc(bitmap->width*bitmap->height))==NULL)
{
     fclose(fp);
     return(BMP_NOMEM);
}

/***read in bitmap pixels***/
for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
{
     for(x=0;x<bitmap->width;x++)
          bitmap->data[i+x]=getc(fp);

   if (bitmap->width%4 != 0)                    
      for(x=4;x>bitmap->width%4;x--)     /*adjust data if width not divisible by 4*/
          getc(fp);
}

/***close file***/
fclose(fp);
return(BMP_OK);
}

int bmp_write(char *filename, BITMAP *bitmap, char *palette, BmpHeader *bmpheader)
{
FILE *fp;
register int i,x;

    /***open file***/
if ((fp=fopen(filename, "wb"))==NULL)
{
     return(BMP_OPEN);
}

/***check for valid bitmap format***/
fwrite(&bmpheader->type, 2, 1, fp);     /*write 2 bytes from file referenced by fp**********/
                                                           /*fwrite can read several fixed size array elements*/
                                                           /*third argument gives no. of element to be write***/
if ((bmpheader->type[0]!='B')||(bmpheader->type[1]!='M'))
{
     fclose(fp);
     return(BMP_INVALID);
}

/***write header information***/
if (fwrite(&bmpheader->size, 52, 1, fp)!=1)
{
     fclose(fp);
     return(BMP_READ);
}


    /***write palette information***/
for(i=0;i<256;i++)
{
     putc(palette[i*3+2]<<2,fp);
     putc(palette[i*3+1]<<2,fp);
     putc(palette[i*3+0]<<2,fp);
     putc(0,fp);
}


/***write in bitmap pixels***/
for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
{
     for(x=0;x<bitmap->width;x++)
          putc(bitmap->data[i+x],fp);

   if (bitmap->width%4 != 0)
     for(x=4;x>bitmap->width%4;x--)     /*adjust data if width not divisible by 4*/
          putc(0,fp);
}

/***close file***/
fclose(fp);
return(BMP_OK);
}



Dhyanesh
Hi

What kind of processing function do you require?

Dhyanesh
Hi

What kind of processing function do you require?

Dhyanesh
Dhyanesh

Any of the processing function is enough for me, for example negatife function or a simple filtering or one you can do:)
ASKER CERTIFIED SOLUTION
Avatar of dhyanesh
dhyanesh

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I had meant to say negative:)
By the way great help,
i thank you very much
Dhyanesh

Can you send  a few more processing functions?
What other processing functions? I do not have much info of other functions or how they work. Negative was quite a simple one.

If you know the algorithm of other functions you can apply it as I have done in changepalette() function. Changing the palette is the key for 8bit bitmaps as all color info is stored in there.

If you do have other functions in mind do post here the algorithms or names and I will help out with them.

Dhyanesh
Hi Dhyanesh,
can you find the HSV (Hue - Saturation - Value) values of a bmp image?
Do you know the algorithm? I do not know how to do it. I am searching for algo myself. If you do know the algo please post and I will help out.

Dhyanesh
I have such an algorithm but dont know whether it works; if you dont understand or cannot implement it, try to do with the algorithm you find.

Let me give some info before;
     Hue + Saturation ---> Chromaticity

CR: Red portion of Chromaticity
CG: Green portion of Chromaticity
CB: Blue portion of Chromaticity

To transform from RGB to HSV;
           R, G, B values must be normalized to [0-1] from [0-255]

/* pseudocode starts here */
   
V=max(R,G,B);

Determine Saturation:
         temp=min(R,G,B)
         if   V=0 then
                S=0
             else
               S=(V-temp)/V
        end if

Determine the Hue;
           if S=0 then
                 H=undefined
              else
                 CR=(V-R)/(V-temp)
                 CG=(V-G)/(V-temp)
                 CB=(V-B)/(V-temp)
             end if
If you want values for each pixel it would be something like:


int index;
double R,G,B,V,temp,*S,*CR,*CG,*CB;

S = (double *)malloc(bitmap->width*bitmap->height*sizeof(double));
CR = (double *)malloc(bitmap->width*bitmap->height*sizeof(double));
CG = (double *)malloc(bitmap->width*bitmap->height*sizeof(double));
CB = (double *)malloc(bitmap->width*bitmap->height*sizeof(double));


for(i=(bitmap->height-1)*bitmap->width;i>=0;i-=bitmap->width)
{
    for(x=0;x<bitmap->width;x++)
    {
        index = bitmap->data[i+x]);
        R  = palette[index*3+0];
        G  = palette[index*3+1];
        B  = palette[index*3+2];
        R /= 255;
        G /= 255;
        B /= 255;
        V = max(R,G,B);
        temp = min(R,G,B);
       if (V == 0)
          S[i+x] = 0;
       else
          S[i+x] = (V - temp) / V ;
       if (S[i+x] != 0)
       {
             CR[i+x] = (V - R) / (V - temp);
             CG[i+x] = (V - G) / (V - temp);
             CB[i+x] = (V - B) / (V - temp);
       }
    }
}

free(S);
free(CR);
free(CG);
free(CB);

double max(double a, double b,double c)
{
     double temp;
     temp = (a > b) ? a:b;
     temp = (temp > c) ? temp:c;
     return temp;
}

double min(double a, double b,double c)
{
     double temp;
     temp = (a < b) ? a:b;
     temp = (temp < c) ? temp:c;
     return temp;
}


Dhyanesh