Creating a WinRT component using C++/CX: DeForm, a Direct2D effect toolkit

Back to my first love, I’m thrilled to present you DeForm which is a WinRT component that uses Direct2D to apply bitmap effect to a source image.

The library and a sample C# client can be found there:

https://deform.codeplex.com/

 

The goal of this article is to describe how I proceeded to write DeForm component.

Revised on 2012/08/24: Thanks to James McNellis, I fixed some allocation bugs.

Creating a WinRT component

A WinRT component is a DLL you can call from any WinRT compliant language (C++, C#, VB.NET and Javascript).

You can create WinRT components using C++ or a .NET language.

Details can be found there:

https://msdn.microsoft.com/en-us/library/windows/apps/hh441572(v=vs.110).aspx.aspx “https://msdn.microsoft.com/en-us/library/windows/apps/hh441572(v=vs.110).aspx")

For DeForm, I decided to create my component using C++ because I wanted to use Direct2D in a really efficient way.

Actually, I used Visual C++ component extensions (C++/CX) which is a set of extensions to the C++ language that enable the creation of WinRT in a way that is close to modern C++.

To do so, you just have to create a new C++ project for Windows Store in Visual Studio 2012:

This project will generate a .dll and a .winmd files. These files are required if you want to reference your code from a WinRT compliant language:

https://msdn.microsoft.com/en-us/library/windows/apps/hh441569(v=vs.110).aspx.aspx “https://msdn.microsoft.com/en-us/library/windows/apps/hh441569(v=vs.110).aspx")

A WinRT component written with C++/CX can contains standard native code and specific code for the WinRT component.

For instance the following class is a standard C++ class:

class Direct2DManager
{
}

And the following class is a WinRT component:

namespace DeForm
{
    public ref class ImageManipulator sealed
    {
    }
}

To be considered as a WinRT component the ImageManipulator class is defined as ref and sealed and must take place inside a namespace.

The class is then projected to WinRT meaning it will become a component available to C#, VB.NET and Javascript.

The ImageManipulator class is the main component of my DeForm Library and is completely defined as follows:

#pragma once

#include "Windows.UI.Xaml.Media.DXInterop.h"
#include "IEffectDescription.h"
#include "Effect.h"

using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml::Media::Imaging;
using namespace Windows::Foundation::Collections;
using namespace Platform::Collections;

namespace DeForm
{
    public ref class ImageManipulator sealed
    {
        // Members
        std::vector<Effect>                effectDescriptions;
        ComPtr<ID2D1Effect>                    m_source;
        SurfaceImageSource^                    m_surfaceImageSource;        
        ComPtr<ISurfaceImageSourceNative>    m_nativeSurfaceImageSource;
        ComPtr<ID2D1Image>                    m_d2dImage;
        UINT                                m_frameWidth;
        UINT                                m_frameHeight;

        // Methods
        ComPtr<IWICFormatConverter> GetConverter(IRandomAccessStream^ sourceStream);

    public:
        ImageManipulator(IRandomAccessStream^ sourceStream);
        virtual ~ImageManipulator();

        void AddEffectDescription(IEffectDescription ^effectDescription);
        void RemoveEffectDescription(IEffectDescription ^effectDescription);
        void ClearEffectDescriptions();

        SurfaceImageSource^ CreateSurfaceImageSource();
        void DeleteSurfaceImageSource();

        void Manipulate(bool updateSurfaceImageSource);

        void SaveToStream(IRandomAccessStream^ destinationStream);
        void UpdateSurfaceImageSource();
    };
}

As you can see, a WinRT component can contain native pointers (std::vector, ComPtr) but all the public members must be built-in types, WinRT interfaces or WinRT components.

In this case, The ImageManipulator class uses the following components:

  • IEffectDescription: An interface used to define an effect to apply to a bitmap
  • SurfaceImageSource: A XAML control (which is obviously a WinRT component) used to display a Direct2D image

 

Using the ImageManipulator for C# can be like this:

var imageManipulator = new ImageManipulator(stream);
imageManipulator.AddEffectDescription(new GaussianBlurEffectDescription());
myImageControl.Source = imageManipulator.CreateSurfaceImageSource();
imageManipulator.Manipulate(true);

In this sample, myImageControl is a XAML image control and stream is a IRandomAccessStream produced from a file for instance.

We will see later how to develop the GaussianBlurEffectDescription.

Initializing Direct2D

Before creating our effects, we need to instantiate Direct2D objects. I decided to create a Direct2DManager native class to centralize the access to Direct2D in one class using a singleton:

#pragma once

using namespace Microsoft::WRL;
using namespace Windows::Foundation::Collections;
using namespace Platform::Collections;

class Direct2DManager
{
    // Instance
    static Direct2DManager*                m_instance;

    // D2D members
    ComPtr<ID2D1Factory1>                m_d2dFactory;
    ComPtr<IWICImagingFactory2>            m_wicFactory;
    ComPtr<IDXGIDevice>                    m_dxgiDevice;
    ComPtr<ID2D1Device>                    m_d2dDevice;
    ComPtr<ID2D1DeviceContext>            m_d2dContext;

    // Private constructor
    Direct2DManager(void);

public:

    // Instance
    static Direct2DManager* GetInstance();

    // Properties
    inline ComPtr<IWICImagingFactory2> GetWICFactory()
    {
        return m_wicFactory;
    }

    inline ComPtr<ID2D1Device> GetD2DDevice()
    {
        return m_d2dDevice;
    }

    inline ComPtr<ID2D1DeviceContext> GetD2DContext()
    {
        return m_d2dContext;
    }

    inline ComPtr<IDXGIDevice> GetDXGIDevice()
    {
        return m_dxgiDevice;
    }
};

As you can see, this class is mainly responsible of giving access to Direct2D objects. All the work is made by the constructor:

#include "pch.h"
#include "Direct2DManager.h"

using namespace D2D1;

Direct2DManager* Direct2DManager::m_instance;

Direct2DManager::Direct2DManager(void)
{
    D2D1_FACTORY_OPTIONS options;
    ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));

