Question

Après plusieurs jours de traquer les erreurs GDI + bizarre, j'ai trébuché sur ce petit bijou sur MSDN :

  

Les classes au sein de l'espace de noms System.Drawing ne sont pas pris en charge pour une utilisation dans un service Windows ou ASP.NET. Toute tentative d'utiliser ces classes à partir de l'un de ces types d'applications peuvent produire des problèmes inattendus, tels que la performance de service diminué et la gestion des exceptions temps.

Je ne sais pas si « service ASP.NET » signifie « application web » dans ce contexte, mais « la performance de service diminuée » semble bien couvrir l'assortiment aléatoire de « Une erreur générique est produite dans GDI + » et « Out of erreurs de mémoire » que mon application est de lancer - intermittent, erreurs non reproductibles lecture et l'écriture des images JPEG - dans de nombreux cas - ont été effectivement. créés par System.Drawing.Imaging en premier lieu

Donc - si GDI + ne peut pas lire et écrire des fichiers JPEG de manière fiable dans une application Web, que dois-je utiliser à la place

Je veux que les utilisateurs soient en mesure de télécharger des images (JPEG nécessaire, d'autres formats nice-to-have), rééchantillonner les fiable , et afficher des messages d'erreur utiles en cas de problème. Des idées? Sont les espaces de noms System.Media de WPF à considérer?

EDIT: Oui, je sais fonctionne GDI + "la plupart du temps". Ce n'est pas assez bon, parce que quand elle échoue, elle le fait d'une manière qui est impossible d'isoler ou de se remettre de grâce. Je ne suis pas intéressé par des exemples de code GDI + qui fonctionne pour vous: Je cherche bibliothèques alternatives à utiliser pour le traitement d'images

.
Était-ce utile?

La solution

Il y a un excellent article de blog y compris le code C # sur l'utilisation du ImageMagick bibliothèque graphique par Interop sur TopTen Software Blog . Cet article traite de poste spécifiquement en cours d'exécution ASP.net sur linux sous mono; cependant, le code C # doit être parfaitement copier-coller-mesure, la seule chose que vous aurez besoin de changer est l'Interop attribue si vous exécutez sous Windows référençant un binaire de fenêtre (DLL).

  

ImageMagick® est une suite logicielle pour créer, éditer, composer ou convertir   images bitmap. Il peut lire et écrire des images dans une variété de formats   (Plus de 100), y compris DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD,   PNG, PostScript, SVG et TIFF. Utilisez ImageMagick pour redimensionner, retourner,   miroir, faire pivoter, déformer, de cisaillement et de transformer les images, régler l'image   couleurs, appliquer des effets spéciaux, ou afficher du texte, des lignes, des polygones,   ellipses et des courbes de Bézier.

Il y a aussi un ImageMagick projet de développement .Net sur CodePlex qui enveloppe tout pour vous. Mais il ne montre pas le développement actif depuis 2009, de sorte qu'il peut être en retard par rapport à la version de la bibliothèque ImageMagick actuelle. Pour une petite routine de redimensionnement trivial, je serais probablement coller avec l'Interop. Vous avez juste besoin de regarder votre mise en œuvre avec soin pour votre propre fuite de mémoire ou de ressources non libérées (la bibliothèque elle-même est bien testé et approuvées par la communauté).

La bibliothèque est gratuit et open source. La licence Apache 2 semble être compatible avec les fins personnelles et commerciales. Voir ImageMagick Licence .

La bibliothèque est une plateforme totalement croix et met en œuvre de nombreuses manipulations d'images puissantes et des routines de transformation qui ne figurent pas dans GDI + (ou non mis en œuvre en mono) et a une bonne réputation comme une alternative pour le traitement d'image ASP.net.

Mise à jour: On dirait qu'il est une version mise à jour d'une enveloppe .NET ici: http: //magick.codeplex. com /

Autres conseils

Oui, utiliser les classes System.Windows.Media WPF. Pleinement réussi, ils ne souffrent pas les mêmes problèmes que les choses GDI.

Voici un extrait de du code MVC-je utiliser pour rendre les gradients, pour vous donner une idée comment obtenir d'un Visual WPF à un 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;
        }
    }
}

Vous pouvez trouver un très bon article d'un employé de Microsoft ici: Redimensionnement images à partir du serveur en utilisant WPF / WIC au lieu de GDI + qui propose d'utiliser WPF au lieu de GDI +. Il est plus sur thumbnailing mais il est globalement les mêmes problèmes.

Quoi qu'il en soit, à la fin, il dit ceci:

  

J'ai contacté l'équipe WPF d'avoir le dernier mot que ce soit   prise en charge. Malheureusement, ce n'est pas, et la documentation est en cours   mis à jour en conséquence. Je présente mes excuses au sujet de toute confusion que cela peut avoir   causé. Nous cherchons des moyens de rendre cette histoire plus acceptable   l'avenir.

WPF est également non pris en charge dans les applications web et est encore, je crois: -S

ImageSharp

ImageSharp est une bibliothèque graphique 2D multi-plateforme open-source. Il est écrit en C # sur le dessus de la nouvelle norme .NET, sans dépendance à une API spécifique à l'OS.

Il est actuellement encore en pré-libération MyGet (vous devrez ajouter la source de package dans les options VS ou un fichier NuGet.config), mais nous utilisons déjà avec des résultats très positifs.

La plupart des questions que j'ai lu sur les ressources concernent pas éliminées correctement.

Je l'ai utilisé des variantes de ce temps de code et encore sans problème des applications Web:

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

}

Vous pouvez consulter http://gd-sharp.sourceforge.net/ qui est un wrapper pour la bibliothèque GD. Je ne l'ai pas testé, mais il semble prometteur.

J'ai eu un bon comportement de la bibliothèque du Caire (http://www.cairographics.org) dans un environnement de serveur web ASP.Net. Je me suis déplacé en fait caire de WPF en raison du modèle d'utilisation de la mauvaise mémoire de WPF pour des trucs sur le web.

WPF tend effectivement à exécuter votre processus de travail de mémoire. Aucun des objets WPF mettre en œuvre IDisposable, et beaucoup d'entre eux la mémoire de référence non géré qui est seulement libéré par un finaliseur. Une utilisation intensive de WPF (surtout si votre serveur est nettement CPU imposé) finira par vous manquer de mémoire car la file d'attente de finaliseur est saturé. Quand je profilage mon application, par exemple, la file d'attente de finalisation avait plus de 50.000 objets sur elle, beaucoup d'entre eux à la mémoire contenant une référence non géré. Le Caire a comporté beaucoup mieux pour moi, et son mode d'utilisation de la mémoire a été beaucoup plus prévisible que WPF de.

Si vous êtes intéressé à utiliser le caire, saisir les libs de site Web de GTK +. Ils ont un système x86 ainsi qu'un ensemble de binaires x64.

Le seul inconvénient est que le caire ne peut pas en lecture / écriture JPG en mode natif; Cependant, vous pouvez facilement adapter les affaires de WPF pour la lecture / écriture JPG et faire le ré-échantillonnage / mise à l'échelle / dessin / quel que soit d'autre à l'aide du Caire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top