Click to Rate and Give Feedback
MSDN
MSDN Library
.NET Development
.NET Framework 3.5
Collapse All/Expand All Collapse All
This page is specific to
Microsoft Visual Studio 2008/.NET Framework 3.5

Other versions are also available for the following:
.NET Framework Class Library
WriteableBitmap Class

Updated: July 2008

Provides a BitmapSource that can be written to and updated.

Namespace:  System.Windows.Media.Imaging
Assembly:  PresentationCore (in PresentationCore.dll)
Visual Basic (Declaration)
Public NotInheritable Class WriteableBitmap _
    Inherits BitmapSource
Visual Basic (Usage)
Dim instance As WriteableBitmap
C#
public sealed class WriteableBitmap : BitmapSource
Visual C++
public ref class WriteableBitmap sealed : public BitmapSource
JScript
public final class WriteableBitmap extends BitmapSource
XAML
You cannot directly create an instance of this class in XAML.

Use the WriteableBitmap class to update and render a bitmap on a per-frame basis. This is useful for generating algorithmic content, such as a fractal image, and for data visualization, such as a music visualizer.

The WriteableBitmap class uses two buffers. The back buffer is allocated in system memory and accumulates content that is not currently displayed. The front buffer is allocated in system memory and contains the content that is currently displayed. The rendering system copies the front buffer to video memory for display.

Two threads use these buffers. The user interface (UI) thread generates the UI but does not present it to the screen. The UI thread responds to user input, timers, and other events. An application can have multiple UI threads. The render thread composes and renders changes from the UI thread. There is only one render thread per application.

The UI thread writes content to the back buffer. The render thread reads content from the front buffer and copies it to video memory. Changes to the back buffer are tracked with changed rectangular regions.

Call one of the WritePixels overloads to update and display content in the back buffer automatically.

For greater control over updates, and for multi-threaded access to the back buffer, use the following workflow.

  1. Call the Lock method to reserve the back buffer for updates.

  2. Obtain a pointer to the back buffer by accessing the BackBuffer property.

  3. Write changes to the back buffer. Other threads may write changes to the back buffer when the WriteableBitmap is locked.

  4. Call the AddDirtyRect method to indicate areas that have changed.

  5. Call the Unlock method to release the back buffer and allow presentation to the screen.

When updates are sent to the rendering thread, the rendering thread copies the changed rectangles from the back buffer to the front buffer. The rendering system controls this exchange to avoid deadlocks and redraw artifacts, such as "tearing".

The following example demonstrates how a WriteableBitmap can be used as the source of an Image to draw pixels when the mouse moves.

C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Input;

namespace WriteableBitmapDemo
{
    class Program
    {
        static WriteableBitmap writeableBitmap;
        static Window w;
        static Image i;

        [STAThread]
        static void Main(string[] args)
        {
            i = new Image();
            RenderOptions.SetBitmapScalingMode(i, BitmapScalingMode.NearestNeighbor);
            RenderOptions.SetEdgeMode(i, EdgeMode.Aliased);
           
            w = new Window();
            w.Content = i;
            w.Show();

            writeableBitmap = new WriteableBitmap(
                (int)w.ActualWidth, 
                (int)w.ActualHeight, 
                96, 
                96, 
                PixelFormats.Bgr32, 
                null);

            i.Source = writeableBitmap;

            i.Stretch = Stretch.None;
            i.HorizontalAlignment = HorizontalAlignment.Left;
            i.VerticalAlignment = VerticalAlignment.Top;

            i.MouseMove += new MouseEventHandler(i_MouseMove);
            i.MouseLeftButtonDown += 
                new MouseButtonEventHandler(i_MouseLeftButtonDown);
            i.MouseRightButtonDown += 
                new MouseButtonEventHandler(i_MouseRightButtonDown);

            w.MouseWheel += new MouseWheelEventHandler(w_MouseWheel);

            Application app = new Application();
            app.Run();
        }

        // The DrawPixel method updates the WriteableBitmap by using
        // unsafe code to write a pixel into the back buffer.
        static void DrawPixel(MouseEventArgs e)
        {
            int column = (int)e.GetPosition(i).X;
            int row = (int)e.GetPosition(i).Y;

            // Reserve the back buffer for updates.
            writeableBitmap.Lock();

            unsafe
            {
                // Get a pointer to the back buffer.
                int pBackBuffer = (int)writeableBitmap.BackBuffer;

                // Find the address of the pixel to draw.
                pBackBuffer += row * writeableBitmap.BackBufferStride;
                pBackBuffer += column * 4;

                // Compute the pixel's color.
                int color_data = 255 << 16; // R
                color_data |= 128 << 8;   // G
                color_data |= 255 << 0;   // B

                // Assign the color data to the pixel.
                *((int*) pBackBuffer) = color_data;
            }

            // Specify the area of the bitmap that changed.
            writeableBitmap.AddDirtyRect(new Int32Rect(column, row, 1, 1));

            // Release the back buffer and make it available for display.
            writeableBitmap.Unlock();
        }

