Windows API/図形の描画
塗りつぶし

図形を塗りつぶしたい場合には、図形描画関数の直前に、下記のように描画のモードをブラシに設定します。
塗りつぶし

塗りつぶし専用の関数は、無いのです。
塗りつぶし

Windows API でいう「ブラシ」とは、図形の塗りつぶしの色を設定するためのツールのことです。画像作成ソフトで例えるなら、Windows API でいうブラシとは、画像作成ソフトの「バケツ」ツールに近いです。世間一般の画材でいう「ブラシ」とは、意味が違います。
塗りつぶし

上記の2段階のブラシ作成の作業は、CreateSolidBrush はブラシの色作成のためのアドレス確保を意味し、もう片方 SelectObject は、どのウィンドウでどのブラシ色を使うかを定義するための情報を保存するアドレスの確保を意味しています。
塗りつぶし

「Rectangle」は、単に、四角形を描くための関数です。これが塗りつぶしか、それとも輪郭線だけをペンで描くのかは、このRectangle関数だけでは指定できず、この関数が来る前の設定に依存します。
塗りつぶし

当然、これらの関数は、WM_PAINT ケースにある
塗りつぶし

のあるブロックで書く必要があります。
塗りつぶし

つまり、下記のコードのようになります。
塗りつぶし

さて、上記コードを実際に描画すると、四角形の輪郭が黒色で描画されます。これは、ペンの設定が黒色になってるからです。
塗りつぶし

図形をピンク色の長方形だけにしたい場合、ペンの色もピンク色にします。
塗りつぶし

Rectangle 関数の前に、あらかじめ
塗りつぶし

のように、ペンを指定します。 CreatePen 関数の第2引数の「0」は、ペン幅の追加の線幅です。「0」に指定しても、最低でも1ドットぶんの線幅はあります。
塗りつぶし

よって、今までの話をまとめると、
塗りつぶし

のように、なります。
塗りつぶし

上記のプログラムにあるような手順の、
塗りつぶし

といった順序は、長方形以外のほかの図形の描画などでも同様の手順になります。特別な理由の無いかぎり、この順序で関数を宣言することになるでしょう。
塗りつぶし

Win32 API では、polygon() という関数で、任意の多角形を塗りつぶしできる。ただし、長方形と正方形については、これらの四角形を書ける Rectangle という関数でも塗りつぶしできます。
塗りつぶし

さて、Polygon関数について説明する。
塗りつぶし

polygon関数の使用のさい、その多角形の頂点それぞれの座標位置の格納のために事前に POINT 配列という専用の配列を宣言します。
塗りつぶし

また、ブラシなどの設定や関連づけもする必要があります。
塗りつぶし

コード例は、下記のようになります。
塗りつぶし

POINT配列は、配列なので配列の順番を0番目から数えるので、三角形を書きたい場合は tenretu[2] のようになります。
塗りつぶし

なお、Wikibooksおよび一部のサイトでは「POINT配列」と呼んでいますが(実用的には配列の形式で宣言して使う事が多そうなので)、しかしマイクロソフト社や多くのweb解説サイトなどでは「POINT構造体」と呼んでいます。
塗りつぶし

なお、最新のマイクロソフト社のあるプログラム言語では FillPolygon という多角形の塗りつぶしの関数があるが、しかしWindows32API では FillPolygon は使えない。
塗りつぶし

ExtFloodFill 関数で、たとえるならペイントソフトのバケツ塗りのような、線などで囲まれた領域の塗りつぶしをできる。詳しくは外部サイトを参照せよ。
その他の描画

べつに塗りつぶしをせずに、単に線を描くだけの機能も存在している。
その他の描画

直線を描くだけなら、 MoveToEx() 関数と LineTo() 関数で描ける。
その他の描画

なお、 MoveToEx() で起点を指定しており、引数で起点を指定する。LineTo() 関数では終点を指定しており、引数で終点を指定すり。
その他の描画

