Istnieje wiele pytań poświęconych wykorzystaniu biblioteki System.Drawing w usługach ASP.NET. Najczęstszą odpowiedzią jest to, że Microsoft nie zaleca używania System.Drawing w usługach ASP.NET.
W tym artykule poznasz szczegóły wykorzystania interfejsu biblioteki System.Drawing w usługach ASP.NET z Aspose.Drawing for .NET. Poniższe sekcje porządkują wszystkie istotne informacje:
- Dlaczego Aspose.Drawing?
- Instalowanie Aspose.Drawing dla interfejsu API platformy .NET
- Aspose.Drawing dla interfejsu API platformy .NET — wprowadzenie
- Używanie Aspose.Drawing w usługach ASP.NET
- Pobierz kod źródłowy
- Wniosek
Dlaczego Aspose.Drawing?
Firma Microsoft nie zaleca używania swojej biblioteki System.Drawing w usługach ASP.NET. Strona główna System.Drawing dokumentacja brzmi:
Klasy w przestrzeni nazw System.Drawing nie są obsługiwane w usługach Windows lub ASP.NET. Próba użycia tych klas z jednego z tych typów aplikacji może spowodować wyjątki w czasie wykonywania i zmniejszoną wydajność usługi.
Istnieją dwa podstawowe problemy, które zmuszają Microsoft do napisania powyżej ostrożności. Pierwszym problemem jest użycie natywnej biblioteki GDI+ iw efekcie użycie uchwytów GDI. Podczas gdy drugim problemem są problemy z współbieżnością. Na przykład podczas dowolnej operacji DrawImage() występuje blokada obejmująca cały proces. Dlatego nie można tworzyć szybkich i skalowalnych usług ASP.NET przy użyciu biblioteki System.Drawing firmy Microsoft.
Instalowanie Aspose.Drawing dla interfejsu API platformy .NET
Możesz łatwo pobrać plik DLL z sekcji Downloads lub skonfigurować go za pomocą menedżera pakietów NuGet za pomocą następującego polecenia:
PM> Install-Package Aspose.Drawing
Aspose.Drawing dla interfejsu API platformy .NET — wprowadzenie
Rozumiemy, że System.Drawing jest bardzo popularny wśród programistów ze względu na jego funkcje manipulacji obrazami. Dlatego stworzyliśmy podobne i kompatybilne API bez żadnych problemów ze zgodnością. Dla Twojej wygody i możliwości adaptacji interfejs API zawiera te same nazwy klas, funkcji, wyliczeń i interfejsów. Możesz po prostu zmienić odniesienie do projektu z System.Drawing na Aspose.Drawing i ponownie skompilować program.
Co więcej, Aspose.Drawing jest zarządzaną biblioteką dostępną dla NET Framework 2.0 i NET Core 2.0. W przeciwieństwie do System.Drawing nie ma zależności od żadnej platformy, takiej jak Linux, Azure itp.
Używanie Aspose.Drawing w usługach ASP.NET
Implementacja Aspose.Drawing nie zależy od GDI ani GDI+. Nie używa uchwytów GDI i rzadko używa blokad obejmujących cały proces.
Demonstracja użycia Aspose.Drawing w usługach ASP.NET
Stwórzmy prostą aplikację wyjaśniającą korzyści płynące z korzystania z biblioteki Aspose.Drawing:
Wyobraź sobie, że postanawiasz stworzyć zupełnie nową usługę internetową lub aplikację. Aplikacja wygeneruje zestaw miniaturek z dołączonymi do nich filtrami z obrazu użytkownika.
Możesz zacząć od wprowadzenia kilku nowych podmiotów:
///<summary>
/// Dostępne rodzaje filtrów.
///</summary>
public enum FilterType
{
///<summary>
/// Filtr do generowania obrazu nasyconego kolorem czerwonym.
///</summary>
Red,
///<summary>
/// Filtr do generowania obrazu nasyconego kolorem zielonym.
///</summary>
Green,
///<summary>
/// Filtr do generowania obrazu nasyconego kolorem niebieskim.
///</summary>
Blue,
///<summary>
/// Filtr do generowania obrazu w skali szarości.
///</summary>
Grayscale,
///<summary>
/// Filtr do generowania negatywu.
///</summary>
Negative,
///<summary>
/// Filtr do generowania obrazu w sepii.
///</summary>
Sepia,
}
///<summary>
/// Wynik generowania przefiltrowanych miniatur.
///</summary>
public class FilterThumbnailResult
{
///<summary>
/// Inicjuje nową instancję klasy FilterThumbnailResult.
///</summary>
///<param name="filterType"> Typ filtra zastosowanego do miniatury.</param>
///<param name="pngData"> Dane obrazu w formacie PNG.</param>
///<param name="width"> Szerokość miniatury.</param>
///<param name="height"> Wysokość 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>
/// Pobiera typ filtra zastosowanego do miniatury.
///</summary>
public FilterType FilterType { get; }
///<summary>
/// Pobiera dane obrazu w formacie PNG.
///</summary>
public byte[] PngData { get; }
///<summary>
/// Pobiera szerokość miniatury.
///</summary>
public int Width { get; }
///<summary>
/// Pobiera wysokość miniatury.
///</summary>
public int Height { get; }
}
Teraz możesz zdefiniować interfejs do generowania miniatur z dołączonymi filtrami:
using System.Collections.Generic;
///<summary>
/// Interfejs do generowania miniatur obrazów.
///</summary>
public interface IThumbnailGenerator
{
///<summary>
/// Generuje zestaw miniatur dla wszystkich dostępnych filtrów.
///</summary>
///<param name="sourceImage"> Bajty obrazu źródłowego.</param>
///<param name="width"> Żądana szerokość obrazów podglądu.</param>
///<param name="height"> Żądana wysokość obrazów podglądu.</param>
///<returns> Zestaw miniatur.</returns>
IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height);
}
Przechodząc do implementacji, załóżmy implementację interfejsu IThumbnailGenerator z wykorzystaniem biblioteki System.Drawing. Będzie wyglądać jak następny fragment kodu:
///<summary>
/// Implementacja interfejsu IThumbnailGenerator przy użyciu System.Drawing.
///</summary>
public class ThumbnailGenerator
: IThumbnailGenerator
{
///<summary>
/// Zestaw procesorów miniatur.
///</summary>
private static readonly FilterThumbnailProcessor[] Processors = new FilterThumbnailProcessor[]
{
ApplyRedFilter,
ApplyGreenFilter,
ApplyBlueFilter,
ApplyGrayFilter,
ApplyNegativeFilter,
ApplySepiaFilter,
};
///<summary>
/// Delegat do przetwarzania miniatur.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private delegate FilterThumbnailResult FilterThumbnailProcessor(Bitmap thumbnail);
///<summary>
/// Generuje zestaw miniatur dla wszystkich dostępnych filtrów.
///</summary>
///<param name="sourceImage"> Bajty obrazu źródłowego.</param>
///<param name="width"> Żądana szerokość obrazów podglądu.</param>
///<param name="height"> Żądana wysokość obrazów podglądu.</param>
///<returns> Zestaw 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>
/// Stosuje czerwony filtr do miniatury.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private static FilterThumbnailResult ApplyRedFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Stosuje zielony filtr do miniatury.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private static FilterThumbnailResult ApplyGreenFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Stosuje niebieski filtr do miniatury.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private static FilterThumbnailResult ApplyBlueFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Stosuje szary filtr do miniatury.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private static FilterThumbnailResult ApplyGrayFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Stosuje filtr negatywny do miniatury.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private static FilterThumbnailResult ApplyNegativeFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Stosuje filtr sepii do miniatury.
///</summary>
///<param name="thumbnail"> Miniatura oryginalnego obrazu.</param>
///<returns> Wynik generowania przefiltrowanych miniatur.</returns>
private static FilterThumbnailResult ApplySepiaFilter(Bitmap thumbnail)
{
...
}
}
Kod będzie działał dobrze, ale ma jedną wadę - generuje wszystkie miniatury po kolei. Biblioteka System.Drawing jest oparta na dość starej bibliotece GDI+, która została zaprojektowana jako biblioteka jednowątkowa, więc może marnować zasoby, gdy jest wiele rdzeni procesora.
Korzystanie z Aspose.Drawing może znacznie poprawić wydajność, ponieważ nie ma żadnych ograniczeń związanych z pojedynczym wątkiem. Spróbuj zmienić tylko jedną funkcję:
///<summary>
/// Generuje zestaw miniatur dla wszystkich dostępnych filtrów.
///</summary>
///<param name="sourceImage"> Bajty obrazu źródłowego.</param>
///<param name="width"> Żądana szerokość obrazów podglądu.</param>
///<param name="height"> Żądana wysokość obrazów podglądu.</param>
///<returns> Zestaw 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;
}
}
Ten kod może teraz wykorzystywać wiele rdzeni procesora bez żadnych znaczących zmian w oryginalnym kodzie źródłowym. Zamiana System.Drawing na Aspose.Drawing przyspiesza działanie aplikacji i usług.
Pobierz kod źródłowy
Możesz pobrać Kod źródłowy związany z tym przykładem w celach informacyjnych.
Bezpłatna licencja na ocenę interfejsu API
Możesz poprosić o Bezpłatną licencję tymczasową, aby przetestować interfejs API w pełni.
Wniosek
Podsumowując, nauczyłeś się na przykładzie, jak proste jest użycie biblioteki Aspose.Drawing w usługach ASP.NET i ASP.NET Core. Co więcej, Aspose.Drawing nie ma problemów ani zewnętrznych zależności, które istnieją w System.Drawing. Ponadto możesz szczegółowo zapoznać się z interfejsem API, przeglądając Dokumentację. W każdej chwili możesz skontaktować się z nami za pośrednictwem bezpłatnego forum pomocy technicznej w przypadku jakichkolwiek pytań!