#if defined(_DEBUG)
    options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif

    // D2D Factory
    Tools::Check(
        D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        __uuidof(ID2D1Factory1),
        &options,
        &m_d2dFactory
        )
        );

    // WIC Factory
    Tools::Check(
        CoCreateInstance(
        CLSID_WICImagingFactory,
        nullptr,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&m_wicFactory)
        )
        );

    // D3D stuff
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;    

#if defined(_DEBUG)
    creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
    };

    ComPtr<ID3D11Device> device;
    ComPtr<ID3D11DeviceContext> context;
    D3D_FEATURE_LEVEL returnedFeatureLevel;

    Tools::Check(
        D3D11CreateDevice(
            nullptr,                  
            D3D_DRIVER_TYPE_HARDWARE,
            0,                        
            creationFlags,            
            featureLevels,            
            ARRAYSIZE(featureLevels), 
            D3D11_SDK_VERSION,        
            &device,                  
            &returnedFeatureLevel,    
            &context                  
            )
        );

    Tools::Check(
        device.As(&m_dxgiDevice)
        );

    Tools::Check(
        m_d2dFactory->CreateDevice(m_dxgiDevice.Get(), &m_d2dDevice)
        );

    Tools::Check(
        m_d2dDevice->CreateDeviceContext(
            D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
            &m_d2dContext
            )
        );
}

Direct2DManager* Direct2DManager::GetInstance()
{
    if (m_instance == NULL)
    {
        m_instance = new Direct2DManager();
    }

    return m_instance;
}

As Direct2D is based on Direct3D, you need to instantiate a Direct3D device. Then you have to create a Direct2D device and context.

To learn more about Direct2D, you can go there:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd370990(v=vs.85).aspx.aspx “https://msdn.microsoft.com/en-us/library/windows/desktop/dd370990(v=vs.85).aspx")

Please note that I also created a WIC (Windows Imaging Component) factory object in order to help me manipulate (load, transform and save) pictures. To learn more about WIC, please go there:

https://msdn.microsoft.com/en-us/library/windows/desktop/ee719655(v=vs.85).aspx.aspx “https://msdn.microsoft.com/en-us/library/windows/desktop/ee719655(v=vs.85).aspx")

Direct2D Effects

The Direct2D effects API is an addition to Direct2D that provides image effect processing. The great thing about Direct2D effects is that they are GPU accelerated!

For DeForm, I decided to create a WinRT component for each effect I want to support. These components allow the user to configure effects added to the effects pipeline. Indeed, you can chain Direct2D effects to apply more complex transformations to a picture.

Every effect has to implement the following interface:

#pragma once

#include "EffectParameterValue.h"

namespace DeForm
{
    public enum class EffectType {Blur, ConvolveMatrix, ColorMatrix, Morphology};

    public interface class IEffectDescription
    {
        EffectType GetType();
        int GetParametersCount();
        EffectParameterValue^ GetParameter(int index);
    };
}

A Direct2D effect is created with the following native code (context is the Direct2D context):

    ComPtr<ID2D1Effect> d2dEffect;
    Tools::Check(
        context->CreateEffect(CLSID_D2D1GaussianBlur, &d2dEffect)
        );

You can notice that the CreateEffect method requires a GUID (D2D1GaussianBlur) to identify the effect. So basically every IEffectDescription should have to return a GUID. But it is not permitted for WinRT components because GUID is a non built-in native type.

So every IEffectDescription must have a GetType method which returns a EffectType enum:

public enum class EffectType {Blur, ConvolveMatrix, ColorMatrix, Morphology};

This enum is defined to be compatible with WinRT.

Using this enum, a tool method returns the associated GUIDs:

