System.Drawing v ASP .NET ASP.NET Core

Existuje mnoho otázek věnovaných použití knihovny System.Drawing ve službách ASP.NET. Nejčastější odpovědí je, že Microsoft nedoporučuje použití System.Drawing ve službách ASP.NET.

V tomto článku se dozvíte podrobnosti o používání rozhraní knihovny System.Drawing ve službách ASP.NET s Aspose.Drawing for .NET. Následující sekce strukturují všechny relevantní informace:

Proč Aspose.Drawing?

Společnost Microsoft nedoporučuje použití své knihovny System.Drawing ve službách ASP.NET. Domovská stránka System.Drawing dokumentace zní:

Třídy v oboru názvů System.Drawing nejsou podporovány pro použití ve službě Windows nebo ASP.NET. Pokus o použití těchto tříd v rámci jednoho z těchto typů aplikací může mít za následek výjimky za běhu a snížený výkon služby.

Existují dva základní problémy, které nutí Microsoft psát nad opatrností. Prvním problémem je použití GDI+ nativní knihovny a v důsledku toho použití GDI handles. Zatímco druhým problémem jsou problémy se souběžností. Například během jakékoli operace DrawImage() dojde k uzamčení celého procesu. Proto nemůžete vytvářet rychlé a škálovatelné služby ASP.NET pomocí knihovny System.Drawing od společnosti Microsoft.

Instalace Aspose.Drawing for .NET API

Soubor DLL si můžete snadno stáhnout ze sekce Downloads nebo jej nakonfigurovat pomocí správce balíčků NuGet pomocí následujícího příkazu:

PM> Install-Package Aspose.Drawing

Aspose.Drawing for .NET API - Úvod

Chápeme, že System.Drawing je mezi vývojáři velmi oblíbený kvůli jeho funkcím pro manipulaci s obrázky. Proto jsme vytvořili podobné a kompatibilní API bez problémů s kompatibilitou. Pro vaše pohodlí a přizpůsobivost obsahuje API stejné názvy tříd, funkcí, výčtů a rozhraní. Můžete jednoduše změnit odkaz na projekt z System.Drawing na Aspose.Drawing a překompilovat program.

Aspose.Drawing je navíc spravovaná knihovna dostupná pro NET Framework 2.0 a NET Core 2.0. Na rozdíl od System.Drawing nemá žádné závislosti na žádné platformě, jako je Linux, Azure atd.

Použití Aspose.Drawing ve službách ASP.NET

Implementace Aspose.Drawing nezávisí na GDI nebo GDI+. Nepoužívá úchyty GDI a zřídka používá zámky celého procesu.

Ukázka použití Aspose.Drawing ve službách ASP.NET

Pojďme vytvořit jednoduchou aplikaci, která vysvětluje výhody používání knihovny Aspose.Drawing:

Představte si, že se rozhodnete vytvořit zcela novou webovou službu nebo aplikaci. Aplikace vygeneruje sadu miniatur s připojenými filtry z obrázku uživatele.

Můžete začít představením několika nových entit:

///<summary>
/// Dostupné typy filtrů.
///</summary>
public enum FilterType
{
    ///<summary>
    /// Filtr pro generování obrazu nasyceného červenou barvou.
    ///</summary>
    Red,

    ///<summary>
    /// Filtr pro generování obrazu nasyceného zelenou barvou.
    ///</summary>
    Green,

    ///<summary>
    /// Filtr pro generování obrazu nasyceného modrou barvou.
    ///</summary>
    Blue,

    ///<summary>
    /// Filtr pro generování obrázku ve stupních šedi.
    ///</summary>
    Grayscale,

    ///<summary>
    /// Filtr pro generování negativního obrazu.
    ///</summary>
    Negative,

    ///<summary>
    /// Filtr pro generování sépiového obrazu.
    ///</summary>
    Sepia,
}
///<summary>
/// Výsledek generování filtrovaných náhledů.
///</summary>
public class FilterThumbnailResult
{
    ///<summary>
    /// Inicializuje novou instanci třídy FilterThumbnailResult.
    ///</summary>
    ///<param name="filterType"> Typ filtru použitého na miniaturu.</param>
    ///<param name="pngData"> Obrazová data ve formátu PNG.</param>
    ///<param name="width"> Šířka miniatury.</param>
    ///<param name="height"> Výška miniatury.</param>
    public FilterThumbnailResult(FilterType filterType, byte[] pngData, int width, int height)
    {
        this.FilterType = filterType;
        this.PngData = pngData;
        this.Width = width;
        this.Height = height;
    }

    ///<summary>
    /// Získá typ filtru použitého na miniaturu.
    ///</summary>
    public FilterType FilterType { get; }

    ///<summary>
    /// Získá obrazová data ve formátu PNG.
    ///</summary>
    public byte[] PngData { get; }

