Вопрос

После нескольких дней отслеживания причудливых ошибок GDI+ я наткнулся на этот маленький драгоценный камень на MSDN:

Классы в системе. Распространение имен не поддерживается для использования в службе Windows или ASP.NET. Попытка использовать эти классы из одного из этих типов приложений может создать неожиданные проблемы, такие как снижение производительности обслуживания и исключения времени выполнения.

Я не знаю, означает ли «сервис ASP.NET» «веб -приложение» в этом контексте, но «снижение производительности обслуживания», безусловно, охватывает случайный ассортимент «общей ошибки в ошибках GDI+» и «Out Out» То, что мое приложение бросает - прерывистые, непроизводимые ошибки, чтение и написание изображений JPEG, которые, во многих случаях, были фактически созданы System.Drawing.Imaging в первую очередь.

Итак - если GDI+ не смогут надежно читать и записывать файлы JPEG в веб -приложении, что я должен использовать вместо этого?

Я хочу, чтобы пользователи имели возможность загружать изображения (JPEG, необходимые, другие форматы хороши), повторно их надежно, и отображать полезные сообщения об ошибках, если что -то пойдет не так. Любые идеи? Стоит ли рассмотреть пространство имен System.Media от WPF?

РЕДАКТИРОВАТЬ: Да, я знаю, что GDI+ работает «большую часть времени». Этого недостаточно, потому что, когда он терпит неудачу, это делает это так, как невозможно изолировать или изящно изящно. Меня не интересует примеры кода GDI+, который работает для вас: я ищу Альтернативные библиотеки для использования для обработки изображений.

Это было полезно?

Решение

Есть отличный пост в блоге, включая C# код об использовании ImageMagick Graphics Library через Блог программного обеспечения Tapten. Анкет Этот пост занимается конкретно с запуском ASP.NET на Linux под Mono; Тем не менее, код C# должен быть идеально копировать вставку, единственное, что вам нужно изменить,-это атрибуты взаимодействия, если вы работаете под Windows, ссылающимися на бинарный окно (DLL).

ImageMagick® - это программный набор для создания, редактирования, составления или преобразования изображений растрового изображения. Он может читать и писать изображения в различных форматах (более 100), включая DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, PNG, PostScript, SVG и TIFF. Используйте ImageMagick для изменения размера, переворачивания, зеркала, вращения, искажения, сдвига и преобразования изображений, регулировки цвета изображений, применять различные спецэффекты или нарисовать текст, линии, полигоны, эллипсы и кривые Bézier.

Есть также ImageMagick .net Development Project На Codeplex, который заполняет все для вас. Но он не показывает активную разработку с 2009 года, поэтому он может отставать за текущей версией библиотеки ImageMagick. Для небольшой тривиальной процедуры изменения размера я бы, вероятно, придерживался взаимодействия. Вам просто нужно внимательно следить за вашей реализацией для вашей собственной утечки памяти или неизданных ресурсов (сама библиотека хорошо протестирована и проверяется сообществом).

Библиотека бесплатна и с открытым исходным кодом. Лицензия Apache 2, по -видимому, совместима как с личными, так и с коммерческими целями. Видеть Страница лицензии ImageMagick.

Библиотека является полностью поперечной платформой и реализует много мощных процедур обработки изображений и преобразования, которые не найдены в GDI+ (или не реализованы в моно) и имеют хорошую репутацию в качестве альтернативы для обработки изображений ASP.NET.

Обновление: Похоже, здесь есть обновленная версия обертки .NET: http://magick.codeplex.com/

Другие советы

Да, используйте WPF System.Windows.Media классы Будучи полностью управлять, они не страдают от тех же проблем, что и вещи GDI.

Вот выдержка из некоторого кода MVC, который я использую для рендеринга, чтобы дать вам представление о том, как получить от WPF Visual к PNG:

using System;
using System.IO;
using System.Web.Mvc;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace MyMvcWebApp.Controllers
{
    public class ImageGenController : Controller
    {
        // GET: ~/ImageGen/Gradient?color1=red&color2=pink
        [OutputCache(CacheProfile = "Image")]
        public ActionResult Gradient(Color color1, Color color2, int width = 1, int height = 30, double angle = 90)
        {
            var visual = new DrawingVisual();
            using (DrawingContext dc = visual.RenderOpen())
            {
                Brush brush = new LinearGradientBrush(color1, color2, angle);
                dc.DrawRectangle(brush, null, new Rect(0, 0, width, height));
            }

            return new FileStreamResult(renderPng(visual, width, height), "image/png");
        }

        static Stream renderPng(Visual visual, int width, int height)
        {
            var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
            rtb.Render(visual);

            var frame = BitmapFrame.Create(rtb);
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(frame);

            var stream = new MemoryStream();
            encoder.Save(stream);
            stream.Position = 0;

            return stream;
        }
    }
}