inline GUID GetEffectGUID(EffectType type)
{
    switch (type)
    {
        case EffectType::Blur:
            return CLSID_D2D1GaussianBlur;
        case EffectType::ConvolveMatrix:
            return CLSID_D2D1ConvolveMatrix;
        case EffectType::ColorMatrix:
            return CLSID_D2D1ColorMatrix;
        case EffectType::Morphology:
            return CLSID_D2D1Morphology;
        default:
            break;
    }
}

In a same way, every effect has parameters which are defined by a key (an int enum) and a value that can be an int, a float, a boolean, a vector2 or an array of float.

To expose these parameters, I added a new WinRT class called EffectParameterValue:

#pragma once

#include "pch.h"
#include "IEffectDescription.h"
#include "Direct2DManager.h"
#include "Vector2.h"

using namespace Platform;

namespace DeForm
{
    public enum class EffectParameterType {Float, Int, FloatArray, Vector2, Bool};

    union ValueType
    {
        int     asInt;
        float   asFloat[2];
        bool    asBool;
    };

    public ref class EffectParameterValue sealed
    {
        int                  m_key;
        EffectParameterType  m_type;
        ValueType            m_value;
        Array<float>^        m_array;

    public:
        EffectParameterValue(int key, int value);
        EffectParameterValue(int key, float value);
        EffectParameterValue(int key, const Array<float>^ array);
        EffectParameterValue(int key, Vector2^ vector);
        EffectParameterValue(int key, bool value);

        property EffectParameterType Type {
            EffectParameterType get() {
                return m_type;
            }
        }

        property int Key {
            int get() {
                return m_key;
            }
        }

        property int ValueAsInt {
            int get() {
                return m_value.asInt;
            }
        }

        property float ValueAsFloat {
            float get() {
                return m_value.asFloat[0];
            }
        }

        property Array<float>^ ValueAsArray {
            Array<float>^ get() {
                return m_array;
            }
        }

        property bool ValueAsBool {
            bool get() {
                return m_value.asBool;
            }
        }
    };
}

This class uses a union to store standard values, a WinRT array to store float array and a WinRT enum to define the type of the stored value. The code associated is as follows:

#include "pch.h"
#include "EffectParameterValue.h"


DeForm::EffectParameterValue::EffectParameterValue(int key, int value): m_key(key), 
m_type(EffectParameterType::Int) { m_value.asInt = value; } DeForm::EffectParameterValue::EffectParameterValue(
int key, float value): m_key(key),
m_type(EffectParameterType::Float) { m_value.asFloat[0] = value; } DeForm::EffectParameterValue::EffectParameterValue(
int key, const Array<float>^ value): m_key(key),
m_type(EffectParameterType::FloatArray) { m_array =
ref new Array<float>(value); } DeForm::EffectParameterValue::EffectParameterValue(int key, Vector2^ vector): m_key(key),
m_type(EffectParameterType::Vector2) { m_value.asFloat[0] = vector->X; m_value.asFloat[1] = vector->Y; } DeForm::EffectParameterValue::EffectParameterValue(
int key, bool value): m_key(key),
m_type(EffectParameterType::Bool) { m_value.asBool = value; }

So defining a new effect can be done like that:

#pragma once

namespace DeForm
{
    public enum struct MorphologyMode { Erode, Dilate};

    public ref class MorphologyEffectDescription sealed : IEffectDescription
    {
    public:        
        MorphologyEffectDescription(MorphologyMode mode, float width, float height);
        MorphologyEffectDescription();

        virtual EffectType GetType()
        {
            return EffectType::Morphology;
        }

        virtual int GetParametersCount()
        {
            return 3;
        }

        virtual EffectParameterValue^ GetParameter(int index)
        {
            switch (index)
            {
            case 0:
                return ref new EffectParameterValue(D2D1_MORPHOLOGY_PROP_MODE, (int)Mode);
            case 1:
                return ref new EffectParameterValue(D2D1_MORPHOLOGY_PROP_WIDTH, Width);
            case 2:
                return ref new EffectParameterValue(D2D1_MORPHOLOGY_PROP_HEIGHT, Height);
            }

            return nullptr;
        }

        property MorphologyMode Mode;
        property float Width;
        property float Height;
    };
}

