Reputation: 166
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
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