Windowsフォームのインク機能②
2013年12月26日
今回は、InkPictureに描画した内容をISF(Ink Serialized Format)形式・画像ファイルで保存する方法について紹介します。
WPFの記事でも紹介しましたが、ISF (Ink Serialized Format) 形式はマイクロソフトが策定したインク情報を保存するためのデータ形式です。
Windowsフォーム以外のマイクロソフト技術でも利用することができます。
InkPictureもWPFのInkCanvasと同様に、標準で保存・読み込みをサポートしています。
画像ファイルについては、GIF形式での保存を標準でサポートしていますが、読み込みには対応していません。
1. 保存・読み込みボタンの設置
以下のように、保存・読み込みボタンを配置します。
2. 保存処理の追加
保存ボタンのクリック時のイベントに、以下のような保存処理を追加します。
ISF・GIF形式共に、「InkPicture.Ink.Save」というメソッドを利用して、保存するデータを取得することができます。
// Saveボタンのクリック private void saveButton_Click(object sender, EventArgs e) { SaveFileDialog fileDialog = new SaveFileDialog(); fileDialog.Filter = "Ink Serialization Format(.isf)|*.isf" + "|GIFファイル(.gif)|*.gif"; fileDialog.DefaultExt = "isf"; if (fileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } // 拡張子から保存フォーマットを決定する string fileName = fileDialog.FileName; string ext = System.IO.Path.GetExtension(fileName).ToLower(); if (ext == ".isf") { // ISF形式の保存 using (FileStream fs = new FileStream(fileName, FileMode.Create)) { byte[] isfData = inkPicture1.Ink.Save(Microsoft.Ink.PersistenceFormat.InkSerializedFormat); fs.Write(isfData, 0, isfData.Length); } } else { // GIF形式の保存 using (FileStream fs = new FileStream(fileName, FileMode.Create)) { byte[] gifData = inkPicture1.Ink.Save(Microsoft.Ink.PersistenceFormat.Gif); fs.Write(gifData, 0, gifData.Length); } } }
3. 読み込み処理の追加
読み込みボタンのクリック時のイベントに、以下のような読み込み処理を追加します。
読み込み処理は、ISF形式のみ対応しています。
// Loadボタンのクリック private void loadButton_Click(object sender, EventArgs e) { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Filter = "Ink Serialization Format(.isf)|*.isf"; fileDialog.CheckFileExists = true; if (fileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } string fileName = fileDialog.FileName; try { using (FileStream fs = new FileStream(fileName, FileMode.Open)) { byte[] isfData = new byte[fs.Length]; fs.Read(isfData, 0, isfData.Length); // Inkが有効な間は変更できない inkPicture1.InkEnabled = false; // 読み込んだISF形式を反映 inkPicture1.Ink.Dispose(); inkPicture1.Ink = new Microsoft.Ink.Ink(); inkPicture1.Ink.Load(isfData); // ISF形式の反映後にInkを有効にする inkPicture1.InkEnabled = true; // 読み込み後にコントロールを再描画する inkPicture1.Refresh(); } } catch (Exception ex) { System.Diagnostics.Debug.Write(ex.Message); } }
以上で、保存・読み込み処理の実装が完了しました。
実際にアプリケーションを実行して、動作を確認してみましょう。
ISF形式の保存・読み込みは問題ないかと思いますが、GIF形式の場合は、背景が透明で線が描画された部分のみ抜き出されるので、画像のサイズがバラバラになります。
■InkPicture上に描画したもの
■実際に保存したGIF画像
次は、GIF形式で保存する部分を修正し、コントロールのサイズに合わせて画像を作成するよう修正します。
4. GIF形式の保存処理修正
GIF形式の保存には、「InkPicture.Ink.Save」を利用していましたが、「InkPicture.Ink.Strokes」を直接Bitmapに描画するように修正しました。
この方法の場合、コントロールのサイズに合わせるだけではなく、「System.Drawing.Imaging.ImageFormat.Gif」の部分を他のフォーマットに変更することで、PNGやJPGなどの他のフォーマットに対応することが可能です。
// Saveボタンのクリック private void saveButton_Click(object sender, EventArgs e) { SaveFileDialog fileDialog = new SaveFileDialog(); fileDialog.Filter = "Ink Serialization Format(.isf)|*.isf" + "|GIFファイル(.gif)|*.gif"; fileDialog.DefaultExt = "isf"; if (fileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } // 拡張子から保存フォーマットを決定する string fileName = fileDialog.FileName; string ext = System.IO.Path.GetExtension(fileName).ToLower(); if (ext == ".isf") { // ISF形式の保存 using (FileStream fs = new FileStream(fileName, FileMode.Create)) { byte[] isfData = inkPicture1.Ink.Save(Microsoft.Ink.PersistenceFormat.InkSerializedFormat); fs.Write(isfData, 0, isfData.Length); } } else { using (Bitmap bm = new Bitmap(inkPicture1.Width, inkPicture1.Height)) { // 背景を塗りつぶし Graphics g = Graphics.FromImage(bm); g.FillRectangle(Brushes.White, new Rectangle(0, 0, bm.Width, bm.Height)); // InkPictureの線を描画 inkPicture1.Renderer.Draw(bm, inkPicture1.Ink.Strokes); // 画像の保存 bm.Save(fileName, System.Drawing.Imaging.ImageFormat.Gif); } /* // GIF形式の保存 using (FileStream fs = new FileStream(fileName, FileMode.Create)) { byte[] gifData = inkPicture1.Ink.Save(Microsoft.Ink.PersistenceFormat.Gif); fs.Write(gifData, 0, gifData.Length); } */ } }
それでは、アプリケーションを実行し、画像を保存してみましょう。
■InkPicture上に描画したもの
■実際に保存したGIF画像
これでどのような線を描いても、コントロールのサイズに合わせた画像を作成できるようになりました。
サンプルソースはこちらにアップしてありますので、興味のある方は実際に試して頂ければと思います。
次回は、文字認識の実装について紹介します。