System.Drawing in ASP .NET ASP.NET Core

Ci sono molte domande dedicate all’utilizzo della libreria System.Drawing nei servizi ASP.NET. La risposta più comune è che Microsoft sconsiglia l’utilizzo di System.Drawing nei servizi ASP.NET.

In questo articolo imparerai i dettagli sull’utilizzo dell’interfaccia della libreria System.Drawing nei servizi ASP.NET con Aspose.Drawing for .NET. Le seguenti sezioni strutturano tutte le informazioni rilevanti:

Perché Aspose.Drawing?

Microsoft sconsiglia l’utilizzo della sua libreria System.Drawing nei servizi ASP.NET. La home page di System.Drawing documentazione recita:

Le classi all’interno dello spazio dei nomi System.Drawing non sono supportate per l’uso all’interno di un servizio Windows o ASP.NET. Il tentativo di utilizzare queste classi da uno di questi tipi di applicazione può causare eccezioni di runtime e prestazioni del servizio ridotte.

Esistono due problemi di base che obbligano Microsoft a scrivere sopra cautela. Il primo problema è l’utilizzo della libreria nativa GDI+ e, di conseguenza, l’utilizzo degli handle GDI. Mentre la seconda preoccupazione riguarda i problemi di concorrenza. Ad esempio, si verifica un blocco a livello di processo durante qualsiasi operazione DrawImage(). Pertanto, non è possibile creare servizi ASP.NET veloci e scalabili utilizzando la libreria System.Drawing di Microsoft.

Installazione di Aspose.Drawing per .NET API

Puoi facilmente scaricare il file DLL dalla sezione Download o configurarlo tramite NuGet Package Manager con il seguente comando:

PM> Install-Package Aspose.Drawing

Aspose.Drawing per .NET API - Introduzione

Comprendiamo che System.Drawing è molto popolare tra gli sviluppatori grazie alle sue funzionalità di manipolazione delle immagini. Ecco perché abbiamo creato un’API simile e compatibile senza problemi di compatibilità. Per comodità e adattabilità, l’API contiene gli stessi nomi di classi, funzioni, enumerazioni e interfacce. Puoi semplicemente modificare il riferimento del progetto da System.Drawing a Aspose.Drawing e ricompilare il programma.

Inoltre, Aspose.Drawing è una libreria gestita disponibile per NET Framework 2.0 e NET Core 2.0. A differenza di System.Drawing, non ha dipendenze da nessuna piattaforma come Linux, Azure, ecc.

Utilizzo di Aspose.Drawing nei servizi ASP.NET

L’implementazione di Aspose.Drawing non dipende da GDI o GDI+. Non usa gli handle GDI e usa raramente i blocchi a livello di processo.

Dimostrazione per l’utilizzo di Aspose.Drawing nei servizi ASP.NET

Creiamo una semplice applicazione che spiega i vantaggi dell’utilizzo della libreria Aspose.Drawing:

Immagina di decidere di creare un servizio Web o un’applicazione completamente nuovi. L’applicazione genererà una serie di miniature con filtri allegati dall’immagine dell’utente.

Puoi iniziare introducendo alcune nuove entità:

///<summary>
/// Tipi disponibili dei filtri.
///</summary>
public enum FilterType
{
    ///<summary>
    /// Filtro per la generazione di immagini saturate di colore rosso.
    ///</summary>
    Red,

    ///<summary>
    /// Filtro per la generazione di immagini saturate di colore verde.
    ///</summary>
    Green,

    ///<summary>
    /// Filtro per la generazione di immagini saturate di colore blu.
    ///</summary>
    Blue,

    ///<summary>
    /// Filtro per la generazione di un'immagine in scala di grigi.
    ///</summary>
    Grayscale,

    ///<summary>
    /// Filtro per la generazione di un'immagine negativa.
    ///</summary>
    Negative,

    ///<summary>
    /// Filtro per la generazione di un'immagine color seppia.
    ///</summary>
    Sepia,
}
///<summary>
/// Il risultato della generazione di miniature filtrate.
///</summary>
public class FilterThumbnailResult
{
    ///<summary>
    /// Inizializza una nuova istanza della classe FilterThumbnailResult.
    ///</summary>
    ///<param name="filterType"> Il tipo di filtro applicato alla miniatura.</param>
    ///<param name="pngData"> I dati dell'immagine in formato PNG.</param>
    ///<param name="width"> La larghezza della miniatura.</param>
    ///<param name="height"> L'altezza della miniatura.</param>
    public FilterThumbnailResult(FilterType filterType, byte[] pngData, int width, int height)
    {
        this.FilterType = filterType;
        this.PngData = pngData;
        this.Width = width;
        this.Height = height;
    }

    ///<summary>
    /// Ottiene il tipo di filtro applicato alla miniatura.
    ///</summary>
    public FilterType FilterType { get; }

    ///<summary>
    /// Ottiene i dati dell'immagine in formato PNG.
    ///</summary>
    public byte[] PngData { get; }