        static void ErasePixel(MouseEventArgs e)
        {
            byte[] ColorData = { 0, 0, 0, 0 }; // B G R

            Int32Rect rect = new Int32Rect(
                    (int)(e.GetPosition(i).X), 
                    (int)(e.GetPosition(i).Y), 
                    1, 
                    1);

            writeableBitmap.WritePixels( rect, ColorData, 4, 0);
        }

        static void i_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            ErasePixel(e);
        }

        static void i_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DrawPixel(e);
        }

        static void i_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                DrawPixel(e);
            }
            else if (e.RightButton == MouseButtonState.Pressed)
            {
                ErasePixel(e);
            }
        }

        static void w_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            System.Windows.Media.Matrix m = i.RenderTransform.Value;

            if (e.Delta > 0)
            {
                m.ScaleAt(
                    1.5, 
                    1.5, 
                    e.GetPosition(w).X, 
                    e.GetPosition(w).Y);
            }
            else
            {
                m.ScaleAt(
                    1.0 / 1.5, 
                    1.0 / 1.5, 
                    e.GetPosition(w).X, 
                    e.GetPosition(w).Y);
            }

            i.RenderTransform = new MatrixTransform(m);
        }
    }
}
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Windows 7, Windows Vista, Windows XP SP2, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0

Date

History

Reason

July 2008

Updated several members in the WriteableBitmap class.

Information enhancement.

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Here's the missing vb.net example      NealAndrews   |   Edit   |   Show History
Imports Microsoft.VisualBasic
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Input

Namespace WriteableBitmapDemo

Friend Class Program

Private Shared writeableBitmap As WriteableBitmap
Private Shared w As Window
Private Shared i As Image

<STAThread()> _
Shared Sub Main(ByVal args() As String)
i = New Image()
RenderOptions.SetBitmapScalingMode(i, BitmapScalingMode.NearestNeighbor)
RenderOptions.SetEdgeMode(i, EdgeMode.Aliased)

w = New Window()
w.Content = i
w.Show()

writeableBitmap = New WriteableBitmap(CInt(w.ActualWidth), CInt(w.ActualHeight), 96, 96, PixelFormats.Bgr32, Nothing)

i.Source = writeableBitmap

i.Stretch = Stretch.None
i.HorizontalAlignment = HorizontalAlignment.Left
i.VerticalAlignment = VerticalAlignment.Top

AddHandler i.MouseMove, AddressOf i_MouseMove
AddHandler i.MouseLeftButtonDown, AddressOf i_MouseLeftButtonDown
AddHandler i.MouseRightButtonDown, AddressOf i_MouseRightButtonDown

AddHandler w.MouseWheel, AddressOf w_MouseWheel

Dim app As New Application()
app.Run()
End Sub

' The DrawPixel method updates the WriteableBitmap by using
' unsafe code to write a pixel into the back buffer.
Private Shared Sub DrawPixel(ByVal e As MouseEventArgs)
Dim column As Integer = CInt(e.GetPosition(i).X)
Dim row As Integer = CInt(e.GetPosition(i).Y)

' Reserve the back buffer for updates.
writeableBitmap.Lock()

' Get a pointer to the back buffer.
Dim pBackBuffer As IntPtr = writeableBitmap.BackBuffer

' Find the address of the pixel to draw.
Dim backBufferOffset As Int32 = (row * writeableBitmap.BackBufferStride) + (column * 4)

' Compute the pixel's color.
Dim color_data As Integer = 255 << 16 ' R
color_data = color_data Or 128 << 8 ' G
color_data = color_data Or 255 << 0 ' B

' Assign the color data to the pixel.
System.Runtime.InteropServices.Marshal.WriteInt32(pBackBuffer, backBufferOffset, color_data)

' Specify the area of the bitmap that changed.
writeableBitmap.AddDirtyRect(New Int32Rect(column, row, 1, 1))

' Release the back buffer and make it available for display.
writeableBitmap.Unlock()
End Sub

Private Shared Sub ErasePixel(ByVal e As MouseEventArgs)
Dim ColorData() As Byte = {0, 0, 0, 0} ' B G R

Dim rect As New Int32Rect(CInt(e.GetPosition(i).X), CInt(e.GetPosition(i).Y), 1, 1)

writeableBitmap.WritePixels(rect, ColorData, 4, 0)
End Sub

Private Shared Sub i_MouseRightButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
ErasePixel(e)
End Sub

Private Shared Sub i_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
DrawPixel(e)
End Sub

Private Shared Sub i_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
If e.LeftButton = MouseButtonState.Pressed Then
DrawPixel(e)
ElseIf e.RightButton = MouseButtonState.Pressed Then
ErasePixel(e)
End If
End Sub

Private Shared Sub w_MouseWheel(ByVal sender As Object, ByVal e As MouseWheelEventArgs)
Dim m As System.Windows.Media.Matrix = i.RenderTransform.Value

If e.Delta > 0 Then
m.ScaleAt(1.5, 1.5, e.GetPosition(w).X, e.GetPosition(w).Y)
Else
m.ScaleAt(1.0 / 1.5, 1.0 / 1.5, e.GetPosition(w).X, e.GetPosition(w).Y)
End If

i.RenderTransform = New MatrixTransform(m)
End Sub
End Class

End Namespace
Tags What's this?: Add a tag
Flag as ContentBug
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement | Site Feedback
Page view tracker