ASP .NET ASP.NET Core 中的 System.Drawing

有很多关于在 ASP.NET 服务中使用 System.Drawing 库的问题。最常见的答案是 Microsoft 不建议在 ASP.NET 服务中使用 System.Drawing。

在本文中,您将通过 Aspose.Drawing for .NET 了解有关在 ASP.NET 服务中使用 System.Drawing 库接口的详细信息。以下部分构建了所有相关信息:

为什么选择 Aspose.Drawing?

Microsoft 不建议在 ASP.NET 服务中使用其 System.Drawing 库。 System.Drawing 文档 的主页内容如下:

System.Drawing 命名空间中的类不支持在 Windows 或 ASP.NET 服务中使用。尝试从这些应用程序类型之一中使用这些类可能会导致运行时异常和服务性能下降。

有两个基本问题迫使微软在上面谨慎地写。第一个问题是 GDI+ 本地库的使用,以及 GDI 句柄的使用。而第二个问题是并发问题。例如,在任何 DrawImage() 操作期间都会发生进程范围的锁定。因此,您无法使用 Microsoft 的 System.Drawing 库创建快速且可扩展的 ASP.NET 服务。

为 .NET API 安装 Aspose.Drawing

您可以从 Downloads 部分轻松下载 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 可以加快应用程序和服务的性能。

下载源代码

您可以下载本示例相关的源码供您参考。

免费 API 评估许可证

您可以申请 免费临时许可证 以充分测试 API。

结论

总之,您已经通过示例了解到在您的 ASP.NET 和 ASP.NET Core 服务中使用 Aspose.Drawing 库是多么简单。此外,Aspose.Drawing 没有 System.Drawing 中存在的问题或外部依赖关系。此外,您可以通过 文档 详细了解 API。如有任何疑问,请随时通过 免费支持论坛 与我们联系!

也可以看看