0

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.

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • WIC is just defined in SDK's wincodec.idl and .h (generated from .idl) files. The .idl does not define a TLB, so you can't use that from .NET. I'm afraid you'll have to redeclare all needed interfaces and other artifacts manually (I can give you some example but if you don't know how to do that, you'll be in trouble anyway :-). Another solution is to start from wincodec.idl, tweak it, build a TLB using MIDL, and reference that from .NET but it's almost as hard to get it right. – Simon Mourier Sep 21 '17 at 15:03
  • Where is that wincodec.cs and xml stuff? – Simon Mourier Sep 21 '17 at 20:16
  • Ok I think you were talking about this: https://github.com/saucecontrol/PhotoSauce/tree/master/src/MagicScaler/Interop this is probably the easiest thing to use WIC indeed, much simpler than trying to rebuild SharpDX wich has its own way of doing thing (plus it needs unsafe environement which can pose issues) – Simon Mourier Sep 21 '17 at 20:51
  • @SimonMourier - ah, I see I may be going about this wrong by starting with SharpDX. WicCop / wincodec.cs and wincodecsdk.cs may contain everything needed. I'll also look at MagicScaler... – ToolmakerSteve Sep 21 '17 at 20:58
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155043/discussion-between-toolmakersteve-and-simon-mourier). – ToolmakerSteve Sep 21 '17 at 21:00
  • @HansPassant - I looked at System.WIndows.Media.Imaging, but I did not see any calls that looked similar to `IWICImagingFactory.CreateDecoderFromFilename`, etc. Lots of bitmap manipulation, but not seeing what I would need to convert bitmaps to work with direct2d. Can you point me to a relevant resource on that topic? – ToolmakerSteve Sep 22 '17 at 19:01
  • @HansPassant In fact, I am having difficulty finding any useful info on using System.Windows.Media.Imaging. Suggestions? [I am adding some Direct2D drawing to an old Windows Forms app.] – ToolmakerSteve Sep 22 '17 at 19:05

1 Answers1

0

(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.)

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • 1
    Note I've created a full WIC interop layer for .NET (in C#) here, open source MIT: https://github.com/smourier/WicNet – Simon Mourier Jul 25 '22 at 08:53