C言語で画像を二値化してみる
画像処理と言っていいのか怪しいくらい簡単な内容。
バイナリをとり出して閾値で判別して二値化するってだけの関数。
しかも今回使う画像はbmp。楽でしかない。
ちょうど制作中のプログラムに組み込む必要があったためついでに投稿します。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
// 二値化プログラム int binarization(char *file_name_in, char *file_name_out, int border_line) { // ファイル宣言 FILE *file_in; // 変換元ファイル FILE *file_out; // 変換後ファイル // read binary/write binary mode file_in = fopen(file_name_in, "rb"); file_out = fopen(file_name_out, "wb"); // ファイル存在確認 if (file_in == NULL) { printf("指定されたファイルは存在しません\n"); exit(EXIT_FAILURE); } // 画像形式確認 if (getputc(file_in) != 'B' || getputc(file_in) != 'M') { printf("ファイル形式が違います\n"); fclose(file_in); fclose(file_out); exit(EXIT_FAILURE); } // ファイルサイズを取得 int file_size = getputc() + getputc() * 256 + getputc() * 65536 + getputc() * 4096; printf("file size: %d \n", file_size); // 位置指定子を画像データ位置情報まで移動 for (int i = 0; i < 4; i++) { getputc(); } // ファイルの先頭から画像データまでのバイト数を取得 int file_data = getputc() + getputc() * 256 + getputc() * 65536 + getputc() * 4096; printf("image data: %d \n", file_data); // 情報ヘッダサイズ for (int i = 0; i < 4; i++) { getputc(); } // 画像サイズ取得 int file_width = getputc() + getputc() * 256 + getputc() * 65536 + getputc() * 4096; int file_height = getputc() + getputc() * 256 + getputc() * 65536 + getputc() * 4096; printf("width: %d px\n", file_width); printf("height: %d px\n", file_height); // プレーン数 for (int i = 0; i < 2; i++) { getputc(); } // 色bit数取得 int color_bit = getputc() + getputc() * 256; printf("color bit: %d\n", color_bit); // 圧縮形式 for (int i = 0; i < 4; i++) { getputc(); } // 画像データサイズ int file_datasize = getputc() + getputc() * 256 + getputc() * 65536 + getputc() * 4096; printf("image data size: %d\n", file_datasize); // 解像度 縦横 for (int i = 0; i < 8; i++) { getputc(); } // パレット数取得 int file_pallet = getputc() + getputc() * 256 + getputc() * 65536 + getputc() * 4096; printf("pallet: %d", file_pallet); // 重要色数 for (int i = 0; i < 4; i++) { getputc(); } // 画像データ位置まで移動 for (int i = 0; i < file_data - 54; i++) { getputc(); } // 二値化 for (int i = 0; i < file_datasize; i++) { if (getc(file_in) <= border_line) { // 黒色 putc(0, file_out); } else { // 白色 putc(255, file_out); } } // close fclose(file_in); fclose(file_out); return 0; } |
解説
引数として渡す値は以下の3つ
- 変換前のファイルのパス
- 変換後のファイルのパス
- 二値化用の閾値
です。
今回は256色のbmpファイルしか使わないため、256色のみに対応させています。
閾値と二値化処理部分を少し変更したら16色や24bitのbmpファイルにも対応できるかと思います。
まぁ、一部特に必要のない機能も入っているので(一部パラメータ取得/表示等)その辺は欲しい方は利用して、要らない方は適当に抜かしてください。
参考にしたサイト
【バイナリファイル入門】Bitmapファイルを手書きで作って遊んでみる -Qiita
バイナリファイルの読み書き -Programming Place Plus
今回のブログ曲
今回投稿中に聴いていた曲はこちら