そのほか、円や楕円を塗りつぶしで描くなら Ellipse() 関数で書ける。
その他の描画

また、この円・楕円の引数では、その円を内接円とする長方形を指定する方式で、その長方形の左上の座標と右下の座標を指定する。
その他の描画

このため、ナナメに傾いた楕円は書けない。(後述する SetPixel()など別の関数に頼ることになるだろう。)
その他の描画

そのほか、円弧および楕円弧を塗りつぶさずに弧だけ描くなら Arc() 関数で書ける。
その他の描画

そのほか、円弧および楕円を塗りつぶして描くなら Pie() 関数で書ける。
その他の描画

これら Arc() や Pie() もまた、内接円を囲む長方形を引数として指定する方式で、その長方形の左上の座標と右下の座標を指定する。
その他の描画

また、点を打つだけの関数もあり、それは SetPixel() 関数である。
その他の描画

原理的には、パソコン画面に表示されるどんな画像もピクセル単位の点の集まりにすぎないので、原理的には SetPixel だけで、どんな画像も書ける。
その他の描画

だが、もちろん実用では、上述に紹介したように、線を描くなら線を引くための専用の関数があるし、塗りつぶしをしたいなら専用の関数があるので、そういう専用の関数を使うことで、プログラマーの作業を簡略化するのが常識的である。
その他の描画

ちなみに、1文字ちがいの GetPixel() 関数は、これは指定した座標の色を取得する関数である。
無い機能

さて、Win32APIに無さそうな機能として(※ あったら本文を訂正してください)、数学の関数の、二次関数や三次関数のグラフ、あるいは三角関数や指数関数などのグラフなどの曲線は、特に用意はされてないようなので、SetPixel()などで描くことになるだろう。
無い機能

なお、単に数値を計算するだけなら、標準C言語の math.h などで数学の関数が用意されているので、それをインクルードして関数を使用してパソコンに計算してもらえばいい。
無い機能

一例として、三角関数のグラフは、たとえば次のようなコードで実際にグラフを書ける。( case WM_PAINT 部分の抜粋)
無い機能

なお、冒頭で math.h をインクルードしておくのを忘れないように。なお、説明の単純化のため、上記コードを実行しても座標軸などの描画は無く、描かれるのは三角関数の正弦波のグラフだけである。
無い機能

さて、SetPixel でグラフを書いた場合、計算のケタ落ちなどの問題からか、グラフが 飛び飛び の 途切れ途切れ になるような場合がある。(実際、上記のコードを windows10 で実行したところ(2019年に実行)、三角関数の曲線がところどころ途切れ途切れ になっている。)
無い機能

また、SetPixel によるグラフ描画は、計算回数も多いので、用途によっては不適切である。
無い機能

もし、図形が飛び飛びになってしまうと、グラフに沿って塗りつぶしをしたい場合、飛び飛びだと塗りつぶしの境界枠にできない。
無い機能

なので、用途によっては SetPixel ではなく、近似的に LineTo 関数などを使って描画する例も、ネット上では、よく見かける。
無い機能

得られる図形の大まかな形状があらかじめ分かっているなら、LineTo() 関数などで描画するのがよいだろう。
無い機能

Windows32API には、画面を初期状態に戻すようなクリア機能の専用の関数は、無いようです。(※ 参考文献:林晴彦『明快入門 visual C++ 2010』、ソフトバンククリエイティブ(出版社)、2011年3月8日 初版 第1刷、179ページ。 )
無い機能

Win32APIで もし画面をクリアしたい場合、さきほどの節で紹介した長方形の描画の機能などを用いて、単にウィンドウ内を塗りつぶせばいい。
無い機能

Win32APIに無い機能として、画面の画像をビットマップファイルなどに出力する機能は無い。
無い機能

よって、どうしても、そういう機能の(あなたの制作している)アプリへの組み込みが必要なら、自作するか、ネット上で出回ってる無料ライブラリを使用することになる。
無い機能

