Last week at the build conference Microsoft announced Windows Phone 8.1 with Universal Apps. Windows Universal apps are Windows Store apps for Windows Phone. The whole architecture of apps is based on what we do for Windows Store apps. The old know Windows Phone Silverlight has also been updated, but this doesn’t support universal apps structure. I believe the Windows Phone Store apps has the feature. As we know, for Windows and Windows Phone live tiles are really important. In WP7/8 the possibilities were very limited here. For Windows 8 Microsoft did a great job with the tiles. Updating them was based on a template (constructed in xml). It gives us developers much more flexibility to update our tiles and show the right data to the end users. The bad thing with those templates it is getting little boring and you still restrained to the possibilities of the times. These restraints can be annoying for some applications. In Windows 8.1 we can render xaml to an image. But to do this the application needs to be running because we need the UI Thread and so it cannot be done from a background task. Microsoft identified this problem as well and for Windows Phone 8.1 Microsoft went one step further. In windows apps it’s possible to render Xaml to an image when the application is at the foreground, but it is not possible when the application is running in the background (in a background task). For Windows Phone 8.1 they solved this with an XamlRenderingBackgroundTask (http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.ui.xaml.media.imaging.xamlrenderingbackgroundtask.aspx)



Created images in the background with managed api's can be expsive and let you go out of resources. So if we want to generated images in the background we have to do this in an efficient way. For this we can use Direct2D with WIC (Windows Imaging Component). There are no managed api's for this so we have to use C++ for it.



























Create 2 projects, one UI project. This can be any kind of project you like (C++/Xaml, Javascript/Html, C#/Xaml) and a Windows Runtime Component which is written in C++.















To start using Direct2D and WIC we first need to do some linking:













First i added a helper method. This because all OS calls give a HResult and you need to check if its succeeded or failed. This helper method will throw an exception if the HResult is false. This method comes from the samples microsoft provided with all DirectX examples











namespace DX
{
    inline void ThrowIfFailed(HRESULT hr)
    {
        if (FAILED(hr))
        {
            throw Platform::Exception::CreateException(hr);
        }
    }
 
    inline D2D1_COLOR_F ConvertToColorF(Windows::UI::Color color)
    {
        return D2D1::ColorF(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f);
    }
 
    inline D2D1_RECT_F ConvertToRectF(Windows::Foundation::Rect source)
    {
        return D2D1::RectF(source.Left, source.Top, source.Right, source.Bottom);
    }
}


First let create a class that does some initializing of direct2d. I called it D2DController.







class D2DController sealed
{
public:
    D2DController();
    IWICBitmap *pWICBitmap = NULL;
    ID2D1Factory *pD2DFactory = NULL;
    IDWriteFactory *pDWriteFactory = NULL;
    ID2D1RenderTarget *pRT = NULL;
 
    void Begin(UINT width, UINT height);
    void End(IRandomAccessStream^ ram, WICPixelFormatGUID format);
 
 
 
private:
    IWICImagingFactory *pWICFactory = NULL;
    UINT sc_bitmapWidth = 0;
    UINT sc_bitmapHeight = 0;
};




The Begin method initialized everything and the End method saves the created image to an RandomAccessStream. 











The implementation of this class:







void D2DController::Begin(UINT width, UINT height)
{
    DX::ThrowIfFailed(
        CoCreateInstance(
        CLSID_WICImagingFactory,
        nullptr,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pWICFactory)
    ));
 
    DX::ThrowIfFailed(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory));
 
    DX::ThrowIfFailed(DWriteCreateFactory(
        DWRITE_FACTORY_TYPE_SHARED,
        __uuidof(pDWriteFactory),
        reinterpret_cast<IUnknown **>(&pDWriteFactory)
    ));
 
    sc_bitmapWidth = width;
    sc_bitmapHeight = height;
 
 
    DX::ThrowIfFailed(pWICFactory->CreateBitmap(
        sc_bitmapWidth,
        sc_bitmapHeight,
        GUID_WICPixelFormat32bppBGR,
        WICBitmapCacheOnLoad,
        &pWICBitmap
    ));
 
    DX::ThrowIfFailed(pD2DFactory->CreateWicBitmapRenderTarget(
        pWICBitmap,
        D2D1::RenderTargetProperties(),
        &pRT
    ));
}
 
