none
В GDI+ возникла ошибка общего вида RRS feed

  • Вопрос

  • Посмотрел предыдущие обсуждения темы «В GDI+ возникла ошибка общего вида». Не нашёл решения своего вопроса. Заранее благодарю за уделённое внимание.

    Работаю в WINDOWS 7, Microsoft Visual Studio 2008. Столкнулся с тем, что сохранение изображения в Stream работает не для всех картинок. Вот фрагмент кода:

    public Image Изображение;

    public void Записать( Stream поток ) {

       Изображение.Save( поток, System.Drawing.Imaging.ImageFormat.Png );

       }

    При выполнении сохранения некоторых картинок и возникает ошибка. Появление ошибки не зависит от размера картинки и от выбранного формата. Сами картинки я открывал и сохранял в другом формате в Paint. Не помогает. Зато, помогает клавиша PrtScr. Тем же Paint вырезаю картинку и сохраняю, и всё работает. Но, с большой картинкой (больше экрана) этот номер не проходит.

    Помогите, кто знает как обойти эту неприятность. Спасибо!

    6 июня 2018 г. 14:55

Все ответы

  • Термин "ошибка" сам по себе ни о чем не говорит. Вы, как программист, должны понимать, что любой объект исключения имеет дополнительную информацию. Где она? Или Вы предлагаете нам угадать ее?

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    6 июня 2018 г. 20:54
  • Сообщение (Message) в точности соответствует заголовку темы.

    Source: System.Drawing.

    ErrorCode: -2147467259.

    Это вся существенная информация из свойств прерывания.


  • Я нашёл способ обойти описанную неприятность. Но этот способ порождает другой вопрос. По порядку. Как оказалось, возникнет ли прерывание во время записи в поток (Stream) изображения (Image), зависит от того, каким образом я его прочитал из файла!!!

    PictureBox Картинка;

    Если оно прочитано так:

    Картинка.Load( имя_файла );

    То при записи в поток может возникнуть прерывание.

    Если оно было прочитано так:

    Картинка.Image = new Bitmap( имя_файла );

    То запись в поток происходит без сбоев.

    Чудеса!

    Могу предоставить одну из тестовых картинок, на которой и возникает обсуждаемое прерывание.

    7 июня 2018 г. 12:15
  • Могу предоставить одну из тестовых картинок, на которой и возникает обсуждаемое прерывание.

    Давайте.

    Вообще, согласно документации, метод Load изменяет свойство PictureBox.ImageLocation, а не Image. Может быть поэтому и возникает исключение при доступе к Image? Посмотрите в отладчике, как изменяются свойства PictureBox-а после вызова Load.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    7 июня 2018 г. 12:58
  • Тогда вопрос: почему запись в поток всё же работает для некоторых картинок? А с точки зрения прочих операций разницы не вижу. Более того, загрузив картинку, не важно как, в дальнейшем я работаю с её клоном. И операцию записи в поток тоже выполняет клон («изображение» в примере).

    Небольшая картинка, скачал где-то.

    https://box.poi.dvo.ru/owncloud/index.php/s/Dju2idoAyS1yKy5

    7 июня 2018 г. 13:34
  • Все работает. И с Вашей картинкой тоже. Вот код обработчиков кнопок "Открыть" и "Сохранить" (_box - это объект типа PictureBox):

    private void _load_Click(object sender, EventArgs e) { OpenFileDialog fd = new OpenFileDialog { Filter = "Изображения|*.jpg;*.png;*.bmp|Все файлы|*.*" }; if (DialogResult.OK == fd.ShowDialog(this)) { _box.Load(fd.FileName); } } private void _save_Click(object sender, EventArgs e) { if (_box.Image != null) { SaveFileDialog fd = new SaveFileDialog { DefaultExt = "png", Filter = "PNG files|*.png" }; if (DialogResult.OK == fd.ShowDialog(this)) { using (Stream s = new FileStream(fd.FileName, FileMode.Create, FileAccess.Write)) { try { _box.Image.Save(s, System.Drawing.Imaging.ImageFormat.Png); } catch (Exception ex) { // обработка

    }

    } } } }



    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    7 июня 2018 г. 14:00
  • Мой пример. Файл создаётся, возникает прерывание, в результате файл пустой. И ОС и VS2008 лицензионные, обновлены.

    namespace WindowsFormsApplication1 {

       
       public partial class Form1 : Form {
          
          public Form1() {
             InitializeComponent();
             }

          private void прочитать_Click( object sender, EventArgs e ) {
             OpenFileDialog диалог = new OpenFileDialog();
             if ( диалог.ShowDialog() == DialogResult.OK )
                Картинка.Load( диалог.FileName );
             }

          private void записать_Click( object sender, EventArgs e ) {
             SaveFileDialog диалог = new SaveFileDialog();
             if ( диалог.ShowDialog() == DialogResult.OK )
                Картинка.Image.Save( диалог.FileName, System.Drawing.Imaging.ImageFormat.Png );
             }

          }

       }

    7 июня 2018 г. 14:18
  • VS 2008! Следовательно версия .NET 2.0-3.5, так? Ошибка возникает именно на этой версии платформы, проверил. Почему, не понятно. В 4.0 и выше работает на ура.

    Тут, как говорится, "медицина бессильна" :) Переходите на новые версии студии.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    7 июня 2018 г. 14:41
  • Пусть будет ошибка среды. Есть какой-то вариант её обхода.

    Спасибо всем!

    7 июня 2018 г. 14:46
  • Конечно есть, я же Вам уже сказал. Здесь совершенно бесплатно получите самую свежую версию VS Community 2017.

    Если же хотите непременно остаться в 2008-ой, используйте другие способы загрузки изображений (собственно, Вы сами это уже выяснили). Видимо в .NET 2.0 имеется ошибка, которую теперь исправлять вряд-ли будут.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    7 июня 2018 г. 19:58
  • На самом деле, никаких чудес нет. PictureBox.Load создает на основе файла поток и использует для загрузки изображения метод Image.FromStream. В .NET 2.0 он при этом освобождает базовый поток сразу же после создания изображения, оставляя иозображение в частично некорректном состоянии (рисование работает, но сохранение или считывание свойств EXIF - нет). В .NET 4.0 он не освобождает поток и сохраняет его в поле класса (пользуясь IL Disassembler, можно увидеть в 4.0 у класса PictureBox поле localImageStreamReader, которого нет в предыдущих версиях), так что поток существует в течение всего времени жизни Image, и все нормально работает. 

    Способ обхода вы уже сами написали. В качестве альтернативы можно клонировать Bitmap перед сохранением:

    Bitmap bmp = new Bitmap(_box.Image);
    bmp.Save(s, System.Drawing.Imaging.ImageFormat.Png);

    • Предложено в качестве ответа Alexandr_Smirnoff 11 июня 2018 г. 14:14
  • VadimTagil, Ваша версия неубедительна.

    Во-первых, я изначально работаю с клоном. В первом своём сообщении я привёл фрагмент кода, касающегося сохранения картинки. А само изображение создаётся так: Изображение = (Image) картинка.Clone(), где «Image картинка» - параметр конструктора класса. Т. е. я абсолютно, казалось бы, не связан с методом получения картинки из файла.

    Во-вторых, из этого предположения следует, что каким-то чудесным образом в другом моём примере каждый раз перед сохранением «плохой» картинки успевает отработать сборщик мусора. А если картинка «хорошая», то он вообще не считает нужным работать.

  • Это не версия, это факт. Я отвечал не на первое сообщение, а на это:

    Если оно прочитано так:
    
    Картинка.Load( имя_файла );
    
    То при записи в поток может возникнуть прерывание.
    
    Если оно было прочитано так:
    
    Картинка.Image = new Bitmap( имя_файла );
    
    То запись в поток происходит без сбоев.
    В котором вы, очевидно, работаете не с клоном. В первом сообщении не видно, откуда берется Image, поэтому ничего определенного сказать нельзя. 

    "Во-вторых, из этого предположения следует, что каким-то чудесным образом в другом моём примере каждый раз перед сохранением «плохой» картинки успевает отработать сборщик мусора. А если картинка «хорошая», то он вообще не считает нужным работать."

    Это не так. Причем тут сборщик мусора? Stream явно освобождается вызовом Dispose. А что такое "хорошая картинка"? У меня на всех падает

    + Под клонированием я понимаю не "картинка.Clone() ", а "new Bitmap(картинка);". Первый вариант не решает проблему, картинка все равно остается некорректной.

    • Изменено VadimTagil 8 июня 2018 г. 9:12
  • Вот «хорошая» картинка. В 2.0 второй пример с этой картинкой отрабатывает всегда. А можно ещё провести «плохую» картинку через PrtScr.

    https://box.poi.dvo.ru/owncloud/index.php/s/ZjjfgcTp8ZAVABZ


  • То PNG, да, для них работает, видимо из-за отсутствия метаданных. JPEG ни одного не нашел "хорошего".
  • Возьмите "плохую" картинку. Откройте её в Paint и сохраните как PNG. Она останется "плохой".
  • У меня этого не наблюдается. После сохранения "плохой" JPEG в PNG она становится "хорошей". Иными словами, ошибка отчетливо проявляется на всех JPEG и ни на одном PNG.
    8 июня 2018 г. 10:02
  • Извиняюсь, как PNG картинка сохраняется, а как BMP нет. На то она и ошибка, чтобы проявляется "необъяснимым" образом.
    8 июня 2018 г. 10:10