11.キャンバスに描いた絵を画像ファイルとして保存する
InkCnavasに描いた絵を画像として保存するTipsを紹介します。下の方にコードを示しますので、併せてご覧ください。
- InkCanvasに描かれた画像を別な場所に転送(描画)します。この転送先は、DrawingVisual クラスを使用して作成した変数とします。
- 作成した変数(DrawingVisual オブジェクト)の RederOpen() メソッドを使用し、返されたDrawingContext オブジェクトに対して描画行います。
- 2.で描画されたオブジェクトを RendarTagetBitmap クラスを利用して、ビットマップへ変換しておきます。
- ビットマップへ変換されたオブジェクトから、目的の形式に合わせたエンコーダーのインスタンスを作成します。
使用できるエンコーダーには下記のようなものがあります。
| クラス名 | 説明 |
| BmpBitmapEncoder | BMP形式のエンコーダー |
| GifBitmapEncoder | GIF形式のエンコーダー |
| JpegBitmapEncoder | JPEG形式のエンコーダー |
| PngBitmapEncoder | PNG形式のエンコーダー |
| TiffBitmapEncoder | TIFF形式のエンコーダー |
- BitmapFrameクラスからビットマップフレームを作成して、4. で作成したエンコーダーのフレームに追加します。
- 最後に Streamクラスを使用して、画像をファイルに書き込みます。
下記がキャンバスに描いた絵を画像ファイルとして保存する例です。

<StackPanel Name="parentStack">
<StackPanel Orientation="Horizontal" Name="menuStack">
<Button Name="btnSave" Content="保存" />
</StackPanel>
<InkCanvas Name="InkCanvas1" EditingMode="Ink" />
</StackPanel>
' [保存]ボタンクリック時の処理
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnSave.Click
Dim dlgSave As New Microsoft.Win32.SaveFileDialog()
dlgSave.Filter = "ビットマップファイル(*.bmp)|*.bmp|" &
"JPEGファイル(*.jpg)|*,jpg|" &
"PNGファイル(*.png)|*.png"
dlgSave.AddExtension = True
If dlgSave.ShowDialog() Then
'拡張子を取得する
Dim extension As String =
System.IO.Path.GetExtension(dlgSave.FileName).ToUpper()
'ストロークが描画されている境界を取得
Dim rectBounds As Rect = InkCanvas1.Strokes.GetBounds()
'描画先を作成
Dim dv As New DrawingVisual
Dim dc As DrawingContext = dv.RenderOpen()
'描画エリアの位置補正(補正しないと黒い部分ができてしまう)
dc.PushTransform(New TranslateTransform(-rectBounds.X, -rectBounds.Y))
'描画エリア(dc)に四角形を作成
'四角形の大きさはストロークが描画されている枠サイズとし、
'背景色はInkCanvasコントロールと同じにする
dc.DrawRectangle(InkCanvas1.Background, Nothing, rectBounds)
'上記で作成した描画エリアに(dc)にInkCanvasのストロークを描画
InkCanvas1.Strokes.Draw(dc)
dc.Close()
'ビジュアルオブジェクトをビットマップに変換する
Dim rtb As New RenderTargetBitmap(
rectBounds.Width, rectBounds.Height,
96, 96,
PixelFormats.Default)
rtb.Render(dv)
'ビットマップエンコーダー変数の宣言
Dim enc As BitmapEncoder = Nothing
'画像のエンコーダーを作成(拡張子で判断)
Select Case extension
Case ".BMP"
enc = New BmpBitmapEncoder()
Case ".JPG"
enc = New JpegBitmapEncoder()
Case ".PNG"
enc = New PngBitmapEncoder()
End Select
If Not IsNothing(enc) Then
'ビットマップフレームを作成してエンコーダーにフレームを追加する
enc.Frames.Add(BitmapFrame.Create(rtb))
'ファイルに書き込む
Dim stream As System.IO.Stream = System.IO.File.Create(dlgSave.FileName)
enc.Save(stream)
stream.Close()
End If
End If
End Sub
// [保存]ボタンクリック時の処理
private void btnSave_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog dlgSave = new Microsoft.Win32.SaveFileDialog();
dlgSave.Filter = "ビットマップファイル(*.bmp)|*.bmp|" +
"JPEGファイル(*.jpg)|*,jpg|" +
"PNGファイル(*.png)|*.png";
dlgSave.AddExtension = true;
if ((bool)dlgSave.ShowDialog())
{
// 拡張子を取得する
string extension = System.IO.Path.GetExtension(dlgSave.FileName).ToUpper();
// ストロークが描画されている境界を取得
Rect rectBounds = inkCanvas1.Strokes.GetBounds();
// 描画先を作成
DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();
// 描画エリアの位置補正(補正しないと黒い部分ができてしまう)
dc.PushTransform(new TranslateTransform(-rectBounds.X, -rectBounds.Y));
// 描画エリア(dc)に四角形を作成
// 四角形の大きさはストロークが描画されている枠サイズとし、
// 背景色はInkCanvasコントロールと同じにする
dc.DrawRectangle(inkCanvas1.Background, null, rectBounds);
// 上記で作成した描画エリア(dc)にInkCanvasのストロークを描画
inkCanvas1.Strokes.Draw(dc);
dc.Close();
// ビジュアルオブジェクトをビットマップに変換する
RenderTargetBitmap rtb = new RenderTargetBitmap(
(int)rectBounds.Width, (int)rectBounds.Height,
96,96,
PixelFormats.Default);
rtb.Render(dv);
// ビットマップエンコーダー変数の宣言
BitmapEncoder enc = null;
switch (extension)
{
case ".BMP":
enc = new BmpBitmapEncoder();
break;
case ".JPG":
enc = new JpegBitmapEncoder();
break;
case ".PNG":
enc = new PngBitmapEncoder();
break;
}
if (enc != null)
{
// ビットマップフレームを作成してエンコーダーにフレームを追加する
enc.Frames.Add(BitmapFrame.Create(rtb));
// ファイルに書き込む
System.IO.Stream stream = System.IO.File.Create(dlgSave.FileName);
enc.Save(stream);
stream.Close();
}
}
}
InkCanvas へ描いた絵を画像ファイル(gif,jpg,pngなど)として保存するには、いったん新しく描画エリアを作成して、キャンバス上の画像を転送する。
次に、任意のイメージ用エンコーダーを作成し、Streamクラスを使用して保存する。
12.InkSeriah2zedFormat 形式で保存/読み込みをする
InkCanvas に描いたストロークは、InkSerializedFormat 形式(拡張子 ISF)と呼ばれる専用のファイルに保存したり読み込んだりすることが可能です。専用のファイルを利用することで、途中まで描いた絵を保存し、続きは後から描くといったように再利用を可能にします。
ISF形式で保存するには FileStremを作成して、Strokes プロパティのSaveメソッドを使用します。
また、ISF形式のファイルを読み込んで InkCanvasに表示するには、FileStream で任意のファイルを開いて StrokeCollection クラスのインスタンスを作成し、 Strokes プロパティにセットします。
下記は InkCanvas に描かれたストロークをISF形式で保存したり開いたりする例です。