Using the new C++/CX extensions, it is pretty simple to create properties (https://msdn.microsoft.com/en-us/library/windows/apps/hh755807(v=vs.110).aspx.aspx “https://msdn.microsoft.com/en-us/library/windows/apps/hh755807(v=vs.110).aspx"))

 

The ImageManipulator class

The ImageManipulator stores all activated effects using the following methods:

void DeForm::ImageManipulator::AddEffectDescription(IEffectDescription ^effectDescription)
{
    auto effect = new Effect(effectDescription);
    effectDescriptions.push_back(effect);
}

void DeForm::ImageManipulator::RemoveEffectDescription(IEffectDescription ^effectDescription)
{
    int index;
    auto ite = effectDescriptions.begin();
    auto endIte = effectDescriptions.end();

    for (int index = 0; ite != endIte; index++, ite++)
    {
        Effect effect = *ite;
        if (effect.GetEffectDescription() == effectDescription)
        {
            effectDescriptions.erase(ite);
            return;
        }
    }
}

You can note that every IEffectDescription is embedded in a Effect native class. This class is used to connect Direct2D effects (the WinRT component is unable to do that because it cannot expose native types (such as Direct2D COM interfaces)).

When the user calls Manipulate, the following code is executed:

void DeForm::ImageManipulator::Manipulate(bool updateSurfaceImageSource)
{    
    // Effets
    ComPtr<ID2D1Effect> previousD2DEffect = m_source;
    std::for_each(effectDescriptions.begin(), effectDescriptions.end(), 
[&previousD2DEffect](
Effect effect) { previousD2DEffect = effect.Apply(previousD2DEffect); }); previousD2DEffect->GetOutput(&m_d2dImage); if (updateSurfaceImageSource) UpdateSurfaceImageSource(); }

The key point here is the usage of the Apply method of the Effect class:

ComPtr<ID2D1Effect> Effect::Apply(ComPtr<ID2D1Effect> previousD2DEffect)
{
    auto context = Direct2DManager::GetInstance()->GetD2DContext();

        // Create the effect
    ComPtr<ID2D1Effect> d2dEffect;
    Tools::Check(
        context->CreateEffect(Tools::GetEffectGUID(m_effectDescription->GetType()), &d2dEffect)
        );

    d2dEffect->SetInputEffect(0, previousD2DEffect.Get());

    // Properties
    for (int index = 0; index < m_effectDescription->GetParametersCount(); index++)
    {
        auto parameter = m_effectDescription->GetParameter(index);

        switch (parameter->Type)
        {
        case EffectParameterType::Float:
            Tools::Check(
                d2dEffect->SetValue(parameter->Key, parameter->ValueAsFloat)
                );
            break;
        case EffectParameterType::Int:
            Tools::Check(
                d2dEffect->SetValue(parameter->Key, parameter->ValueAsInt)
                );
            break;
        case EffectParameterType::Bool:
            Tools::Check(
                d2dEffect->SetValue(parameter->Key, (BOOL)parameter->ValueAsBool)
                );
            break;
        case EffectParameterType::FloatArray:
            auto vector = parameter->ValueAsArray;
            UINT byteArraySize = vector->Length * sizeof(float);
            auto byteArray = std::vector<byte>(byteArraySize);

            memcpy(&byteArray[0], &vector[0], byteArraySize);

            Tools::Check(
                d2dEffect->SetValue(parameter->Key, &byteArray[0], byteArraySize)
                );

            delete[] byteArray;
        }
    }

    return d2dEffect.Get();
}

The ImageManipulator class is created using a stream (the picture to load) thanks to WIC:

DeForm::ImageManipulator::ImageManipulator(IRandomAccessStream^ sourceStream)
{
    auto context = Direct2DManager::GetInstance()->GetD2DContext();
    auto wicFactory = Direct2DManager::GetInstance()->GetWICFactory();

    // Converter
    ComPtr<IWICFormatConverter> converter = GetConverter(sourceStream);

    // Create source effect
    Tools::Check(
        context->CreateEffect(CLSID_D2D1BitmapSource, &m_source)
        );


    Tools::Check(
        m_source->SetValue(D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE, converter.Get())
        );

Tools::Check( m_source->SetValue(D2D1_PROPERTY_CACHED, TRUE) );

    // Size        
    converter->GetSize(&m_frameWidth, &m_frameHeight);
}

 

Then, the UpdateSurfaceImageSource method of the ImageManipulator is in charge of updating the SurfaceImageSource:

void DeForm::ImageManipulator::UpdateSurfaceImageSource()
{
    if (m_nativeSurfaceImageSource == nullptr)
        throw Platform::NullReferenceException::CreateException(1);

    auto context = Direct2DManager::GetInstance()->GetD2DContext();

    RECT updateRect;
    POINT offset;

    updateRect.left = 0;
    updateRect.top = 0;
    updateRect.right = m_frameWidth - 1;
    updateRect.bottom = m_frameHeight - 1;

    offset.x = 0;
    offset.y = 0;

    ComPtr<IDXGISurface> surface;
    Tools::Check(
        m_nativeSurfaceImageSource->BeginDraw(updateRect, &surface, &offset)
        );

    ComPtr<ID2D1Bitmap1> targetBitmap;
    D2D1_BITMAP_PROPERTIES1 bitmapProperties = {};
    bitmapProperties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
    bitmapProperties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
    bitmapProperties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
    bitmapProperties.colorContext = nullptr;
    bitmapProperties.dpiX = Windows::Graphics::Display::DisplayProperties::LogicalDpi;
    bitmapProperties.dpiY = Windows::Graphics::Display::DisplayProperties::LogicalDpi;

    Tools::Check(
        context->CreateBitmapFromDxgiSurface(
        surface.Get(),
        &bitmapProperties,
        &targetBitmap
        )
        );

    context->SetTarget(targetBitmap.Get());

    context->BeginDraw();

    context->DrawImage(
        m_d2dImage.Get(),
        D2D1_INTERPOLATION_MODE_LINEAR,
        D2D1_COMPOSITE_MODE_SOURCE_COPY
        );

    context->EndDraw();

    m_nativeSurfaceImageSource->EndDraw();

    context->SetTarget(nullptr);
    targetBitmap = nullptr;
    surface = nullptr;
}

Please note that the ImageManipulator provides the CreateSurfaceImageSource method to create the SurfaceImageSource:

SurfaceImageSource^ DeForm::ImageManipulator::CreateSurfaceImageSource()
{
    if (m_surfaceImageSource == nullptr)
    {
        auto context = Direct2DManager::GetInstance()->GetD2DContext();

        m_surfaceImageSource = ref new SurfaceImageSource(m_frameWidth, m_frameHeight);
        IInspectable* inspectable = (IInspectable*) reinterpret_cast<IInspectable*>(m_surfaceImageSource);
        inspectable->QueryInterface(__uuidof(ISurfaceImageSourceNative), 
(
void **)&m_nativeSurfaceImageSource); m_nativeSurfaceImageSource->SetDevice(Direct2DManager::GetInstance()->GetDXGIDevice().Get()); } return m_surfaceImageSource; }

The SurfaceImageSource must be cast to IInspectable (every WinRT component derives from IInspectable interface which in turn derives from IUnknown) to get access to QueryInterface to get acess to ISurfaceImageSourceNative to connect the SurfaceImageSource with our Direct2D pipeline.

Finally you can call the SaveToStream method to save the picture to a stream (thanks to WIC):

void DeForm::ImageManipulator::SaveToStream(IRandomAccessStream^ destinationStream)
{
    auto wicFactory = Direct2DManager::GetInstance()->GetWICFactory();
    auto d2dDevice = Direct2DManager::GetInstance()->GetD2DDevice();

    // Output stream
    ComPtr<IStream> outputStream;
    Tools::Check(
        CreateStreamOverRandomAccessStream(destinationStream, IID_PPV_ARGS(&outputStream))
        );

    // Png encoder
    ComPtr<IWICBitmapEncoder> wicBitmapEncoder;
    Tools::Check(
        wicFactory->CreateEncoder(
        GUID_ContainerFormatPng,
        nullptr,
        &wicBitmapEncoder
        )
        );

    Tools::Check(
        wicBitmapEncoder->Initialize(
        outputStream.Get(),
        WICBitmapEncoderNoCache
        )
        );

    // Frame encoder
    ComPtr<IWICBitmapFrameEncode> wicFrameEncode;
    Tools::Check(
        wicBitmapEncoder->CreateNewFrame(
        &wicFrameEncode,
        nullptr     
        )
        );

    Tools::Check(
        wicFrameEncode->Initialize(nullptr)
        );

    // Create IWICImageEncoder.
    ComPtr<IWICImageEncoder> imageEncoder;
    Tools::Check(
        wicFactory->CreateImageEncoder(
        d2dDevice.Get(),
        &imageEncoder
        )
        );

    Tools::Check(
        imageEncoder->WriteFrame(
        m_d2dImage.Get(),
        wicFrameEncode.Get(),
        nullptr 
        )
        );

    Tools::Check(
        wicFrameEncode->Commit()
        );

    Tools::Check(
        wicBitmapEncoder->Commit()
        );

    // Flush all memory buffers to the next-level storage object.
    Tools::Check(
        outputStream->Commit(STGC_DEFAULT)
        );
}

Using DeForm from C# or Javascript

To use the DeForm Library, you just have to reference the .winmd file from your client project:

Please note that you will become depend on a specific architecture (x86, x64 or Arm) when you reference a C++/CX WinRT component.

You have to provide a specific version of your component for each architecture.

The DeForm Codeplex project

The current version of the DeForm project supports the following effects (which can be mixed):

Gaussian Blur

imageManipulator.AddEffectDescription(
new GaussianBlurEffectDescription(2.0f, GaussianBlurOptimization.Quality, GaussianBlurBorderMode.Hard));

Convolve Matrix

 

var convolve = new ConvolveMatrixEffectDescription();
convolve.SetKernelMatrix(new[] { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f, -1.0f }, 3, 3);

imageManipulator.AddEffectDescription(convolve);

Black and White

// B&W
imageManipulator.AddEffectDescription(new ColorMatrixEffectDescription(
    new[] {
            0.2125f, 0.2125f, 0.2125f, 0.0f,
            0.7154f, 0.7154f, 0.7154f, 0.0f,
            0.0721f, 0.0721f, 0.0721f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 0.0f, 0.0f
    },
    ColorMatrixAlphaMode.Straight, true));

Sepia

// B&W
imageManipulator.AddEffectDescription(new ColorMatrixEffectDescription(
    new[] {
            0.2125f, 0.2125f, 0.2125f, 0.0f,
            0.7154f, 0.7154f, 0.7154f, 0.0f,
            0.0721f, 0.0721f, 0.0721f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 0.0f, 0.0f
    },
    ColorMatrixAlphaMode.Straight, true)); 

// Sepia
imageManipulator.AddEffectDescription(new ColorMatrixEffectDescription(
    new[] {
            0.90f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.70f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.30f, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 0.0f, 0.0f
    },
    ColorMatrixAlphaMode.Straight, true));

Morphology

imageManipulator.AddEffectDescription(new MorphologyEffectDescription(MorphologyMode.Dilate, 1.0f, 0.0f));

Tips and Tricks for C# Windows 8 developer: Read and write roamed application settings

Windows 8 offers a really cool tool to save and load settings for your application: the roaming settings. It is a dictionary container where the name of each setting can be 255 characters in length at most. Each setting can be up to 8K bytes in size.

For more information about the roaming, you can go there:

https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx

The today’s code is about creating a set of tools to handle application settings. With the following code you can save and retrieve typed settings. If a roamed version exists it will be used else a local version will be used:

public static bool GetSerializedBoolValue(string name, bool defaultValue = false, bool roaming = true)
{
    var value = GetSerializedStringValue(name, roaming);
    if (value == null)
        return defaultValue;

    bool result;
    if (bool.TryParse(value, out result))
        return result;

    return defaultValue;
}

public static int GetSerializedIntValue(string name, int defaultValue = 0, bool roaming = true)
{
    var value = GetSerializedStringValue(name, roaming);
    if (value == null)
        return defaultValue;

    int result;
    if (int.TryParse(value, out result))
        return result;

    return defaultValue;
}

public static double GetSerializedDoubleValue(string name, double defaultValue = 0, bool roaming = true)
{
    var value = GetSerializedStringValue(name, roaming);
    if (value == null)
        return defaultValue;

    double result;
    if (double.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result))
        return result;

    return defaultValue;
}