void D2DController::End(IRandomAccessStream^ ram, WICPixelFormatGUID format)
{
    ComPtr<IStream> stream = NULL;
    DX::ThrowIfFailed(CreateStreamOverRandomAccessStream(ram, IID_PPV_ARGS(&stream)));
 
    ComPtr<IWICBitmapEncoder> wicBitmapEncoder;
    DX::ThrowIfFailed(
        pWICFactory->CreateEncoder(
        format,
        nullptr,    // No preferred codec vendor.
        &wicBitmapEncoder
    ));
 
    DX::ThrowIfFailed(
        wicBitmapEncoder->Initialize(
        stream.Get(),
        WICBitmapEncoderNoCache
    ));
 
    // Create and initialize WIC Frame Encoder.
    ComPtr<IWICBitmapFrameEncode> wicFrameEncode;
    DX::ThrowIfFailed(
        wicBitmapEncoder->CreateNewFrame(
        &wicFrameEncode,
        nullptr     // No encoder options.
        )
        );
 
    DX::ThrowIfFailed(wicFrameEncode->Initialize(nullptr));
 
    DX::ThrowIfFailed(wicFrameEncode->SetSize(sc_bitmapWidth, sc_bitmapHeight));
    DX::ThrowIfFailed(wicFrameEncode->SetPixelFormat(&format));
    DX::ThrowIfFailed(wicFrameEncode->WriteSource(pWICBitmap, NULL));
 
    DX::ThrowIfFailed(wicFrameEncode->Commit());
    DX::ThrowIfFailed(wicBitmapEncoder->Commit());
 
    // Flush all memory buffers to the next-level storage object.
    DX::ThrowIfFailed(stream->Commit(STGC_DEFAULT));
 
    SafeRelease(&pWICFactory);
    SafeRelease(&pD2DFactory);
    SafeRelease(&pDWriteFactory);
    SafeRelease(&pWICBitmap);
    SafeRelease(&pRT);
}




Now i create a class that generated the image we want to have. That class will use the controller we created here above











public ref class TileGenerator sealed
        {
        public:
            TileGenerator();
 
            void Draw(IRandomAccessStream^ stream);
        };
in the draw method we going to make our images, first we begin with starting the D2DController. With the begin method. As argument of the begin method we pass the width and height of the image we want to generate.





auto controller = new D2DController();
controller->Begin(150, 150);







controller->pRT->BeginDraw();



























then the next step would be to set the background color of our tile













controller->pRT->Clear(D2D1::ColorF(D2D1::ColorF::White));




the pRT field is an ID2D1RenderTarget . With this interface you can do all your custom painting stuff which isn't too hard to figure out. You can find all details here:









http://msdn.microsoft.com/en-us/library/windows/desktop/dd371766(v=vs.85).aspx . To give a few examples what you can do:







Draw Rectangles:







D2D1_RECT_F rectangle1 = D2D1::RectF(0.0f, 0.0f, 50.0f, 50.0f);
    ID2D1SolidColorBrush *brush = nullptr;
    DX::ThrowIfFailed(controller->pRT->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Aqua),
        &brush
        ));
 
 
    controller->pRT->FillRectangle(rectangle1, brush);




Draw a text





IDWriteTextFormat *pTextFormat = NULL;
    static const WCHAR sc_helloWorld[] = L"Hello, World!";
    controller->pRT->DrawText(
        sc_helloWorld,
        ARRAYSIZE(sc_helloWorld) - 1,
        pTextFormat,
        D2D1::RectF(0, 0, rtSize.width, rtSize.height),
        pBlackBrush);








After you do your painting





DX::ThrowIfFailed(controller->pRT->EndDraw());
controller->End(stream, GUID_ContainerFormatPng);


As you can see in the last line, i save the image to a stream as a png format. You can choose here different formats.



The solution here provided can be used in any kind of store app and also work in BackgroundTasks. Beside that its pretty fast and wont consume too many resources so background tasks wont get killed by the operating system because your out of your resource quote. Still its not that easy as the XamlRenderTask that MIcrosoft provided with Windows Phone 8.1