2016-01-27 74 views
-1

當試圖從一個bmp文件簽名來讀取,並調用FREAD後,sig包含52428注意這是0xCCCC而不是19778,這是0x4D42'BM'正確的十進制值,它是一個BMP文件的正確頭標識。爲什麼fread沒有正確讀入uint16_t的值?

uint16_t sig; 
// 0. If any of the operations fail, free any memory and return 0 

// 1. Open the file 
FILE *f = fopen(file, "r"); 
if (f == 0) { 
    printf("Cannot open file\n"); 
} 

// 2a. Read the initial fields of the header; verify that the file type (BM) is correct. 
fseek(f, 0, SEEK_SET); 
fread(&sig, sizeof(uint16_t), 1, f); // signature 
printf("%d\n", sig); 
if (sig != 0x4D42) { 
    printf("not a bmp file!\n"); 
    return 0; 
} 

我嘗試使用uint8_t一次讀取一個字節,以及許多其他解決方案來解決這個問題。

看起來好像fread只是沒有正確寫入sig,因爲CC是使用我正在使用的編譯器的未初始化內存的默認格式。任何幫助,將不勝感激。

這裏是我想讀的bmp文件: image

+5

你爲什麼不檢查'fread()'的返回值。 –

+1

也許你應該退出,如果文件沒有打開。 – drescherjm

+2

@Bobby:那麼,您是否檢查了「無法打開文件」消息的輸出? – AnT

回答

0

你的代碼完全應該工作。您正在爲sig分配2個字節,然後從文件的開頭正確讀入2個字節。只要前兩個字節是BM或'0x4D42',那麼你應該是好的。

我的猜測是,問題在於你的目錄/文件路徑。

檢查,以確保您傳遞的文件具有正確的文件路徑。請注意,要通過相對文件路徑傳遞它,您需要使文件路徑相對於項目的根目錄。

希望這會有所幫助!

+0

他正在打開一些東西。否則,我會期待分段錯誤。我會說他正在打開一個不是BMP的文件 – Flikk

+0

你爲什麼堅持要開什麼東西?它不處於模式「r +」,它看起來像在該位置的內存仍未初始化 – Tresdon

+1

OMG!我的bmp文件在我的項目文件夾中,但是我的.cpp和.h文件在整個時間都在不同的文件夾中。一切都完美了!當我打印sig的值時,我得到了19778這正是我所需要的,謝謝 – Bobby

1

假設該文件存在,你應該知道,你打開的,而不是二進制文件爲文本。

嘗試:

FILE *f = fopen(file, "rb"); 
+2

這是一個很好的觀察,但我懷疑這會有所幫助。 –

+1

在Unix上,'r'和'rb'沒有區別。在Windows上,我認爲它隻影響如何處理新行。 – Barmar

+0

@barmar:如果二進制文件包含'0x1A'字節,它也會引起EOF神祕的信號。 – rici

1

我會嘗試幾件事情:

  1. 初始化sig爲零。
  2. 檢查返回值fread以確保操作成功。

如果沒有談到的是,要儘量接下來的事情將是使用

char sig[2]; 

... 

