MemoryStream в BitmapImage

Я немного затрудняюсь с конвертацией MemoryStream в BitmapImage, Есть много вопросов по SO Что касается подобных ситуаций, но, попробовав все на них, я не смог это исправить, поэтому я обращаюсь к вам. Обратите внимание, что я работаю с Magick.NET (ImageMagick.NET) и Tessnet2 - это то, что является частью этого кода.

я использую Bitmap класс для выполнения большей части работы в Magick.NET и Tessnet2. BitmapImage используется для отображения целей.

Сначала я загружаю PDF и извлекаю обрезанное растровое изображение с его первой страницы:

public Task PdfToBmp(string path)
{
    return Task.Run(() =>
    {
        using (var image = new MagickImage())
        {
            MagickNET.SetGhostscriptDirectory("./");

            var settings = new MagickReadSettings
            {
                Density = new MagickGeometry(300, 300),
                FrameCount = 1
            };

            image.Read(path, settings);
            image.Crop(new MagickGeometry(1850, 200, 600, 140));

            // ImageStream is a MemoryStream property.
            ImageStream = new MemoryStream();
            image.Write(ImageStream, MagickFormat.Bmp);
            ImageStream.Position = 0;
        }
    });
}

Именно тогда я сохраняю растровое изображение в MemoryStream, Однажды MemoryStream загружен, я перехожу к работе с ним. Я создаю экземпляр Bitmapтак что я могу использовать его для Tessnet2 связанная работа, а затем попытаться создать экземпляр BitmapImage,

public Task DoOcr()
{
    if (ImageStream == null)
    {
        return null;
    }

    TargetImage = new Bitmap(ImageStream);
    ImageStream.Position = 0;

    // ----------------------- Problem Area ----------------------- //
    DisplayImage = new BitmapImage();
    DisplayImage.BeginInit();
    DisplayImage.StreamSource = ImageStream;
    DisplayImage.CacheOption = BitmapCacheOption.OnLoad;
    DisplayImage.EndInit();

    //ImageStream.Close();
    // ------------------------------------------------------------ //

    return Task.Run(() =>
    {
        var ocr = new Tesseract();
        ocr.Init("tessdata", "eng", false);
        var results = ocr.DoOCR(TargetImage, Rectangle.Empty);
        Dispatcher.Invoke(() =>
        {
            Results = new ObservableCollection<Word>(results);
        });
    });
}

Вот где у меня проблема. Без этого DisplayImage Блок, программа работает нормально, и я просто не получаю отображаемое изображение. Я даже могу спасти Bitmap (TargetImage) в файл без проблем. Однако с DisplayImage блок, я получаю System.NullReferenceException:

System.NullReferenceException occurred
_HResult=-2147467261
_message=Object reference not set to an instance of an object.
HResult=-2147467261
IsTransient=false
Message=Object reference not set to an instance of an object.
Source=System
StackTrace:
     at System.Uri.CreateThisFromUri(Uri otherUri)
InnerException: 

Я не могу точно определить, где именно это происходит, потому что ImageStream объект выглядит "хорошо" при осмотре. Он содержит данные и находится в позиции 0. Если я попытаюсь закрыть его или сделать что-нибудь с ним, после назначения его в качестве StreamSource в DisplayImageЯ получаю null исключение на линии, которая пытается выполнить такое действие. Я даже попытался создать два разных потока, чтобы увидеть, в этом ли проблема; однако я получал точно такое же поведение. Отладка это своего рода боль, учитывая, что она не указывает ни на одну конкретную строку. Там, очевидно, проблема между этим MemoryStream а также BitmapImage, Возможно ли, что между ними есть какая-то проблема форматирования / преобразования, но не между MemoryStream а также Bitmap в этой конкретной ситуации?

Я пробовал файл маршрута, куда я сохраняю MagickImage в файл и загрузить его в BitmapImage через Uri и это сработало без нареканий; Тем не менее, я хотел бы иметь возможность выполнить это в памяти. Кстати, установив положение на 0 на MemoryStream, похоже, тоже не влияет Bitmap (загружается правильно) или BitmapImage (то же исключение).

Временное исправление, которое я сейчас использую, - сделать DisplayImage BitmapSource, скорее, чем BitmapImage:

DisplayImage = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    TargetImage.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
    BitmapSizeOptions.FromWidthAndHeight(TargetImage.Width, TargetImage.Height));

1 ответ

Магия.NET Write() Метод имеет некоторые ошибки, поэтому мы должны использовать ToBitmap(),

image.ToBitmap().Save(ImageStream, System.Drawing.Imaging.ImageFormat.Bmp);
Другие вопросы по тегам