Alternatywy dla systemu.Rysunek do użytku z ASP.NET?

Po kilku dniach śledzenia dziwacznych błędów GDI+ natknąłem się na ten mały klejnot na MSDN :

Klasy w systemie.Przestrzeń nazw rysunków nie jest obsługiwana do użytku w systemie Windows lub ASP.NET obsługa. Próba użycia tych klas z jednego z tych typów aplikacji może powodować nieoczekiwane problemy, takie jak zmniejszona wydajność usługi i wyjątki w czasie wykonywania.

Nie wiem czy "ASP.NET serwis" oznacza " www aplikacja "w tym kontekście, ale" zmniejszona wydajność usługi "z pewnością wydaje się obejmować losowy asortyment" ogólny błąd wystąpił w GDI+ "i" z pamięci " błędy, które moja aplikacja rzuca-przerywane, nie odtwarzalne błędy czytania i pisania obrazów JPEG, które - w wielu przypadkach-zostały rzeczywiście utworzone przez System.Rysunek.Obrazowanie w pierwszej kolejności.

Tak więc - jeśli GDI+ nie może niezawodnie odczytywać i zapisywać plików JPEG w aplikacji internetowej, co powinienem używać zamiast tego?

Chcę, aby użytkownicy mogli przesyłać obrazy (wymagany JPEG, inne formaty ładne-to-have), resamplować je niezawodnie i wyświetlać przydatne komunikaty o błędach, jeśli coś pójdzie nie tak. Jakieś pomysły? Są systemem.Przestrzenie nazw mediów z WPF warte rozważenia?

Dzięki,

Dylan

EDIT: tak, Wiem, że GDI + działa "najczęściej". To nie jest wystarczająco dobre, ponieważ gdy zawodzi, robi to w sposób niemożliwy do wyizolowania lub odzyskania z wdzięku. I nie interesują mnie przykłady kodu GDI+, który działa dla Ciebie: Szukam alternatywnych bibliotek do wykorzystania do przetwarzania obrazów.

Author: rick schott, 2009-10-07

7 answers

Istnieje doskonały wpis na blogu zawierający kod C# o korzystaniu z biblioteki graficznej ImageMagickprzez Interop na TopTen Software Blog. Ten post dotyczy w szczególności biegania ASP.net w Linuksie pod mono; jednak kod C# powinien być doskonale copy-paste-able, jedyną rzeczą, którą musisz zmienić, to atrybuty Interop, jeśli pracujesz pod windows odwołując się do binarnego okna (DLL).

ImageMagick® to pakiet oprogramowania do tworzenia, edycji, skomponuj lub przekonwertuj obrazy bitmapowe. Może odczytywać i zapisywać obrazy w różnych formatach (ponad 100) w tym DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, PNG, Postscript, SVG i TIFF. Użyj ImageMagick, aby zmienić rozmiar, Odwróć, lustrzane, obracanie, zniekształcanie, ścinanie i przekształcanie obrazów, dostosowywanie obrazu kolorów, stosować różne efekty specjalne lub rysować tekst, linie, wielokąty, elipsy i krzywe Béziera.

Istnieje również ImageMagick. Net development project na codeplex, który wszystko dla Ciebie. Ale nie wykazuje aktywnego rozwoju od 2009 roku, więc może pozostawać w tyle za obecną wersją biblioteki ImageMagick. Dla małej trywialnej procedury zmiany rozmiaru, prawdopodobnie zostałbym przy interop. Wystarczy uważnie obserwować implementację pod kątem wycieku pamięci lub niepublikowanych zasobów (sama Biblioteka jest dobrze przetestowana i sprawdzona przez społeczność).

Biblioteka jest wolna i otwarta. Licencja Apache 2 wydaje się być kompatybilna zarówno z cele osobiste i handlowe. Zobacz Strona Licencji ImageMagick .

Biblioteka jest całkowicie wieloplatformowa i implementuje wiele zaawansowanych procedur obsługi obrazów i transformacji, które nie występują w GDI+ (lub nie są zaimplementowane w mono) i ma dobrą reputację jako alternatywa dla ASP.net przetwarzanie obrazu.

