🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

2回答

1874閲覧

C言語によるグレースケール変換ができない

Takayou

総合スコア15

C

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

0グッド

0クリップ

投稿2019/09/28 07:05

グレースケール変換をしたいのですが,処理前と処理後で画像が変化しません.
どの部分が間違っているのか,どなたか教えてください.

グレースケール変換の処理をする関数は以下です

C

1 2//グレースケール変換 3void ConvertToGrey(BMP* bmp) 4{ 5 for (int h = 0; h < bmp->Height; h++) { 6 for (int w = 0; w < bmp->Width; w++) { 7 unsigned char Average = '00'; 8 Average = (bmp->img.red[w + h * bmp->Width] 9 + bmp->img.green[w + h * bmp->Width] 10 + bmp->img.blue[w + h * bmp->Width]) / 3; 11 12 bmp->img.red[w + h + bmp->Width] = Average; 13 bmp->img.green[w + h + bmp->Width] = Average; 14 bmp->img.blue[w + h + bmp->Width] = Average; 15 16 } 17 18 19 20 } 21 printf("\n"); 22}

全体のプログラムは以下です

C

1/* 2BMPファイルに対して, 以下の処理を行う 3・グレースケール変換 4・エッジ検出(Prewittオペレータ, Sobelオペレータ) 5・拡大,縮小,回転, 移動(線形補間法) 6*/ 7 8 9#include<stdio.h> 10#include<stdlib.h> 11 12typedef struct { 13 unsigned char *red; 14 unsigned char *blue; 15 unsigned char *green; 16}ImageData; 17 18typedef struct { 19 unsigned char FileHeader[14]; 20 unsigned int Size; 21 int Width, Height; 22 unsigned char InfoHeader[28]; 23 ImageData img; 24}BMP; 25 26//BMPファイル読み込み 27void ReadBmp(const char FileName[], BMP* bmp); 28//画像を書き込む 29void WriteBmp(const char FileName[], BMP* bmp); 30//BMP構造体ののメモリ開放 31void Destruct_Bmp(BMP* bmp); 32//BMP構造体の情報を表示 33void Show_BmpInfo(BMP* bmp); 34//グレースケール変換 35void ConvertToGrey(BMP* bmp); 36 37 38int main() { 39 BMP bmp, bmp_forGrey; 40 41 ReadBmp("lenna.bmp", &bmp); 42 ReadBmp("lenna_out.bmp", &bmp_forGrey); 43 44 ConvertToGrey(&bmp_forGrey); 45 46 //Show_BmpInfo(&bmp); 47 Show_BmpInfo(&bmp_forGrey); 48 49 WriteBmp("lenna_out.bmp", &bmp); 50 WriteBmp("lenna_out_Grey.bmp", &bmp_forGrey); 51 52 53 Destruct_Bmp(&bmp); 54 Destruct_Bmp(&bmp_forGrey); 55 56 return 0; 57} 58 59 60//BMPファイル読み込み 61void ReadBmp(const char FileName[], BMP* bmp) 62{ 63 FILE* fp; 64 65 fopen_s(&fp, FileName, "rb"); 66 if (fp == NULL) { 67 printf("Not Found : %s", FileName); 68 exit(1); 69 } 70 71 //ヘッダー情報を読み込み 72 fread(bmp->FileHeader, sizeof(unsigned char), 14, fp); 73 fread(&bmp->Size, sizeof(int), 1, fp); 74 fread(&bmp->Width, sizeof(int), 1, fp); 75 fread(&bmp->Height, sizeof(int), 1, fp); 76 fread(bmp->InfoHeader, sizeof(unsigned char), 28, fp); 77 78 79 //画像本体の読み込み 80 bmp->img.red = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char)); 81 bmp->img.blue = (unsigned char*)malloc( (bmp->Width) * (bmp->Height) * sizeof(unsigned char)); 82bmp->img.green = (unsigned char*)malloc((bmp->Width) * (bmp->Height) * sizeof(unsigned char)); 83if (bmp->img.red == NULL) { 84 printf("メモリ確保に失敗\n"); 85 exit(1); 86} 87if (bmp->img.green == NULL) { 88 printf("メモリ確保に失敗\n"); 89 exit(1); 90} 91if (bmp->img.blue == NULL) { 92 printf("メモリ確保に失敗\n"); 93 exit(1); 94} 95//一列4byte単位の長さでないといけないので, padding処理を行う 96int stride = (bmp->Width * 3 + 3) / 4 * 4; 97unsigned char padding; 98 99for (int h = 0; h < bmp->Height; h++) { 100 for (int w = 0; w < bmp->Width; w++) { 101 fread(&bmp->img.red[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 102 fread(&bmp->img.green[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 103 fread(&bmp->img.blue[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 104 } 105 for (int i = 0; i < stride - bmp->Width * 3; i++) { 106 fread(&padding, sizeof(unsigned char), 1, fp); 107 } 108} 109 110//読みこんだファイルを閉じる 111fclose(fp); 112} 113 114//画像を書き込む 115void WriteBmp(const char FileName[], BMP* bmp) 116{ 117 FILE* fp; 118 fopen_s(&fp, FileName, "wb"); 119 if (fp == NULL) { 120 printf("Not Found : %s\n", FileName); 121 exit(1); 122 } 123 124 fwrite(bmp->FileHeader, sizeof(unsigned char), 14, fp); 125 fwrite(&bmp->Size, sizeof(int), 1, fp); 126 fwrite(&bmp->Width, sizeof(int), 1, fp); 127 fwrite(&bmp->Height, sizeof(int), 1, fp); 128 fwrite(bmp->InfoHeader, sizeof(unsigned char), 28, fp); 129 130 //一列4byte単位でなければならないので、padding処理を行う 131 int stride = (bmp->Width * 3 + 3) / 4 * 4; 132 unsigned char padding = '00'; 133 134 //画像本体の書き込み 135 for (int h = 0; h < bmp->Height; h++) { 136 for (int w = 0; w < bmp->Width; w++) { 137 fwrite(&bmp->img.red[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 138 fwrite(&bmp->img.green[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 139 fwrite(&bmp->img.blue[w + h * bmp->Width], sizeof(unsigned char), 1, fp); 140 } 141 for (int i = 0; i < stride - bmp->Width * 3; i++) { 142 fwrite(&padding, sizeof(unsigned char), 1, fp); 143 } 144 145 } 146 147 fclose(fp); 148} 149 150//BMP構造体のメモリを解放 151void Destruct_Bmp(BMP* bmp) 152{ 153 free(bmp->img.red); 154 free(bmp->img.green); 155 free(bmp->img.blue); 156} 157 158void Show_BmpInfo(BMP* bmp) 159{ 160 printf("幅 =%d\n", bmp->Width); 161 printf("高さ=%d\n", bmp->Height); 162 printf("大きさ = %d\n", bmp->Height * bmp->Width); 163 164} 165 166 167 168//グレースケール変換 169void ConvertToGrey(BMP* bmp) 170{ 171 for (int h = 0; h < bmp->Height; h++) { 172 for (int w = 0; w < bmp->Width; w++) { 173 unsigned char Average = '00'; 174 Average = (bmp->img.red[w + h * bmp->Width] 175 + bmp->img.green[w + h * bmp->Width] 176 + bmp->img.blue[w + h * bmp->Width]) / 3; 177 178 bmp->img.red [w + h + bmp->Width] = Average; 179 bmp->img.green[w + h + bmp->Width] = Average; 180 bmp->img.blue [w + h + bmp->Width] = Average; 181 } 182 } 183 printf("\n"); 184}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2019/09/28 13:28