もし .NET Framework ならば SaveImage メソッドというのがある。しかし Win32API には、そういうのは無い。
無い機能

Win32APIでも、画面の画像をキャプチャしてメモリなどに蓄える関数( GetShellWindow 関数 )はあるが、しかし、そうやって蓄えた画像情報を外部ファイルに出力して書き込む専用の関数は無い。
無い機能

なので、C言語のバイナリ書き込み関数などを利用して、自分でビットマップ形式ファイルへの画像エンコーダーを自作することになる。このため、BITMAP構造体の仕様などを把握しておく必要がある。
関数的な処理の活用

ソースの冒頭で関数を宣言する際、通常の関数と同じように、
関数的な処理の活用

のように宣言する必要があります。引数の型と変数名が、単にハンドル型(HDC)とハンドル変数(hdc)になっただけです。通常のC言語の関数と同じです。
関数的な処理の活用

さて、また、呼び出し側(親側)で、
関数的な処理の活用

のように、hdcの値を渡す必要があります(通常のC言語の関数と同じです)。
関数的な処理の活用

もし、上述の引数定義の手間を面倒くさがって、hdc の定義を static に変更すると、コードの他の部分の動作結果がバグります。なので、hdc は static に変更せず、ウィザードの初期設定のままにしておいてください。
関数的な処理の活用

当然、呼び出し側(親側)の関数のコードのある位置は、
関数的な処理の活用

の
関数的な処理の活用

より下の部分です。
関数的な処理の活用

つまり、
関数的な処理の活用

のように書かれます。
関数的な処理の活用

WindowsAPIで関数を使う場合、関数の内容を記述する場所が、呼び出し元の場所から、大きく離れた場所に記述しなければならない場合があります。
関数的な処理の活用

このような場合、いっそ関数をつかわずに、For文で記述するという方法もあります。
関数的な処理の活用

WindowsAPI でも、標準C言語と同様にFor文を使えます。
関数的な処理の活用

For文の繰り返しの数(たとえば for (int j = 1; j <= 20; ++j) の20の部分)を十分に大きな自然数にしておいて、使い終わったら break でそのブロックを脱出すればいいだけです。
関数的な処理の活用

たとえば、5種類の違う作業の前に、共通する前段階の作業を5回呼び出したい場合、
関数的な処理の活用

のように書くのです。
関数的な処理の活用

このFor文による代用の方法は、有限の回数しか呼び出しをしない処理にしか使えません。何度使うのか不特定な場合や、ずっとループ的に処理させたい場合には、むいてない方法です。
関数的な処理の活用

しかし、有限の回数しか呼び出さない処理ならば、この方法でも充分なのです。
関数的な処理の活用

また、もし関数を使う場合でも、For文で書いた処理を関数に置き換えるのはラクです。なので、関数を作る前に、とりあえず、For文で試しに似たような処理を書くという方法もあります。
関数的な処理の活用

上記のようなfor文とif文による関数代用の方法には、欠点もあります。
関数的な処理の活用

まず、if文を使うと、原理的に、もし今後の編集によって条件分岐用の変数に想定外の変数(上記コード例では変数 j )が代入された場合には、バグの発生原因にもなります。
関数的な処理の活用

なのでプログラミングの流儀には、こういう想定外のミスを防止する観点から if 文をなるべく使わないでコードを書くという流儀もあります。
関数的な処理の活用

ですが、似たような処理の場合分けのために if 文をなるべく使わないでfor文だけで似たようなコードをまとめて処理を書く方式だと、コードが長くなる場合があります。コードが長くなると、今度はその長さにより、バグの発生率が増えます。コードが長ければ長いほど、バグが混入しやすくなるし、仕様変更の際などにも変更の手間が増えたり、仕様変更のための修正箇所が多すぎて変更し忘れのミスをするなど、そういったバグが発生しやすくなります。
関数的な処理の活用

