System.Drawing ใน ASP .NET ASP.NET Core

มีคำถามมากมายเกี่ยวกับการใช้ไลบรารี System.Drawing ในบริการ ASP.NET คำตอบที่พบบ่อยที่สุดคือ Microsoft ไม่แนะนำให้ใช้ System.Drawing ในบริการ ASP.NET

ในบทความนี้ คุณจะได้เรียนรู้รายละเอียดเกี่ยวกับการใช้อินเทอร์เฟซของไลบรารี System.Drawing ในบริการ ASP.NET ด้วย Aspose.Drawing for .NET ส่วนต่อไปนี้จัดโครงสร้างข้อมูลที่เกี่ยวข้องทั้งหมด:

ทำไมต้อง Aspose. Drawing?

Microsoft ไม่แนะนำให้ใช้ไลบรารี System.Drawing ในบริการ ASP.NET หน้าแรกของ System.Drawing เอกสารประกอบ อ่าน:

คลาสภายในเนมสเปซ System.Drawing ไม่ได้รับการสนับสนุนสำหรับการใช้งานภายในบริการ Windows หรือ ASP.NET การพยายามใช้คลาสเหล่านี้จากภายในแอปพลิเคชันประเภทใดประเภทหนึ่งอาจส่งผลให้เกิดข้อยกเว้นรันไทม์และประสิทธิภาพของบริการลดลง

มีปัญหาพื้นฐานสองประการที่บังคับให้ Microsoft เขียนเหนือคำเตือน ปัญหาแรกคือการใช้ไลบรารีเนทีฟ GDI+ และเป็นผลให้มีการใช้ตัวจัดการ GDI ในขณะที่ข้อกังวลประการที่สองคือปัญหาที่เกิดขึ้นพร้อมกัน ตัวอย่างเช่น การล็อกทั่วทั้งกระบวนการเกิดขึ้นระหว่างการดำเนินการ DrawImage() ใดๆ ดังนั้น คุณไม่สามารถสร้างบริการ ASP.NET ที่รวดเร็วและปรับขนาดได้โดยใช้ไลบรารี System.Drawing จาก Microsoft

การติดตั้ง Aspose.Drawing for .NET API

คุณสามารถดาวน์โหลดไฟล์ DLL ได้ง่ายๆ จากส่วน ดาวน์โหลด หรือกำหนดค่าผ่านตัวจัดการแพ็กเกจ NuGet ด้วยคำสั่งต่อไปนี้:

PM> Install-Package Aspose.Drawing

Aspose.Drawing for .NET API - บทนำ

เราเข้าใจดีว่า System.Drawing เป็นที่นิยมมากในหมู่นักพัฒนาเนื่องจากคุณสมบัติการจัดการรูปภาพ นั่นคือเหตุผลที่เราสร้าง API ที่คล้ายกันและเข้ากันได้โดยไม่มีปัญหาความเข้ากันได้ เพื่อความสะดวกและความสามารถในการปรับเปลี่ยนของคุณ API มีชื่อคลาส ฟังก์ชัน enums และอินเทอร์เฟซเดียวกัน คุณสามารถเปลี่ยนการอ้างอิงโครงการจาก System.Drawing เป็น Aspose.Drawing และคอมไพล์โปรแกรมใหม่ได้

นอกจากนี้ Aspose.Drawing เป็นไลบรารีที่มีการจัดการสำหรับ NET Framework 2.0 และ NET Core 2.0 ไม่เหมือนกับ System.Drawing ซึ่งไม่มีการพึ่งพาแพลตฟอร์มใด ๆ เช่น Linux, Azure เป็นต้น

การใช้ Aspose.Drawing ในบริการ ASP.NET

Aspose การใช้งาน Drawing ไม่ได้ขึ้นอยู่กับ GDI หรือ GDI+ ไม่ใช้ตัวจัดการ GDI และไม่ค่อยใช้การล็อกทั่วทั้งกระบวนการ

สาธิตการใช้งาน Aspose.Drawing ใน ASP.NET Services

ให้เราสร้างแอปพลิเคชั่นง่าย ๆ ที่อธิบายถึงประโยชน์ของการใช้ไลบรารี Aspose.Drawing:

ลองนึกภาพว่าคุณตัดสินใจสร้างบริการเว็บหรือแอปพลิเคชันใหม่ทั้งหมด แอปพลิเคชันจะสร้างชุดภาพขนาดย่อพร้อมตัวกรองที่แนบมาจากภาพของผู้ใช้

คุณสามารถเริ่มต้นด้วยการแนะนำเอนทิตีใหม่:

///<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);
}

การดำเนินการต่อไป สมมติว่าใช้อินเทอร์เฟซ IThumbnailGenerator โดยใช้ไลบรารี System.Drawing จะมีลักษณะเหมือนข้อมูลโค้ดถัดไป:

///<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 หลายแกนโดยไม่มีการเปลี่ยนแปลงที่สำคัญในซอร์สโค้ดดั้งเดิม การแทนที่ System.Drawing ด้วย Aspose.Drawing ช่วยเร่งประสิทธิภาพของแอปพลิเคชันและบริการของคุณ

ดาวน์โหลดซอร์สโค้ด

คุณสามารถดาวน์โหลด Source Code ที่เกี่ยวข้องกับตัวอย่างนี้เพื่อใช้อ้างอิงได้

ใบอนุญาตการประเมิน API ฟรี

คุณสามารถขอ ใบอนุญาตชั่วคราวฟรี เพื่อทดสอบ API ได้อย่างเต็มประสิทธิภาพ

บทสรุป

โดยสรุป คุณได้เรียนรู้จากตัวอย่างแล้วว่าการใช้ไลบรารี Aspose.Drawing ในบริการ ASP.NET และ ASP.NET Core นั้นง่ายเพียงใด นอกจากนี้ Aspose.Drawing ไม่มีปัญหาหรือการพึ่งพาภายนอกที่มีอยู่ใน System.Drawing นอกจากนี้ คุณสามารถสำรวจ API โดยละเอียดได้โดยไปที่ เอกสารประกอบ โปรดติดต่อเราได้ทุกเมื่อผ่าน ฟอรัมสนับสนุนฟรี สำหรับข้อสงสัยของคุณ!

ดูสิ่งนี้ด้วย