public static string GetSerializedStringValue(string name, bool roaming = true)
{
    if (roaming && ApplicationData.Current.RoamingSettings.Values.ContainsKey(name))
    {
        return ApplicationData.Current.RoamingSettings.Values[name].ToString();
    }

    if (ApplicationData.Current.LocalSettings.Values.ContainsKey(name))
    {
        return ApplicationData.Current.LocalSettings.Values[name].ToString();
    }

    return null;
}



public static void SetSerializedValue(string name, object value, bool roaming = true)
{
    string valueToStore;

    if (value is double)
        valueToStore = ((double)value).ToString(CultureInfo.InvariantCulture);
    else
        valueToStore = value.ToString();

    if (roaming)
        ApplicationData.Current.RoamingSettings.Values[name] = valueToStore;
    ApplicationData.Current.LocalSettings.Values[name] = valueToStore;
}



Tips and Tricks for C# Windows 8 developer: Try to catch the famous ‘It works for me’ bug

As an experienced developer, you do not have bug. Never. At least on your computer. And when sometimes (so rarely that you can barely remember) a bug appears, it is never on your computer.

And in this case, it is a true hell to find at least where in your application the bug is (because as you never have bugs, you do not need to integrate an error log system).

The first solution can be to decline the responsibility with a “It works for me, you should have a problem with your drivers”.