かといって、「コードを短くしよう」と思って、いきなり関数ばかり使ってコードを書くと、前の節でも説明したような欠点により、windowsAPIプログラミングでは関数の位置が、呼び出し場所と離れすぎている場合がほとんどなので、それが原因で別のコードの記述ミスをする可能性だって増えてしまいます。また、windowsAPIプログラミングの特殊事情で、関数を呼び出して引数を渡す際に、プログラマーの作成した変数だけを渡すのではなく、さらに各種のAPI用の様々な変数を渡す必要もあったりして、かなり関数を呼び出すことが、(windowsAPIでは)大変です。
関数的な処理の活用

一方、DOSプロンプトで呼び出すようなテキスト表示のプログラムなら、もしかしたら関数を使ったほうが良いのかもしれません。また、OSはwindowsではないですが、LinuxやBSDなどのオープンソースOSにてサーバーなどのような堅牢性の必要でテキスト形式なプログラムの作成とかなら、もしかしたら関数を多めに使ったほうが良いのかもしれません。
関数的な処理の活用

ですが、windowsAPIプログラミングは、まったく事情が異なります。windwosAPIはグラフィカルやサウンド処理なども必要な、マルチメディアかつイベントドリブンなプログラムです。
関数的な処理の活用

こういったAPI的な特殊事情もwindowsAPIプログラミングにはあるので、DOSプロンプトなどのコンソール画面で標準C言語のプログラムを呼び出す場合とは違うのです。よって、必ずしもwindowsAPIのグラフィカルなアプリでは「関数」はプログラマーにとって使いやすいとは、限りません。
関数的な処理の活用

ともかく、どんなプログラミング様式も一長一短です。 なので、簡単で短い単純なプログラムだけを書く場合には、似たような処理の繰り返しがあっても、あえて関数もfor文もif文も全く使わずに、逐次的に1行ずつ関数を書いていく場合もあります。 もちろん、この逐次的な方式も、欠点があり、コードがかなり長くなるので、長くなるにつれて記述ミスをしやすくなります。
関数的な処理の活用

結局、けっして完璧なプログラミング様式は、ありません。結局、どんなプログラミング様式でコードを書いても、けっしてバグを完全に防ぐことはできないのです。
関数的な処理の活用

よって、プログラマーは色々と妥協しながら、テストやデバッグを何度も繰り返して、コードを書くことになります。
構造体は無印C言語とやや異なる

WindowsAPIでは、構造体の宣言場所(いわゆる「グローバル領域」、コード冒頭の変数宣言などの場所)と、構造体の代入場所(wWinMain関数ブロック内など)とは、離れざるを得ない。
構造体は無印C言語とやや異なる

なぜなら (WindowsAPIの)wWinMain 関数と (無印C言語の)main関数との仕組みが、違うからである。
構造体は無印C言語とやや異なる

wWinMain 関数ブロックで構造体の型を宣言しても、wWinMain 関数はアプリ起動イベント専用のローカルな関数なので、他のイベント(たとえば画面描画の関数など)の関数ブロックからは原則的に、その構造体の型を呼び出せなくなってしまうので、まったく実用的では無くなる。
構造体は無印C言語とやや異なる

しかし、一方でもしもグローバル領域で宣言した構造体ならば、その構造体は画像描画の関数などの全てのイベントで(構造体を)呼び出せる。
構造体は無印C言語とやや異なる

しかし、グローバル領域では、代入などの操作が出来ないので、構造体の各要素の初期値の代入すら出来ない。
構造体は無印C言語とやや異なる

このため、代入などは wWinMain 関数ブロック内で行う必要があるという制約がある。
構造体は無印C言語とやや異なる

そして、この制約は、WinodowsAPIにおいては、wWinMain関数周辺にコードが膨大にある状況では、構造体の宣言と初期値代入が離れるのは、とても構造体のコードが一覧しづらくなり不便である。
構造体は無印C言語とやや異なる

