System.Drawing dans ASP .NET ASP.NET Core

De nombreuses questions sont consacrées à l’utilisation de la bibliothèque System.Drawing dans les services ASP.NET. La réponse la plus courante est que Microsoft ne recommande pas l’utilisation de System.Drawing dans les services ASP.NET.

Dans cet article, vous apprendrez des détails sur l’utilisation de l’interface de la bibliothèque System.Drawing dans les services ASP.NET avec Aspose.Drawing for .NET. Les sections suivantes structurent toutes les informations pertinentes :

Pourquoi Aspose.Drawing ?

Microsoft ne recommande pas l’utilisation de sa bibliothèque System.Drawing dans les services ASP.NET. La page d’accueil de System.Drawing documentation indique :

Les classes au sein de l’espace de noms System.Drawing ne sont pas prises en charge pour une utilisation dans un service Windows ou ASP.NET. Toute tentative d’utilisation de ces classes à partir de l’un de ces types d’application peut entraîner des exceptions d’exécution et une diminution des performances du service.

Il existe deux problèmes de base qui obligent Microsoft à écrire au-dessus de la prudence. Le premier problème est l’utilisation de la bibliothèque native GDI + et, par conséquent, l’utilisation des poignées GDI. Alors que la deuxième préoccupation concerne les problèmes de concurrence. Par exemple, un verrou à l’échelle du processus se produit lors de toute opération DrawImage(). Par conséquent, vous ne pouvez pas créer de services ASP.NET rapides et évolutifs à l’aide de la bibliothèque System.Drawing de Microsoft.

Installation de l’API Aspose.Drawing for .NET

Vous pouvez facilement télécharger le fichier DLL à partir de la section Téléchargements ou le configurer via le gestionnaire de packages NuGet avec la commande suivante :

PM> Install-Package Aspose.Drawing

Aspose.Drawing for .NET - Introduction

Nous comprenons que System.Drawing est très populaire parmi les développeurs en raison de ses fonctionnalités de manipulation d’images. C’est pourquoi nous avons créé une API similaire et compatible sans aucun problème de compatibilité. Pour votre commodité et votre adaptabilité, l’API contient les mêmes noms de classes, de fonctions, d’énumérations et d’interfaces. Vous pouvez simplement changer la référence du projet de System.Drawing à Aspose.Drawing et recompiler le programme.

De plus, Aspose.Drawing est une bibliothèque gérée disponible pour NET Framework 2.0 et NET Core 2.0. Contrairement à System.Drawing, il ne dépend d’aucune plate-forme telle que Linux, Azure, etc.

Utilisation d’Aspose.Drawing dans les services ASP.NET

L’implémentation d’Aspose.Drawing ne dépend pas de GDI ou GDI+. Il n’utilise pas de handles GDI et utilise rarement des verrous à l’échelle du processus.

Démonstration d’utilisation d’Aspose.Drawing dans les services ASP.NET

Créons une application simple qui explique les avantages de l’utilisation de la bibliothèque Aspose.Drawing :

Imaginez que vous décidiez de créer un service ou une application Web entièrement nouveau. L’application générera un ensemble de vignettes avec des filtres attachés à partir de l’image de l’utilisateur.

Vous pouvez commencer par introduire quelques nouvelles entités :

///<summary>
/// Types de filtres disponibles.
///</summary>
public enum FilterType
{
    ///<summary>
    /// Filtre pour la génération d'image saturée de couleur rouge.
    ///</summary>
    Red,

    ///<summary>
    /// Filtre pour la génération d'image saturée de couleur verte.
    ///</summary>
    Green,

    ///<summary>
    /// Filtre pour la génération d'image saturée de couleur bleue.
    ///</summary>
    Blue,

    ///<summary>
    /// Filtre pour la génération d'une image en niveaux de gris.
    ///</summary>
    Grayscale,

    ///<summary>
    /// Filtre pour la génération d'une image négative.
    ///</summary>
    Negative,

    ///<summary>
    /// Filtre pour la génération d'une image sépia.
    ///</summary>
    Sepia,
}
///<summary>
/// Le résultat de la génération de vignettes filtrées.
///</summary>
public class FilterThumbnailResult
{
    ///<summary>
    /// Initialise une nouvelle instance de la classe FilterThumbnailResult.
    ///</summary>
    ///<param name="filterType"> Le type de filtre appliqué à la vignette.</param>
    ///<param name="pngData"> Les données d'image au format PNG.</param>
    ///<param name="width"> La largeur de la vignette.</param>
    ///<param name="height"> La hauteur de la vignette.</param>
    public FilterThumbnailResult(FilterType filterType, byte[] pngData, int width, int height)
    {
        this.FilterType = filterType;
        this.PngData = pngData;
        this.Width = width;
        this.Height = height;
    }

    ///<summary>
    /// Obtient le type de filtre appliqué à la vignette.
    ///</summary>
    public FilterType FilterType { get; }

    ///<summary>
    /// Obtient les données d'image au format PNG.
    ///</summary>
    public byte[] PngData { get; }

    ///<summary>
    /// Obtient la largeur de la vignette.
    ///</summary>
    public int Width { get; }

    ///<summary>
    /// Obtient la hauteur de la vignette.
    ///</summary>
    public int Height { get; }
}

Vous pouvez maintenant définir l’interface pour la génération des vignettes avec les filtres attachés :

using System.Collections.Generic;

