ASP.NET ASP.NET Core 中的系統繪圖

有很多問題專門針對 ASP.NET 服務中 System.Drawing 庫的使用。最常見的答案是 Microsoft 不建議在 ASP.NET 服務中使用 System.Drawing。

在本文中,您將了解有關在 ASP.NET 服務中使用 System.Drawing 庫的接口與 Aspose.Drawing for .NET 的詳細信息。以下部分構成了所有相關信息:

為什麼選擇 Aspose.Drawing?

Microsoft 不建議在 ASP.NET 服務中使用其 System.Drawing 庫。 System.Drawing 文檔 的主頁顯示:

不支持在 Windows 或 ASP.NET 服務中使用 System.Drawing 命名空間中的類。嘗試從其中一種應用程序類型中使用這些類可能會導致運行時異常和服務性能下降。

有兩個基本問題迫使 Microsoft 必須小心謹慎。第一個問題是 GDI+ 本機庫的使用以及 GDI 句柄的使用。而第二個問題是並發問題。例如,在任何 DrawImage() 操作期間都會發生進程範圍的鎖定。因此,您無法使用 Microsoft 的 System.Drawing 庫創建快速且可擴展的 ASP.NET 服務。

安裝 Aspose.Drawing for .NET API

您可以從 下載 部分輕鬆下載 DLL 文件,或使用以下命令通過 NuGet 包管理器對其進行配置:

PM> Install-Package Aspose.Drawing

Aspose.Drawing for .NET API - 簡介

據我們了解,System.Drawing 因其圖像處理功能而在開發人員中非常受歡迎。這就是為什麼我們創建了一個沒有任何兼容性問題的相似且兼容的 API。為了您的方便和適應性,API 包含相同名稱的類、函數、枚舉和接口。您可以簡單地將項目引用從 System.Drawing 更改為 Aspose.Drawing 並重新編譯程序。

此外,Aspose.Drawing 是可用於 NET Framework 2.0 和 NET Core 2.0 的託管庫。與 System.Drawing 不同,它不依賴任何平台,如 Linux、Azure 等。

在 ASP.NET 服務中使用 Aspose.Drawing

Aspose.Drawing 實現不依賴於 GDI 或 GDI+。它不使用 GDI 句柄並且很少使用進程範圍的鎖。

在 ASP.NET 服務中使用 Aspose.Drawing 的演示

讓我們創建一個簡單的應用程序來解釋使用 Aspose.Drawing 庫的好處:

想像一下,您決定創建一個全新的 Web 服務或應用程序。該應用程序將從用戶圖像生成一組帶有過濾器的縮略圖。

您可以從引入幾個新實體開始:

///<summary>
/// 可用的過濾器類型。
///</summary>
public enum FilterType
{
    ///<summary>
    /// 用於生成紅色飽和圖像的過濾器。
    ///</summary>
    Red,

    ///<summary>
    /// 用於生成綠色飽和圖像的過濾器。
    ///</summary>
    Green,

    ///<summary>
    /// 用於生成藍色飽和圖像的過濾器。
    ///</summary>
    Blue,

    ///<summary>
    /// 用於生成灰度圖像的過濾器。
    ///</summary>
    Grayscale,

    ///<summary>
    /// 用於生成負像的過濾器。
    ///</summary>
    Negative,

    ///<summary>
    /// 用於生成棕褐色圖像的過濾器。
    ///</summary>
    Sepia,
}
///<summary>
/// 過濾縮略圖生成的結果。
///</summary>
public class FilterThumbnailResult
{
    ///<summary>
    /// 初始化 FilterThumbnailResult 類的新實例。
    ///</summary>
    ///<param name="filterType">應用於縮略圖的過濾器類型。</param>
    ///<param name="pngData"> PNG 格式的圖像數據。</param>
    ///<param name="width">縮略圖的寬度。</param>
    ///<param name="height">縮略圖的高度。</param>
    public FilterThumbnailResult(FilterType filterType, byte[] pngData, int width, int height)
    {
        this.FilterType = filterType;
        this.PngData = pngData;
        this.Width = width;
        this.Height = height;
    }

    ///<summary>
    /// 獲取應用於縮略圖的過濾器類型。
    ///</summary>
    public FilterType FilterType { get; }

    ///<summary>
    /// 獲取PNG格式的圖像數據。
    ///</summary>
    public byte[] PngData { get; }

