ksh999
ksh999

Reputation: 21

save bmp file using c on linux

I tried to open bmp file and save it using c code. My code worked well on window compiler(visual studio) but it didn't work on linux using gcc. Even though the format of final output is bmp, it shows like empty file(white). I'm a beginner for using linux and c programming so I'm not sure what's wrong with this happening! I compiled it using gcc: gcc bmp.c -o bmp. the code below is what I used.

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<string.h>
#include<stdio.h>

#define  WIDTHBYTES(bits)    (((bits)+31)/32*4)

#pragma pack(push, 1) 

typedef unsigned short WORD;
typedef unsigned long  DWORD;
typedef long           LONG;




typedef struct tagBITMAPFILEHEADER {    
WORD    bfType;  
DWORD   bfSize;  
WORD    bfReserved1;  
WORD    bfReserved2;  
DWORD   bfOffBits;  
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {  
DWORD biSize; 
LONG biWidth;  
LONG biHeight;  
WORD biPlanes;  
WORD biBitCount; 
DWORD biCompression;  
DWORD biSizeImage;  
LONG biXPelsPerMeter;  
LONG biYPelsPerMeter;  
DWORD biClrUsed;  
DWORD biClrImportant;  
} BITMAPINFOHEADER;


typedef struct tagRGBQUAD { 
unsigned char  rgbBlue;  
unsigned char  rgbGreen; 
unsigned char  rgbRed;   
unsigned char  rgbReserved;
} RGBQUAD;

typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;

 int main(int argc, char* argv[]){

FILE             *infile;

FILE             *outfile;

BITMAPFILEHEADER  hf;

BITMAPINFOHEADER  hInfo;

RGBQUAD           hRGBpal[256];


unsigned char              *lpImg;


int               i, j, pos, rwsize;

int               nBitCount = 1;
infile = fopen("image.bmp", "rb");
if (infile == NULL)
{
    printf("no image");
    return 1;
}
fread(&hf, sizeof(BITMAPFILEHEADER), 1, infile);
if (hf.bfType != 0x4d42)
{
    printf("ERROR\n");
    fclose(infile);
    exit(1);
}
fread(&hInfo, sizeof(BITMAPINFOHEADER), 1, infile);
if (hInfo.biBitCount == 8 || hInfo.biBitCount == 16 ||
    hInfo.biBitCount == 24 || hInfo.biBitCount == 32)
{
    nBitCount = hInfo.biBitCount / 8;
    if (hInfo.biBitCount == 8)
    {
        pos = hf.bfOffBits - hf.bfSize - hInfo.biSize;
        if (pos > 0)
        {
            fread((unsigned char *)hRGBpal, sizeof(unsigned char), pos, infile);
        }
    }

    lpImg = (unsigned char*)malloc(hInfo.biSizeImage);
    fseek(infile, hf.bfOffBits, SEEK_SET);
    fread(lpImg, sizeof(unsigned char), hInfo.biSizeImage, infile);
    fclose(infile);
}

rwsize = WIDTHBYTES(hInfo.biBitCount*hInfo.biWidth);
for (i = 0; i < hInfo.biHeight; i++)
{
    for (j = 0; j < hInfo.biWidth; j++)
    {
        lpImg[i*rwsize + j];
    }
}

outfile = fopen("out.bmp", "wb")

    if (hInfo.biBitCount == 8)
    {
        hf.bfOffBits = sizeof(BITMAPFILEHEADER)
            + sizeof(BITMAPINFOHEADER) + sizeof(hRGBpal);
    }
fwrite(&hf, sizeof(char), sizeof(BITMAPFILEHEADER), outfile);
fwrite(&hInfo, sizeof(char), sizeof(BITMAPINFOHEADER), outfile);

if (hInfo.biBitCount == 8)
{
    fwrite(hRGBpal, sizeof(RGBQUAD), 256, outfile);
}
fwrite(lpImg, sizeof(unsigned char), hInfo.biSizeImage, outfile);
fclose(outfile);
if (lpImg)
    free(lpImg);

printf("DONE!");}

Upvotes: 2

Views: 2224

Answers (1)

user2371524
user2371524

Reputation:

This probably goes wrong here:

typedef unsigned short WORD;
typedef unsigned long  DWORD;
typedef long           LONG;

If you're on 64bit Linux, long has 64 bits. On 64bit Windows, it has only 32bits. For portable code, use fixed-size integers:

typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef int32_t LONG;

On a further note, there's no need to introduce these ugly (my opinion here) winapi typedefs at all. A (sloppy) version of the bitmap file header I'm using (still relying on the "packed struct" feature and merging both structs into one) looks like this:

#pragma pack(push)
#pragma pack(1)
struct bmphdr
{
    uint16_t    bfType;
    uint32_t    bfSize;
    uint32_t    bfReserved;
    uint32_t    bfOffBits;
    uint32_t    biSize;
    uint32_t    biWidth;
    int32_t     biHeight;
    uint16_t    biPlanes;
    uint16_t    biBitCount;
    uint32_t    biCompression;
    uint32_t    biSizeImage;
    int32_t     biXPelsPerMeter;
    int32_t     biYPelsPerMeter;
    uint32_t    biClrUsed;
    uint32_t    biClrImportant;
};
#pragma pack(pop)

Upvotes: 3

Related Questions