/*
http://i...content-available-to-author-only...e.com/fskVl3
http://t...content-available-to-author-only...h.net/test/read.cgi/tech/1349527750/951
> [1] 授業単元:2値化
> [2] 問題文(含コード&リンク):
> http://i...content-available-to-author-only...e.com/fskVl3
> 画像読み込み→2値化→2値化した画像を表示するプログラムを作成せよ
> 画像読み込みまでは出来ましたが、2値化がよくわかりませんでした。
> フルカラー前提でRGBの全チャンネルが同値なら濃淡画像に変換され、その濃淡画像を閾値処理によって2値にするらしいですがその辺がよくわかりません
> [3] 環境
> [3.1] OS:Windows7
> [3.2] コンパイラ名とバージョン:VS2010
> [3.3] 言語:C
> [4] 期限:12/1
> [5] その他の制限:出来るだけ標準ライブラリでお願いします
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define WIDTH (640)
#define HEIGHT (480)
#define BMP_HEADER_SIZE (54)
#define INPUT_IMAGE_FILE "image.bmp"
#define OUT_IMAGE_FILE "image2.bmp"
#define OUT_IMAGE_COMMAND "start" // image 出力コマンド
//#define OUT_IMAGE_COMMAND "eog" // Linux Gnome の「Eye of GNOME」を使う場合
typedef struct color {
unsigned char r; // 入力画像 赤
unsigned char g; // 緑
unsigned char b; // 青
int v; // 出力画像 2値 (0 or 1)
} COLOR;
int main()
{
int i, j;
int mode = 3; // 2値変換モード (1:要求通り、2:RGBの平均値から計算、3:YCrCb変換)
unsigned char sikiichi = 0x80; // しきい値(これ以上なら白、未満なら黒)
int ave; // RGB3値平均計算用
unsigned char head[BMP_HEADER_SIZE]; // BMPヘッダ
static COLOR data[WIDTH][HEIGHT], *pColor; // データ
FILE *fp; // ファイル
// init
memset(data
, 0x00, sizeof(data
));
// read
if ((fp
= fopen(INPUT_IMAGE_FILE
, "rb")) == NULL
) { fprintf(stderr
, "file open error\n"); }
fread(head
, BMP_HEADER_SIZE
, 1, fp
); for (j = HEIGHT - 1; j >= 0; j--) {
for (i = 0; i < WIDTH; i++) {
pColor = &data[i][j];
}
}
// 2値計算
for (j = HEIGHT - 1; j >= 0; j--) {
for (i = 0; i < WIDTH; i++) {
pColor = &data[i][j];
switch (mode) {
case 1:
// ※ RGB値が同値でないドットは「黒」とする
if ((pColor->b == pColor->g) && (pColor->g == pColor->r) && (sikiichi <= pColor->r)) {
data[i][j].v = 1;
}
break;
case 2:
ave = (int) pColor->b + (int) pColor->g + (int) pColor->r;
ave /= 3;
if (sikiichi <= ave) {
data[i][j].v = 1;
}
break;
case 3:
ave = (int) (((double) pColor->r * 0.299 + (double) pColor->g * 0.587 + (double) pColor->b * 0.114) / (0.114 + 0.587 + 0.299));
if (sikiichi <= ave) {
data[i][j].v = 1;
}
break;
}
}
}
// 画像出力
fp
= fopen(OUT_IMAGE_FILE
, "wb"); fwrite(head
, BMP_HEADER_SIZE
, 1, fp
); for (j = HEIGHT - 1; j >= 0; j--) {
for (i = 0; i < WIDTH; i++) {
if (data[i][j].v) {
} else {
}
}
}
system(OUT_IMAGE_COMMAND
" " OUT_IMAGE_FILE
);
// end
return 0;
}
LyoKICAgIGh0dHA6Ly9pLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5lLmNvbS9mc2tWbDMKIAogICAgaHR0cDovL3QuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmgubmV0L3Rlc3QvcmVhZC5jZ2kvdGVjaC8xMzQ5NTI3NzUwLzk1MQogICAgID4gWzFdIOaOiOalreWNmOWFg++8mjLlgKTljJYKICAgICA+IFsyXSDllY/poYzmloco5ZCr44Kz44O844OJJuODquODs+OCrynvvJoKICAgICA+IGh0dHA6Ly9pLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5lLmNvbS9mc2tWbDMKICAgICA+IOeUu+WDj+iqreOBv+i+vOOBv+KGkjLlgKTljJbihpIy5YCk5YyW44GX44Gf55S75YOP44KS6KGo56S644GZ44KL44OX44Ot44Kw44Op44Og44KS5L2c5oiQ44Gb44KICiAgICAgPiDnlLvlg4/oqq3jgb/ovrzjgb/jgb7jgafjga/lh7rmnaXjgb7jgZfjgZ/jgYzjgIEy5YCk5YyW44GM44KI44GP44KP44GL44KK44G+44Gb44KT44Gn44GX44Gf44CCCiAgICAgPiDjg5Xjg6vjgqvjg6njg7zliY3mj5DjgadSR0Ljga7lhajjg4Hjg6Pjg7Pjg43jg6vjgYzlkIzlgKTjgarjgonmv4Pmt6HnlLvlg4/jgavlpInmj5vjgZXjgozjgIHjgZ3jga7mv4Pmt6HnlLvlg4/jgpLplr7lgKTlh6bnkIbjgavjgojjgaPjgaYy5YCk44Gr44GZ44KL44KJ44GX44GE44Gn44GZ44GM44Gd44Gu6L6644GM44KI44GP44KP44GL44KK44G+44Gb44KTCiAgICAgPiBbM10g55Kw5aKDIAogICAgID4g44CAWzMuMV0gT1PvvJpXaW5kb3dzNwogICAgID4g44CAWzMuMl0g44Kz44Oz44OR44Kk44Op5ZCN44Go44OQ44O844K444On44Oz77yaVlMyMDEwCiAgICAgPiDjgIBbMy4zXSDoqIDoqp7vvJpDCiAgICAgPiBbNF0g5pyf6ZmQ77yaMTIvMQogICAgID4gWzVdIOOBneOBruS7luOBruWItumZkO+8muWHuuadpeOCi+OBoOOBkeaomea6luODqeOCpOODluODqeODquOBp+OBiumhmOOBhOOBl+OBvuOBmSAKKi8KI2luY2x1ZGU8c3RkaW8uaD4KI2luY2x1ZGU8c3RkbGliLmg+CiNpbmNsdWRlPHN0cmluZy5oPgoKI2RlZmluZSBXSURUSCAgKDY0MCkKI2RlZmluZSBIRUlHSFQgKDQ4MCkKI2RlZmluZSBCTVBfSEVBREVSX1NJWkUgICAgICg1NCkKI2RlZmluZSBJTlBVVF9JTUFHRV9GSUxFICAgICJpbWFnZS5ibXAiCiNkZWZpbmUgT1VUX0lNQUdFX0ZJTEUgICAgICAiaW1hZ2UyLmJtcCIKI2RlZmluZSBPVVRfSU1BR0VfQ09NTUFORCAgICJzdGFydCIgLy8gaW1hZ2Ug5Ye65Yqb44Kz44Oe44Oz44OJCi8vI2RlZmluZSBPVVRfSU1BR0VfQ09NTUFORCAgICJlb2ciICAgLy8gTGludXggR25vbWUg44Gu44CMRXllIG9mIEdOT01F44CN44KS5L2/44GG5aC05ZCICgp0eXBlZGVmIHN0cnVjdCBjb2xvciB7CiAgICB1bnNpZ25lZCBjaGFyIHI7ICAgICAgICAgICAgLy8g5YWl5Yqb55S75YOPIOi1pAogICAgdW5zaWduZWQgY2hhciBnOyAgICAgICAgICAgIC8vICAgICAgICAgIOe3kQogICAgdW5zaWduZWQgY2hhciBiOyAgICAgICAgICAgIC8vICAgICAgICAgIOmdkgogICAgaW50IHY7ICAgICAgICAgICAgICAgICAgICAgIC8vIOWHuuWKm+eUu+WDjyAy5YCkICgwIG9yIDEpCn0gQ09MT1I7CgppbnQgbWFpbigpCnsKICAgIGludCBpLCBqOwogICAgaW50IG1vZGUgPSAzOyAgICAgICAgICAgICAgIC8vIDLlgKTlpInmj5vjg6Ljg7zjg4kgKDE66KaB5rGC6YCa44KK44CBMjpSR0Ljga7lubPlnYflgKTjgYvjgonoqIjnrpfjgIEzOllDckNi5aSJ5o+bKQogICAgdW5zaWduZWQgY2hhciBzaWtpaWNoaSA9IDB4ODA7ICAvLyDjgZfjgY3jgYTlgKQo44GT44KM5Lul5LiK44Gq44KJ55m944CB5pyq5rqA44Gq44KJ6buSKQogICAgaW50IGF2ZTsgICAgICAgICAgICAgICAgICAgIC8vIFJHQjPlgKTlubPlnYfoqIjnrpfnlKgKICAgIHVuc2lnbmVkIGNoYXIgaGVhZFtCTVBfSEVBREVSX1NJWkVdOyAgICAvLyBCTVDjg5jjg4Pjg4AKICAgIHN0YXRpYyBDT0xPUiBkYXRhW1dJRFRIXVtIRUlHSFRdLCAqcENvbG9yOyAgLy8g44OH44O844K/CiAgICBGSUxFICpmcDsgICAgICAgICAgICAgICAgICAgLy8g44OV44Kh44Kk44OrCgogICAgLy8gaW5pdAogICAgbWVtc2V0KGRhdGEsIDB4MDAsIHNpemVvZihkYXRhKSk7CgogICAgLy8gcmVhZAogICAgaWYgKChmcCA9IGZvcGVuKElOUFVUX0lNQUdFX0ZJTEUsICJyYiIpKSA9PSBOVUxMKSB7CiAgICAgICAgZnByaW50ZihzdGRlcnIsICJmaWxlIG9wZW4gZXJyb3JcbiIpOwogICAgICAgIGV4aXQoMSk7CiAgICB9CiAgICByZXdpbmQoZnApOwogICAgZnJlYWQoaGVhZCwgQk1QX0hFQURFUl9TSVpFLCAxLCBmcCk7CiAgICBmb3IgKGogPSBIRUlHSFQgLSAxOyBqID49IDA7IGotLSkgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBXSURUSDsgaSsrKSB7CiAgICAgICAgICAgIHBDb2xvciA9ICZkYXRhW2ldW2pdOwogICAgICAgICAgICBwQ29sb3ItPmIgPSBnZXRjKGZwKTsKICAgICAgICAgICAgcENvbG9yLT5nID0gZ2V0YyhmcCk7CiAgICAgICAgICAgIHBDb2xvci0+ciA9IGdldGMoZnApOwogICAgICAgIH0KICAgIH0KICAgIGZjbG9zZShmcCk7CgogICAgLy8gMuWApOioiOeulwogICAgZm9yIChqID0gSEVJR0hUIC0gMTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgV0lEVEg7IGkrKykgewogICAgICAgICAgICBwQ29sb3IgPSAmZGF0YVtpXVtqXTsKICAgICAgICAgICAgc3dpdGNoIChtb2RlKSB7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgIC8vIOKAuyBSR0LlgKTjgYzlkIzlgKTjgafjgarjgYTjg4njg4Pjg4jjga/jgIzpu5LjgI3jgajjgZnjgosKICAgICAgICAgICAgICAgIGlmICgocENvbG9yLT5iID09IHBDb2xvci0+ZykgJiYgKHBDb2xvci0+ZyA9PSBwQ29sb3ItPnIpICYmIChzaWtpaWNoaSA8PSBwQ29sb3ItPnIpKSB7CiAgICAgICAgICAgICAgICAgICAgZGF0YVtpXVtqXS52ID0gMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICBhdmUgPSAoaW50KSBwQ29sb3ItPmIgKyAoaW50KSBwQ29sb3ItPmcgKyAoaW50KSBwQ29sb3ItPnI7CiAgICAgICAgICAgICAgICBhdmUgLz0gMzsKICAgICAgICAgICAgICAgIGlmIChzaWtpaWNoaSA8PSBhdmUpIHsKICAgICAgICAgICAgICAgICAgICBkYXRhW2ldW2pdLnYgPSAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICAgIGF2ZSA9IChpbnQpICgoKGRvdWJsZSkgcENvbG9yLT5yICogMC4yOTkgKyAoZG91YmxlKSBwQ29sb3ItPmcgKiAwLjU4NyArIChkb3VibGUpIHBDb2xvci0+YiAqIDAuMTE0KSAvICgwLjExNCArIDAuNTg3ICsgMC4yOTkpKTsKICAgICAgICAgICAgICAgIGlmIChzaWtpaWNoaSA8PSBhdmUpIHsKICAgICAgICAgICAgICAgICAgICBkYXRhW2ldW2pdLnYgPSAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgLy8g55S75YOP5Ye65YqbCiAgICBmcCA9IGZvcGVuKE9VVF9JTUFHRV9GSUxFLCAid2IiKTsKICAgIGZ3cml0ZShoZWFkLCBCTVBfSEVBREVSX1NJWkUsIDEsIGZwKTsKICAgIGZvciAoaiA9IEhFSUdIVCAtIDE7IGogPj0gMDsgai0tKSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IFdJRFRIOyBpKyspIHsKICAgICAgICAgICAgaWYgKGRhdGFbaV1bal0udikgewogICAgICAgICAgICAgICAgcHV0YygweEZGLCBmcCk7CiAgICAgICAgICAgICAgICBwdXRjKDB4RkYsIGZwKTsKICAgICAgICAgICAgICAgIHB1dGMoMHhGRiwgZnApOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgcHV0YygwLCBmcCk7CiAgICAgICAgICAgICAgICBwdXRjKDAsIGZwKTsKICAgICAgICAgICAgICAgIHB1dGMoMCwgZnApOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgZmNsb3NlKGZwKTsKICAgIHN5c3RlbShPVVRfSU1BR0VfQ09NTUFORCAiICIgT1VUX0lNQUdFX0ZJTEUpOwoKICAgIC8vIGVuZAogICAgcmV0dXJuIDA7Cn0=