Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I catch this WPF Bitmap loading exception?

I'm developing an application that loads bitmaps off of the web using .NET 3.5 sp1 and C#.

The loading code looks like:

        try {
            CurrentImage = pics[unChosenPics[index]];
            bi = new BitmapImage(CurrentImage.URI);
            // BitmapImage.UriSource must be in a BeginInit/EndInit block.
            bi.DownloadCompleted += new EventHandler(bi_DownloadCompleted);
            AssessmentImage.Source = bi;
        }
        catch {
            System.Console.WriteLine("Something broke during the read!");
        }

and the code to load on bi_DownloadCompleted is:

    void bi_DownloadCompleted(object sender, EventArgs e) {
        try {
            double dpi = 96;
            int width = bi.PixelWidth;
            int height = bi.PixelHeight;

            int stride = width * 4; // 4 bytes per pixel
            byte[] pixelData = new byte[stride * height];
            bi.CopyPixels(pixelData, stride, 0);

            BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, stride);

            AssessmentImage.Source = bmpSource;
            Loading.Visibility = Visibility.Hidden;
            AssessmentImage.Visibility = Visibility.Visible;
        }
        catch {
            System.Console.WriteLine("Exception when viewing bitmap.");
        }
    }

Every so often, an image comes along that breaks the reader. I guess that's to be expected. However, rather than being caught by either of those try/catch blocks, the exception is apparently getting thrown outside of where I can handle it. I could handle it using global WPF exceptions, like this SO question. However, that will seriously mess up the control flow of my program, and I'd like to avoid that if at all possible.

I have to do the double source assignment because it appears that many images are lacking in width/height parameters in the places where the microsoft bitmap loader expects them to be. So, the first assignment appears to force the download, and the second assignment gets the dpi/image dimensions happen properly.

What can I do to catch and handle this exception?

If you'd like to replicate, try loading this image as the uri:

http://i.pbase.com/o2/26/519326/1/123513540.Yub8hciV.Longford12.jpg

The exception itself is:

System.ArgumentException in PresentationCore
Value does not fall within the expected range.

The inner exception is:

An invalid character was found in text context.

Stack trace:

   at MS.Internal.HRESULT.Check(Int32 hr)
   at System.Windows.Media.Imaging.BitmapFrameDecode.get_ColorContexts()
   at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
   at System.Windows.Media.Imaging.BitmapImage.OnDownloadCompleted(Object sender, EventArgs e)
   at System.Windows.Media.UniqueEventHelper.InvokeEvents(Object sender, EventArgs args)
   at System.Windows.Media.Imaging.LateBoundBitmapDecoder.DownloadCallback(Object arg)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.TranslateAndDispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Application.RunInternal(Window window)
   at LensComparison.App.Main() in C:\Users\Mark64\Documents\Visual Studio 2008\Projects\LensComparison\LensComparison\obj\Release\App.g.cs:line 48
   at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
like image 702
mmr Avatar asked Dec 13 '22 22:12

mmr


1 Answers

This exception is the result of 'broken' color profile information contained in the image. If you don't care about this information (or would like to try parsing again after exception), use the BitmapCreateOptions.IgnoreColorProfile flag.

Example:

BitmapImage i = new BitmapImage();
i.BeginInit();
i.CreateOptions |= BitmapCreateOptions.IgnoreColorProfile;
i.UriSource = new Uri(@"http://www.bing.com/fd/hpk2/KiteFestival_EN-US2111991920.jpg");
i.EndInit();

If you're looking for more information, check out Scott Hanselman's post. (We were all in communication about this issue today, via email.)

like image 120
Rafael Rivera Avatar answered Dec 15 '22 13:12

Rafael Rivera