Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語でPGM形式の画像ファイルを書き出す方法

PGM形式とは

PGM(Portable Gray Map:ポータブルグレイマップ)は、グレースケール画像を扱うためのシンプルな画像フォーマットです。C言語で保持している2次元配列をPNGやJPEGなどの一般的な画像形式として保存するには、データを所定のフォーマットにエンコードするための複雑な処理を大量に実装する必要があります。

そこで役立つのがNetpbm形式です。Netpbmはオープンソースのグラフィックスプログラム群で、主にLinuxやUnixプラットフォームで利用されていますが、Microsoft Windows環境でも動作します。この形式を利用すれば、2次元配列のデータを簡単かつ移植性の高い形で画像ファイルとして書き出せます。

マジックナンバーについて

各ファイルは2バイトのマジックナンバーから始まります。このマジックナンバーは、ファイルの種類(PBM、PGM、PPMなど)とエンコーディング方式(ASCIIまたはバイナリ)を識別するために使われます。マジックナンバーは、大文字の「P」に1桁の数字を続けたもので表されます。

ASCIIエンコーディングでは人間が内容を読み取りやすく、他のプラットフォームへの受け渡しも簡単です。一方、バイナリ形式はファイルサイズの面で効率的ですが、バイトオーダー(エンディアン)に起因する問題が生じる可能性があります。

PGMファイルの書き込み手順

  • マジックナンバー「P2」を設定する
  • 空白文字(スペース、タブ、CR、LF)を追加する
  • 幅(width)を10進数のASCII文字として追加する
  • 空白を追加する
  • 高さ(height)を10進数のASCII文字として追加する
  • 空白を追加する
  • 最大グレー値をASCIIの10進数で記述する
  • 空白を追加する
  • 幅 × 高さの個数のグレー値(0~最大値の範囲)を、上から下へ空白区切りでASCIIの10進数として並べる

サンプルコード

#include <stdio.h>
main() {
  int i, j;
  int w = 13, h = 13;
  // この2次元配列が画像に変換される(サイズは13 x 13)
  int image[13][13] = {
    { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 },
    { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31},
    { 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47},
    { 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63},
    { 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79},
    { 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95 },
    { 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111},
    { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127},
    { 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143},
    { 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159},
    { 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175},
    { 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191},
    { 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207}
  };
  FILE* pgmimg;
  pgmimg = fopen("my_pgmimg.pgm", "wb"); // バイナリモードでファイルを開く
  fprintf(pgmimg, "P2\n"); // マジックナンバーをファイルに書き込む
  fprintf(pgmimg, "%d %d\n", w, h); // 幅と高さをファイルに書き込む
  fprintf(pgmimg, "255\n"); // 最大グレー値を書き込む
  int count = 0;
  for (i = 0; i < h; i++) {
    for (j = 0; j < w; j++) {
      fprintf(pgmimg, "%d ", image[i][j]); // 配列からグレー値をファイルへコピー
    }
    fprintf(pgmimg, "\n");
  }
  fclose(pgmimg);
}

このプログラムでは、値が15から207まで16ずつ増加する13×13の2次元配列を用意しています。各行の輝度値が異なるため、実行すると濃淡の異なる横縞模様のグレースケール画像が生成されます。

出力結果

上記のコードをコンパイルして実行すると、「my_pgmimg.pgm」という名前のPGMファイルがカレントディレクトリに作成され、GIMPやIrfanViewなどの対応ビューアで開くことで以下のような画像を確認できます。

C言語でPGM形式の画像ファイルを書き出す方法

なお、ここで紹介した「P2」はASCII形式の指定です。よりコンパクトなファイルサイズが必要な場合は、バイナリ形式を表すマジックナンバー「P5」を使用する方法もあります。その際はfwrite関数を使ってグレー値を直接書き出すことになります。

  1. C言語でポインタの使い方を学べるサンプルプログラムを作成する

    ポインタとは、別の変数のアドレス(メモリ上の場所)を格納するための変数のことです。C言語においてポインタは非常に重要な概念であり、メモリを直接操作することで効率的なプログラミングを可能にします。 ポインタの特徴 ポインタを使うことでメモリ空間を節約できます。 メモリ上の場所へ直接アクセスできるため、実行速度が速くなります。 ポインタを利用すると、メモリへのアクセスが効率化され、動的なメモリの割り当て(確保)と解放が可能になります。 連結リストや木構造などのデータ構造でもポインタが広く使われています。 ポインタの宣言 int *p; これは「p」がポインタ変数であり、別の整数型変数のアドレ

  2. C言語で配列を逆順に反転させるプログラムの書き方

    配列とは、共通の名前のもとで管理される、関連性のあるデータ項目の集まりのことです。同じ型の複数の値を効率的に扱いたい場合に活用されます。配列の宣言構文C言語で配列を宣言する際の基本的な構文は以下のとおりです。データ型 配列名 [サイズ];配列の初期化配列は、宣言と同時に初期化することもできます。int a[5] = { 10,20,30,40,50};この例では、整数型の配列 a の5つの要素に、それぞれ10から50までの値が順番に格納されています。C言語で配列を逆順にする方法配列の要素を逆順に並べ替えるには、要素の入れ替え(スワップ)やコピーのテクニックを利用します。たとえば、4つの要素を持