<StackPanel Name="parentStack">
<StackPanel Orientation="Horizontal" Name="menuStack">
<Button Name="btnSaveAsISF" Content="ISF形式で保存" />
<Button Name="btnOpenISF" Content="ISF形式ファイルを開く" />
</StackPanel>
<InkCanvas Name="InkCanvas1" EditingMode="Ink" />
</StackPanel>
' [ISF形式で保存する]ボタンクリック時の処理
Private Sub btnSaveAsISF_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnSaveAsISF.Click
Dim dlgSave As New Microsoft.Win32.SaveFileDialog()
dlgSave.Filter = "ISFファイル(*.isf)|*.isf"
If dlgSave.ShowDialog() Then
Using fs As New System.IO.FileStream(dlgSave.FileName, IO.FileMode.Create)
InkCanvas1.Strokes.Save(fs)
End Using
MessageBox.Show("保存しました")
End If
End Sub
' [ISF形式ファイルを開く]ボタンクリック時の処理
Private Sub btnOpenISF_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnOpenISF.Click
Dim dlgOpen As New Microsoft.Win32.OpenFileDialog()
dlgOpen.Filter = "ISFファイル(*.isf)|*.isf"
If dlgOpen.ShowDialog() Then
'現在のストロークをクリア
InkCanvas1.Strokes.Clear()
Using fs As New System.IO.FileStream(dlgOpen.FileName, IO.FileMode.Open)
InkCanvas1.Strokes = New Ink.StrokeCollection(fs)
End Using
End If
End Sub
// [ISF形式で保存する]ボタンクリック時の処理
private void btnSaveAsISF_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog dlgSave = new Microsoft.Win32.SaveFileDialog();
dlgSave.Filter = "ISFファイル(*.isf)|*.isf";
if ((bool)dlgSave.ShowDialog())
{
using ( System.IO.FileStream fs =
new System.IO.FileStream(dlgSave.FileName, System.IO.FileMode.Create))
{
inkCanvas1.Strokes.Save(fs);
}
MessageBox.Show("保存しました");
}
}
// [ISF形式ファイルを開く]ボタンクリック時の処理
private void btnOpenISF_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlgOpen = new Microsoft.Win32.OpenFileDialog();
dlgOpen.Filter = "ISFファイル(*.isf)|*.isf";
if ((bool)dlgOpen.ShowDialog())
{
// 現在のストロークをクリア
inkCanvas1.Strokes.Clear();
using (System.IO.FileStream fs =
new System.IO.FileStream(dlgOpen.FileName, System.IO.FileMode.Open))
{
inkCanvas1.Strokes = new System.Windows.Ink.StrokeCollection(fs);
}
}
}
キャンバスに描いた絵を InkSerializedFormat 形式で保存するには Strokes プロパティの Saveメソッド を使用する。
また、InkSerializedFormat 形式のファイルを読み込んでキャンバスに表示するには StrokeCollection クラスを使用して InkCanvasのStrokesプロパティにセットする。
まとめ
今回は、InkCanvasコントロールについて取り上げました。
InkCanvasコントロールには多くのプロパティ、イベント、メソッドが備わっており、それ単体でも非常に強力なコントロールだということがお分かりいただけたかと思います。
今回紹介した Tips を組み合わせるだけでもかなり高機能な「お絵かきソフト」が作成できると思いますので、是非挑戦してみて下さい。
最後に、InkCanvas のMSDNリンクを下記に記しておきます