しかし、不便であるが、他に簡便な方法が少ないので、しかたなく、構造体の宣言は、グローバル領域で行い、構造体の各要素への初期値代入などはwWinMain関数ブロックなどで行うことになる。
構造体は無印C言語とやや異なる

これらの離れた場所にあるコードを同時に見たいなら、Visual Stuido で作業中のコードを開きつつ、メモ帳などで別のアプリでコードをテキストファイルなふどとして開いて、メモ帳のほうを離れた場所の側のコードにあわせて閲覧しよう。ただし、メモ帳側で上書き保存などをしないように。
構造体は無印C言語とやや異なる

安全のため、作業が終わったら、メモ帳を閉じてから、Visual Stuido 側でセーブ保存すると安全だろう。
画像ファイルを作成したい場合

CreateDIBSection 関数を使うことになる。
画像ファイルを作成したい場合

MSDN公式 によると、シンタックスは
画像ファイルを作成したい場合

である。
画像ファイルを作成したい場合

また、BITMAPINFO構造体の設定は、
画像ファイルを作成したい場合

のようになる。
画像ファイルを作成したい場合

その後、・・・(※ 調査中)
画像ファイルを作成したい場合

だが、実際はまず、作成しようとする画像を目視しながら編集するためのプログラムが先に必要である。このため、下記のような、バイナリファイルの知識が必要になるだろう。
画像ファイルのバイナリ

たとえばビットマップ画像を作りたい場合、
画像ファイルのバイナリ

バイナリーデータで、いわゆる「ビットマップ構造体」の仕様で決められた様式で、バイナリーデータをファイルに書き込む。
画像ファイルのバイナリ

すると、たいていのデスクトップ用OS(ウィンドウズも含む)では、ビットマップ形式のバイナリーデータをサポートしているので、そのバイナリーデータを画像ファイルとして認識してくれるので、クリックなどをするとOSが画像表示などをしてくれる。
画像ファイルのバイナリ

なお、ネットや専門書の解説では画像フォーマットの仕様を説明するためによくC言語の「構造体」の書式が説明されるが、しかし、その構造体を入力しても、画像は生成されない。
画像ファイルのバイナリ

さて、たとえば何らかのビットマップ画像をバイナリエディタで読み込むと、ファイルの先頭は必ず「42 4D」という16進数である。この数字は、アスキーコードで翻訳すると「BM」になる。
画像ファイルのバイナリ

この「42 4D」という冒頭の数字を識別子とすることで、ファイルの種類を認識している。
画像ファイルのバイナリ

誤解しないでほしいが、けっして「BM」とバイナリーデータで書かれているのでなく(そもそも十六進数に「M」は無い)、書かれているのは あくまで「42 4D」である。
画像ファイルのバイナリ

ネット検索で調べる場合は「42 4D」というキーワードを付け加えて「ビットマップ 42 4D」などで調べれば、ビットマップ画像のバイナリでの扱いに関する有益な情報が入手しやすいだろう。
画像ファイルのバイナリ

たとえば、Windows用のフリーのバイナリエディタ stiring で3×5ピクセルの白色だけのビットマップファイルを見ると、下記のようになっている。
画像ファイルのバイナリ

stiring に限らず一般にバイナリエディタの画面の構成は、上記のようになっている。(なお、「ファイル」→「ダンプイメージの保存」などの操作で、上記のようなバイナリーデータのイメージをテキストエディタ(Windowsの場合は『ワードパッド』など)で見られる形式に変換して出力できる。)
画像ファイルのバイナリ

バイナリーデータはそのままでは、テキスト表示できない。なので、それをテキスト化したり、見やすくするために書式を整えたりして、バイナリーデータの内容を出力したものをダンプ イメージという。
画像ファイルのバイナリ

また、そのようなダンプイメージを出力することを、俗に(ぞくに)「ダンプする」などとIT業界では言う。
画像ファイルのバイナリ

さて、このダンプイメージのうち、バイナリーデータの本体は、真ん中のブロックである、下記の
画像ファイルのバイナリ

