質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

BMPファイルを書き込む際にデータが欠損してしまう

Takayou
Takayou

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

2回答

0グッド

0クリップ

1042閲覧

投稿2019/09/28 01:15

編集2019/09/28 02:06

c言語でBMP画像の入出力を実装したいのですがうまくいきません。

具体的には、読み込んだBMPファイルをそのまま出力しようとしたところ、出力したファイルを開くと
「このファイルはサポートしていない形式のようです」
となり、画像が表示されません。

また、入力ファイルのサイズにくらべて出力ファイルのサイズが小さくなってしまっています。
(入力ファイル4144kBに対して、出力ファイル4142KB)

以下にプログラムを示します。
どなたか教えてください!

追記
visual studio2019で動かしています。
また、画像は以下のリンクのものをしようしています。
https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwjG5LHctfLkAhXC62EKHWyLBJ0QjRx6BAgBEAQ&url=http%3A%2F%2Fimagingsolution.blog.fc2.com%2Fblog-entry-180.html&psig=AOvVaw0T4Qw7OXJeYByGbmMmddTJ&ust=1569722386315809

C

1/* 2BMPファイルに対して, 以下の処理を行う 3・グレースケール変換 4・エッジ検出(Prewittオペレータ, Sobelオペレータ) 5・拡大,縮小,回転, 移動(線形補間法) 6*/ 7 8 9#include<stdio.h> 10#include<stdlib.h> 11 12#define IMG_MAX_SIZE 512 13 14typedef struct { 15 unsigned char *red; 16 unsigned char *blue; 17 unsigned char *green; 18}ImageData; 19 20typedef struct { 21 unsigned char FileHeader[14]; 22 unsigned int Size; 23 int Width, Height; 24 unsigned char InfoHeader[28]; 25 ImageData img; 26}BMP; 27 28//BMPファイル読み込み 29void ReadBmp(char FileName[], BMP* bmp); 30//画像を書き込む 31void WriteBmp(char FileName[], BMP* bmp); 32 33int main() { 34 BMP bmp; 35 36 char input_file[] = "lena.bmp"; 37 char output_file[] = "lenaout.bmp"; 38 ReadBmp(input_file, &bmp); 39 WriteBmp(output_file, &bmp); 40 41 return 0; 42 43 free(bmp.img.red); 44 free(bmp.img.green); 45 free(bmp.img.blue); 46} 47 48 49//BMPファイル読み込み 50void ReadBmp(char FileName[], BMP* bmp) 51{ 52 FILE* fp; 53 54 fopen_s(&fp, FileName, "rb"); 55 if (fp == NULL) { 56 printf("Not Found : %s", FileName); 57 exit(1); 58 } 59 60 //ヘッダー情報を読み込み 61 fread(bmp->FileHeader, sizeof(unsigned char), 14, fp); 62 fread(&bmp->Size, sizeof(int), 1, fp); 63 fread(&bmp->Width, sizeof(int), 1, fp); 64 fread(&bmp->Height, sizeof(int), 1, fp); 65 fread(bmp->InfoHeader, sizeof(unsigned char), 28, fp); 66 67 //画像本体の読み込み 68 bmp->img.red = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char)); 69 bmp->img.blue = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char)); 70 bmp->img.green = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char)); 71 if (bmp->img.red == NULL) { 72 printf("メモリ確保に失敗\n"); 73 exit(1); 74 } 75 if (bmp->img.green == NULL) { 76 printf("メモリ確保に失敗\n"); 77 exit(1); 78 } 79 if (bmp->img.blue == NULL) { 80 printf("メモリ確保に失敗\n"); 81 exit(1); 82 } 83 84 for (int h = 0; h < bmp->Height; h++) { 85 for (int w = 0; w < bmp->Width; w++) { 86 fread(&bmp->img.red [w + h * bmp->Width], sizeof(unsigned char), 1, fp); 87 fread(&bmp->img.green [w + h * bmp->Width], sizeof(unsigned char), 1, fp); 88 fread(&bmp->img.blue [w + h * bmp->Width], sizeof(unsigned char), 1, fp); 89 } 90 } 91 92 //読みこんだファイルを閉じる 93 fclose(fp); 94} 95 96//画像を書き込む 97void WriteBmp(char FileName[], BMP* bmp) 98{ 99 FILE* fp; 100 fopen_s(&fp, FileName, "wb"); 101 if (fp == NULL) { 102 printf("Not Found : %s\n", FileName); 103 exit(1); 104 } 105 106 fwrite(bmp->FileHeader, sizeof(unsigned char), 14, fp); 107 fwrite(&bmp->Size, sizeof(int), 1, fp); 108 fwrite(&bmp->Width, sizeof(int), 1, fp); 109 fwrite(&bmp->Height, sizeof(int), 1, fp); 110 fwrite(bmp->InfoHeader, sizeof(unsigned char), 28, fp); 111 112 113 printf("%s\n", bmp->FileHeader); 114 printf("%d %d %d\n", bmp->Size, bmp->Width, bmp->Height); 115 printf("%s\n", bmp->InfoHeader); 116 117 118 //画像本体の読み込み 119 for (int h = 0; h < bmp->Height; h++) { 120 for (int w = 0; w < bmp->Width; w++) { 121 fwrite(&bmp->img.red [w + h * bmp->Width], sizeof(unsigned char), 1, fp); 122 fwrite(&bmp->img.green[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 123 fwrite(&bmp->img.blue [w + h * bmp->Width], sizeof(unsigned char), 1, fp); 124 } 125 } 126 127 fclose(fp); 128}

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

