ASP.NET 서비스에서 System.Drawing 라이브러리를 사용하는 것과 관련된 많은 질문이 있습니다. 가장 일반적인 대답은 Microsoft가 ASP.NET 서비스에서 System.Drawing 사용을 권장하지 않는다는 것입니다.
이 기사에서는 Aspose.Drawing for .NET과 함께 ASP.NET 서비스에서 System.Drawing 라이브러리의 인터페이스를 사용하는 방법에 대해 자세히 설명합니다. 다음 섹션에서는 모든 관련 정보를 구성합니다.
- 왜 Aspose.Drawing인가?
- .NET API용 Aspose.Drawing 설치
- .NET API용 Aspose.Drawing - 소개
- ASP.NET 서비스에서 Aspose.Drawing 사용
- 소스 코드 다운로드
- 결론
왜 Aspose.Drawing?
Microsoft는 ASP.NET 서비스에서 System.Drawing 라이브러리의 사용을 권장하지 않습니다. System.Drawing 문서의 홈 페이지는 다음과 같습니다.
System.Drawing 네임스페이스 내의 클래스는 Windows 또는 ASP.NET 서비스 내에서 사용하도록 지원되지 않습니다. 이러한 응용 프로그램 유형 중 하나에서 이러한 클래스를 사용하려고 하면 런타임 예외가 발생하고 서비스 성능이 저하될 수 있습니다.
Microsoft가 위의 주의 사항을 작성하도록 하는 두 가지 기본 문제가 있습니다. 첫 번째 문제는 GDI+ 네이티브 라이브러리의 사용과 결과적으로 GDI 핸들의 사용입니다. 두 번째 관심사는 동시성 문제입니다. 예를 들어 모든 DrawImage() 작업 중에 프로세스 전체 잠금이 발생합니다. 따라서 Microsoft의 System.Drawing 라이브러리를 사용하여 빠르고 확장 가능한 ASP.NET 서비스를 만들 수 없습니다.
.NET API용 Aspose.Drawing 설치
다운로드 섹션에서 DLL 파일을 쉽게 다운로드하거나 다음 명령을 사용하여 NuGet 패키지 관리자를 통해 구성할 수 있습니다.
PM> Install-Package Aspose.Drawing
.NET API용 Aspose.Drawing - 소개
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 라이브러리 사용의 이점을 설명하는 간단한 응용 프로그램을 만들어 보겠습니다.
완전히 새로운 웹 서비스나 애플리케이션을 만들기로 결정했다고 상상해 보십시오. 응용 프로그램은 사용자의 이미지에서 필터가 첨부된 축소판 집합을 생성합니다.
몇 가지 새로운 항목을 도입하여 시작할 수 있습니다.
///<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>
/// System.Drawing을 사용한 IThumbnailGenerator 인터페이스 구현.
///</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으로 교체하면 애플리케이션 및 서비스의 성능이 빨라집니다.
소스 코드 다운로드
참고용으로 이 예제와 관련된 소스 코드를 다운로드할 수 있습니다.
무료 API 평가 라이선스
API를 전체 용량으로 테스트하려면 무료 임시 라이선스를 요청할 수 있습니다.
결론
결론적으로, ASP.NET 및 ASP.NET Core 서비스에서 Aspose.Drawing 라이브러리를 사용하는 것이 얼마나 간단한지 예제를 통해 배웠습니다. 또한 Aspose.Drawing에는 System.Drawing에 존재하는 문제나 외부 종속성이 없습니다. 또한 Documentation을 통해 API를 자세히 탐색할 수 있습니다. 궁금한 사항은 무료 지원 포럼을 통해 언제든지 문의해 주세요!