James R
James R

Reputation: 166

Get supported image formats from BitmapImage

How can I get a list of image formats supported by System.Windows.Media.Imaging.BitmapImage?

I am writing a simple image processing tool in C# WPF. The BitmapImage class is one of the more useful bitmap classes as it is able to decode from a wide variety of formats.

In particular, it is able to open NEF (Nikon's RAW format) on my computer. It is likely that BitmapImage can open a wide variety of RAW formats from other manufacturers, a function I am keen to make use of.

As I don't know every format that can be opened as a BitmapImage, I am currently using a try/catch to try and construct a BitmapImage from every file that the user tries to open. This is clearly not the most efficient way.

As far as I know, BitmapImage inherits from BitmapSource, which decides which files it can open by looking on the user's system for available codecs. It's likely therefore that codec availability varies between machines, meaning a list of supported formats can't be hard-coded into the program. I need a way to check what these supported formats on a user's machine are.

I found this method in System.Drawing. This returns a list of supported codecs with a list of supported file extensions, and an equivalent for Systems.Windows.Media.Imaging would be exactly what I need.

Upvotes: 5

Views: 2566

Answers (1)

NineBerry
NineBerry

Reputation: 28499

If you do not want to deal with WIC directly as shown in the source code linked to in the answer mentioned by Clemens, you can read a list of additional codecs (those that are not supported by WIC by default) with their names and supported file extensions directly from the registry.

See the following sample code.

/// <summary>
/// Sample code: Show the additional registered decoders 
/// </summary>
private void Button_Click(object sender, RoutedEventArgs e)
{
    var additionalDecoders = GetAdditionalDecoders();

    foreach(var additionalDecoder in additionalDecoders)
    {
        MessageBox.Show(additionalDecoder.FriendlyName + ":" + additionalDecoder.FileExtensions);
    }
}

/// <summary>
/// GUID of the component registration group for WIC decoders
/// </summary>
private const string WICDecoderCategory = "{7ED96837-96F0-4812-B211-F13C24117ED3}";

/// <summary>
/// Represents information about a WIC decoder
/// </summary>
public struct DecoderInfo
{
    public string FriendlyName;
    public string FileExtensions;
}

/// <summary>
/// Gets a list of additionally registered WIC decoders
/// </summary>
/// <returns></returns>
public static IEnumerable<DecoderInfo> GetAdditionalDecoders()
{
    var result = new List<DecoderInfo>();

    string baseKeyPath;
    
    // If we are a 32 bit process running on a 64 bit operating system, 
    // we find our config in Wow6432Node subkey
    if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
    {
        baseKeyPath = "Wow6432Node\\CLSID";
    }
    else
    {
        baseKeyPath = "CLSID";
    }
    
    RegistryKey baseKey = Registry.ClassesRoot.OpenSubKey(baseKeyPath, false);
    if (baseKey != null)
    {
        var categoryKey = baseKey.OpenSubKey(WICDecoderCategory + "\\instance", false);
        if (categoryKey != null)
        {
            // Read the guids of the registered decoders
            var codecGuids = categoryKey.GetSubKeyNames();

            foreach (var codecGuid in codecGuids)
            {
                // Read the properties of the single registered decoder
                var codecKey = baseKey.OpenSubKey(codecGuid);
                if (codecKey != null)
                {
                    DecoderInfo decoderInfo = new DecoderInfo();
                    decoderInfo.FriendlyName = Convert.ToString(codecKey.GetValue("FriendlyName", ""));
                    decoderInfo.FileExtensions = Convert.ToString(codecKey.GetValue("FileExtensions", ""));
                    result.Add(decoderInfo);
                }
            }
        }
    }
    
    return result;
}

Note that this can return different results depending on whether you are running in a 32 bit or 64 bit process. For example, on my Windows 10 machine I have a Photoshop decoder by Microsoft installed to read psd files. However, only a 32 bit version is installed.

So, when I try to load a Photoshop psd file via BitmapImage, this succeeds when running a 32 bit application but not when running a 64 bit application. The code above reading the installed decoders from the registry reflects this correctly.

Upvotes: 10

Related Questions