///<summary>
/// L'interface de génération d'images miniatures.
///</summary>
public interface IThumbnailGenerator
{
    ///<summary>
    /// Génère un ensemble de vignettes pour tous les filtres disponibles.
    ///</summary>
    ///<param name="sourceImage"> Octets de l'image source.</param>
    ///<param name="width"> Largeur demandée des images d'aperçu.</param>
    ///<param name="height"> Hauteur demandée des images d'aperçu.</param>
    ///<returns> Un ensemble de vignettes.</returns>
    IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height);
}

Passant à l’implémentation, supposons l’implémentation de l’interface IThumbnailGenerator à l’aide de la bibliothèque System.Drawing. Cela ressemblera à l’extrait de code suivant :

///<summary>
/// Implémentation de l'interface IThumbnailGenerator à l'aide de System.Drawing.
///</summary>
public class ThumbnailGenerator
    : IThumbnailGenerator
{
    ///<summary>
    /// Un ensemble de processeurs de vignettes.
    ///</summary>
    private static readonly FilterThumbnailProcessor[] Processors = new FilterThumbnailProcessor[] 
    {
        ApplyRedFilter,
        ApplyGreenFilter,
        ApplyBlueFilter,
        ApplyGrayFilter,
        ApplyNegativeFilter,
        ApplySepiaFilter,
    };

    ///<summary>
    /// Délégué pour le traitement des vignettes.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private delegate FilterThumbnailResult FilterThumbnailProcessor(Bitmap thumbnail);

    ///<summary>
    /// Génère un ensemble de vignettes pour tous les filtres disponibles.
    ///</summary>
    ///<param name="sourceImage"> Octets de l'image source.</param>
    ///<param name="width"> Largeur demandée des images d'aperçu.</param>
    ///<param name="height"> Hauteur demandée des images d'aperçu.</param>
    ///<returns> Un ensemble de vignettes.</returns>
    public IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height)
    {
        using (MemoryStream ms = new MemoryStream(sourceImage))
        using (Bitmap bitmap = new Bitmap(ms))
        {
            foreach (var processor in Processors)
            {
                using (Bitmap previewBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
                using (Graphics graphics = Graphics.FromImage(previewBitmap))
                {
                    graphics.DrawImage(bitmap, 0, 0, width, height);

                    yield return processor(previewBitmap);
                }
            }
        }
    }

    ///<summary>
    /// Applique un filtre rouge à la vignette.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private static FilterThumbnailResult ApplyRedFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applique un filtre vert à la vignette.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private static FilterThumbnailResult ApplyGreenFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applique un filtre bleu à la vignette.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private static FilterThumbnailResult ApplyBlueFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applique un filtre gris à la vignette.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private static FilterThumbnailResult ApplyGrayFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applique un filtre négatif à la vignette.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private static FilterThumbnailResult ApplyNegativeFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applique un filtre sépia à la vignette.
    ///</summary>
    ///<param name="thumbnail"> Vignette de l'image d'origine.</param>
    ///<returns> Résultat de la génération de vignettes filtrées.</returns>
    private static FilterThumbnailResult ApplySepiaFilter(Bitmap thumbnail)
    {
    ...
    }
}

Le code fonctionnera bien mais il a un inconvénient - il génère toutes les vignettes de manière séquentielle. La bibliothèque System.Drawing est basée sur une bibliothèque GDI + assez ancienne qui a été conçue comme une bibliothèque à thread unique afin qu’elle puisse gaspiller des ressources lorsqu’il y a plusieurs cœurs de processeur.

L’utilisation d’Aspose.Drawing peut aider à améliorer considérablement les performances car il n’a aucune limitation liée au thread unique. Veuillez essayer de modifier une seule fonction :

///<summary>
/// Génère un ensemble de vignettes pour tous les filtres disponibles.
///</summary>
///<param name="sourceImage"> Octets de l'image source.</param>
///<param name="width"> Largeur demandée des images d'aperçu.</param>
///<param name="height"> Hauteur demandée des images d'aperçu.</param>
///<returns> Un ensemble de vignettes.</returns>
public IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height)
{
    using (MemoryStream ms = new MemoryStream(sourceImage))
    using (Bitmap bitmap = new Bitmap(ms))
    {
        ConcurrentBag<FilterThumbnailResult> collection = new ConcurrentBag<FilterThumbnailResult>();

        Parallel.ForEach(Processors, (processor) =>
        {
            using (Bitmap previewBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
            using (Graphics graphics = Graphics.FromImage(previewBitmap))
            {
                graphics.DrawImage(bitmap, 0, 0, width, height);
                collection.Add(processor(previewBitmap));
            }
        });

        return collection;
    }
}

Ce code peut désormais utiliser plusieurs cœurs de processeur sans aucune modification significative du code source d’origine. Le remplacement de System.Drawing par Aspose.Drawing accélère les performances de vos applications et services.

Télécharger le code source

Vous pouvez télécharger le code source lié à cet exemple pour votre référence.

Licence d’évaluation API gratuite

Vous pouvez demander une Licence temporaire gratuite pour tester l’API dans toute sa capacité.

Conclusion

En conclusion, vous avez appris avec l’exemple qu’il est simple d’utiliser la bibliothèque Aspose.Drawing dans vos services ASP.NET et ASP.NET Core. De plus, Aspose.Drawing n’a pas de problèmes ou de dépendances externes qui existent dans System.Drawing. De plus, vous pouvez explorer l’API en détail en parcourant la Documentation. N’hésitez pas à nous contacter à tout moment via Forum d’assistance gratuit pour toutes vos questions !

Voir également