C言語でBMPファイルの入力・出力を行うプログラムを作成しています.
具体的には入力されたBMPファイルをそのまま別名のBMPファイルとして出力するプログラムを作成しているのですが,
ファイルの一部分が欠損して出力されてしまいます.(なので,ペイント等を使用して出力されたファイルを開くことができません.)
バイナリエディタを使用して入出力ファイルを比較したところ,どうやら画素データの末尾から数十バイトが出力されていないようでした.
ヘッダや欠損した末尾以外の部分はきちんと出力されていました.
データが最後までfwrite()で出力できていないのではと思いfputs()によりエラーを出力するようにしましたが,エラー出力もされません.
ソースコードを記載しますので,ご意見を頂ければと思います.
該当のソースコード
C
1#include<stdio.h> 2#include<stdlib.h> 3#define NAME 20 //ファイル名の長さ 4 5int main() { 6 char infile[NAME], outfile[NAME]; 7 FILE *infp, *outfp; 8 unsigned char header[54]; 9 unsigned char **data; 10 int width, height; 11 int pixWidth; 12 int i; 13 14 //BMPファイル読み込み 15 printf("input file name:"); 16 scanf("%s", infile); 17 18 infp = fopen(infile, "rb"); 19 if (infp == NULL) { 20 printf("ファイルの読み込みに失敗しました\n"); 21 return -1; 22 } 23 24 //ヘッダ読み込み 25 fread(header, sizeof(unsigned char), 54, infp); 26 27 width = header[18] + header[19] * 256 + header[20] * 256 * 256 + header[21] * 256 * 256 * 256; 28 height = header[22] + header[23] * 256 + header[24] * 256 * 256 + header[25] * 256 * 256 * 256; 29 //1行は1pixelにつき3byteかつ4byteの倍数 30 pixWidth = width * 3 + width % 4; 31 32 //画素データ読み込み 33 data = (unsigned char**)malloc(sizeof(unsigned char*) * height); 34 for (i = 0; i < height; i++) { 35 data[i] = (unsigned char*)malloc(sizeof(unsigned char) * pixWidth); 36 } 37 38 for (i = 0; i < height; i++) { 39 fread(data[i], sizeof(unsigned char), pixWidth, infp); 40 } 41 42 fclose(infp); 43 44 //BMPファイル書き出し 45 printf("output file name:"); 46 scanf("%s", outfile); 47 48 outfp = fopen(outfile, "wb"); 49 if (outfp == NULL) { 50 printf("ファイルの読み込みに失敗しました\n"); 51 return -1; 52 } 53 54 //ヘッダ書き出し 55 fwrite(header, sizeof(unsigned char), 54, outfp); 56 57 //画素データ書き出し 58 for (i = 0; i < height; i++) { 59 if (fwrite(data[i], sizeof(unsigned char), pixWidth, outfp) < pixWidth) { 60 fputs("書き出しに失敗しました\n", stderr); 61 } 62 63 } 64 65 fclose(outfp); 66 67 for (i = 0; i < height; i++) { 68 free(data[i]); 69 } 70 free(data); 71 return 0; 72}
ヘッダから読んだり計算した値を出力して想定とあっていますか?
念の為確認ですが、ファイルのリネーム方法を知りたいではなく、後々独自処理(フォーマットも自前)もしたい想定の質問でしょうか?
情報ヘッダからヘッダのサイズを確認したところ108byteとなっており,入力ファイルはヘッダを108(ファイルヘッダも含めて122)byteとすると計算が合うのですが,出力ファイルはヘッダが54byteとなっており、ここが計算が合っていない箇所ではないかと考えています.ただバイナリエディタ上ではヘッダの情報には過不足は見られないように思えます.ヘッダのサイズは54byteで固定なのだと考えていましたがそうならない場合があるのでしょうか.
このプログラムには後々独自処理を追加する予定でいます.
とりあえず入出力から作ろうとしているところです.
どうやらGimpでの入力ファイル作成時にパレット情報が書き込まれていたようです.
改めてパレット情報を出力しないように設定したところ無事入出力を行うことができました.
ベストアンサーはこれに気づくきっかけとなったdodox86様の回答とさせていただきます.
皆さまご助力いただきありがとうございました.
ヘッダのサイズが 108byte なら PBITMAPV4HEADER ですね。
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv4header
ファイルヘッダーに bfOffBits(ファイル先頭から画像データまでのオフセット)と言う項目があります。
これが事実上(ファイルヘッダー・情報ヘッダー・パレットデータを合わせた)ヘッダーサイズになります。
回答3件
あなたの回答
tips
プレビュー