Invert Background Brush
I need to draw a rectangle and its Fill brush will be the invert of the background. this background may be it will be an Image.
how can I do that?
Answers
Unfortunately, currently version of WPF doesn't allow you to directly manipulate the BitmapSource at pixel level, but with the knowledge of this codeproject article and a bit of interop code, you can achieve this with the following helper class:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Interop;
using GdiPlus = System.Drawing;
namespace InvertPixelDemo
{
public static class BitmapSourceHelper
{
// The following code is originally from http://www.codeproject.com/cs/media/csharpgraphicfilters11.asp
private static GdiPlus.Bitmap InvertBitmap(GdiPlus.Bitmap srcBitmap)
{
GdiPlus::Bitmap destImage = new System.Drawing.Bitmap(srcBitmap);
GdiPlus.Imaging.BitmapData bmData = destImage.LockBits(
new GdiPlus.Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height),
GdiPlus.Imaging.ImageLockMode.ReadWrite,
GdiPlus.Imaging.PixelFormat.Format32bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte* p = (byte*)(void*)Scan0;
int nPadding = stride - srcBitmap.Width * 4;
int nWidth = srcBitmap.Width * 4;
for (int y = 0; y < srcBitmap.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
p[0] = (byte)(255 - p[0]);
++p;
}
p += nPadding;
}
}
destImage.UnlockBits(bmData);
return destImage;
}
public static BitmapSource ConvertToBitmapSource(GdiPlus::Bitmap gdiPlusBitmap)
{
IntPtr hBitmap = gdiPlusBitmap.GetHbitmap();
return Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
public static BitmapSource ConvertToInvertedBitmapSource(GdiPlus::Bitmap gdiPlusBitmap)
{
return ConvertToBitmapSource(InvertBitmap(gdiPlusBitmap));
}
}
}
Only you get the BitmapSource from ConvertToInvertedBitmapSource() method, you can directly feed it into ImageBrush's constructor.
Hope this helps
All Replies
Unfortunately, currently version of WPF doesn't allow you to directly manipulate the BitmapSource at pixel level, but with the knowledge of this codeproject article and a bit of interop code, you can achieve this with the following helper class:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Interop;
using GdiPlus = System.Drawing;
namespace InvertPixelDemo
{
public static class BitmapSourceHelper
{
// The following code is originally from http://www.codeproject.com/cs/media/csharpgraphicfilters11.asp
private static GdiPlus.Bitmap InvertBitmap(GdiPlus.Bitmap srcBitmap)
{
GdiPlus::Bitmap destImage = new System.Drawing.Bitmap(srcBitmap);
GdiPlus.Imaging.BitmapData bmData = destImage.LockBits(
new GdiPlus.Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height),
GdiPlus.Imaging.ImageLockMode.ReadWrite,
GdiPlus.Imaging.PixelFormat.Format32bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte* p = (byte*)(void*)Scan0;
int nPadding = stride - srcBitmap.Width * 4;
int nWidth = srcBitmap.Width * 4;
for (int y = 0; y < srcBitmap.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
p[0] = (byte)(255 - p[0]);
++p;
}
p += nPadding;
}
}
destImage.UnlockBits(bmData);
return destImage;
}
public static BitmapSource ConvertToBitmapSource(GdiPlus::Bitmap gdiPlusBitmap)
{
IntPtr hBitmap = gdiPlusBitmap.GetHbitmap();
return Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
public static BitmapSource ConvertToInvertedBitmapSource(GdiPlus::Bitmap gdiPlusBitmap)
{
return ConvertToBitmapSource(InvertBitmap(gdiPlusBitmap));
}
}
}
Only you get the BitmapSource from ConvertToInvertedBitmapSource() method, you can directly feed it into ImageBrush's constructor.
Hope this helps

