トップ回答者
カラーのビットパターンで描画したい。

質問
回答
-
さて、最後に「画像を交互に並べる」という部分です。交互にならべるためには、まず画像を2つ読み込まなければなりません。画像の読み込みの部分を2つに増やします。次に必要なことは、「どちらの画像を描画するべきか?」ということを判断しなければならない点です。このあたりのアルゴリズムの考え方は、やはり書籍などで勉強するのが手早いと思いますが、ここまでの処理を残してシンプルに作るとCode Snippet
private void Form1_Paint(object sender, PaintEventArgs e)
{
using (Image image1 = Image.FromFile("testC1.bmp"))
using (Image image2 = Image.FromFile("testC2.bmp"))
{
bool isOddLine = true;for (int x = 0; x < 10; x ++)
{
// 偶数列は image1 を最初に描画する (= true)
// 奇数列は image2 を最初に描画する (= false)
bool drawImage1 = isOddLine;// 交互になるように、isOddLine を反転する
isOddLine = !isOddLine;for (int y = 0; y < 10; y ++)
{
Point upperLeftCorner = new Point(x * 5, y * 5);// 画像を描画する
if (drawImage1)
e.Graphics.DrawImage(image1, upperLeftCorner);
else
e.Graphics.DrawImage(image2, upperLeftCorner);// 交互になるように drawImage1 を反転する
drawImage1 = !drawImage1;
}
}
}
}こんなイメージになりますでしょうか? 一気に処理がふえていますが、何をやっているのか理解できますか? x と y の数字をつかって数式でシンプルに計算する方法もありますが、とりあえず条件分岐で処理をするかたちにしてみました。とりあえず、この時点で当初の目的は達成できているのですが、フォームの Paint イベントは描画が必要になるたびに呼び出されるようになっています。つまり、このままではフォームを描画するたびに画像をファイルから読み込みにいくため、すこしよろしくないかんじになります。画像の読み込みは、アプリケーションを起動したら1度だけでよいはずですね? フォームのイベントの一覧をながめたり、調べたり、していけば、Load イベントで画像を準備しておけることに気がつけるかもしれません。Code Snippet
private Image image1;
private Image image2;private void Form_Load(object sender, EventArgs e)
{
image1 = Image.FromFile("testC1.bmp"))
image2 = Image.FromFile("testC2.bmp"))
}private void Form_Closed(object sender, EventArgs e)
{
image1.Dispose();
image2.Dispose();
}private void Form1_Paint(object sender, PaintEventArgs e)
{
bool isOddLine = true;for (int x = 0; x < 10; x ++)
{
// 偶数列は image1 を最初に描画する (= true)
// 奇数列は image2 を最初に描画する (= false)
bool drawImage1 = isOddLine;// 交互になるように、isOddLine を反転する
isOddLine = !isOddLine;for (int y = 0; y < 10; y ++)
{
Point upperLeftCorner = new Point(x * 5, y * 5);// 画像を描画する
if (drawImage1)
e.Graphics.DrawImage(image1, upperLeftCorner);
else
e.Graphics.DrawImage(image2, upperLeftCorner);// 交互になるように drawImage1 を反転する
drawImage1 = !drawImage1;
}
}
}using がなくなったかわりに Dispose が入っていたりしますが、やっていることは基本的に同じです。なお、すべてのサンプルコードは、私は実際に試していない手書きのコードです。内容の解説をしているので、コンパイルエラーになったり動作しなかったりした場合は、なにをやろうとしているのかを読み取って修正してみてください。
すべての返信
-
この内容では、acslearner さんが、何が可能で何が不可能なのか、何が理解できて何に困っているのかがまったく読み取れません。具体的に問題となっている点や、考えていることをきちんと記述すると適切なレスポンスが得られるのではないでしょうか?とりあえず、どこで詰まっているのかわからないので、1点だけカラーのビットパターンを保持するのは、後のことを考えると画像として保持するのが楽だと思います。この場合も手法は2つあって、・ビットパターンを白黒の画像で保持して、カラー情報を別に持つ・カラーの画像に色ごと保存するという方法です。5×5程度の小さい画像であれば、カラーで保持してもたいした情報量にならないので必要な色深度をもったカラー画像として保持すると良いかと思います。
-
3度ぐらいにわけて応対するのがよさそうなのですが、一気に書いちゃいますね。まず、最初にやるべきことを日本語で考えてみてください。
-
画像ファイル testC1.bmp を読み込み
-
読み込んだ画像をフォームに表示する
というのが基本的な処理になることはわかりますね?画像をファイルから読み込む場合は、System.Drawing.Image クラスあたりを利用すると良いでしょう。このクラス名を発見することが難しいかもしれませんが、ヘルプを「画像」などで検索すると見つかるかな?と思います。また、このクラスを発見することができれば、このクラスのヘルプからいくつかのサンプルコードや、System.Drawing.Bitmap クラスやイメージ、ビットマップ、およびメタファイルやイメージ、ビットマップ、アイコン、およびメタファイルの操作といったHOWTO文章も発見できるでしょう。(これらのリンクはオンラインヘルプにつながっていますが、インストールされているヘルプでも同様です)このあたりについては、体系的に学習できる書籍や web サイトをざっくりと読まれるほうが理解は早いと思います。これらのヘルプをうまいこと読み取っていけば-
画像ファイル testC1.bmp を読み込み
→ Image クラスの FromFile メソッドでよさそうだ
というところまでわかれば、実装もある程度みえてくると思います。ヘルプのサンプルなどを見て、Code Snippetusing (Image image1 = Image.FromFile("testC1.bmp")){// ここで image1 をフォームに表示する}という実装になります。 -
-
次に、
-
読み込んだ画像をフォームに表示する
という部分ですが、これはよく詰まる人がいる部分です。Windows の描画システムに関する理解がある程度必要なので、やはり書籍や web サイト、ヘルプの Windows Form アプリケーションの開発関連についてをきちんと読んでほしいところです。Form に画像を表示するには、おもに3つの方法があります。-
PictureBox コントロールなどをフォームに配置して表示する
-
Form の BackgorundImage に画像を指定する
-
Form の Paint メソッドを使用して自分で描画する
というものです。おそらく1つめは試されていると思うので飛ばします。次のBackgroundImage プロパティは、一見使えそうだと思われると思いますし、こちらも試されているかもしれませんが、「2つの画像を交互に並べる」という部分に少しひっかかるところがあるため、断念されたかもしれません。もし、↑のように、実際に BackgroundImage が使えるかどうかと考えたり、それを試していたりしていたのであれば、そういったことを最初に書いておくと、返答をする人たちの参考になってよいです。というわけで、最後の Paint イベントを利用することを考えましょう。ヘルプでは、文章と線を引くサンプルが記載されていますが、このサンプルをみて、描画処理は System.Drawing.Graphics クラスを使用するということに気がつかれるでしょうか? これが気がつけないようであれば、繰り返しになりますが、書籍や web サイトなどで体系的に学ばれることをおすすめします。さて、Graphics クラスについても調べてみると、ズバリ画像を描画するサンプルが記載されています。前の投稿で書いたように Image クラスを使用したものですので、これはすぐに利用できると思います。Visual Studio を使用して Form の Paint イベントをダブルクリックすると、Code Snippetprivate void Form1_Paint(object sender, PaintEventArgs e){}のようなコードが自動的に作成されますので、Paint イベントのサンプルと Graphics クラスのサンプルを参考に、前の投稿に書いたコードとあわせるとCode Snippetprivate void Form1_Paint(object sender, PaintEventArgs e){using (Image image1 = Image.FromFile("testC1.bmp")){// 左上は 0,0 ですPoint upperLeftCorner = new Point(0, 0);// 画像を描画するe.Graphics.DrawImage(image1, upperLeftCorner);}}このような感じになりますでしょうか? これを実行すると、フォームの左上に testC1.bmp が表示されると思います。あとは、-
フォームに画像を10個表示する
-
2つの画像を交互に表示する
という2つの点をクリアしなければなりませんね。まず、前者ですが繰り返し構造をつかって画像を何度も描画すればよいことがわかりますでしょうか? 繰り返し構造は for 文を使用して、Code Snippetfor (int x = 0; x < 10; x ++)
{
for (int y = 0; y < 10; y ++)
{
Point upperLeftCorner = new Point(x * 5, y * 5);e.Graphics.DrawImage(image1, upperLeftCorner);
}
}などとすると、testC1.bmp が上下左右に10個並ぶことがわかると思います。繰り返しになりますが、上のようなループによる描画が理解できないようであれば書籍や(略)
ここまでをまとめると、
Code Snippetprivate void Form1_Paint(object sender, PaintEventArgs e)
{
using (Image image1 = Image.FromFile("testC1.bmp"))
{
for (int x = 0; x < 10; x ++)
{
for (int y = 0; y < 10; y++)
{
Point upperLeftCorner = new Point(x * 5, y * 5);// 画像を描画する
e.Graphics.DrawImage(image1, upperLeftCorner);
}
}
}
}こんなかんじになりますね。 -
-
さて、最後に「画像を交互に並べる」という部分です。交互にならべるためには、まず画像を2つ読み込まなければなりません。画像の読み込みの部分を2つに増やします。次に必要なことは、「どちらの画像を描画するべきか?」ということを判断しなければならない点です。このあたりのアルゴリズムの考え方は、やはり書籍などで勉強するのが手早いと思いますが、ここまでの処理を残してシンプルに作るとCode Snippet
private void Form1_Paint(object sender, PaintEventArgs e)
{
using (Image image1 = Image.FromFile("testC1.bmp"))
using (Image image2 = Image.FromFile("testC2.bmp"))
{
bool isOddLine = true;for (int x = 0; x < 10; x ++)
{
// 偶数列は image1 を最初に描画する (= true)
// 奇数列は image2 を最初に描画する (= false)
bool drawImage1 = isOddLine;// 交互になるように、isOddLine を反転する
isOddLine = !isOddLine;for (int y = 0; y < 10; y ++)
{
Point upperLeftCorner = new Point(x * 5, y * 5);// 画像を描画する
if (drawImage1)
e.Graphics.DrawImage(image1, upperLeftCorner);
else
e.Graphics.DrawImage(image2, upperLeftCorner);// 交互になるように drawImage1 を反転する
drawImage1 = !drawImage1;
}
}
}
}こんなイメージになりますでしょうか? 一気に処理がふえていますが、何をやっているのか理解できますか? x と y の数字をつかって数式でシンプルに計算する方法もありますが、とりあえず条件分岐で処理をするかたちにしてみました。とりあえず、この時点で当初の目的は達成できているのですが、フォームの Paint イベントは描画が必要になるたびに呼び出されるようになっています。つまり、このままではフォームを描画するたびに画像をファイルから読み込みにいくため、すこしよろしくないかんじになります。画像の読み込みは、アプリケーションを起動したら1度だけでよいはずですね? フォームのイベントの一覧をながめたり、調べたり、していけば、Load イベントで画像を準備しておけることに気がつけるかもしれません。Code Snippet
private Image image1;
private Image image2;private void Form_Load(object sender, EventArgs e)
{
image1 = Image.FromFile("testC1.bmp"))
image2 = Image.FromFile("testC2.bmp"))
}private void Form_Closed(object sender, EventArgs e)
{
image1.Dispose();
image2.Dispose();
}private void Form1_Paint(object sender, PaintEventArgs e)
{
bool isOddLine = true;for (int x = 0; x < 10; x ++)
{
// 偶数列は image1 を最初に描画する (= true)
// 奇数列は image2 を最初に描画する (= false)
bool drawImage1 = isOddLine;// 交互になるように、isOddLine を反転する
isOddLine = !isOddLine;for (int y = 0; y < 10; y ++)
{
Point upperLeftCorner = new Point(x * 5, y * 5);// 画像を描画する
if (drawImage1)
e.Graphics.DrawImage(image1, upperLeftCorner);
else
e.Graphics.DrawImage(image2, upperLeftCorner);// 交互になるように drawImage1 を反転する
drawImage1 = !drawImage1;
}
}
}using がなくなったかわりに Dispose が入っていたりしますが、やっていることは基本的に同じです。なお、すべてのサンプルコードは、私は実際に試していない手書きのコードです。内容の解説をしているので、コンパイルエラーになったり動作しなかったりした場合は、なにをやろうとしているのかを読み取って修正してみてください。