Как перехватить это исключение загрузки растрового изображения WPF? - PullRequest
4 голосов
/ 28 апреля 2010

Я разрабатываю приложение, которое загружает растровые изображения из Интернета, используя .NET 3.5 sp1 и C #.

Код загрузки выглядит так:

        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!");
        }

и код для загрузки на bi_DownloadCompleted:

    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.");
        }
    }

Время от времени появляется изображение, которое ломает читателя. Я полагаю, этого следовало ожидать. Однако вместо того, чтобы быть пойманным одним из этих блоков try / catch, исключение, по-видимому, выбрасывается за пределы того, где я могу его обработать. Я мог бы справиться с этим, используя глобальные исключения WPF, такие как этот вопрос . Однако это серьезно испортит поток управления моей программой, и я хотел бы избежать этого, если это вообще возможно.

Я должен выполнить двойное назначение источника, потому что кажется, что многим изображениям не хватает параметров ширины / высоты в тех местах, где их ожидает загрузчик растрового изображения Microsoft. Таким образом, первое назначение, по-видимому, вызывает загрузку, а второе назначение позволяет получить размеры dpi / изображения должным образом.

Что я могу сделать, чтобы поймать и обработать это исключение?

Если вы хотите повторить, попробуйте загрузить это изображение как uri:

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

Само исключение:

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

Внутреннее исключение:

An invalid character was found in text context.

Трассировка стека:

   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()

Ответы [ 2 ]

13 голосов
/ 31 июля 2010

Это исключение является результатом неправильной информации о цветовом профиле, содержащейся на изображении. Если вас не волнует эта информация (или вы хотите снова выполнить анализ после исключения), используйте флаг BitmapCreateOptions.IgnoreColorProfile.

Пример:

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();

Если вам нужна дополнительная информация, проверьте сообщение Скотта Хансельмана . (Мы все общались по этому вопросу сегодня по электронной почте.)

0 голосов
/ 11 июня 2010

Это похоже на работу:

try
{
    frame = BitmapFrame.Create(new Uri("http://i.pbase.com/o2/26/519326/1/123513540.Yub8hciV.Longford12.jpg"));
}
catch
{
    return;
}

BitmapFrame имеет событие DecodeFailed, но я не могу его перехватить, потому что BitmapFrame заморожен после его создания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...