|
25.02.2020, 17:59 | #1 |
Участник
|
Поговорим о сохранении картинки в файл.
Всем привет.
Хотел обсудить, кто как сохраняет картинки в файл из аксапты. Столкнулся со странным поведением. Дано: Ax4.0 В серверном коде из бд начитывается контейнер с картинкой. Нужно сохранить его в файл. Перегоняем картинку в System.IO.MemoryStream а его уже сохраняем на диск. Все хорошо работало. Но! В какой-то момент попалась нехорошая картинка, при сохранении которой на диск выскакивала ошибка "A generic error occurred in GDI+." Сохранение на диск через вызов X++: image = System.Drawing.Image::FromStream(memoryStream); image.Save(_fileName); Если переделать вызов на X++: byteArray = memoryStream.ToArray(); netFile = _fileName; CLRInterop::staticInvoke(@'System.IO.File', @'WriteAllBytes', netFile, byteArray); Jpg файлы, получаемые этими методами - разные. При общем размере порядка 286 кб отличаются на 32 байта. При открытии в браузере IE визуально никакой разницы не заметно. Вопрос: 1. Почему так происходит (ошибка GDI) ? 2. Почему размер и содержимое разное, хотя визуально разницы незаметно. Всегда ли так будет ? 3. Как правильно сохранять картинку в файл ? P.S. Зачем это было надо. В бд хранятся картинки, они начитываются, сохраняются на диск в виде файла, вставляются в Excel, который сохраняется как pdf отчет и отдается наружу через бизнес коннектор. P.P.S. Image класс клиентский, поэтому для нашего случая не подходит. P.P.P.S Несколько ссылок где была подсказка при разработке исправленной версии: 1. В этой ссылке https://habr.com/ru/post/482274/ идет критика System.Drawing и не рекомендуется его использовать при работе с изображениями в ASP.NET. Все из-за проблем с GDI и блокировками. 2. Здесь предложено решение: https://stackoverflow.com/questions/...-save-the-file Но нет уверенности, что результат эквивалентен и его везде можно применять. |
|
26.02.2020, 07:37 | #2 |
Участник
|
Не пробовали переделать вызов image.Save() на image.SaveImage()?
Или у вас падало именно на System.Drawing.Image::FromStream()?
__________________
// no comments Последний раз редактировалось dech; 26.02.2020 в 07:39. |
|
|
За это сообщение автора поблагодарили: Logger (3). |
26.02.2020, 07:57 | #3 |
Участник
|
Цитата:
Немного о JPG. Этот формат подразумевает, что вы сжимаете данные с потерей качества. Соответственно при сохранении файла, вы должны указывать степень сжатия/потери качества. Если не указываете, используется какое-то стандартное значение. Поэтому в большинстве случаев размер и содержимое - разное. Например, у вас картинка содержит 300 цветов, сжатие с потерей качества уменьшает это количество до 256 цветов. Разницу глаз может и не заметить, особенно если нет плавных переходов, однако сжатие цвета до 1 байта дает существенное уменьшение размера.
__________________
// no comments |
|
28.02.2020, 13:48 | #4 |
Участник
|
Падало именно на image.Save()
Проанализировал получше в чем отличаются файлы. Есть небольшое отличие в заголовке, и в середине jpg файла есть xml кусок, который в одном случае отформатирован (вставлены отступы и переносы кареток) а в другом случае - нет. С учетом этого включили новый способ сохранения везде в системе. Не думаю что это что-то поломает. Никаких преобразований формата картинок мы не делали. У нас просто хранится в базе в контейнере jpg или png файл. Поэтому я не предполагал, что при сохранении бинарных данных на диск винда пытается с ними что-то дополнительное делать и как-то задействовать GDI ресурсы. То что виндовая функция image.Save() как-то задействовала GDI и пыталась делать некие обработки при сохранении - оказалось сюрпризом. |
|
Теги |
error, gdi, system.drawing.image, баг |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|