「コントロールやフォームに画像を表示する」ではコントロールに画像を表示する方法として、PictureBoxコントロールのImageLocationやImageプロパティを使用する方法と、コントロールのGraphicsオブジェクトを作成する方法の2つを紹介しています。そちらでも指摘していますが、この2つを併用すると、思ったようにいかなくなるかもしれません。
例えば以下の例では、画像(C:\test\1.jpg)の上に文字列を合成して表示しようとしています。そのために、PictureBoxコントロール(PictureBox1)のImageプロパティを使って画像を表示して、さらにPictureBoxのPaintイベントで文字列を表示しています。さらに、Buttonコントロール(Button1)をクリックすると、その画像をファイルに保存できるようにしています。
'Imports System.Drawing 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles MyBase.Load '画像ファイルを表示する PictureBox1.Image = New Bitmap("C:\test\1.jpg") End Sub 'PictureBox1のPaintイベントハンドラ Private Sub PictureBox1_Paint(ByVal sender As Object, _ ByVal e As PaintEventArgs) _ Handles PictureBox1.Paint '画像の上に文字列を描画する e.Graphics.DrawString("DOBON.NET", Me.Font, Brushes.White, 1, 1) e.Graphics.DrawString("DOBON.NET", Me.Font, Brushes.Black, 0, 0) End Sub 'Button1のClickイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click 'PictureBox1に表示されている画像を保存する PictureBox1.Image.Save("C:\test\new1.jpg", _ System.Drawing.Imaging.ImageFormat.Jpeg) End Sub
//using System.Drawing; //フォームのLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { //画像ファイルを表示する PictureBox1.Image = new Bitmap(@"C:\test\1.jpg"); } //PictureBox1のPaintイベントハンドラ private void PictureBox1_Paint(object sender, PaintEventArgs e) { //画像の上に文字列を描画する e.Graphics.DrawString("DOBON.NET", this.Font, Brushes.White, 1, 1); e.Graphics.DrawString("DOBON.NET", this.Font, Brushes.Black, 0, 0); } //Button1のClickイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //PictureBox1に表示されている画像を保存する PictureBox1.Image.Save(@"C:\test\new1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); }
このコードを実行すると、期待通りにPictureBox1には画像の上に文字列が表示されます。しかしButton1をクリックして作成した画像ファイルには、文字列が描き込まれません。
なぜこのようなことが起こるのかといいますと、Paintイベントで描き込んだ文字列はコントロールのGraphicsオブジェクトに描き込んでおり、PictureBox.Imageプロパティに設定されているImageオブジェクトに描き込んでいるわけではないからです。
それでは以下に、2つの方法を併用せずに、この問題を解決する方法を紹介します。
PictureBox.Imageプロパティしか使わないのであれば、Imageプロパティに設定されているImageオブジェクトに画像と文字列の両方を描画することになります。その方法は、「プログラムで画像を動的に作成する」で説明しています。
この方法で上記のコードを書き直した例を示します。
'Imports System.Drawing 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles MyBase.Load '画像ファイルからImage(ここではBitmap)オブジェクトを作成する Dim img As New Bitmap("C:\test\1.jpg") 'ImageオブジェクトのGraphicsオブジェクトを作成する Dim g As Graphics = Graphics.FromImage(img) 'Graphicsオブジェクトに文字列を描画する g.DrawString("DOBON.NET", Me.Font, Brushes.White, 1, 1) g.DrawString("DOBON.NET", Me.Font, Brushes.Black, 0, 0) g.Dispose() 'PictureBoxのImageプロパティに設定する PictureBox1.Image = img End Sub 'Button1のClickイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click 'PictureBox1に表示されている画像を保存する PictureBox1.Image.Save("C:\test\new1.jpg", _ System.Drawing.Imaging.ImageFormat.Jpeg) End Sub
//using System.Drawing; //フォームのLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { //画像ファイルからImage(ここではBitmap)オブジェクトを作成する Bitmap img = new Bitmap(@"C:\test\1.jpg"); //ImageオブジェクトのGraphicsオブジェクトを作成する Graphics g = Graphics.FromImage(img); //Graphicsオブジェクトに文字列を描画する g.DrawString("DOBON.NET", this.Font, Brushes.White, 1, 1); g.DrawString("DOBON.NET", this.Font, Brushes.Black, 0, 0); g.Dispose(); //PictureBoxのImageプロパティに設定する PictureBox1.Image = img; } //Button1のClickイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //PictureBox1に表示されている画像を保存する PictureBox1.Image.Save(@"C:\test\new1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); }
今度はPictureBox.Imageプロパティを一切使用せずに、PictureBoxのGraphicsオブジェクトだけを使って表示する方法を考えてみます。これにはいろいろなやり方が考えられると思いますが、ここでは指定したGraphicsオブジェクトに画像と文字列を描画するメソッドを用意する方法でやってみます。
'Imports System.Drawing '表示する画像ファイルからImage(ここではBitmap)オブジェクトを作成する Private originalImaga As Bitmap = New Bitmap("C:\test\1.jpg") '指定されたGraphicsに画像と文字列を描画するメソッド Private Sub DrawImageAndString(ByVal g As Graphics) '画像を描画する g.DrawImage(Me.originalImaga, _ 0, 0, Me.originalImaga.Width, Me.originalImaga.Height) 'さらに文字列を描画する g.DrawString("DOBON.NET", Me.Font, Brushes.White, 1, 1) g.DrawString("DOBON.NET", Me.Font, Brushes.Black, 0, 0) End Sub 'PictureBox1のPaintイベントハンドラ Private Sub PictureBox1_Paint(ByVal sender As Object, _ ByVal e As PaintEventArgs) _ Handles PictureBox1.Paint Me.DrawImageAndString(e.Graphics) End Sub 'Button1のClickイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click '画像を保存するためのImage(ここではBitmap)オブジェクトを作成する Dim saveImg As New Bitmap(Me.originalImaga.Width, Me.originalImaga.Height) 'ImageオブジェクトのGraphicsオブジェクトを作成する Dim g As Graphics = Graphics.FromImage(saveImg) 'Imageオブジェクトに画像と文字列を描画する Me.DrawImageAndString(g) 'Graphicsオブジェクトを解放する g.Dispose() 'Imageオブジェクトをファイルに保存する saveImg.Save("C:\test\new1.jpg", _ System.Drawing.Imaging.ImageFormat.Jpeg) 'Imageオブジェクトを解放する saveImg.Dispose() End Sub
//using System.Drawing; //表示する画像ファイルからImage(ここではBitmap)オブジェクトを作成する private Bitmap originalImaga = new Bitmap(@"C:\test\1.jpg"); //指定されたGraphicsに画像と文字列を描画するメソッド private void DrawImageAndString(Graphics g) { //画像を描画する g.DrawImage(this.originalImaga, 0, 0, this.originalImaga.Width, this.originalImaga.Height); //さらに文字列を描画する g.DrawString("DOBON.NET", this.Font, Brushes.White, 1, 1); g.DrawString("DOBON.NET", this.Font, Brushes.Black, 0, 0); } //PictureBox1のPaintイベントハンドラ private void PictureBox1_Paint(object sender, PaintEventArgs e) { this.DrawImageAndString(e.Graphics); } //Button1のClickイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //画像を保存するためのImage(ここではBitmap)オブジェクトを作成する Bitmap saveImg = new Bitmap(this.originalImaga.Width, this.originalImaga.Height); //ImageオブジェクトのGraphicsオブジェクトを作成する Graphics g = Graphics.FromImage(saveImg); //Imageオブジェクトに画像と文字列を描画する this.DrawImageAndString(g); //Graphicsオブジェクトを解放する g.Dispose(); //Imageオブジェクトをファイルに保存する saveImg.Save(@"C:\test\new1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); //Imageオブジェクトを解放する saveImg.Dispose(); }
このようにメソッドを作成する方法以外では、以下のような方法も考えられます。
上記した方法では解決できない問題とその解決法を紹介します。
PictureBoxに画像を表示する時、PictureBoxのGraphicsオブジェクトを使って描画していると、PictureBoxのSizeModeプロパティが無視されます。
SizeModeプロパティは、PictureBox.Imageプロパティに設定されている画像に対してのみ有効です。よって、もしSizeModeプロパティを使いたいのであれば、PictureBoxのImageプロパティに画像を設定してください。もしPictureBoxのImageプロパティを使いたくないのであれば、画像の表示位置と大きさは自分で決定して描画するようにします。
実は、PictureBox.Imageプロパティで画像を表示する方法は、Paintイベントで画像を描画する方法と全く同じことを内部で行っています。ピクチャボックスのImageプロパティに設定された画像は、ピクチャボックスのPaintイベントが発生する直前(OnPaintメソッド)にDrawImageメソッドを使って描画されているだけです。よって「2つの方法」というのは正確ではなく、実際には1つの方法しかありません。PictureBox.Imageプロパティは、画像をPictureBoxに簡単に表示する方法として用意されているだけと考えてよいでしょう。
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。