    ///<summary>
    /// Ottiene la larghezza della miniatura.
    ///</summary>
    public int Width { get; }

    ///<summary>
    /// Ottiene l'altezza della miniatura.
    ///</summary>
    public int Height { get; }
}

Ora puoi definire l’interfaccia per la generazione delle miniature con i filtri allegati:

using System.Collections.Generic;

///<summary>
/// L'interfaccia per la generazione di immagini in miniatura.
///</summary>
public interface IThumbnailGenerator
{
    ///<summary>
    /// Genera una serie di miniature per tutti i filtri disponibili.
    ///</summary>
    ///<param name="sourceImage"> Byte dell'immagine di origine.</param>
    ///<param name="width"> Larghezza richiesta delle immagini di anteprima.</param>
    ///<param name="height"> Altezza richiesta delle immagini di anteprima.</param>
    ///<returns> Una serie di miniature.</returns>
    IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height);
}

Passando all’implementazione, si supponga di implementare l’interfaccia IThumbnailGenerator utilizzando la libreria System.Drawing. Sembrerà il prossimo frammento di codice:

///<summary>
/// Implementazione dell'interfaccia IThumbnailGenerator tramite System.Drawing.
///</summary>
public class ThumbnailGenerator
    : IThumbnailGenerator
{
    ///<summary>
    /// Un set di processori di miniature.
    ///</summary>
    private static readonly FilterThumbnailProcessor[] Processors = new FilterThumbnailProcessor[] 
    {
        ApplyRedFilter,
        ApplyGreenFilter,
        ApplyBlueFilter,
        ApplyGrayFilter,
        ApplyNegativeFilter,
        ApplySepiaFilter,
    };

    ///<summary>
    /// Delegato per l'elaborazione delle miniature.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private delegate FilterThumbnailResult FilterThumbnailProcessor(Bitmap thumbnail);

    ///<summary>
    /// Genera una serie di miniature per tutti i filtri disponibili.
    ///</summary>
    ///<param name="sourceImage"> Byte dell'immagine di origine.</param>
    ///<param name="width"> Larghezza richiesta delle immagini di anteprima.</param>
    ///<param name="height"> Altezza richiesta delle immagini di anteprima.</param>
    ///<returns> Una serie di miniature.</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>
    /// Applica un filtro rosso alla miniatura.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private static FilterThumbnailResult ApplyRedFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applica un filtro verde alla miniatura.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private static FilterThumbnailResult ApplyGreenFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applica un filtro blu alla miniatura.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private static FilterThumbnailResult ApplyBlueFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applica un filtro grigio alla miniatura.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private static FilterThumbnailResult ApplyGrayFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applica un filtro negativo alla miniatura.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private static FilterThumbnailResult ApplyNegativeFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Applica un filtro seppia alla miniatura.
    ///</summary>
    ///<param name="thumbnail"> Miniatura dell'immagine originale.</param>
    ///<returns> Risultato della generazione di miniature filtrate.</returns>
    private static FilterThumbnailResult ApplySepiaFilter(Bitmap thumbnail)
    {
    ...
    }
}

Il codice funzionerà bene ma ha uno svantaggio: genera tutte le miniature in sequenza. La libreria System.Drawing si basa su una libreria GDI+ piuttosto vecchia che è stata progettata come libreria a thread singolo in modo che possa sprecare risorse quando sono presenti più core della CPU.

L’uso di Aspose.Drawing può aiutare a migliorare significativamente le prestazioni perché non ha limitazioni relative al thread singolo. Prova a cambiare solo una funzione:

///<summary>
/// Genera una serie di miniature per tutti i filtri disponibili.
///</summary>
///<param name="sourceImage"> Byte dell'immagine di origine.</param>
///<param name="width"> Larghezza richiesta delle immagini di anteprima.</param>
///<param name="height"> Altezza richiesta delle immagini di anteprima.</param>
///<returns> Una serie di miniature.</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;
    }
}

Questo codice ora può utilizzare più core della CPU senza modifiche significative nel codice sorgente originale. La sostituzione di System.Drawing con Aspose.Drawing accelera le prestazioni delle applicazioni e dei servizi.

Scarica il codice sorgente

Puoi scaricare il Codice sorgente relativo a questo esempio come riferimento.

Licenza di valutazione API gratuita

Puoi richiedere una Licenza temporanea gratuita per testare l’API nella sua piena capacità.

Conclusione

In conclusione, hai imparato con l’esempio quanto sia semplice usare la libreria Aspose.Drawing nei tuoi servizi ASP.NET e ASP.NET Core. Inoltre, Aspose.Drawing non ha problemi o dipendenze esterne che esistono in System.Drawing. Inoltre, puoi esplorare l’API in dettaglio consultando la Documentazione. Non esitare a contattarci in qualsiasi momento tramite il Forum di supporto gratuito per qualsiasi tua domanda!

Guarda anche