DCSIMG
WPF Image Processing Under the Hood - Essential WPF

WPF Image Processing Under the Hood

In the last two posts I have showed how to create a BitmapSource image and access its underlying WIC image, for manipulating its pixels. In this post I will explain how does the WICBitmap* works.

Download the code from here.

Looking inside the BitmapSource class using Reflector, it figures out that it encapsulates a WIC image (_wicSource). The WICBitmap class uses reflection to retrieve this private field:

image

        public WICBitmap(BitmapSource source)
        {
            Type bitmapSource = typeof(BitmapSource);
            FieldInfo wicSourceField = bitmapSource.GetField(
                "_wicSource", BindingFlags.NonPublic | BindingFlags.Instance);
            _wicBitmapSafeHandle = (SafeHandle)wicSourceField.GetValue(source);            
        }

Now that we have the underlying WIC image safe handle, we can do anything with it. In order to have an access to the pixels buffer, one must call the WIC lock API. If you look further inside the BitmapSource class you will find that it uses WIC Proxy Functions. These kinds of functions provide an easy interop to the WIC API since it's based on COM.

To have a lock, WICBitmap class exposes Lock and TryLock methods. These methods create a WICBitmapLock instance which actually provides the lock:

image

        private static readonly MethodInfo GetDataPointerMethod;
        private static readonly MethodInfo LockMethod;
        static WICBitmapLock()
        {
            Type internalWICBitmapType = Type.GetType(
                "MS.Win32.PresentationCore.UnsafeNativeMethods+WICBitmap, PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            LockMethod = internalWICBitmapType.GetMethod(
                "Lock", BindingFlags.NonPublic | BindingFlags.Static);
            Type internalWICBitmapLockType = Type.GetType(
                "MS.Win32.PresentationCore.UnsafeNativeMethods+WICBitmapLock, PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            GetDataPointerMethod = internalWICBitmapLockType.GetMethod(
                "GetDataPointer", BindingFlags.NonPublic | BindingFlags.Static);            
        }
        internal bool Lock(SafeHandle wicBitmapSafeHandle, LockFlags flags, out int errorCode)
        {
            object[] args = new object[] { wicBitmapSafeHandle, _region, flags, null };
            errorCode = (int)LockMethod.Invoke(null, args);
            if (errorCode != 0)
            {
                return false;
            }
            
            _wicBitmapLockSafeHandle = (SafeHandle)args[3];
            args = new object[] { _wicBitmapLockSafeHandle, null, null };
            errorCode = (int)GetDataPointerMethod.Invoke(null, args);
            if (errorCode != 0)
            {
                return false;
            }
            _wicBitmapBuffer = new WICBitmapBuffer((IntPtr)args[2], (uint)args[1]);
            return true;
        }

To create a lock, WICBitmapLock calls the internal "Lock" method using reflection. To get the size and pointer to the pixel buffer WICBitmapLock calls the internal "GetDataPointer" method using reflection.

Now that we have a pointer to the pixels memory, we can directly manipulate it using native or unsafe code.

Download the code from here.

WARNING: This code calls WPF internal methods using reflection and it is preliminary to changed. Use it on your own risk.

Published Monday, October 01, 2007 11:43 PM by Tomer Shamam

Comments

# re: WPF Image Processing Under the Hood

Thursday, October 04, 2007 12:27 AM by Ran Trifon

Nice post.

What would you do without the Reflector :)

To make life easier in the release of the VS2008, they will also release the source code of the .NET Framework 3.5

weblogs.asp.net/.../releasing-the-source-code-for-the-net-framework-libraries.aspx

# re: WPF Image Processing Under the Hood

Thursday, October 11, 2007 10:52 PM by Jonathan Meyer

This definitely seems pretty cool, but is there an analog for this in the Silverlight world?  It seems to me there wouldn't be one by design (until proven safe), which is a little disheartening, but I suppose understandable.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above:
Powered by Community Server (Commercial Edition), by Telligent Systems