Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define byte unsigned char
#define dword unsigned int
#define word unsigned short int
#pragma pack (1)
//4 Bytes per each pallete color
typedef struct {
unsigned char rgbBlue,
rgbGreen,
rgbRed,
rgbReserved;
}BITMAP_PALETTE;
// BMP File header
typedef struct bitmap_file_header {
byte bfType[2];
dword bfSize;
word bfReserved1;
word bfReserved2;
dword bfOffBits;
} BITMAP_FILE_HEADER;
// BMP Image header
typedef struct bitmap_info_header {
dword biSize;
dword biWidth;
dword biHeight;
word biPlanes;
word biBitCount;
dword biCompression;
dword biSizeImage;
dword biXPelsPerMeter;
dword biYPelsPerMeter;
dword biClrUsed;
dword biClrImportant;
} BITMAP_INFO_HEADER;
typedef struct image
{
BITMAP_FILE_HEADER file_info;
BITMAP_INFO_HEADER bitmap_info;
BITMAP_PALETTE *bitmap_palette;
byte *data;
} IMAGE;
int save_image(IMAGE *image, char name[])
{
FILE *fp;
int i, rowsize;
byte temp;
unsigned int row, col, colour;
int nx, ny;
if(image == NULL)
return EXIT_FAILURE;
fp=fopen(name, "wb");
if(fp==NULL)
{
printf("cannot open the file %s\n", name);
return EXIT_FAILURE;
}
fwrite(&image->file_info, sizeof(BITMAP_FILE_HEADER),1,fp);
fwrite(&image->bitmap_info, sizeof(BITMAP_INFO_HEADER),1,fp);
int itotalPalettbytes = (int) image->file_info.bfOffBits - sizeof(BITMAP_FILE_HEADER) - (int)sizeof(BITMAP_INFO_HEADER);
fwrite((void *)(&image->bitmap_palette),4, itotalPalettbytes / 4, fp);
if (((image->bitmap_info.biWidth * 3) % 4) == 0) {
nx = image->bitmap_info.biWidth * 3;
}
else {
nx = image->bitmap_info.biWidth * 3 + 4 -((image->bitmap_info.biWidth * 3) % 4);
}
ny = image->bitmap_info.biHeight;
fwrite((void *)image->data, sizeof(byte),nx * ny , fp);
fclose(fp);
return EXIT_SUCCESS;
}
int main(int argc, char **argv)
{
int iNx = 9, iNy;
FILE *fp;
int iTotalPaletteBytes;
unsigned short int iType; //holds the first two bytes of the file
IMAGE *ImageInput = (IMAGE *) malloc(sizeof(IMAGE));
if ((fp = fopen(argv[1], "rb")) == NULL)
{
printf("%s doesn't exist.\n",argv[1]);
}
else
{
fread((void *)&iType, 2, 1, fp);
//The BM is a short integer... 19778
if (iType == 19778)
{
fseek(fp,0,SEEK_SET);
//dump the first 14 bytes
fread((void *)&(ImageInput->file_info), sizeof(BITMAP_FILE_HEADER), 1, fp);
//dump the next 40 bytes
fread((void *)&(ImageInput->bitmap_info), sizeof(BITMAP_INFO_HEADER), 1, fp);
iTotalPaletteBytes = (int)ImageInput->file_info.bfOffBits - sizeof(BITMAP_FILE_HEADER) - (int)sizeof(BITMAP_INFO_HEADER);
//Dimention the array
ImageInput->bitmap_palette = (BITMAP_PALETTE *) malloc(iTotalPaletteBytes);
//dump the next 4*n bytes
fread((void *)(ImageInput->bitmap_palette),4, iTotalPaletteBytes / 4, fp); //works same way
if (ImageInput->bitmap_info.biBitCount == 24) {
//Go to the beginning of the pixel data in the file
fseek(fp, ImageInput->file_info.bfOffBits, SEEK_SET);
//Calculate the width of the bitmap taking into account padding bytes
if (((ImageInput->bitmap_info.biWidth * 3) % 4) == 0) {
iNx = ImageInput->bitmap_info.biWidth * 3;
}
else {
iNx = ImageInput->bitmap_info.biWidth * 3 + 4 -((ImageInput->bitmap_info.biWidth * 3) % 4);
}
iNy = ImageInput->bitmap_info.biHeight;
ImageInput->data = (unsigned char *) malloc(iNx * iNy * 3);
memset(ImageInput->data,0, sizeof ImageInput->data);
//Retrive the data array from the file
fread((void *)ImageInput->data, iNx * iNy * 3, 1, fp);
save_image(ImageInput, "Test.bmp");
}
}
}
return 0;
}