But you can also try to locate it J

This article presents you some tips to find some information about a bug on a non-developer computer.

Using Visual Studio 2012

Ok, it is unusual but if your customer owns Visual Studio, you can use the powerful “Debug Installed App Package” menu:

Obviously, if the app package does not contain symbols you can get no really interesting information:

To really debug the application, you need to have access to the source code and you must incorporate the PDB (Program Database file that contains the symbols) when you generate the app package:

 

But as you must know, it is pretty rare when a Customer already has Visual Studio 2012 and your source code in his computer Sourire

DebugView

DebugView is a member of the excellent Tools suite called “Sysinternals Suite” developed by Mark Russinovich:

https://technet.microsoft.com/en-us/sysinternals/bb842062.aspx

This tool allows you to capture debug message send by applications so you don’t need a debugger to catch the debug output your applications generate.

Obviously, the prerequisite is that your applications generate debug output Sourire(System.Diagnostics.Debug.Write).

For instance, WorldMonger (a game I develop with some friends) has these lines of code:

System.Diagnostics.Debug.WriteLine("Starting WorldMonger");
System.Diagnostics.Debug.WriteLine("Launching Babylon engine");

And when I launch DebugView (using Administrator rights) on any computer running WorldMonger, here is the resulting window:

ProcessMonitor

