Copying a bmp in c

南笙酒味 提交于 2019-12-02 06:05:18

I fiddled a little bit with the data provided, and I'm quite sure what happened:

FILE *inptr = fopen(infile, "r");

and

FILE *outptr = fopen(outfile, "w");

open the files in text mode.

This is a special behavior I know from Microsoft's C API and it seems that this applies to mingw TDM-GCC as well (which I struggled to believe until the dumped data convinced me that my suspicion was right).

The file I/O in Microsoft's C API distinguishs between text mode and binary mode:

  • fopen(infile, "rt") and fopen(outfile, "wt") open the files in text mode.
  • fopen(infile, "rb") and fopen(outfile, "wb") open the files in binary mode.
  • fopen(infile, "r") and fopen(outfile, "w") default to text mode.

In text mode the file reading replaces all Microsoft line-endings ("\r\n") by Unix line-endings ("\n") as well as the writing does the opposite ("\n" becomes "\r\n").

This is reasonable if the contents is plain text but it probably corrupts output of binary contents where a byte 0x0d is inserted whenever a byte 0x0a (with any meaning) occurs in the data stream.

To prove this,

  1. I downloaded your sample files (unfortunately uploaded in PNG format)
  2. converted the files (back) to 24 bit BMP (using GIMP)
  3. made a hex-dump for each:

    $ hexdump -C IkW6FbN.bmp >IkW6FbN.bmp.txt
    
    $ hexdump -C jnxpTwE.bmp >jnxpTwE.bmp.txt
    
  4. and finally loaded IkW6FbN.bmp.txt and jnxpTwE.bmp.txt into WinMerge for comparison.

As the snapshot illustrates, the input and output file have identical contents for the first 14037 (0x36d5) bytes. Then, the input file contains "accidentally" three bytes 0a 0a 0a where the output file has instead 0d 0a 0d 0a 0d 0a. Thus, the respective original pixels (and all following) are corrupted.

(As you might already guess, 0a is the hexadecimal value of the line-feed character '\n', 0d the one of the carriage-return '\r'.)

Btw. the output file is probably a little bit longer than the input file (due to the inserted CR bytes). This might be ignored by a BMP viewer as the BMP header states exactly how many bytes are needed for the raw image (and the extra bytes are simply ignored).

As you already might've recognized you should change the fopen() calls to

FILE *inptr = fopen(infile, "rb");

and

FILE *outptr = fopen(outfile, "wb");

to fix your issue.

Btw. the C APIs on *x OSes (e.g. Linux) doesn't have such a distinction of text and binary mode. Instead, the b is simply ignored (which is helpful to write portable code).

Further reading: fopen, fopen_s on cppreference.com

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!