適当に落書き帳みたいなのを作ってみた。(適当すぎるので注意w)
ソースおいとく
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Geometry;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage.Pickers;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 を参照してください
namespace TestWin2d2
{
/// <summary>
/// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
/// </summary>
public sealed partial class MainPage : Page
{
// 描画対象のイメージ
private CanvasRenderTarget backImage = null;
// 初期イメージのサイズ
private const int IMAGE_WIDTH = 1280;
private const int IMAGE_HEIGHT = 720;
private const int IMAGE_DPI = 96;
// 線の太さ
private const int STROKE_WIDTH = 5;
// イメージの表示開始位置
private Point offset;
// 拡縮率
private double rate = 1.0;
// イメージ全体の矩形
private Rect srcRect;
// canvas上のイメージコピー先矩形
private Rect dstRect;
// 描画中フラグ
private bool nowDrawing = false;
// 描画開始位置座標(イメージ上での座標)
private Vector2 startPoint;
public MainPage()
{
this.InitializeComponent();
// 初期イメージの作成
var device = CanvasDevice.GetSharedDevice();
backImage = new CanvasRenderTarget(device, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_DPI);
using (var session = backImage.CreateDrawingSession())
{
session.Clear(Colors.White);
}
srcRect = new Rect(new Point(0, 0), backImage.Size);
canvas.Invalidate();
}
/// <summary>
/// 開くボタンをクリックしたときの処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void button_Click(object sender, RoutedEventArgs e)
{
// 開くダイアログを表示
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".jpg");
var file = await picker.PickSingleFileAsync();
if (file == null)
{
return;
}
// イメージファイルを読み込む
var device = CanvasDevice.GetSharedDevice();
using (var stream = await file.OpenReadAsync())
using (var image = await CanvasBitmap.LoadAsync(device, stream))
{
if (backImage != null)
{
backImage.Dispose();
backImage = null;
}
// バックイメージを作成して読み込んだイメージをコピーする。
backImage = new CanvasRenderTarget(device, (float)image.Size.Width, (float)image.Size.Height, IMAGE_DPI);
using (var session = backImage.CreateDrawingSession())
{
session.DrawImage(image, 0, 0);
CalcRateAndSize();
}
canvas.Invalidate();
}
}
/// <summary>
/// 保存ボタンをクリックしたときの処理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void button1_Click(object sender, RoutedEventArgs e)
{
// 保存ダイアログ表示
var picker = new FileSavePicker();
picker.FileTypeChoices.Add("PNGファイル", new List<string>() { ".png" });
var file = await picker.PickSaveFileAsync();
if(file == null)
{
return;
}
// ファイルに保存
using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
await backImage.SaveAsync(stream, CanvasBitmapFileFormat.Png);
}
}
/// <summary>
/// canvasの再描画イベント
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void canvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
var session = args.DrawingSession;
session.Clear(Colors.Gray);
if (backImage != null)
{
session.DrawImage(backImage, dstRect, srcRect);
}
}
/// <summary>
/// canvasのサイズ変更イベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void canvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
if(backImage !=null)
{
// 拡縮率などの再計算
CalcRateAndSize();
}
}
/// <summary>
/// ポインティングデバイスの移動イベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
if (nowDrawing) // 描画中なら
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
if (pointerPoint.Properties.IsLeftButtonPressed)
{
Vector2 p2;
using (var session = backImage.CreateDrawingSession())
using (var brush = new CanvasSolidColorBrush(backImage.Device, Colors.Red))
using (var style = CreateStrokeStyle())
{
// 現在位置をイメージ上の座標に変換
p2 = dispPosToOffscreenPos(pointerPoint.Position);
float strokeWidth = (float)((double)STROKE_WIDTH * canvas.Dpi / backImage.Dpi / rate);
// 前回位置との間で線を引く
session.DrawLine(startPoint, p2, brush, strokeWidth, style);
canvas.Invalidate();
}
startPoint = p2;
}
}
}
/// <summary>
/// ポインティングデバイスのプレスイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
if(pointerPoint.Properties.IsLeftButtonPressed)
{
// 描画中にする
nowDrawing = true;
// 現在位置をイメージ上の座標に変換して保存
startPoint = dispPosToOffscreenPos(pointerPoint.Position);
}
}
/// <summary>
/// ポインティングデバイスのリリースイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
if (nowDrawing)
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
Vector2 p2;
using (var session = backImage.CreateDrawingSession())
using (var brush = new CanvasSolidColorBrush(backImage.Device, Colors.Red))
using (var style = CreateStrokeStyle())
{
// 現在位置をイメージ上の座標に変換
p2 = dispPosToOffscreenPos(pointerPoint.Position);
float strokeWidth = (float)((double)STROKE_WIDTH * canvas.Dpi / backImage.Dpi / rate);
// 前回位置との間で線を引く
session.DrawLine(startPoint, p2, brush, strokeWidth, style);
canvas.Invalidate();
}
nowDrawing = false;
}
}
/// <summary>
/// 画面上の座標からイメージ上の座標に変換
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
private Vector2 dispPosToOffscreenPos(Point p)
{
return new Vector2((float)((p.X - offset.X) / rate),
(float)((p.Y - offset.Y) / rate));
}
/// <summary>
/// Strokeのスタイルの生成
/// </summary>
/// <returns></returns>
private CanvasStrokeStyle CreateStrokeStyle()
{
var style = new CanvasStrokeStyle();
style.StartCap = CanvasCapStyle.Round;
style.LineJoin = CanvasLineJoin.Round;
style.EndCap = CanvasCapStyle.Round;
return style;
}
/// <summary>
/// 拡縮率などの再計算
/// </summary>
private void CalcRateAndSize()
{
double ratex = canvas.Size.Width / backImage.Size.Width;
double ratey = canvas.Size.Height / backImage.Size.Height;
rate = ratex < ratey ? ratex : ratey;
double width = rate * backImage.Size.Width;
double height = rate * backImage.Size.Height;
offset.X = ((float)canvas.Size.Width - width) / 2;
offset.Y = ((float)canvas.Size.Height - height) / 2;
dstRect = new Rect(offset.X, offset.Y, width, height);
}
}
}
コメント