Enumerate WIC Components

In an older article, I presented a function that enumerates Windows Imaging Component codecs. Recently I had the idea to make a set of WIC Interfaces wrapper classes for easily enumerate and get info about all types of WIC components: bitmap decoders and encoders, metadata readers and writers, format converters, and supported pixel formats. Here are just few samples of code.

CComponentEnumT – a template class for enumerating WIC components

namespace wic
{
    template<class TCompInfoCls, DWORD dwTypes>
    class CComponentEnumT
    {
        // ...
    public:
        using CompInfoList = std::list<std::shared_ptr<TCompInfoCls>>;
        using EnumOptions = WICComponentEnumerateOptions;

        CComponentEnumT()
        {
            HRESULT hr = m_spWICFactory.CoCreateInstance(CLSID_WICImagingFactory);
            ATLENSURE_SUCCEEDED(hr);
        }
        ~CComponentEnumT() = default;
        const CompInfoList& DoEnum(EnumOptions opt = WICComponentEnumerateDefault)
        {
            m_listCompInfo.clear();
            CComPtr<IEnumUnknown> spEnum;
            HRESULT hr = m_spWICFactory->CreateComponentEnumerator(dwTypes, opt, &spEnum);
            ATLENSURE_SUCCEEDED(hr);

            ULONG cbActual = 0;
            CComPtr<IUnknown> spEnumElement = NULL;
            while (S_OK == spEnum->Next(1, &spEnumElement, &cbActual))
            {
                auto spCompInfo = std::make_shared<TCompInfoCls>(spEnumElement);
                m_listCompInfo.push_back(spCompInfo);
                spEnumElement = nullptr;
            }
            return m_listCompInfo;
        }

    private:
        CompInfoList m_listCompInfo;
        CComPtr<IWICImagingFactory> m_spWICFactory;
    };
}

CComponentInfoBaseT – base class for all other component info classes

namespace wic
{
    template <class TCompInfoInterface>
    class CComponentInfoBaseT
    {
        // ...
    protected:
        CComponentInfoBaseT(const CComPtr<IUnknown>& spEnumElement)
        {
            ATLASSERT(spEnumElement);
            m_spCompInfo = spEnumElement;
        }
        ~CComponentInfoBaseT() = default;

        // data
        CComQIPtr<TCompInfoInterface> m_spCompInfo;
    };
}

CPixelFormatInfoT – just one of classes getting WIC component info

namespace wic
{
    template <class TCompInfoInterface>
    class CPixelFormatInfoT : public CComponentInfoT<TCompInfoInterface>
    {
    public:
        CPixelFormatInfoT(const CComPtr<IUnknown>& spEnumElement);
        ~CPixelFormatInfoT();

        UINT GetBitsPerPixel() const;
        UINT GetChannelCount() const;
        GUID GetFormatGUID() const;
        bool SupportsTransparency() const;
        WICPixelFormatNumericRepresentation GetNumericRepresentation() const;
    };

    using CPixelFormatInfo = CPixelFormatInfoT<IWICPixelFormatInfo2>;
}

Just note that, for further easier using, I’ve defined here CPixelFormatInfo, an alias for CPixelFormatInfoT<IWICPixelFormatInfo2>.

CComponentEnumT specializations and aliases

namespace wic
{
    using CAllComponentEnum = CComponentEnumT<CComponentInfo, WICAllComponents>;
    using CBitmapDecoderEnum = CComponentEnumT<CBitmapCodecInfo, WICDecoder>;
    using CBitmapEncoderEnum = CComponentEnumT<CBitmapCodecInfo, WICEncoder>;
    using CBitmapCodecEnum = CComponentEnumT<CBitmapCodecInfo, WICDecoder | WICEncoder>;
    using CPixelFormatEnum = CComponentEnumT<CPixelFormatInfo, WICPixelFormat>;
    using CMetadataReaderEnum = CComponentEnumT<CMetadataHandlerInfo, WICMetadataReader>;
    using CMetadataWriterEnum = CComponentEnumT<CMetadataHandlerInfo, WICMetadataWriter>;
    using CMetadataHandlerEnum = CComponentEnumT<CMetadataHandlerInfo, WICMetadataReader | WICMetadataWriter>;
    using CFormatConverterEnum = CComponentEnumT<CFormatConverterInfo, WICPixelFormatConverter>;
}

Finally, let’s see how to use these classes!

Enumerating WIC pixel formats

void CDemo_MFCDlg::EnumWICPixelFormats(WICComponentEnumerateOptions opt)
{
    wic::CPixelFormatEnum wicEnum;
    const auto& list = wicEnum.DoEnum(opt);
    for (const auto& spItem : list)
    {
        m_editReport.PrintComponentAttributes(spItem);
        m_editReport.PrintPixelFormatAttributes(spItem);
    }
}

Quite easy, isn’t it?

Get the pixel format info

template<class T> void CWICReportEdit::PrintPixelFormatAttributes(T& spItem)
{
    PrintLineV(_T("Bits per pixel:       %u"), spItem->GetBitsPerPixel());
    PrintLineV(_T("Channel count:        %u"), spItem->GetChannelCount());
    // ...
}
// Easy, as well.

You can find the complete source code in the attached demo solution.

Demo solution

Download: Enumerate WIC Components - Demo Solution.zip (967 downloads)

Enumerate WIC Components - Demo
Enumerate WIC Components – Demo

The demo solution contains an MFC and a console project that use the classes described above in order to enumerate WIC components and get info about each one. The MFC one allows choosing the component type(s) as well as enum options (include the disabled components or enum only Windows built-in components). The console application is simpler and I wrote it just to demonstrate that my little library of wrapper classes can be used both in MFC and non-MFC applications.

Notes

  • I hope, this article can be useful.
  • If you have any observation or remarks, please do not hesitate to post a reply!

Resources and related articles

Leave a Comment