ProcessMonitor is another really useful tool of the “SysInternals Suite”. It allows you to monitor your processes in realtime and can give you tons of useful information in order to help you debug your applications.

By installing a virtual driver on top of the system, ProcessMonitor can track:

  • Registry access
  • Files access
  • Network access
  • Process and thread activity (access to Windows API)

You just have to set a filter Inside ProcessMonitor to track only your own application. For instance, I added the following filter to see what is going wrong with my game:

Then I have to launch my game and wait for the bug (in this case, my music is not played). Inside ProcessMonitor, I can see that the file I wanted to played is not found:

You can see the [NAME NOT FOUND] indicating that the file cannot be found (a typo in the name).

So using ProcessMonitor, you can track the activity of your application and use it to inspect every interaction between your application and the operating system.

The Event Viewer

Finally you can find some useful information in the event log dedicated to Windows 8 Metro applications. The log can be located right there:

Applications and Services LogsMicrosoftWindowsAppsMicrosoft-Windows-TWinUI/Operationnal

Book about Kinect and Gestures

You want to learn how to develop with Kinect?Programming with the Kinect for Windows Software Development Kit: Add gesture and posture recognition to your applications

You want to learn how to detect gestures or postures?

You want to learn how to create reality augmented application using Kinect?

If yes, this book is for you:

https://www.amazon.com/Programming-Kinect-Windows-Software-Development/dp/0735666814/ref=sr_1_11?ie=UTF8&qid=1343746483&sr=8-11&keywords=Kinect+book

It will be available on September 22, 2012 and here is the pitch:

Create rich experiences for users of Windows 7 and Windows 8 Developer Preview with this pragmatic guide to the Kinect for Windows Software Development Kit (SDK). The author, a developer evangelist for Microsoft, walks you through Kinect sensor technology and the SDK—providing hands-on insights for how to add gesture and posture recognition to your apps. If you’re skilled in C# and Windows Presentation Foundation, you’ll learn how to integrate Kinect in your applications and begin writing UIs and controls that can handle Kinect interaction.

  • This book introduces the Kinect for Windows Software Development Kit to developers looking to enrich applications they build for Windows 7 and later with human motion tracking
  • Teaches developers with core C# and WPF skills how to program gesture and posture recognition in Kinect
  • Describes how to integrate 3D representation on top of a real scene
  • Provides expert insights and code samples to get you up and running

Kinect Toolbox 1.2

I’m thrilled to announce the availability of Kinect Toolbox 1.2!

You can download it just there: https://kinecttoolbox.codeplex.com/releases/view/91988

This new version introduces a lot of new features alongside bug fixes and various optimizations. As always, you will find in the archive the sources and associated samples (GestureViewer and KinectUI) in order to help you learn how to use the toolbox.

Context tracking

In order to help you detect wrong gestures, I added two classes:

  • ContextTracker: this class detects for you if the user is stable (and so if you can detect gestures or not)
  • EyeTracker: Using the new Face Tracking system of the SDK 1.5, this class allows you to detect if the user is currently looking at the sensor (to avoid detecting unwanted gestures)

With Kinect, you are the mouse!

To help you define adapted UI and control the mouse, the Kinect Toolbox introduces the following new Tools:

  • MouseController: A tool to control the mouse with your Kinect
  • MouseImpostor: A new control to replace the mouse pointer (like on Xbox)
  • Magnetic controls: An attached property to make magnetic controls in order to help you select controls with your Kinect

Combined gestures

With the ParallelCombinedGestureDetector and the SerialCombinedGestureDetector, you will be able to compose gestures (in a parallel or serial way) in order to create really complex gestures.

New PresenceControl control

The PresenceControl control is a WPF control you can use to give a visual feedback to your user. The position of the user’s hands is displayed on top of a depth stream representation.

New KinectUI sample

Kinect Toolbox 1.2 adds a new sample called KinectUI to show you how to create user interface adapted to Kinect:

Tips and Tricks for C# Metro developer: How to find a XAML control by its name

Today, I would like to share with you a bunch of code that is able to find the first control with a given name. With this code, you do not have to bother with XAML namespace (like with FindControl) and it will go through the entire hierarchy for you.

I use it in WorldMonger to display tutorials in top of given controls:

 

The code:

public static FrameworkElement GetChildByNameRecursively(this FrameworkElement current, string name)
{
    if (current.Name == name)
        return current;

    // App Bars
    var page = current as Page;

    if (page != null)
    {
        if (page.BottomAppBar != null)
        {
            var result = page.BottomAppBar.GetChildByNameRecursively(name);
            if (result != null)
                return result;
        }

        if (page.TopAppBar != null)
        {
            var result = page.TopAppBar.GetChildByNameRecursively(name);
            if (result != null)
                return result;
        }
    }

    // Children
    var childrenCount = VisualTreeHelper.GetChildrenCount(current);

    for (var index = 0; index < childrenCount; index++)
    {
        var frameworkElementChild = (FrameworkElement) VisualTreeHelper.GetChild(current, index);

        if (frameworkElementChild != null)
        {
            var result = frameworkElementChild.GetChildByNameRecursively(name);

            if (result != null)
                return result;
        }
    }

    return null;
}

