reneschulte / WriteableBitmapEx

Collection of extension methods for the XAML WriteableBitmap
MIT License
533 stars 121 forks source link

WriteableBitmapEx

The WriteableBitmapEx library is a collection of extension methods for the WriteableBitmap. The WriteableBitmap class is available for all XAML flavors including WPF, Windows 10 UWP, Windows Phone, WinRT Windows Store XAML and Silverlight. It supports the .NET Framework and .NET Core 3 and was even ported to Windows Embedded. WriteableBitmapEx allows the direct manipulation of a bitmap and can be used for image manipulation, to generate fast procedural images by drawing directly to a bitmap and more.

The WriteableBitmap API is very minimalistic and there's only the raw Pixels array for such operations. The WriteableBitmapEx library tries to compensate that with extensions methods that are easy to use like built in methods and offer GDI+ like functionality. The library extends the WriteableBitmap class with elementary and fast (2D drawing) functionality, conversion methods and functions to combine (blit) WriteableBitmaps.

The extension methods are grouped into different C# files using a partial class approach. It is possible to include just a few methods by using the specific source code files directly or the full functionality via the built binaries.

The latest binaries are available as NuGet package.

Please use the GitHub Issues functionality to add new issues which are not already reported.

wbx_announcement.png

News

Features

GDI+ like drawing functionality for the WriteableBitmap. Support for WPF, Windows 10 UWP (, Windows 8/8.1 WinRT XAML, Windows Phone Silverlight, Windows Phone WinRT and desktop Silverlight).

Performance!

The WriteableBitmapEx methods are much faster than the XAML Shape subclasses. For example, the WriteableBitmapEx line drawing approach is more than 20-30 times faster than the Silverlight Line element. If a lot of shapes need to be drawn, the WriteableBitmapEx methods are the right choice.

Easy to use!

// Initialize the WriteableBitmap with size 512x512 and set it as source of an Image control
WriteableBitmap writeableBmp = BitmapFactory.New(512, 512);
ImageControl.Source = writeableBmp;
using(writeableBmp.GetBitmapContext())
{

   // Load an image from the calling Assembly's resources via the relative path
   writeableBmp = BitmapFactory.New(1, 1).FromResource("Data/flower2.png");

   // Clear the WriteableBitmap with white color
   writeableBmp.Clear(Colors.White);

   // Set the pixel at P(10, 13) to black
   writeableBmp.SetPixel(10, 13, Colors.Black);

   // Get the color of the pixel at P(30, 43)
   Color color = writeableBmp.GetPixel(30, 43);

   // Green line from P1(1, 2) to P2(30, 40)
   writeableBmp.DrawLine(1, 2, 30, 40, Colors.Green);

   // Line from P1(1, 2) to P2(30, 40) using the fastest draw line method 
   int[] pixels = writeableBmp.Pixels;
   int w = writeableBmp.PixelWidth;
   int h = writeableBmp.PixelHeight;
   WriteableBitmapExtensions.DrawLine(pixels, w, h, 1, 2, 30, 40, myIntColor);

   // Blue anti-aliased line from P1(10, 20) to P2(50, 70) with a stroke of 5
   writeableBmp.DrawLineAa(10, 20, 50, 70, Colors.Blue, 5);

   // Fills a text on the bitmap, Font, size, weight and almost any option is changable, all text supported with WPF is also supported here including Persian, Arabic, Chinese etc
   var formattedText = new FormattedText("Test String", CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface(new FontFamily("Sans MS"), FontStyles.Normal, FontWeights.Medium, FontStretches.Normal), 80.0, System.Windows.Media.Brushes.Black);
   writeableBmp.FillText(formattedText, 100, 100, Colors.Blue, 5);

   // Black triangle with the points P1(10, 5), P2(20, 40) and P3(30, 10)
   writeableBmp.DrawTriangle(10, 5, 20, 40, 30, 10, Colors.Black);

   // Red rectangle from the point P1(2, 4) that is 10px wide and 6px high
   writeableBmp.DrawRectangle(2, 4, 12, 10, Colors.Red);

   // Filled blue ellipse with the center point P1(2, 2) that is 8px wide and 5px high
   writeableBmp.FillEllipseCentered(2, 2, 8, 5, Colors.Blue);

   // Closed green polyline with P1(10, 5), P2(20, 40), P3(30, 30) and P4(7, 8)
   int[] p = new int[] { 10, 5, 20, 40, 30, 30, 7, 8, 10, 5 };
   writeableBmp.DrawPolyline(p, Colors.Green);

   // Cubic Beziér curve from P1(5, 5) to P4(20, 7) 
   // with the control points P2(10, 15) and P3(15, 0)
   writeableBmp.DrawBezier(5, 5, 10, 15, 15, 0, 20, 7,  Colors.Purple);

   // Cardinal spline with a tension of 0.5 
   // through the points P1(10, 5), P2(20, 40) and P3(30, 30)
   int[] pts = new int[] { 10, 5, 20, 40, 30, 30};
   writeableBmp.DrawCurve(pts, 0.5,  Colors.Yellow);

   // A filled Cardinal spline with a tension of 0.5 
   // through the points P1(10, 5), P2(20, 40) and P3(30, 30) 
   writeableBmp.FillCurveClosed(pts, 0.5,  Colors.Green);

   // Blit a bitmap using the additive blend mode at P1(10, 10)
   writeableBmp.Blit(new Point(10, 10), bitmap, sourceRect, Colors.White, WriteableBitmapExtensions.BlendMode.Additive);

   // Override all pixels with a function that changes the color based on the coordinate
   writeableBmp.ForEach((x, y, color) => Color.FromArgb(color.A, (byte)(color.R / 2), (byte)(x * y), 100));

} // Invalidate and present in the Dispose call

// Take snapshot
var clone = writeableBmp.Clone();

// Save to a TGA image stream (file for example)
writeableBmp.WriteTga(stream);

// Crops the WriteableBitmap to a region starting at P1(5, 8) and 10px wide and 10px high
var cropped = writeableBmp.Crop(5, 8, 10, 10);

// Rotates a copy of the WriteableBitmap 90 degress clockwise and returns the new copy
var rotated = writeableBmp.Rotate(90);

// Flips a copy of the WriteableBitmap around the horizontal axis and returns the new copy
var flipped = writeableBmp.Flip(FlipMode.Horizontal);

// Resizes the WriteableBitmap to 200px wide and 300px high using bilinear interpolation
var resized = writeableBmp.Resize(200, 300, WriteableBitmapExtensions.Interpolation.Bilinear);

Additional Information

The WriteableBitmapEx library has its origin in several blog posts that also describe the implemenation and usage of some aspects in detail. The blog posts might be seen as the documentation:

Support it

Donate

Credits

And all the other amazing contributors you can see in the Contributors tab here on GitHub.