WPFのBitmapオブジェクトへ直線を描画してみます。
ピクセル単位での描画する方法は調べてありますので、「直線を引く」ぐらいはプログラムならば簡単に出来るだろうと考えていました。 「直線を引く」アルゴリズムを考えてみて1分ぐらいで自分の手に余ると断念しました。
ネット検索したところWikipediaに直線を引くアルゴリズムがありましたので、C#で書き直してみました。
【WPF学習中】Bitmapにピクセル単位で描画
WPFでBitmap画像に対しピクセル単位で描画する方法を探したところ、byte配列でピクセルデータを用意し、そのbyte配列をWriteableBitmapオブジェクトに書き込む方法が見つかりましたので試してみます。 プロジェクトの作成 ...
ブレゼンハムのアルゴリズム - Wikipedia
プロジェクトの作成
PowerShellで実行。要dotnet.exe
mkdir DrawLine
cd DrawLine
dotnet new wpf
code .
ソースコード
<Window x:Class="DrawLine.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:DrawLine"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Image x:Name="image1" Stretch="None" />
</Grid>
</Window>
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace DrawLine
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
static void DrawLine(ref WriteableBitmap bitmap, int x0, int y0, int x1, int y1, Color c)
{
int width = (int)bitmap.PixelWidth;
int height = (int)bitmap.PixelHeight;
int pixelsSize = (width * 4) * height;
byte[] pixels = new byte[pixelsSize];
int stride = (width * bitmap.Format.BitsPerPixel + 7) / 8;
bitmap.CopyPixels(pixels, stride, 0);
bitmap.Lock();
int dx = System.Math.Abs(x1-x0);
int dy = System.Math.Abs(y1-y0);
int sx = (x0 < x1) ? 1 : -1;
int sy = (y0 < y1) ? 1 : -1;
int err = dx - dy;
while(true)
{
// System.Console.WriteLine("x:{0}y:{1}", x0, y0);
int i = (x0 * 4) + (y0 * (width * 4));
pixels[i+0] = (byte)c.B;
pixels[i+1] = (byte)c.G;
pixels[i+2] = (byte)c.R;
pixels[i+3] = (byte)c.A;
if ((x0 == x1) && (y0 == y1)) break;
int e2 = 2 * err;
if (e2 > dy)
{
err = err - dy;
x0 = x0 + sx;
}
if (e2 < dx)
{
err = err + dx;
y0 = y0 + sy;
}
}
bitmap.WritePixels(new Int32Rect(0, 0, width, height), pixels, stride, 0, 0);
bitmap.Unlock();
}
public MainWindow()
{
InitializeComponent();
const int width = 256;
const int height = 256;
var wb = new WriteableBitmap(width, height, 75, 75, PixelFormats.Bgra32, null);
int x0 = 16;
int x1 = 240;
int y0 = 240;
int y1 = 16;
DrawLine(ref wb, x0, y0, x1, y1, Color.FromArgb(255, 255, 0, 0));
image1.Source = wb;
}
}
}
ビルド
dotnet build
実行
dotnet run
作っては見ましたが、WPFの標準機能でbitmapへ直線を引く機能を見つけることが出来ないことを考えると、WPFではラスター画像で図形を描画するのではなくベクター画像を使えと言う事かもしれません。ベクター画像としてパスで直線を描画する方法はこちら。
【WPF学習中】Pathで動的に直線を引く
調べたところWPFで直線を引こうと思ったらXAMLでPathで静的に直線を引くことが出来るようです。 こちらを参考に、マウスのクリックイベントで直線の始点と終点を拾って、動的に直線を引く方法を考えてみました。 MVVMぽくプログラミングしよ...
コメント