2017-08-17 23 views
0

我試圖打開bmp文件並使用c代碼保存它。我的代碼在窗口編譯器(visual studio)上運行良好,但在使用gcc的linux上不起作用。即使最終輸出的格式是bmp,它也會顯示爲空白文件(白色)。我是使用linux和c編程的初學者,所以我不確定發生了什麼問題! 我使用gcc編譯它:gcc bmp.c -o bmp。 下面的代碼是我用過的。在linux上使用c保存bmp文件

#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!");} 
+0

哪裏都是這些東西,比如'BITMAPFILEHEADER'界定?請發佈[mcve]。 –

+0

@FelixPalmen對不起,我添加了一個完整的代碼,我瘋了:) – ksh999

+0

請注意,在你的循環'lpImg [i * rwsize + j];'什麼都不做 –

回答

2

這可能出錯的位置:

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

如果你在64位的Linux,long有64位。在64位Windows上,它只有32位。對於便攜式代碼,使用固定大小的整數:

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

在進一步的說明,沒有必要(在這裏我看來)介紹這些醜陋的typedef WINAPI在所有。我使用(仍然依靠「包裝結構」的功能和結構都合併到一個)位圖文件頭的(馬虎)版本是這樣的:

#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) 
+0

這是個好主意! –

+0

@ ksh999。包括''固定大小的類型。 –

+0

@ ksh999讀取[64位數據模型](https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models),瞭解爲什麼結果在windows和linux上使用內置'long'時會有所不同。 (Windows 64使用'LLP64',Linux 64使用'LP64') –