ファイル処理(画像ファイルの編集)
(ブログ記事の一覧は「こちら」)
C言語での画像ファイルの読み込み・書き込みの処理について確認していきましょう。 (画像ファイルのような、バイトデータの集まりのファイルをバイナリファイルと呼びます)
【復習】 ファイルのオープン/クローズの定義は以下のようになります。
ファイル名(filename)で示されるファイルを、指定モード(mode)でオープン
FILE *fopen(const char *filename, const char *mode);
fopen でオープンされたファイルをクローズ
int fclose(FILE *fp);
「FILE *」は、ファイルポインタというファイルを扱うときの型であるFILE型のポインタです。
以下も復習です。
テキストファイルの読み込み
fp = fopen("test_r.txt", "r");
テキストファイルの書き込み
fp = fopen("test_w.txt", "w");
以下が、今回で扱う書き方になります。
バイナリ・ファイルの読み込み
fp = fopen("input.bmp", "rb");
バイナリ・ファイルの書き込み
fp = fopen("output.bmp", "wb");
Bitmap(ビットマップ)ファイルのフォーマット
Bitmap(ビットマップ)ファイルは、圧縮されていない画像ファイルのことです。 まず、Bitmapファイルを用意します。(「bmp sample」で検索すると見つかります。)
次に、用意したBitmapファイルのフォーマットを確認します。
バイナリファイルのデータを確認するには、「Stirling」というツールを使用すると便利です。 StirlingでBitmapファイルを開くと、16進数の値が16列ずつに並んだ表示が得られます。 バイナリファイルはそれらの値が意味を持っています。
赤い枠で囲った部分が、Bitmapファイルの画像ファイルの幅と高さになります。
(Bitmapファイルのフォーマットについては、「bmp フォーマット」などで検索すると情報が見つかります。)
読み取った順に処理すると、「00 00 01 00」となります。これは10進数で「256」です。 つまり、上の例での、画像ファイルの幅と高さは「256 * 256」です。
Bitmap(ビットマップ)ファイルの読み込みのサンプル
Bitmap(ビットマップ)ファイルのデータを読み込むサンプルです。あらかじめ、プロジェクトフォルダに「input.bmp」をコピーして、以下のプログラムを実行してください。
#include <stdio.h> int main(void) { unsigned char BitMapFileHeader[14]; // BMPのファイルヘッダー unsigned int biSize; // 情報ヘッダーのサイズ int biWidth; // BMPの幅 int biHeight; // BMPの高さ unsigned char BitMapInfoHeader[28]; // 他のBMPの情報ヘッダー unsigned char cData[512][512][3]; //画素情報(幅、高さ、RGB) int i, j, k; FILE *fp; fp = fopen("input.bmp", "rb"); fread(&BitMapFileHeader, sizeof(char), 14, fp); fread(&biSize, sizeof(int), 1, fp); fread(&biWidth, sizeof(int), 1, fp); fread(&biHeight, sizeof(int), 1, fp); fread(&BitMapInfoHeader, sizeof(char), 28, fp); for (i = 0; i < biWidth; i++) { for (j = 0; j < biHeight; j++) { for (k = 0; k < 3; k++) { fread(&cData[i][j][k], sizeof(char), 1, fp); } } } fclose(fp); return 0; }
以下は、Bitmapファイル「input.bmp」を読み込み、「out.bmp」を書き出すサンプルです。
#include <stdio.h> int main(void) { unsigned char BitMapFileHeader[14]; // BMPのファイルヘッダー unsigned int biSize; // 情報ヘッダーのサイズ int biWidth; // BMPの幅 int biHeight; // BMPの高さ unsigned char BitMapInfoHeader[28]; // 他のBMPの情報ヘッダー unsigned char cData[512][512][3]; //画素情報(幅、高さ、RGB) int i, j, k; FILE *fp1; FILE *fp2; // BMPファイルの読み込み fp1 = fopen("lena_color_256.bmp", "rb"); fread(&BitMapFileHeader, sizeof(char), 14, fp1); fread(&biSize, sizeof(int), 1, fp1); fread(&biWidth, sizeof(int), 1, fp1); fread(&biHeight, sizeof(int), 1, fp1); fread(&BitMapInfoHeader, sizeof(char), 28, fp1); for (i = 0; i < biWidth; i++) { for (j = 0; j < biHeight; j++) { for (k = 0; k < 3; k++) { fread(&cData[i][j][k], sizeof(char), 1, fp1); } } } fclose(fp1); // BMPファイルの書き込み fp2 = fopen("out.bmp", "wb"); fwrite(&BitMapFileHeader, sizeof(char), 14, fp2); fwrite(&biSize, sizeof(int), 1, fp2); fwrite(&biWidth, sizeof(int), 1, fp2); fwrite(&biHeight, sizeof(int), 1, fp2); fwrite(&BitMapInfoHeader, sizeof(char), 28, fp2); for (i = 0; i < biWidth; i++) { for (j = 0; j < biHeight; j++) { for (k = 0; k < 3; k++) { fwrite(&cData[i][j][k], sizeof(char), 1, fp2); } } } fclose(fp2); return 0; }