ビットマップに文字列を描画してウインドウに表示する
画像になんらかの文字列を加えてウインドウに表示する場合、通常は下記の流れになります。
ビットマップを生成する
→ピクチャボックスのペイントイベントでビットマップを描画する
→→ペイントイベントでピクチャボックスの上に文字列を描画する
しかし、そのピクチャボックスの内容をファイル保存したい場合などは、下記の流れにしたほうが便利です。
ビットマップを生成する
→ビットマップに文字列を描画する
→→文字列描画済みのビットマップをピクチャボックスのペイントイベントで描画する
→→→文字列描画済みのビットマップをファイル保存する

下記にソースコードを示します。button1 が通常のビットマップ表示の場合です。button2 が文字列描画済みのビットマップを表示する場合です。
ビットマップは Format24bppRgb または Format32bppRgb の必要があります。Format8bppIndexed ではエラーになります。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace aaa
{
public partial class Form1 : Form
{
const int IMAGE_W = 256;
const int IMAGE_H = 256;
const String FONT_NAME = "Courier New";
const float FONT_SIZE = 24.0f;
Bitmap Bmp1 = null;
Bitmap Bmp2 = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e )
{
}
private void button1_Click( object sender, EventArgs e )
{
// ビットマップを生成する.
System.Drawing.Imaging.PixelFormat pixfmt = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
Bmp1 = new Bitmap( IMAGE_W, IMAGE_H, pixfmt );
// 青のグラデーションデータを仕込む.
for ( int j = 0; j < IMAGE_H; j++ )
{
for ( int i = 0; i < IMAGE_W; i++ )
{
byte level = (byte)( i + j );
Color c = Color.FromArgb( 0x00, 0x00, level );
Bmp1.SetPixel( i, j, c );
}
}
// 再描画要求する.
pictureBox1.Size = new Size( Bmp1.Width, Bmp1.Height );
pictureBox1.Invalidate( true );
}
private void pictureBox1_Paint( object sender, PaintEventArgs e )
{
// 描画のタイミングでピクチャボックスに文字列を追加する.
if ( Bmp1 != null )
{
using ( Font font = new Font( FONT_NAME, FONT_SIZE ))
{
using ( SolidBrush sb = new SolidBrush( Color.White ))
{
e.Graphics.DrawImage( Bmp1, pictureBox1.ClientRectangle );
e.Graphics.DrawString( "Bmp1", font, sb, new Point( 0, 0 ));
}
}
}
}
private void button2_Click( object sender, EventArgs e )
{
// ビットマップを生成する.
System.Drawing.Imaging.PixelFormat pixfmt = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
Bmp2 = new Bitmap( IMAGE_W, IMAGE_H, pixfmt );
// 緑のグラデーションデータを仕込む.
for ( int j = 0; j < IMAGE_H; j++ )
{
for ( int i = 0; i < IMAGE_W; i++ )
{
byte level = (byte)( i + j );
Color c = Color.FromArgb( 0x00, level, 0x00 );
Bmp2.SetPixel( i, j, c );
}
}
// ピクチャボックスのサイズを決定する.
pictureBox2.Size = new Size( Bmp2.Width, Bmp2.Height );
// 描画前に文字列を追加する.
using ( Graphics grph = Graphics.FromImage( Bmp2 ) )
{
using ( Font font = new Font( FONT_NAME, FONT_SIZE ))
{
using ( SolidBrush sb = new SolidBrush( Color.White ))
{
grph.DrawImage( Bmp2, pictureBox2.ClientRectangle );
grph.DrawString( "Bmp2", font, sb, new Point( 0, 0 ));
}
}
}
// 再描画要求する.
pictureBox2.Invalidate( true );
}
private void pictureBox2_Paint( object sender, PaintEventArgs e )
{
// 文字列追加済みのビットマップを描画する.
if ( Bmp2 != null )
{
e.Graphics.DrawImage( Bmp2, pictureBox2.ClientRectangle );
}
}
}
}