Вы можете найти очень хорошую статью от сотрудника Microsoft здесь: Изменение размера изображений с сервера с использованием WPF/WIC вместо GDI+ Это предлагает использовать WPF вместо GDI+. Это больше о эфире, но это в целом те же проблемы.

В любом случае, в конце концов указывается:

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

Итак, WPF также не поддерживается в веб-приложениях, и я все еще верю: -s

ImageSharp

ImageSharp это кроссплатформенная 2D-графическая библиотека с открытым исходным кодом. Он написан в C# в дополнение к новому стандарту .NET, без зависимости от любого API, специфичного для ОС.

В настоящее время он все еще находится в предварительном обращении на Myget (вам придется добавить источник пакета в параметрах VS или файл nuget.config), но мы уже используем его с некоторыми очень положительными результатами.

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

Я использовал варианты этого кода снова и снова без проблем из веб -приложений:

public void GenerateThumbNail(HttpPostedFile fil, string sPhysicalPath, 
                              string sOrgFileName,string sThumbNailFileName,
                              System.Drawing.Imaging.ImageFormat oFormat, int rez)
{

    try
    {

        System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);

        decimal pixtosubstract = 0;
        decimal percentage;

        //default
        Size ThumbNailSizeToUse = new Size();
        if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
        {
            if (oImg.Size.Width > oImg.Size.Height)
            {
                percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
                pixtosubstract = percentage * oImg.Size.Height;
                ThumbNailSizeToUse.Width = ThumbNailSize.Width;
                ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
            }
            else
            {
                percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
                pixtosubstract = percentage * (decimal)oImg.Size.Width;
                ThumbNailSizeToUse.Height = ThumbNailSize.Height;
                ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
            }

        }
        else
        {
            ThumbNailSizeToUse.Width = oImg.Size.Width;
            ThumbNailSizeToUse.Height = oImg.Size.Height;
        }

        Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
        bmp.SetResolution(rez, rez);
        System.Drawing.Image oThumbNail = bmp;

        bmp = null;

        Graphics oGraphic = Graphics.FromImage(oThumbNail);

        oGraphic.CompositingQuality = CompositingQuality.HighQuality;

        oGraphic.SmoothingMode = SmoothingMode.HighQuality;

        oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;

        Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);

        oGraphic.DrawImage(oImg, oRectangle);

        oThumbNail.Save(sPhysicalPath  + sThumbNailFileName, oFormat);

        oImg.Dispose();

    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
    }

}

Вы можете взглянуть на http://gd-sharp.sourceforge.net/ которая является оберткой для библиотеки GD. Я не проверял это, но это кажется многообещающим.

У меня было хорошее поведение из Каирской библиотеки (http://www.cairographics.org) в среде Webserver ASP.NET. Я на самом деле переехал в Каир из WPF из-за плохой модели использования памяти WPF для веб-вещей.

WPF на самом деле имеет тенденцию запускать ваш рабочий процесс из памяти. Ни один из объектов WPF не реализует IDisposable, и многие из них ссылаются на неуправляемую память, которая освобождена только через финализатор. Сильное использование WPF (особенно, если ваш сервер значительно имеет налогообложение на налогообложении) в конечном итоге выпустит вас из памяти, потому что ваша очередь финализатора насыщена. Например, когда я профилировал свое приложение, в очереди на завершении было более 50 000 объектов, многие из которых имеют ссылки на неуправляемую память. Каир вел себя намного лучше для меня, и его модель использования памяти была гораздо более предсказуемо, чем WPF.

Если вы заинтересованы в использовании Каира, возьмите Libs с веб -сайта GTK+. У них есть x86, а также набор двоичных файлов x64.

Единственным недостатком является то, что Каир не может читать/писать JPG Nongy; Тем не менее, вы можете легко адаптировать материалы WPF для чтения/написания JPG и выполнить повторную выборку/масштабирование/рисунок/что -либо еще, используя Каир.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top