    ///<summary>
    /// 獲取縮略圖的寬度。
    ///</summary>
    public int Width { get; }

    ///<summary>
    /// 獲取縮略圖的高度。
    ///</summary>
    public int Height { get; }
}

現在您可以定義用於生成帶有附加過濾器的縮略圖的接口:

using System.Collections.Generic;

///<summary>
/// 縮略圖生成界面。
///</summary>
public interface IThumbnailGenerator
{
    ///<summary>
    /// 為所有可用過濾器生成一組縮略圖。
    ///</summary>
    ///<param name="sourceImage">源圖像的字節數。</param>
    ///<param name="width">請求的預覽圖像寬度。</param>
    ///<param name="height">請求的預覽圖像的高度。</param>
    ///<returns>一組縮略圖。</returns>
    IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height);
}

繼續實施,假設使用 System.Drawing 庫實施 IThumbnailGenerator 接口。它看起來像下一個代碼片段:

///<summary>
///IThumbnailGenerator 接口實現使用System.Drawing。
///</summary>
public class ThumbnailGenerator
    : IThumbnailGenerator
{
    ///<summary>
    /// 一組縮略圖處理器。
    ///</summary>
    private static readonly FilterThumbnailProcessor[] Processors = new FilterThumbnailProcessor[] 
    {
        ApplyRedFilter,
        ApplyGreenFilter,
        ApplyBlueFilter,
        ApplyGrayFilter,
        ApplyNegativeFilter,
        ApplySepiaFilter,
    };

    ///<summary>
    /// 委託進行縮略圖處理。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private delegate FilterThumbnailResult FilterThumbnailProcessor(Bitmap thumbnail);

    ///<summary>
    /// 為所有可用過濾器生成一組縮略圖。
    ///</summary>
    ///<param name="sourceImage">源圖像的字節數。</param>
    ///<param name="width">請求的預覽圖像寬度。</param>
    ///<param name="height">請求的預覽圖像的高度。</param>
    ///<returns>一組縮略圖。</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>
    /// 對縮略圖應用紅色濾鏡。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private static FilterThumbnailResult ApplyRedFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// 對縮略圖應用綠色過濾器。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private static FilterThumbnailResult ApplyGreenFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// 對縮略圖應用藍色濾鏡。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private static FilterThumbnailResult ApplyBlueFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// 對縮略圖應用灰色過濾器。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private static FilterThumbnailResult ApplyGrayFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// 對縮略圖應用否定過濾器。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private static FilterThumbnailResult ApplyNegativeFilter(Bitmap thumbnail)
    {
    ...
    }

    ///<summary>
    /// 將棕褐色濾鏡應用於縮略圖。
    ///</summary>
    ///<param name="thumbnail">原始圖像的縮略圖。</param>
    ///<returns>過濾縮略圖生成的結果。</returns>
    private static FilterThumbnailResult ApplySepiaFilter(Bitmap thumbnail)
    {
    ...
    }
}

該代碼可以正常工作,但它有一個缺點 - 它會按順序生成所有縮略圖。 System.Drawing 庫基於相當古老的 GDI+ 庫,它被設計為單線程庫,因此在有多個 CPU 內核時會浪費資源。

使用 Aspose.Drawing 可以幫助顯著提高性能,因為它沒有與單線程相關的任何限制。請嘗試只更改一個功能:

///<summary>
/// 為所有可用過濾器生成一組縮略圖。
///</summary>
///<param name="sourceImage">源圖像的字節數。</param>
///<param name="width">請求的預覽圖像寬度。</param>
///<param name="height">請求的預覽圖像的高度。</param>
///<returns>一組縮略圖。</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;
    }
}

此代碼現在可以使用多個 CPU 內核,而無需對原始源代碼進行任何重大更改。用 Aspose.Drawing 替換 System.Drawing 可以加快應用程序和服務的性能。

下載源代碼

您可以下載與該示例相關的Source Code以供參考。

免費的 API 評估許可證

您可以申請 免費臨時許可證 以全面測試 API。

結論

總之,您已經通過示例了解到在 ASP.NET 和 ASP.NET Core 服務中使用 Aspose.Drawing 庫是多麼簡單。此外,Aspose.Drawing 不存在 System.Drawing 中存在的問題或外部依賴性。此外,您可以通過閱讀 文檔 來詳細探索 API。如有任何疑問,請隨時通過 免費支持論壇 與我們聯繫!

也可以看看