質問の回答ではないのでここに書きますが、 RGB->白黒変換では、人間の目の感度特性の事情からG*0.6+R*0.3+B*0.1ぐらいに混ぜ合わせるのが普通です。係数についてはいろいろ細かい話はありますが、ざっくりこのくらいの値にしておけば大きな破綻はないでしょう。極論、緑信号だけを白黒でみてもそんなに違和感はありません。
thkana

2019/09/28 14:48

>純粋な上位互換ではない というか、互換性という観点はあまりないですね。PAL/SECAMとNTSCで違ったり、いわゆるハイビジョンでもちょっと変わったり、4Kだ8Kだとなったときに「これがいいだろ」的にちょこちょこ数値が変わってきた気がします。職業的映像製作に関わるのでもない限り(アナログの時代ならベクトルスコープを覗くような...)、有効数字は一桁で大体用は足りるんじゃないでしょうか。ということで「ざっくり」でしか紹介しませんでした。とりあえずRGBの平均はないだろ、ということで。
guest

回答2

0

更新時の添え字の計算式が間違っているのでは?w + h + bmp->Widthでなくw + h * bmp->Width

投稿2019/09/28 07:25

nomuken

総合スコア1627

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

できない、と投げてしまう前に、デバッグできる環境を整えましょう。

Windowsであれば、VisualStudio、LinuxならEclipseあたりを使えば、ソースコードの任意の行で実行を止めて、変数やメモリの内容を見ることができます
そうやって、変換関数の実行前と後のデータを見比べてみればどうでしょう

投稿2019/09/28 07:14

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takayou

2019/09/28 07:21

Visual Studioでデバックしてデータは比較しているのですが,3チャンネルの平均が配列に代入できていない(代入前後で値が変化していない)ことはわかっているのですが,なぜそうなるのかわからず,質問させていただきました.
y_waiwai

2019/09/28 07:34

ならそこらへんのことを質問に書きましょうよ なにをどう調べてなにがどうなるはずがどうなったのか、を。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問