LINEで送る

今回は、InkPictureに描画した内容をISF(Ink Serialized Format)形式・画像ファイルで保存する方法について紹介します。

WPFの記事でも紹介しましたが、ISF (Ink Serialized Format) 形式はマイクロソフトが策定したインク情報を保存するためのデータ形式です。
Windowsフォーム以外のマイクロソフト技術でも利用することができます。
InkPictureもWPFのInkCanvasと同様に、標準で保存・読み込みをサポートしています。

画像ファイルについては、GIF形式での保存を標準でサポートしていますが、読み込みには対応していません。

1. 保存・読み込みボタンの設置
以下のように、保存・読み込みボタンを配置します。

winform_02_00

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上に描画したもの

winform_02_01

■実際に保存したGIF画像

winform_02_02

次は、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上に描画したもの

winform_02_03

■実際に保存したGIF画像

winform_02_04

これでどのような線を描いても、コントロールのサイズに合わせた画像を作成できるようになりました。
サンプルソースはこちらにアップしてありますので、興味のある方は実際に試して頂ければと思います。

次回は、文字認識の実装について紹介します。

Top