GDI + исключение при сохранении растрового изображения в MemoryStream - PullRequest
3 голосов
/ 06 февраля 2009

У меня проблема в приложении Windows Forms с растровым изображением. Ошибка сохранения при сохранении в MemoryStream. Кажется, что проблема возникает с перерывами только на одном компьютере (пока), и это плохие новости на сайте клиента. Я не могу отладить на машине, но я получил трассировку стека, которая сузила проблему до одной строки кода.

Вот сокращенная версия моего кода:

byte[] ConvertPixelsToBytes()
{
    // imagine a picture class that creates a 24 bbp image, and has
    // a method to get an unmanaged pixel buffer.
    // imagine it also has methods for getting the width,
    // height, pitch 

    // I suppose this line could return a bad address, but 
    // I would have expected that the Bitmap constructor would have 
    // failed if it was
    System.IntPtr pPixels = picture.GetPixelData();

    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(
            picture.width(),
            picture.height(),
            picture.pitch(),
            System.Drawing.Imaging.PixelFormat.Format24bppRgb,
            pPixels );

    // This line doesn't actually free the memory, but it could be freed in a 
    // background thread
    // (2)
    picture.releasePixelData(pPixels);

    System.IO.MemoryStream memStream = new System.IO.MemoryStream();
    try
    {
        // I don't see how this line could fail, but it does
        // (3)
        bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Bmp);
        return memStream.ToArray();
    }
   catch(System.Runtime.InteropServices.ExternalException e)
   {
       // e.Message is the very helpful " A generic error occurred in GDI+."
   }
   finally
   {
       memStream.Dispose();
   }
   return new byte[0];
}

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

Мои мысли о возможных причинах неудачи

а. Конструктор растрового изображения не копирует пиксельные данные, но сохраняет ссылку на них, и сохранение завершается неудачно, поскольку память освобождается. Я не нахожу документы MSDN ясными по этому вопросу, но я предполагаю, что растровое изображение копирует пиксельные данные, а не предполагает, что они заблокированы.

б. Данные пикселей недопустимы и вызывают сбой метода Save. Я сомневаюсь в этом, поскольку мои пиксельные данные составляют 24 бита на пиксель, поэтому, насколько я знаю, они не должны быть недействительными.

с. Проблема с платформой .NET.

Буду признателен за любые мысли о других возможных причинах сбоев, чтобы я мог добавить дополнительные проверки и информацию о регистрации в свое приложение, чтобы я мог что-то отправить в поле.

Ответы [ 2 ]

5 голосов
/ 07 февраля 2009

Документы MSDN для этого конструктора растровых изображений не оставляют никаких сомнений:

Примечания Вызывающая сторона отвечает за выделение и освобождение блока памяти, указанного параметром scan0, однако память не должна освобождаться до тех пор, пока не будет выпущено соответствующее растровое изображение.

2 голосов
/ 06 февраля 2009

Вы пробовали двигаться

   picture.releasePixelData(pPixels);

до

   finally
   {
       memStream.Dispose();
       picture.releasePixelData(pPixels);
   }

это определенно звучит как проблема с многопоточностью (особенно если учесть, что releasePixelData может происходить в фоновом потоке). Проблемы с многопоточностью всегда возникают на одном компьютере, и всегда на клиентских компьютерах (возможно, из-за того, что у них всего 256 Мегабайт памяти или что-то нелепое, а сборщик мусора запускается на ранней стадии, или машина имеет четырехъядерное ядро и ваш компьютер разработчика - двухъядерный или что-то в этом роде.

...