Scott Hanselman blogged about an ArgumentException that can be thrown when loading an image with a corrupted colour profile. Coincidentally, we had been unifying the exception handling for BitmapImage in the Logos 4 code that same day. These are all the exceptions we have found WPF (or WIC) to throw when loading a BitmapImage (by setting its StreamSource or UriSource property) or BitmapFrame (by calling BitmapFrame.Create).
System.ArgumentException: The image has corrupted metadata header.
---> System.Runtime.InteropServices.COMException (0x88982F63): Exception from HRESULT: 0x88982F63
--- End of inner exception stack trace ---
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri,
Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean&
isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream&
unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapDecoder.Create(Stream bitmapStream,
BitmapCreateOptions createOptions, BitmapCacheOption cacheOption)
at System.Windows.Media.Imaging.BitmapFrame.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Stream bitmapStream,
BitmapCreateOptions createOptions, BitmapCacheOption cacheOption)
An ArgumentException generally seems to be caused by a corrupted image header or metadata. Scott Hanselman suggests using BitmapCreateOptions.IgnoreColorProfile to ignore potentially corrupt colour profile information; we don’t know of any workarounds for other types of corruption.
System.Runtime.InteropServices.COMException (0x80070000): An invalid character was found in text content.
at System.Windows.Media.ColorContextHelper.OpenColorProfile(IntPtr pProfile)
at System.Windows.Media.ColorContext.FromRawBytes(Byte[] data, Int32 dataLength)
at System.Windows.Media.ColorContext.FromStream(Stream stm, String filename)
at System.Windows.Media.ColorContext.Initialize(Uri profileUri, Boolean isStandardProfileUriNotFromUser)
at System.Windows.Media.ColorContext..ctor(PixelFormat pixelFormat)
at System.Windows.Media.Imaging.BitmapSource.CreateCachedBitmap(BitmapFrame frame,
BitmapSourceSafeMILHandle wicSource, BitmapCreateOptions createOptions, BitmapCacheOption
cacheOption, BitmapPalette palette)
at System.Windows.Media.Imaging.BitmapFrameDecode.FinalizeCreation()
at System.Windows.Media.Imaging.BitmapFrameDecode..ctor(Int32 frameNumber,
BitmapSourceSafeMILHandle sourceHandle, BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption, BitmapDecoder decoder)
at System.Windows.Media.Imaging.BitmapDecoder.SetupFrames(BitmapDecoder decoder,
ReadOnlyCollection`1 frames)
at System.Windows.Media.Imaging.BitmapDecoder.get_Frames()
at System.Windows.Media.Imaging.BitmapFrame.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Uri bitmapUri, RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Uri bitmapUri)
This particular exception was caused by an invalid system colour profile (set in the Advanced tab in Color Management in Control Panel). The user with this problem got an error message when he opened that dialog, but once he reset the device profile to the system default, this COMException stopped being thrown.
Note that the exception message (“An invalid character was found”) is completely unrelated to the actual problem; the error handling logic in ColorContextHelper has a bug.
System.IO.FileFormatException: The image format is unrecognized.
---> System.Runtime.InteropServices.COMException (0x88982F07): Exception from HRESULT: 0x88982F07
--- End of inner exception stack trace ---
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri,
Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable,
Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream,
SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
at System.Windows.Media.Imaging.BitmapImage.EndInit()
This can be caused by trying to load a file that isn’t an image. It can also be caused by loading an image from a Stream that is not at the origin. To work around this bug, see my previous blog post and the sample RebasedStream source code.
System.InvalidOperationException: Object must be initialized before operation can be performed.
---> System.Runtime.InteropServices.COMException (0x88982F0C): Exception from HRESULT: 0x88982F0C
--- End of inner exception stack trace ---
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream,
BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable,
Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream,
SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapFrame.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Uri bitmapUri,
BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Uri bitmapUri, BitmapCreateOptions createOptions,
BitmapCacheOption cacheOption)
The underlying error code represents WINCODEC_ERR_NOTINITIALIZED, but the exact cause is unclear. In our experience, this error is thrown on multiple systems when opening the same image file, so it appears to be image-related, not installation-related. As for NotSupportedException below, re-saving or re-encoding the image in a different format may help.
System.NotSupportedException: No imaging component suitable to complete this operation was found.
---> System.Runtime.InteropServices.COMException (0x88982F50): Exception from HRESULT: 0x88982F50
--- End of inner exception stack trace ---
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri,
Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable,
Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream,
SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapFrame.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Uri bitmapUri, RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapFrame.Create(Uri bitmapUri)
This error is typically due to bad metadata in the image. Curiously, we see this error the most often on Windows 7 (and a Vista system may load the same image just fine!); maybe this is due to WIC changes in Windows 7. For images we control, opening and saving them again in Paint.NET (or some other image editing program) overwrites the bad metadata and allows WPF/WIC to load the image.
An alternate suggestion (from SwimmingPool.net) is to recreate some WIC registry keys that may be missing.
If there is already memory pressure on the system (e.g., from other components in your application), and the image being loaded is very large, there may not be enough virtual address space for WIC/WPF to allocate the storage it needs to decode the bitmap. (And, sometimes, both native and managed buffers are required, which doubles memory usage!)
Setting BitmapImage.DecodePixelWidth or BitmapImage.DecodePixelHeight (to something smaller than the actual size) can dramatically reduce memory usage and allow the image to be loaded. This is especially useful if your application only needs to show a thumbnail in the UI; it’s also much more efficient than loading the original image and scaling it in XAML.
System.IO.IOException: Cannot locate resource 'images/icon.png'.
at MS.Internal.AppModel.ResourcePart.GetStreamCore(FileMode mode, FileAccess access)
at System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
at System.IO.Packaging.PackWebResponse.CachedResponse.GetResponseStream()
at System.IO.Packaging.PackWebResponse.GetResponseStream()
at System.IO.Packaging.PackWebResponse.get_ContentType()
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri,
Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable,
Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream,
SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri,
Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption,
RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
at System.Windows.Media.Imaging.BitmapImage.EndInit()
at System.Windows.Media.Imaging.BitmapImage..ctor(Uri uriSource, RequestCachePolicy uriCachePolicy)
at System.Windows.Media.Imaging.BitmapImage..ctor(Uri uriSource)
If you’re loading an image from a file: URI, any normal filesystem-related exceptions that come from opening local files could be thrown. Or, if you’re using pack: URIs, an exception will be thrown if there’s a typo in the URI or the named resource is missing.
###
The BitmapImage and BitmapFrame creation functions can throw a wide variety of exception types–the list above may very well not be exhaustive (and the documentation provides no information on what else may be thrown). Since these exceptions can depend on many environmental factors (client OS, file permissions, memory pressure, etc.), code that loads bitmaps needs to anticipate failure when loading any image and gracefully handle this situation.
Posted by Bradley Grainger on July 31, 2010