2016-11-10 28 views
3

我不確定我的電腦是否試圖欺騙我,或者如果我只是爲了發現錯誤而疲憊不堪。幾個小時和幾乎幾天,我試圖用純C編寫一個位圖文件。我沒有格式或填充,但內容的問題。 這是一個MWE。當寫入.bmp文件時發生字節偏移

int main() { 
    FILE *file; 
    int w = 256; 
    int h = 15; 
    int pad = (4 - ((3 * w) % 4)) % 4; 

    int filesize = 54 + (3 * w + pad) * h; 

    // Create file header 
    unsigned char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 }; 

    bmpfileheader[2] = (unsigned char)(filesize); 
    bmpfileheader[3] = (unsigned char)(filesize >> 8); 
    bmpfileheader[4] = (unsigned char)(filesize >> 16); 
    bmpfileheader[5] = (unsigned char)(filesize >> 24); 

    // Create Info Header 
    unsigned char bmpinfoheader[40] = { 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0 }; 

    bmpinfoheader[4] = (unsigned char)(w); 
    bmpinfoheader[5] = (unsigned char)(w >> 8); 
    bmpinfoheader[6] = (unsigned char)(w >> 16); 
    bmpinfoheader[7] = (unsigned char)(w >> 24); 
    bmpinfoheader[8] = (unsigned char)(h); 
    bmpinfoheader[9] = (unsigned char)(h >> 8); 
    bmpinfoheader[10] = (unsigned char)(h >> 16); 
    bmpinfoheader[11] = (unsigned char)(h >> 24); 

    // Create content 
    // Allocate memory dynamically 
    unsigned char *bmpcontent = (unsigned char *)calloc(filesize - 54, sizeof(unsigned char)); 

    int index; 

    // map data values onto blue-red scale 
    for (int j = 0; j < h; j++) 
    { 
     for (int i = 0; i < w; i++) 
     { 
      index = 3 * i + (3 * w + pad) * j; 

      // blue 
      *(bmpcontent + index) = 255-i; 
     } 
    } 

    // Write to file 
    file = fopen("test.bmp", "w"); 

    fwrite(bmpfileheader, sizeof(bmpfileheader[0]), 14, file); 
    fwrite(bmpinfoheader, sizeof(bmpinfoheader[0]), 40, file); 
    fwrite(bmpcontent, sizeof(bmpcontent[0]), filesize - 54, file); 

    fclose(file); 

    // free memory 
    free(bmpcontent); 

    return 0; 
} 

,因爲我填的每個像素的「藍色字節」與255-i我指望得深藍色光滑黑漸變中的每一行。但我發現了這一點: example1

正如你可以看到有在每個引起顏色的每個新行加每隔二行之後的像素移位的變更線字節偏移。奇怪的是,它只發生在我試圖在文件中寫入13時。使用十六進制編輯器,我發現,在下一個值進入文件之前寫入第二個13。當我將寬度減小到240(現在位圖的內容在14和255之間變化)時,我得到沒有任何移位的平滑圖像:example2

你可以說這是純粹的巧合,而寫一個13,它可能是這樣的。但我也試圖將數據寫入文件,其中13出現在非確定性位置,並且發生了完全相同的效果。

我在我的智慧結尾,請幫助我!

回答

4

這是因爲值爲13對應於Windows中的換行符。 Windows換行符是\r\n,對應於十六進制0D0A。由於您試圖編寫0D,因此將其視爲換行符,因此它將以0D0A的格式寫入文件。這是如此,如果你只將\n放在一個字符串中,它將被正確地寫爲\r\n到一個文件。因此,爲了解決這個問題,你應該確保你以二進制模式寫入文件,防止這個「特性」把額外的字節寫入文件。在這裏看到更多的信息:Strange 0x0D being added to my binary file

要使用二進制模式,只需更換"w""wb"fopen,它會正常工作。我剛纔已經驗證了這一點,並且輸出是正確的:

test.bmp

在其他平臺上,首先就不會發生這樣的問題,所以這個修復纔有效,並且只需要用於Windows平臺。

+3

很好的抓住這裏。 –

+0

根據'fwrite man page',在'mode'描述下,'b'標誌僅用於兼容性,並且在包括Linux在內的所有符合POSIX的系統上被忽略。該運營商尚未指出他們正在開發哪個平臺。 – Matt

+0

它在Linux上的工作原理。由於fopen默認爲二進制。 – Matt