Tips and tricks for C# Metro developers : Handling the keyboard events

I have some users that ask me how can I handle the keyboard ? Should I add an event Handler on a top root grid?

The response is no Sourire. The better solution is to use the KeyUp/KeyDown event of the CoreWindow which is able to catch all the keyboard strokes:

protected override void OnNavigatedTo(NavigationEventArgs e)
{ 
    Window.Current.CoreWindow.KeyUp += CoreWindow_KeyUp;
}

void CoreWindow_KeyUp(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
    switch (args.VirtualKey)
    {
        case Windows.System.VirtualKey.Number1:
            break;
        case Windows.System.VirtualKey.Number2:
            break;

} } protected override void OnNavigatedFrom(NavigationEventArgs e) { Window.Current.CoreWindow.KeyUp -= CoreWindow_KeyUp; }

Please note that the KeyEventArgs class provides a Handled property in order to stop the propagation of the event.

Mishra Reader beta 3! The new version of your prefered RSS reader is now out!

I’m thrilled to announce that the new version of Mishra Reader is out. You can download it here: https://mishrareader.codeplex.com/downloads/get/433898

The team was more than busy (with for instance Windows 8Sourire) in the last months but we manage to release a new version with the following new features:

  • Enable browsing per feed
  • Support for Instapaper
  • Support for ReadIt Later
  • Developed with .NET Framework 4.5
  • Tons of bugs fixed

 

The Codeplex project: https://mishrareader.codeplex.com/

A special thank for Oren Novotny who did an extraordinary job to release this version!

Tips and Tricks for C# Metro developers: Handling the virtual keyboard

As we saw in a previous post (https://blogs.msdn.com/b/eternalcoding/archive/2012/07/03/tips-and-tricks-for-c-metro-developers-the-flyout-control.aspx) it is really easy to create a flyout control.

But if this control is used to type text, you must consider handling the virtual keyboard in order to move your flyout so that it can always be visible:

To do so, it is pretty easy because WinRT has an event for that:

Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing 

So to always keep your flyout on top off its control, just use the following code:

// Handling the virtual keyboard
int flyoutOffset = 0;
Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing += (s, args) =>
    {
        flyoutOffset = (int)args.OccludedRect.Height;
        flyout.VerticalOffset -= flyoutOffset;
    };
Windows.UI.ViewManagement.InputPane.GetForCurrentView().Hiding += (s, args) =>
    {
        flyout.VerticalOffset += flyoutOffset;
    };

So the complete flyout code is as follows:

public static Popup ShowPopup(FrameworkElement source, UserControl control)
{
    Popup flyout = new Popup();

    var windowBounds = Window.Current.Bounds;
    var rootVisual = Window.Current.Content;

    GeneralTransform gt = source.TransformToVisual(rootVisual);

    var absolutePosition = gt.TransformPoint(new Point(0, 0));

    control.Measure(new Size(Double.PositiveInfinity, double.PositiveInfinity));

    flyout.VerticalOffset = windowBounds.Height - control.Height - 120;
    flyout.HorizontalOffset = (absolutePosition.X + source.ActualWidth / 2) - control.Width / 2;
    flyout.IsLightDismissEnabled = true;

    flyout.Child = control;
    var transitions = new TransitionCollection();
    transitions.Add(new PopupThemeTransition() { FromHorizontalOffset = 0, FromVerticalOffset = 100 });
    flyout.ChildTransitions = transitions;
    flyout.IsOpen = true;

    // Handling the virtual keyboard
    int flyoutOffset = 0;
    Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing += (s, args) =>
        {
            flyoutOffset = (int)args.OccludedRect.Height;
            flyout.VerticalOffset -= flyoutOffset;
        };
    Windows.UI.ViewManagement.InputPane.GetForCurrentView().Hiding += (s, args) =>
        {
            flyout.VerticalOffset += flyoutOffset;
        };

    return flyout;
}

Tips and tricks for C# metro developers–The FileExistsAsync method

Today I share with you a small (but useful) piece of code Sourire.

Indeed, for now WinRT does not provide a method to test the existence of a specific file. You can only try/catch an GetFileAsync call and it can be disappointing.

So here is a little solution:

public async static Task<bool> FileExistsAsync(this StorageFolder folder, string name)
{
    var files = await folder.GetFilesAsync();

    return files.Any((f)=>
    {
        return f.Name == name;
    });
}

To use it, just call the following code:

if (!await ApplicationData.Current.LocalFolder.FileExistsAsync(filename))
    return;

StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);