の部分である。
画像ファイルのバイナリ

一番左のブロック、
画像ファイルのバイナリ

は、ファイル内容のバイナリーデータをアスキーコードに変換して表示している。
画像ファイルのバイナリ

このアスキーは、バイナリーデータのファイル内容ではなく、バイナリエディタ側がユーザーが内容を探しやすくする目的などのために表示している。
画像ファイルのバイナリ

一番上の行の
画像ファイルのバイナリ

は、単に何バイト目かをあらわしているだけである。これは、バイナリーデータのファイル内容ではなく、バイナリエディタ側がユーザーが見やすくするために表示している。
画像ファイルのバイナリ

また、一番左の列の
画像ファイルのバイナリ

は、アドレスをあらわしている。
画像ファイルのバイナリ

赤い背景色のブロックで表した部分を「BITMAP FILE HEADER」といい、これの長さは14バイトで固定である。「42 4D」で2バイト、同じように数えて12バイトの長さ。「BITMAP FILE HEADER」とは、つまり、「42 42」「画像のファイルサイズ」「予約領域」「予約領域」「画像の場所の指定」の部分である。
画像ファイルのバイナリ

日本語では、「BITMAP FILE HEADER」のことを、ビットマップの「ファイルヘッダ」と言う場合もある。 つまり、ビットマップのファイルヘッダの長さは14バイトで固定である。
画像ファイルのバイナリ

さて、青い背景色のブロックで表した部分を「BITMAP INFO HEADER」という。
画像ファイルのバイナリ

つまり、「BITMAP INFO HEADER」とは、
画像ファイルのバイナリ

の部分である。日本語では、「BITMAP INFO HEADER」のことを、ビットマップの「情報ヘッダ」と言う場合もある。
画像ファイルのバイナリ

ビットマップ情報ヘッダの長さは40バイトで固定である。 バイナリーデータ本体の右上にあるビットマップ情報ヘッダの「28 00」と次の段の「00 00」は、ヘッダサイズに相当するが、28は十進数に直すと40である(16×2+8=40)。 リトルエンディアンなので、あとの00の3回くりかえしは無視していい。
画像ファイルのバイナリ

さて、ビットマップ構造体の図を、ダンプイメージと照らし合わせてみよう。
画像ファイルのバイナリ

「42 4D」のあとに 「82 00 00 00」と4バイトぶんの数字が続くが、これはファイルサイズを表している。
画像ファイルのバイナリ

なお、このファイルのサイズは130バイトである。16進数の「82」は 10進数で「130」である。算数で10進数の計算で 8×16+2=130 である。
画像ファイルのバイナリ

読者のWindowsパソコンでもバージョンによるかもしれないが、『ペイント』などで3×5ピクセルの16色ビットマップ画像を作成すれば、おおむね、このあたりのファイルサイズになるだろう。
画像ファイルのバイナリ

なお、ペイントのキャンバスサイズの変更は、左上のメニューアイコンから「プロパティ」を選ぶと「イメージのプロパティ」設定ウィンドウが開き、下のほうにキャンバス幅とキャンバス高さの指定欄があるので、そこで数値を入力してサイズを変形できる。
画像ファイルのバイナリ

この「82 00 00 00」の意味は、10進数にすれば
画像ファイルのバイナリ

という意味である。こういう数え方を「リトル エンディアン」という。
画像ファイルのバイナリ

なお「256」の由来は 16×16=256 である。
画像ファイルのバイナリ

けっして、8200万バイトでないし、130万バイトでもないので、勘違いしないように。
画像ファイルのバイナリ

次の、2つの 予約領域 は、ゼロで埋める決まりになっており、なので「00 00 」「00 00」である。
画像ファイルのバイナリ

1段目アドレスのABCDの部分にある「 76 00 00 00」は、まず意味は10進数で118である。7×16+6=118 より。
画像ファイルのバイナリ

