サンプルコードまで飛びたい方はこちらのリンクをクリック
前提条件および動作確認した環境
- C#
- .NET 4.0
- WPF
- VisualStudio 2019
なぜ .NET 4.0 なのか、というのは推し測ってほしい。
確認する内容
- 後述の BEFORE 画像(
640x480
)を画面読み込み時にInkCanvas(640x480)
に背景画像として設定する -
InkCanvas
に書き込み終わった後 Save ボタンをクリックする - 同クリック後、リサイズされた「背景画像とストロークの合成画像」(
320x240
) がC:\Temp\test.jpg
として保存される
上記をサンプルコードで示す。処理内容に粗はあることを了承願いたい。
BEFORE
AFTER
サンプル
xaml
<Window x:Class="ImageReflect.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ImageReflect"
mc:Ignorable="d"
Title="MainWindow" Width="640" Height="600" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="640" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="480"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<InkCanvas
Name="MainCanvas" />
</Grid>
<Grid Grid.Row="1">
<Button
Name="SaveButton"
Content="Save"
FontSize="24px"
Click="onClickSave" />
</Grid>
</Grid>
</Window>
デバッグウィンドウ表示時のイメージ
xaml.cs
{ソリューションディレクトリ}/Resource/Image/sea.jpg
を用意しておく。
using System;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ImageReflect
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.initializeMainCanvas();
}
public void initializeMainCanvas()
{
var imageBrush = new ImageBrush();
imageBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Resource/Image/sea.jpg"));
this.MainCanvas.Background = imageBrush;
}
#region UI event handler
// Save ボタンクリック時の event handler
private void onClickSave(object sender, RoutedEventArgs e)
{
// レンダリングオブジェクトの描画先を作成する
var drawingVisual = new DrawingVisual();
var drawingContext = drawingVisual.RenderOpen();
// InkCanvas 原寸大の描画「領域(rectangle)」を定義する
var rect = new Rect(0, 0, this.MainCanvas.ActualWidth, this.MainCanvas.ActualHeight);
// レンダリングオブジェクトに、背景画像を描画する
drawingContext.DrawRectangle(this.MainCanvas.Background, null, rect);
// レンダリングオブジェクトに、追加でストローク情報を描画する
this.MainCanvas.Strokes.Draw(drawingContext);
// レンダリングオブジェクト情報をフラッシュする
drawingContext.Close();
// 描画先をビットマップにする(96dpi)
var renderTargetBitmap = new RenderTargetBitmap(
(int)rect.Width, (int)rect.Height, 96d, 96d, PixelFormats.Default
);
renderTargetBitmap.Render(drawingVisual);
// 描画先を 幅・高さ共に0.5倍へ変換する
var scaledBitmap = new TransformedBitmap(renderTargetBitmap,
new ScaleTransform(0.5d, 0.5d));
// ここまでの描画情報をエンコーダーのフレームに追加する
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(scaledBitmap));
// C:\Temp\test.jpg へ JPG として出力
using (var fileStream = File.Create(@"C:\Temp\test.jpg"))
{
encoder.Save(fileStream);
}
}
#endregion UI event handler
}
}
その他
まだ把握しきれていないが、RenderBitmap
周りでメモリ枯渇(or リーク) の話がちらほら見えるので
サンプルコードはあくまで参考としてほしい。
参考にしたページ
- http://blog.wdnet.jp/tech/archives/112
- https://stackoverflow.com/questions/15779564/resize-image-in-wpf