WriteableBitmapEx

repository·master·Indexed 20 days ago

https://github.com/reneschulte/writeablebitmapex

A high-performance extension library for WPF's WriteableBitmap that provides GDI+-like drawing, shape, text, and image manipulation capabilities. It supports .NET Framework and .NET Core 3 for WPF, offering features such as direct pixel manipulation, procedural image generation, geometric transformations (resize, rotate, crop), anti-aliased line drawing, and various blend modes for blitting bitmaps.

Tokens
2.7K
Snippets
9
Records
15
Agent score
67%

What's inside WriteableBitmapEx

  1. Overview of WriteableBitmapEx

    master

    WriteableBitmapEx is a collection of extension methods for the WPF WriteableBitmap class. It is designed to provide high-performance, GDI+-like drawing and image manipulation capabilities that are missing from the minimalistic standard WriteableBitmap API.

    Key use cases include:

    • Direct pixel manipulation.
    • Generating fast procedural images.
    • Performing image transformations (resize, rotate, crop).
    • Drawing complex shapes and text.
    • Blitting (combining) bitmaps with various blend modes.

    It supports both .NET Framework and .NET Core 3 for WPF.

  2. Endpoint clamping in DrawLineAa

    master

    The DrawLineAa method implements automatic endpoint clamping to protect the anti-aliasing algorithm. Because anti-aliasing requires access to neighboring pixels to perform color blending, the method clamps all coordinates to the range [1, width-2] and [1, height-2].

    Impact on usage: If you attempt to draw a line starting at (0,0), the actual line will be drawn starting at (1,1). This is expected behavior to prevent out-of-bounds memory access and ensure smooth edges.

  3. Understand precision behavior in DrawLine and DrawLineAa

    master

    When drawing lines on very large bitmaps (e.g., 30,000x10,000 pixels), the DrawLine and DrawLineAa methods use fixed-point arithmetic to maintain performance.

    Precision Expectations

    • DrawLine: Provides high precision using 24-bit fractional arithmetic. On extremely long lines, you may observe a ±1 pixel deviation due to the nature of integer division truncation. This is considered visually imperceptible (e.g., 1 pixel error over 30,000 pixels is a 0.003% error).
    • DrawLineAa (Anti-Aliased): Expect a ±1 pixel deviation in both width and height. This is an intentional design requirement for the anti-aliasing algorithm to ensure neighbor pixels are available for blending and to prevent array out-of-bounds errors.
  4. Understand DrawLine and DrawLineAa precision behavior

    master

    When working with very large bitmaps, be aware of the following precision characteristics for line drawing methods:

    • DrawLine: Uses high-precision fixed-point arithmetic (24-bit precision) to minimize cumulative error on long lines. While integer division may still result in a 0-1 pixel rounding error, this is considered industry-standard and visually imperceptible.
    • DrawLineAa (Anti-aliased): It is intentional that anti-aliased lines may appear 1 pixel off in width or height compared to the exact coordinates. This is because anti-aliasing requires a 1-pixel border to blend with neighboring pixels. To achieve this, lines are clamped to the range [1, width-2] and [1, height-2].

    If you are testing precision on large canvases, use the following pattern to verify behavior:

    WriteableBitmap image = new WriteableBitmap(30000, 10000, 96, 96, PixelFormats.Pbgra32, null);
    image.Clear(Colors.White);
    image.DrawLine(0, 0, 29999, 9999, Colors.Black);
    image.DrawLineAa(0, 0, 29999, 9999, Colors.Red);
  5. Install WriteableBitmapEx via NuGet

    master

    The latest binaries for WriteableBitmapEx are available as a NuGet package. You can install it directly into your WPF project using the NuGet package manager.

    # Use NuGet package manager to install WriteableBitmapEx
    nuget install WriteableBitmapEx
  6. Manual build and packaging on Windows

    master

    If you cannot use GitHub Actions, you can build the libraries and create the NuGet package manually on a Windows machine.

    Prerequisites:

    • Visual Studio 2017 or later
    • .NET Framework 4.0 SDK
    • .NET Core 3.0 SDK

    Note: Manual builds require you to manually update version numbers in Source/Common/GlobalAssemblyInfo.cs and Nuget/WriteableBitmapEx.nuspec.

  7. Build and publish the NuGet package via GitHub Actions

    master

    The recommended way to build and publish WriteableBitmapEx is using the configured GitHub Actions workflow. This process automatically handles versioning (using the pattern 1.6.{run_number}), builds platform-specific libraries, creates the NuGet package, and publishes it to NuGet.org.

    Setup

    To enable automatic publishing, add your NuGet API key as a repository secret:

    1. Go to SettingsSecrets and variablesActionsNew repository secret.
    2. Name: NUGET_API_KEY.
    3. Value: Your NuGet.org API key.

    How to trigger a build

    • Manual Trigger: Go to the Actions tab in the GitHub repository, select the "Build and Pack NuGet" workflow, and click "Run workflow".
    • Tag Trigger: Push a git tag starting with v (e.g., v1.6.100).
  8. Transform and Filter Bitmaps

    master

    You can perform various geometric and visual transformations on a WriteableBitmap:

    Transformations:

    • Crop(int x, int y, int width, int height): Extracts a defined region.
    • Resize(int width, int height, Interpolation mode): Resizes the bitmap. Supported modes: WriteableBitmapExtensions.Interpolation.Bilinear and NearestNeighbor.
    • Rotate(double angle): Rotates the bitmap by a given angle (supports 90° steps).
    • Flip(FlipMode mode): Flips the bitmap vertically or horizontally.

    Filtering:

    • Convolution and Blur.
    • Brightness, Contrast, and Gamma adjustments.
    • Gray/brightness and Invert.
    // Resize using bilinear interpolation
    var resized = writeableBmp.Resize(200, 300, WriteableBitmapExtensions.Interpolation.Bilinear);
    
    // Rotate 90 degrees
    var rotated = writeableBmp.Rotate(90);
    
    // Flip horizontally
    var flipped = writeableBmp.Flip(FlipMode.Horizontal);
  9. Core Bitmap Manipulation Methods

    master

    The library extends WriteableBitmap with several base manipulation methods:

    • Clear(Color): Clears the bitmap with a specific color.
    • SetPixel(int x, int y, Color): Sets the color of a specific pixel. Supports Color structures (with alpha premultiplication) and int32 overloads for faster performance.
    • GetPixel(int x, int y): Retrieves the color at the specified coordinates.
    • Clone(): Creates a fast copy of the WriteableBitmap.
    • ForEach(Func<int, int, Color, Color>): Applies a function to every pixel in the bitmap. Note that changes are applied when the context is disposed.
    • GetBitmapContext(): Used within a using block to manage the bitmap context for efficient writing.
    WriteableBitmap writeableBmp = BitmapFactory.New(512, 512);
    using(writeableBmp.GetBitmapContext())
    {
       writeableBmp.Clear(Colors.White);
       writeableBmp.SetPixel(10, 13, Colors.Black);
       
       writeableBmp.ForEach((x, y, color) => 
           Color.FromArgb(color.A, (byte)(color.R / 2), (byte)(x * y), 100));
    }