で、「バイナリーデータの118バイト目から、画像データが始まります」と宣言している(ファイル先頭から画像デーマまでの「オフセット」という)。1バイトは256で、16×16=256なので16進数では2ケタぶんです。画像データの先頭のバイトが118バイト目であると、を指し示している。
画像ファイルのバイナリ

なお、数え方は左上の「42 4D」ですでに2バイトである。 この調子で118バイト目を探すと
画像ファイルのバイナリ

なので、8行目(商7にプラス1)の7列目(あまり「6」+1)のバイト(6)目が、開始位置である。下図の太字にした部分のバイトである。
画像ファイルのバイナリ

よくみると、この太字の部分からFが5個続き、「000」というのが3回数くりかえすので、合計でFが15回繰り返される。これは、この画像が横5×3であることに対応している。
画像ファイルのバイナリ

さて、「画像の横幅」「画像の縦幅」に対応するのは「05 00 00 00」「 03 00 00 00」である。これは、横5ピクセル×縦3ピクセルという意味である。数値の数え方はリトルエンディアンである。
画像ファイルのバイナリ

ビットマップ情報ヘッダの終わりから画像の開始までは、カラーパレットが16個、続いています。
画像ファイルのバイナリ

上ダンプの太字の直前の「FF FF FF 00」とは、16番目のビットマップのカラーパレットです。カラーパレットは合計で16個あります。また、この16番目パレットを呼び出すのに、画像データ部分のF5回の繰り返しの部分では「F」でパレットを呼び出しています。
画像ファイルのバイナリ

その直前のパレットの「FF FF 00 00」が15番目のパレットです。このパレットは「E」で呼び出されますが、今回の画像データでは使われてないです。
画像ファイルのバイナリ

「プレーン数」と「色ビット数」の「01 00 」「04 00」は。プレーン数が十進数で1で、色ビット数が十進数で4という意味である。
画像ファイルのバイナリ

「圧縮形式」とあるが、無圧縮にする場合はゼロにする。つまり「00 00 00 00」で無圧縮である。ビットマップは、仕様上では、実は圧縮も可能な仕様である。
画像ファイルのバイナリ

解像度「C4 0E 00 00」は、印刷などをする際の1メートルあたりのピクセル数ですが、今回は印刷をしないので、気にしないことにします。
画像ファイルのバイナリ

「パレット数」は、仕様上は策定されていますが、実際には利用されていません。マイクロソフトの『ペイント』アプリで作ったファイルですらも、ここはゼロのままの「00 00 00 00」です。
画像ファイルのバイナリ

「重要な色数」も、仕様上は策定されていますが、やはり実際には利用されていません。これまたマイクロソフトの『ペイント』アプリで作ったファイルですらも、ここはゼロのままの「00 00 00 00」です。
画像ファイルのバイナリ

なお、ビットマップの仕様を策定した起業は、昔のIBMとマイクロソフトです。
画像ファイルのバイナリ

なお、マイクロソフトのサイトでは
画像ファイルのバイナリ

のようにC言語っぽいコードのようなモノが書いてあるが、これは単に構造を説明しているだけであり、このコードをコンパイラなどに入力しても何も起きない。
画像ファイルのバイナリ

背景が白色だと分かりづらいので、黄色にしてみましょう。
画像ファイルのバイナリ

それを横5×縦3ピクセルにしたファイルのバイナリーデータダンプは、次のようになります。
画像ファイルのバイナリ

「BB BB B0 00 」と3回繰り返すことで、パレットBでピクセルを塗るのを横5マスを3行続けていることが分かります。
画像ファイルのバイナリ

末尾の「0」や「00」はおそらく改行のようなものでしょう。
画像ファイルのバイナリ

また、キャンバスサイズを拡大し、横6×縦9ピクセルで黄色一色のビットマップ画像にすると、ダンプは下記のようになります。
画像ファイルのバイナリ

よくみると後半「BB BB BB 00」が9回(※ この画像のタテのピクセル数が9である)、繰り返されています。
画像ファイルのバイナリ