Update: wygląda na to, że istnieje zaktualizowana wersja wrappera. NET tutaj: http://magick.codeplex.com/

 9
Author: BenSwayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-12 17:21:13

Tak, użyj klas WPF System.Windows.Media. Będąc w pełni zarządzanym, nie cierpią na te same problemy, co sprawy z GDI.

Oto fragment kodu MVC, którego używam do renderowania gradientów, aby dać ci pomysł, jak przejść z WPF Visual do 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;
        }
    }
}
 11
Author: Duncan Smart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-12 11:44:03

Możesz znaleźć bardzo dobry artykuł pracownika Microsoft tutaj: Zmiana rozmiaru obrazów z serwera za pomocą WPF / WIC zamiast GDI+, który proponuje użycie WPF zamiast GDI+. Chodzi bardziej o miniaturki, ale ogólnie chodzi o te same problemy.

W każdym razie na końcu jest napisane tak:

Skontaktowałem się z zespołem WPF, aby uzyskać ostateczne słowo, czy jest to obsługiwane. Niestety nie, a dokumentacja jest zaktualizowano odpowiednio. Przepraszam za wszelkie zamieszanie to może mieć spowodowane. Szukamy sposobów, aby ta historia była bardziej akceptowalna w przyszłość.

Więc WPF jest również nieobsługiwany w aplikacjach internetowych i nadal jest moim zdaniem: - S

 8
Author: Simon Mourier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 16:38:18

ImageSharp

ImageSharp to wieloplatformowa biblioteka grafiki 2D o otwartym kodzie źródłowym. Jest napisany w C# na szczycie nowego standardu. Net, bez zależności od jakiegokolwiek API specyficznego dla systemu operacyjnego.

Jest obecnie jeszcze w pre-release na MyGet (musisz dodać źródło pakietu w opcjach VS lub NuGet.plik konfiguracyjny), ale już go używamy z bardzo pozytywnymi wynikami.

 4
Author: Mathieu Renda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-05 08:35:18

Większość problemów, o których czytałem, dotyczy niewłaściwego zarządzania zasobami.

Używałem wariantów tego kodu raz po raz bez problemów z aplikacjami webowymi:

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);
    }

}
 1
Author: rick schott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-09 22:34:15

You may have a look at http://gd-sharp.sourceforge.net/ który jest opakowaniem dla biblioteki GD. Nie testowałem go, ale wygląda obiecująco.

 0
Author: alfred barthand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 17:16:42

Miałem dobre zachowanie z biblioteki w Kairze (http://www.cairographics.org) w ASP.Net środowisko serwera www. Właściwie przeniosłem się do Kairu z WPF ze względu na kiepski model wykorzystania pamięci WPF dla rzeczy internetowych.

WPF faktycznie ma tendencję do uruchamiania procesu roboczego z pamięci. Żaden z obiektów WPF nie implementuje IDisposable, a wiele z nich odwołuje się do niezarządzanej pamięci, która jest uwalniana tylko przez finalizator. Intensywne korzystanie z WPF (zwłaszcza jeśli twój serwer jest znacznie opodatkowany CPU) w końcu uruchomi się tracisz pamięć, bo Kolejka finalizera się nasyca. Na przykład, gdy profilowałem moją aplikację, Kolejka finalizacji miała ponad 50 000 obiektów, z których wiele zawierało odniesienia do niezarządzanej pamięci. Cairo zachował się dla mnie znacznie lepiej, a jego wzór użycia pamięci był znacznie bardziej przewidywalny niż WPF.]}

Jeśli jesteś zainteresowany użyciem cairo, Pobierz libs ze strony GTK+. Mają x86, jak również x64 zestaw binariów.

Jedynym minusem jest cairo nie potrafi odczytać/zapisać JPG natywnie; jednak możesz łatwo dostosować rzeczy WPF do odczytu / zapisu JPG i wykonać resampling/skalowanie/rysowanie / cokolwiek innego za pomocą Cairo.

 0
Author: FMM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-21 21:13:01