dodox86

2019/09/28 01:40

回答未満なのでこちらにコメントさせてもらいますが、何か色々と問題がありそうな気がします。Windowsのビットマップファイルって、単純なフォーマットではないです。また、構造体メンバーのパディングの問題で、正しくメンバーが読めていない気もします。ファイルのヘッダーは確かに14バイト(sizeof(BITMAPFILEHEADER))ですが、32ビット境界ではないのでコンパイル結果によっては以降にズレが生じます。そんなこんなで、ファイルの読み取り時点でおかしくなっているのでは。有名なレナさん画像"lena.bmp"をお使いでしょうから、ファイルの在処(ダウンロード元?)やコンパイルオプションを示せば、有効な回答を得られるかもしれません。
Takayou

2019/09/28 01:52

ありがとうございます、修正させていただきます。
Zuishin

2019/09/28 02:09

BMP ではないようですが。
dodox86

2019/09/28 02:21

>Zuishinさん 本当だ、PNGファイルですね。 >Takayouさん 画像の見た目のお話ではありません。もし本当にここからレナさん画像PNGファイルをダウンロードしたのであれば、ファイルのフォーマットが違うので、絶対に扱えません。それとも、これからBMPファイルに手動で変換したのでしょうか。
Takayou

2019/09/28 03:35

ここから手動でBMPファイルに変換してしまいました。

回答2

1

ベストアンサー

入力ファイルのサイズにくらべて出力ファイルのサイズが小さくなってしまっています。

1ラインごとに4の倍数バイトになるよう、末尾に0パディングする必要があります。

投稿2019/09/28 02:49

編集2019/09/28 02:50
SHOMI

総合スコア4079

ikadzuchi👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

Takayou

2019/09/28 02:55

回答ありがとうございます。 書き出すときに0を追加すればよいのでしょうか? BMPを書き込む関数の一部を以下のように書き換えたら、画像は表示されたのですが、ゆがんだ形になってしまいました。 ```C //一列4byte単位でなければならないので、padding処理を行う int stride = (bmp->Width + 3) / 4 * 4; unsigned char padding = '00'; //画像本体の書き込み for (int h = 0; h < bmp->Height; h++) { for (int w = 0; w < bmp->Width; w++) { fwrite(&bmp->img.red [w + h * bmp->Width], sizeof(unsigned char), 1, fp); fwrite(&bmp->img.green[w + h * bmp->Width], sizeof(unsigned char), 1, fp); fwrite(&bmp->img.blue [w + h * bmp->Width], sizeof(unsigned char), 1, fp); } for (int i = 0; i < stride - bmp->Width; i++) { fwrite(&padding, sizeof(unsigned char), 1, fp); fwrite(&padding, sizeof(unsigned char), 1, fp); fwrite(&padding, sizeof(unsigned char), 1, fp); } } ```
SHOMI

2019/09/28 03:13 編集

0埋めを3バイトごとと決め打ちではずれます。 例:幅2ドットの場合、0埋めは2バイト。 int stride = (bmp->Width*3 + 3) / 4 * 4; unsigned char padding = 0; for (int i = 0; i < stride - bmp->Width*3; i++) { fwrite(&padding, sizeof(unsigned char), 1, fp); } 読み出し側も0埋めを考慮して読んでいませんね。
Takayou

2019/09/28 03:39

上手くいきました!ありがとうございます! 読み出し側でも0埋めをして読むとのはなぜなのでしょうか?
SHOMI

2019/09/28 03:45

画像幅が4の倍数ドットでない場合、1ラインごとに4の倍数バイトになるよう0パディングされているので、 1ライン読むごとにその末尾の0を読み飛ばしてやらないと、次のラインの先頭画素として0が読まれてしまいます。
Takayou

2019/09/28 03:53

なるほど、わかりました。 丁寧に教えてくださりありがとうございます。

0

とりあえず、バイナリエディタなどを使って、書き出したファイルのヘッダ情報だけでも同一になっているかを確認してみたらどうでしょうか。

「BMP ファイルフォーマット」でぐぐればBMPの詳細が出てきますが、これは読んでますか?

投稿2019/09/28 01:48

y_waiwai

総合スコア86072

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。