また、Bの個数も、6回ずつ(※ この画像の横幅は6である)です。
画像ファイルのバイナリ

最後の「00」で、このことから、00バイトで改行を表すのだろう事が分かります。
画像ファイルのバイナリ

とすると、パレット番号に「0」や「00」は使えないハズです。
画像ファイルのバイナリ

なお、画像データの読み方は、バイナリーデータの情報が、画像では左下から右下に対応します。
画像ファイルのバイナリ

なので、2色以上を使った画像で、調べてみましょう。
画像ファイルのバイナリ

下記の画像は、ややサイズが大きい画像ですが(サイズが小さいとビューワーの性能によっては色ボケしたりして不正確になるので)、
画像ファイルのバイナリ

幅30×高さ10 の画像です。白地を基調としておりますが、左上に赤い帯があります。下側に青い帯があります。右上に短く青い帯があります。
画像ファイルのバイナリ

ADDRESS 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
画像ファイルのバイナリ

太字にしたところから、画像の始まりです。ほぼパレット「C」が30回繰り返されています。2行目の最初が「6C」になってるのは、ペイントが勝手にそういう色に変えただけです。2行目は6のあと「C」が28回繰り返され、最後にパレット「6」番の色です。
画像ファイルのバイナリ

パレットCは、斜線にした 「FF 00 00 00」の部分です。「赤色(256段階), 緑色(256段階), 青色(256段階)」の順番になっています。
画像ファイルのバイナリ

なので、
画像ファイルのバイナリ

です。
画像ファイルのバイナリ

さて、幅30×高さ10 の画像は、画像で見ると、青い帯は下側にあります。しかしバイナリーデータでは、青い帯は、最初に書かれています。
画像ファイルのバイナリ

このように、上下が反転しています。そういう仕様だからです。
画像ファイルのバイナリ

Linux だと、このバイナリーデータのテキスト形式のダンプ内容を、バイナリーデータのビットマップ画像形式に変換できるコマンドがある。
画像ファイルのバイナリ

xxd というコマンドを使えばいい。Fedora 31 では標準では、この xxd がついていない。なのでFedoraにこのコマンドをインストールするために vim-common をインストールする必要がある。Fedora ではvim-common に xxd が含まれている。
画像ファイルのバイナリ

xxdはもともと、バイナリーデータを16進ダンプするためのコマンドであるが、このソフトウェアには、さらに16進ダンプされた内容のテキストをバイナリーデータに戻す機能もある。
画像ファイルのバイナリ

引数に -r をつける事により、16進ダンプをバイナリーデータに戻せる。
画像ファイルのバイナリ

たとえば、なんらかのテキストエディタ(Fedora標準の gedit でもよい)に、下記のテキスト(これはstirringで出力したテキストから、上2行の見出しを除去しただけの物である)をそのままコピーペーストしてテキストエディタに貼り付けし、普通に「test」などの名前で保存しよう。この段階では、ファイル「test」は、まだ単なるテキストファイルである。
画像ファイルのバイナリ

だが、コマンド端末で
画像ファイルのバイナリ

と入力して実行すると、なんと『testout』というファイル名で、画像ファイルが新規作成されている。
画像ファイルのバイナリ

画像ファイルに限った事ではないが、バイナリ文字列とテキスト文字列を変換する関数として、windowsAPI
画像ファイルのバイナリ

という2つの関数を用意している。
画像ファイルのバイナリ

使うには、
画像ファイルのバイナリ

が必要である。
画像ファイルのバイナリ

だが、これを使わなくても、C言語で直接に書いてしまう方法もある。C言語で書き込みの際、書き込みモードに「wb」のようにbをつけるだけでバイナリーデータを書き込みできるので、ソレを使って、プログラムを自力で書く方法もある。
画像ファイルのバイナリ

なお、文字列「1」はアスキーコードでは16進数「31」なので、一対一対応しないので、C言語で書く場合には注意しよう。