    ///<summary>
    /// Získá šířku miniatury.
    ///</summary>
    public int Width { get; }

    ///<summary>
    /// Získá výšku miniatury.
    ///</summary>
    public int Height { get; }
}

Nyní můžete definovat rozhraní pro generování náhledů s připojenými filtry:

using System.Collections.Generic;

///<summary>
/// Rozhraní pro vytváření náhledů obrázků.
///</summary>
public interface IThumbnailGenerator
{
    ///<summary>
    /// Vygeneruje sadu miniatur pro všechny dostupné filtry.
    ///</summary>
    ///<param name="sourceImage"> Bajty zdrojového obrázku.</param>
    ///<param name="width"> Požadovaná šířka náhledových obrázků.</param>
    ///<param name="height"> Požadovaná výška náhledových obrázků.</param>
    ///<returns> Sada miniatur.</returns>
    IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height);
}

Když přejdeme k implementaci, předpokládejme implementaci rozhraní IThumbnailGenerator pomocí knihovny System.Drawing. Bude to vypadat jako další fragment kódu:

///<summary>
/// Implementace rozhraní IThumbnailGenerator pomocí System.Drawing.
///</summary>
public class ThumbnailGenerator
    : IThumbnailGenerator
{
    ///<summary>
    /// Sada procesorů náhledů.
    ///</summary>
    private static readonly FilterThumbnailProcessor[] Processors = new FilterThumbnailProcessor[] 
    {
        ApplyRedFilter,
        ApplyGreenFilter,
        ApplyBlueFilter,
        ApplyGrayFilter,
        ApplyNegativeFilter,
        ApplySepiaFilter,
    };

    ///<summary>
    /// Delegát pro zpracování náhledů.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private delegate FilterThumbnailResult FilterThumbnailProcessor(Bitmap thumbnail);

    ///<summary>
    /// Vygeneruje sadu miniatur pro všechny dostupné filtry.
    ///</summary>
    ///<param name="sourceImage"> Bajty zdrojového obrázku.</param>
    ///<param name="width"> Požadovaná šířka náhledových obrázků.</param>
    ///<param name="height"> Požadovaná výška náhledových obrázků.</param>
    ///<returns> Sada miniatur.</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>
    /// Na miniaturu použije červený filtr.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private static FilterThumbnailResult ApplyRedFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Použije na miniaturu zelený filtr.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private static FilterThumbnailResult ApplyGreenFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Na miniaturu použije modrý filtr.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private static FilterThumbnailResult ApplyBlueFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Použije šedý filtr na miniaturu.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private static FilterThumbnailResult ApplyGrayFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Použije negativní filtr na miniaturu.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private static FilterThumbnailResult ApplyNegativeFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// Použije sépiový filtr na miniaturu.
    ///</summary>
    ///<param name="thumbnail"> Miniatura původního obrázku.</param>
    ///<returns> Výsledek generování filtrované miniatury.</returns>
    private static FilterThumbnailResult ApplySepiaFilter(Bitmap thumbnail)
    {
    ...
    }
}

Kód bude fungovat dobře, ale má jednu nevýhodu - generuje všechny náhledy postupně. Knihovna System.Drawing je založena na docela staré knihovně GDI+, která byla navržena jako knihovna s jedním vláknem, takže může plýtvat zdroji, když existuje více jader CPU.

Použití Aspose.Drawing může pomoci výrazně zlepšit výkon, protože nemá žádná omezení týkající se jednoho vlákna. Zkuste změnit pouze jednu funkci:

///<summary>
/// Vygeneruje sadu miniatur pro všechny dostupné filtry.
///</summary>
///<param name="sourceImage"> Bajty zdrojového obrázku.</param>
///<param name="width"> Požadovaná šířka náhledových obrázků.</param>
///<param name="height"> Požadovaná výška náhledových obrázků.</param>
///<returns> Sada miniatur.</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;
    }
}

Tento kód nyní může používat více jader CPU bez jakýchkoliv podstatných změn v původním zdrojovém kódu. Nahrazení System.Drawing za Aspose.Drawing urychlí výkon vašich aplikací a služeb.

Stáhněte si zdrojový kód

Pro vaši referenci si můžete stáhnout Zdrojový kód související s tímto příkladem.

Bezplatná zkušební licence API

Můžete požádat o bezplatnou dočasnou licenci a otestovat API v jeho plné kapacitě.

Závěr

Na závěr jste se na příkladu naučili, jak jednoduché je použití knihovny Aspose.Drawing ve vašich službách ASP.NET a ASP.NET Core. Navíc Aspose.Drawing nemá žádné problémy nebo externí závislosti, které existují v System.Drawing. Kromě toho můžete rozhraní API podrobně prozkoumat pomocí Dokumentace. V případě jakýchkoliv dotazů nás neváhejte kdykoli kontaktovat prostřednictvím Free Support Forum!

Viz také