Search code examples
c#comdirect2dwic

How create WIC ImageFactory (a COM object) from C#?


This is one step in the actual goal, which is mixing Direct2D with GDI from managed code, to update a legacy Windows Form app, that runs on .NET Framework 3.5 (migrating to newer .NET not practical at this time).

See How initialize Direct2D renderer into GDI context from managed code for older version of .NET Framework for the beginning of this project.

I am following this C++ doc: Direct2D/Programming Guide/How-to/How to Load a Bitmap from a File

Specifically this C++:

HRESULT DemoApp::LoadBitmapFromFile(
    ID2D1RenderTarget *pRenderTarget,
    IWICImagingFactory *pIWICFactory,
    PCWSTR uri,
    UINT destinationWidth,
    UINT destinationHeight,
    ID2D1Bitmap **ppBitmap
    )
{
    IWICBitmapDecoder *pDecoder = NULL;
    IWICBitmapFrameDecode *pSource = NULL;
    IWICStream *pStream = NULL;
    IWICFormatConverter *pConverter = NULL;
    IWICBitmapScaler *pScaler = NULL;

    HRESULT hr = pIWICFactory->CreateDecoderFromFilename(
        uri,
        NULL,
        GENERIC_READ,
        WICDecodeMetadataCacheOnLoad,
        &pDecoder
        );

Which requires IWICImagingFactory pIWICFactory, which refers to a COM interface defined in WIC (Windows Imaging Component).


My Question: How refer to IWICImagingFactory COM object from C#?

OR is there some alternative way to get a bitmap into Direct2D?
(Must run on .NET 3.5 and work with WinForms, so Win2D is not an option, AFAIK. WPF solutions also probably won't help, because it is a 32-bit app, and there isn't much memory left; I hesitate to add another technology.)


This task would be easy to do if our app was in .NET Framework 4.0, as we could then use SharpDX, which includes Direct2D+WIC; unfortunately, Direct2D was not added to SharpDX until v.3.0.0 (which requires .NET 4.0).

So I have attempted to extract factory-creation code from SharpDX sources.
File SharpDX.Direct2D1\WIC\ImagingFactory.cs:

using System;

namespace SharpDX.WIC
{
    public partial class ImagingFactory
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ImagingFactory"/> class.
        /// </summary>
        public ImagingFactory()
        {
            Utilities.CreateComInstance(WICImagingFactoryClsid, Utilities.CLSCTX.ClsctxInprocServer, Utilities.GetGuidFromType(typeof(ImagingFactory)), this);
        }
    }
}

I've successfully copied & built all the files used by that code except for one reference:
WICImagingFactoryClsid
This is found in a Mapping.xml file:

<const from-guid="CLSID_WICImagingFactory" class="SharpDX.WIC.ImagingFactory" type="System.Guid" name="WICImagingFactoryClsid">new System.Guid("$1")</const>

I have not yet attempted to build SharpDX from sources, to discover how this file results in a buildable class library;
I would rather solve this by integrating the minimum needed code into our application.

I don't understand what that Mapping.XML is doing. I'd like to manually encode this one COM interface reference. And know how to encode additional WIC interfaces as needed. Or understand how to generate such interfaces, without building all of SharpDX.


Solution

  • (Based on SimonMourier's comments, because he did not come back to post them as an answer.)

    See: https://github.com/saucecontrol/PhotoSauce/tree/master/src/MagicScaler/Interop

    Contains C# access to WIC (via COM Interop).

    (However, this uses C# features that don't build under VS 2010, so I have not tested it yet.)