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
/*
BMPファイルに対して, 以下の処理を行う
・グレースケール変換
・エッジ検出(Prewittオペレータ, Sobelオペレータ)
・拡大,縮小,回転, 移動(線形補間法)
*/
#include<stdio.h>
#include<stdlib.h>
#define IMG_MAX_SIZE 512
typedef struct {
unsigned char *red;
unsigned char *blue;
unsigned char *green;
}ImageData;
typedef struct {
unsigned char FileHeader[14];
unsigned int Size;
int Width, Height;
unsigned char InfoHeader[28];
ImageData img;
}BMP;
//BMPファイル読み込み
void ReadBmp(char FileName[], BMP* bmp);
//画像を書き込む
void WriteBmp(char FileName[], BMP* bmp);
int main() {
BMP bmp;
char input_file[] = "lena.bmp";
char output_file[] = "lenaout.bmp";
ReadBmp(input_file, &bmp);
WriteBmp(output_file, &bmp);
return 0;
free(bmp.img.red);
free(bmp.img.green);
free(bmp.img.blue);
}
//BMPファイル読み込み
void ReadBmp(char FileName[], BMP* bmp)
{
FILE* fp;
fopen_s(&fp, FileName, "rb");
if (fp == NULL) {
printf("Not Found : %s", FileName);
exit(1);
}
//ヘッダー情報を読み込み
fread(bmp->FileHeader, sizeof(unsigned char), 14, fp);
fread(&bmp->Size, sizeof(int), 1, fp);
fread(&bmp->Width, sizeof(int), 1, fp);
fread(&bmp->Height, sizeof(int), 1, fp);
fread(bmp->InfoHeader, sizeof(unsigned char), 28, fp);
//画像本体の読み込み
bmp->img.red = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char));
bmp->img.blue = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char));
bmp->img.green = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char));
if (bmp->img.red == NULL) {
printf("メモリ確保に失敗\n");
exit(1);
}
if (bmp->img.green == NULL) {
printf("メモリ確保に失敗\n");
exit(1);
}
if (bmp->img.blue == NULL) {
printf("メモリ確保に失敗\n");
exit(1);
}
for (int h = 0; h < bmp->Height; h++) {
for (int w = 0; w < bmp->Width; w++) {
fread(&bmp->img.red [w + h * bmp->Width], sizeof(unsigned char), 1, fp);
fread(&bmp->img.green [w + h * bmp->Width], sizeof(unsigned char), 1, fp);
fread(&bmp->img.blue [w + h * bmp->Width], sizeof(unsigned char), 1, fp);
}
}
//読みこんだファイルを閉じる
fclose(fp);
}
//画像を書き込む
void WriteBmp(char FileName[], BMP* bmp)
{
FILE* fp;
fopen_s(&fp, FileName, "wb");
if (fp == NULL) {
printf("Not Found : %s\n", FileName);
exit(1);
}
fwrite(bmp->FileHeader, sizeof(unsigned char), 14, fp);
fwrite(&bmp->Size, sizeof(int), 1, fp);
fwrite(&bmp->Width, sizeof(int), 1, fp);
fwrite(&bmp->Height, sizeof(int), 1, fp);
fwrite(bmp->InfoHeader, sizeof(unsigned char), 28, fp);
printf("%s\n", bmp->FileHeader);
printf("%d %d %d\n", bmp->Size, bmp->Width, bmp->Height);
printf("%s\n", bmp->InfoHeader);
//画像本体の読み込み
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);
}
}
fclose(fp);
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
入力ファイルのサイズにくらべて出力ファイルのサイズが小さくなってしまっています。
1ラインごとに4の倍数バイトになるよう、末尾に0パディングする必要があります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
とりあえず、バイナリエディタなどを使って、書き出したファイルのヘッダ情報だけでも同一になっているかを確認してみたらどうでしょうか。
「BMP ファイルフォーマット」でぐぐればBMPの詳細が出てきますが、これは読んでますか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.19%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
dodox86
2019/09/28 10:40
回答未満なのでこちらにコメントさせてもらいますが、何か色々と問題がありそうな気がします。Windowsのビットマップファイルって、単純なフォーマットではないです。また、構造体メンバーのパディングの問題で、正しくメンバーが読めていない気もします。ファイルのヘッダーは確かに14バイト(sizeof(BITMAPFILEHEADER))ですが、32ビット境界ではないのでコンパイル結果によっては以降にズレが生じます。そんなこんなで、ファイルの読み取り時点でおかしくなっているのでは。有名なレナさん画像"lena.bmp"をお使いでしょうから、ファイルの在処(ダウンロード元?)やコンパイルオプションを示せば、有効な回答を得られるかもしれません。
Takayou
2019/09/28 10:52
ありがとうございます、修正させていただきます。
Zuishin
2019/09/28 11:09
BMP ではないようですが。
dodox86
2019/09/28 11:21
>Zuishinさん
本当だ、PNGファイルですね。
>Takayouさん
画像の見た目のお話ではありません。もし本当にここからレナさん画像PNGファイルをダウンロードしたのであれば、ファイルのフォーマットが違うので、絶対に扱えません。それとも、これからBMPファイルに手動で変換したのでしょうか。
Takayou
2019/09/28 12:35
ここから手動でBMPファイルに変換してしまいました。