if (2 != fread(sig, 1, 2, f)) { ... 
+0

雖然這是一個好主意,沒有理由爲什麼'fread ()'會失敗,除非文件太短。他的'.bmp'文件不太可能是這種情況。 – Barmar

+0

@Barmar,在發佈的代碼中似乎沒有其他問題。 –

+0

我認爲初始化'sig'似乎是最可能的解決方案。這是一種非標準類型,看起來不太好。 – Flikk

0

我測試你的代碼,我沒有問題。 你能提供你想要讀取的BMP文件嗎?

此外,我已經爲您編寫了一些代碼,可以幫助您在項目變大時保持一切組織。我建議把結構放入一個頭文件中。

編輯:必須自己定義結構中的數據類型,因爲我在沒有stdint.h的環境中執行此操作。抱歉。但你可以改變它們。

您可以使用這些結構來存儲你的頭信息:

typedef struct { 
    uint16 Signature; 
    uint32 Size; 
    uint16 Reserved1; 
    uint16 Reserved2; 
    uint32 BitsOffset; 
} BITMAP_FILE_HEADER; 

typedef struct { 
    uint32 biSize; 
    int32 biWidth; 
    int32 biHeight; 
    uint16 biPlanes; 
    uint16 biBitCount; 
    uint32 biCompression; 
    uint32 biSizeImage; 
    int32 biXPelsPerMeter; 
    int32 biYPelsPerMeter; 
    uint32 biClrUsed; 
    uint32 biClrImportant; 
} BITMAP_INFO_HEADER; 

typedef struct { 
    uint32 bcSize; 
    uint16 bcWidth; 
    uint16 bcHeight; 
    uint16 bcPlanes; 
    uint16 bcBitCount; 
} BITMAP_CORE_HEADER; 

使用此功能來讀取頭

int read_header(FILE* inputfile, BITMAP_INFO_HEADER* header, BITMAP_FILE_HEADER* fHeader) { 
    BITMAP_FILE_HEADER fileHeader; 
    BITMAP_INFO_HEADER infoHeader; 
    BITMAP_CORE_HEADER coreHeader; 
    uint32 headersize; 

    fread(&fileHeader.Signature, sizeof(fileHeader.Signature), 1, inputfile); 
    printf("%d", fileHeader.Signature); 
} 

,並使用主函數來調用一切和處理錯誤

int main(void) { 
    FILE* inputfile = NULL; 
    BITMAP_INFO_HEADER infoHeader = {0}; 
    BITMAP_FILE_HEADER fileHeader = {0}; 

    if ((inputfile = fopen("source.bmp", "rb")) == NULL) { 
     ERROR("can't open file.") 
     return 1; 
    } 

    if (read_header(inputfile, &infoHeader, &fileHeader) == 0) { 
     ERROR("Fileformat not supported.") 
     return 1; 
    } 
} 

根據您分配的內容,您可以使用ERROR()宏以清除所有內容:

#define ERROR(ErrMsg) \ 
    printf("Error: %s\n", ErrMsg); \ 
    if (bitmapData != NULL) \ 
     free(bitmapData); \ 
    if (yourAlloc != NULL) \ 
     free(yourAlloc); 
+0

這並不回答這個問題,也依賴於大量的實現細節(例如struct packing和integer endianness) –

+0

@M。M是的,我認爲在測試時我有一點點偏離。但如果他繼續下去,也許對他有幫助。我無法找到他的代碼有任何問題。因此,爲了進一步測試,我們需要知道他是如何編譯它的,還需要他的BMP文件進行測試。 – Flikk

+0

@Flikk我在帖子的底部添加了圖片鏈接 – Bobby

-1

以下是解決方案嘗試理解它,隨時詢問您是否有任何疑問。

記住BMP的前兩個字節應始終'B'遵循「M'hex0x420x4Dint(8 bit)6677

#include<stdio.h> 
#include<stdlib.h> 

int main() 
{ 
    FILE *fp = NULL; 
    int fsize,result; 
    char *buffer = NULL; 

    fp = fopen("fileName.bmp", "rb+"); 
    if (fp == NULL) 
    { 
    printf("Error! File Not found!\n"); 
    } 
    else 
    { 
     fseek(fp, 0, SEEK_END); 
     fsize = ftell(fp); 
     fseek(fp, 0, SEEK_SET); 
     printf("File Size:%d\n",fsize); 

     buffer = malloc(sizeof(char)*fsize); 
     result=fread(buffer, sizeof(char), fsize, fp); 

     if (result != fsize) 
     { 
     printf("Error Reading file!\n"); 
     } 
     fclose(fp); 
    } 

    //Remember the first two bytes of BMP Should always be 
    //'B' followed 'M' or hex values 0x42 and 0x4D or int(8 bit) values 66 and 77 
    if (buffer[0] == 'B' && buffer[1] == 'M') 
    { 
    printf("File is BMP!\n"); 
    } 
    else 
    { 
    printf("Not BMP!\n"); 
    } 

    free(buffer); 
    buffer = NULL; 

    return 0; 
} 
如果你想

INT(8位)的bmp文件的值那麼你可以添加下面的代碼行,

char *buffer = NULL; 
int *fdata = NULL; 

//Get the file size as in above code and after that 
buffer = malloc(sizeof(char)*fsize); 
fdata = malloc(sizeof(int)*fsize); 

result=fread(buffer, sizeof(char), fsize, fp); 
if (result != fsize) 
{ 
    printf("Error Reading file!\n"); 
} 

for (int i = 0; i < fsize; i++) 
{ 
    if (buffer[i] < 0) 
    { 
     fdata[i] = 256 + (int)buffer[i]; 
    } 
    else 
    { 
     fdata[i] = (int)buffer[i]; 
    } 
} 
for (int i = 0; i < fsize; i++) 
{ 
    printf("%d ",fdata[i]); 
} 

//free up after your done 
free(buffer); 
buffer=NULL; 
free(fdata); 
fdata=NULL; 
+0

您是否嘗試執行Bobbys代碼?因爲它在工作。然後,你正在使用C++的問題。我想說他的編譯器/編譯器設置或他的BMP文件有問題 – Flikk

+0

1.你的代碼不能用[tag:c]編譯器編譯,[tag:c]和[tag:C++]不一樣。 2.你對'malloc()'使用強制轉換,但是因爲它是C++,所以你應該使用C++風格轉換。你從不檢查'malloc()'的返回值。 4.如果由於某種原因'fread()'讀取的字節數少於預期值,那麼代碼將取消引用'NULL'指針。我可以繼續,但我不想再讀你的代碼。 –

+0

@Flikk對不起,我沒有正確地解決他的問題。我測試了他的代碼,它顯示了正確的值,如果我加載一個BMP圖像。如果它不是bmp文件,它會顯示一些其他值。你是對的,他的編譯器或他的bmp文件肯定有問題。 – LuckyAli

相關問題