Existem muitas questões dedicadas ao uso da biblioteca System.Drawing em serviços ASP.NET. A resposta mais comum é que a Microsoft não recomenda o uso de System.Drawing em serviços ASP.NET.
Neste artigo, você aprenderá detalhes sobre como usar a interface da biblioteca System.Drawing em serviços ASP.NET com Aspose.Drawing for .NET. As seções a seguir estruturam todas as informações relevantes:
- Por que Aspose.Drawing?
- Instalando o Aspose.Drawing para .NET API
- Aspose.Drawing para .NET API - Introdução
- Usando Aspose.Drawing em ASP.NET Services
- Baixar código fonte
- Conclusão
Por que Aspose.Drawing?
A Microsoft não recomenda o uso de sua biblioteca System.Drawing em serviços ASP.NET. A página inicial do System.Drawing documentação diz:
Não há suporte para classes dentro do namespace System.Drawing para uso em um serviço Windows ou ASP.NET. A tentativa de usar essas classes em um desses tipos de aplicativo pode resultar em exceções de tempo de execução e desempenho de serviço reduzido.
Existem dois problemas básicos que obrigam a Microsoft a escrever acima de cautela. O primeiro problema é o uso da biblioteca nativa GDI+ e, como resultado, o uso de handles GDI. Enquanto a segunda preocupação é questões de simultaneidade. Por exemplo, um bloqueio em todo o processo ocorre durante qualquer operação DrawImage(). Portanto, você não pode criar serviços ASP.NET rápidos e escaláveis usando a biblioteca System.Drawing da Microsoft.
Instalando o Aspose.Drawing para .NET API
Você pode facilmente baixar o arquivo DLL da seção Downloads, ou configurá-lo através do gerenciador de pacotes NuGet com o seguinte comando:
PM> Install-Package Aspose.Drawing
Aspose.Drawing para .NET API - Introdução
Entendemos que System.Drawing é muito popular entre os desenvolvedores por causa de seus recursos de manipulação de imagens. É por isso que criamos uma API semelhante e compatível sem problemas de compatibilidade. Para sua conveniência e adaptabilidade, a API contém os mesmos nomes de classes, funções, enumerações e interfaces. Você pode simplesmente alterar a referência do projeto de System.Drawing para Aspose.Drawing e recompilar o programa.
Além disso, Aspose.Drawing é uma biblioteca gerenciada disponível para NET Framework 2.0 e NET Core 2.0. Ao contrário do System.Drawing, ele não tem dependências em nenhuma plataforma como Linux, Azure, etc.
Usando Aspose.Drawing em ASP.NET Services
A implementação do Aspose.Drawing não depende de GDI ou GDI+. Ele não usa identificadores GDI e raramente usa bloqueios em todo o processo.
Demonstração para usar o Aspose.Drawing no ASP.NET Services
Vamos criar um aplicativo simples que explica os benefícios de usar a biblioteca Aspose.Drawing:
Imagine que você decida criar um serviço ou aplicativo da Web totalmente novo. O aplicativo irá gerar um conjunto de miniaturas com filtros anexados a elas a partir da imagem do usuário.
Você pode começar apresentando algumas novas entidades:
///<summary>
/// Tipos de filtros disponíveis.
///</summary>
public enum FilterType
{
///<summary>
/// Filtro para geração de imagem saturada com cor vermelha.
///</summary>
Red,
///<summary>
/// Filtro para geração de imagem saturada com cor verde.
///</summary>
Green,
///<summary>
/// Filtro para geração de imagem saturada com cor azul.
///</summary>
Blue,
///<summary>
/// Filtro para geração de imagem em tons de cinza.
///</summary>
Grayscale,
///<summary>
/// Filtro para geração de imagem negativa.
///</summary>
Negative,
///<summary>
/// Filtro para geração de imagem sépia.
///</summary>
Sepia,
}
///<summary>
/// O resultado da geração de miniaturas filtradas.
///</summary>
public class FilterThumbnailResult
{
///<summary>
/// Inicializa uma nova instância da classe FilterThumbnailResult.
///</summary>
///<param name="filterType"> O tipo de filtro aplicado à miniatura.</param>
///<param name="pngData"> Os dados da imagem no formato PNG.</param>
///<param name="width"> A largura da miniatura.</param>
///<param name="height"> A altura da miniatura.</param>
public FilterThumbnailResult(FilterType filterType, byte[] pngData, int width, int height)
{
this.FilterType = filterType;
this.PngData = pngData;
this.Width = width;
this.Height = height;
}
///<summary>
/// Obtém o tipo de filtro aplicado à miniatura.
///</summary>
public FilterType FilterType { get; }
///<summary>
/// Obtém os dados da imagem no formato PNG.
///</summary>
public byte[] PngData { get; }
///<summary>
/// Obtém a largura da miniatura.
///</summary>
public int Width { get; }
///<summary>
/// Obtém a altura da miniatura.
///</summary>
public int Height { get; }
}
Agora você pode definir a interface para a geração de miniaturas com filtros anexados:
using System.Collections.Generic;
///<summary>
/// A interface para geração de imagens em miniatura.
///</summary>
public interface IThumbnailGenerator
{
///<summary>
/// Gera um conjunto de miniaturas para todos os filtros disponíveis.
///</summary>
///<param name="sourceImage"> Bytes da imagem de origem.</param>
///<param name="width"> Largura solicitada das imagens de visualização.</param>
///<param name="height"> Altura solicitada das imagens de visualização.</param>
///<returns> Um conjunto de miniaturas.</returns>
IEnumerable<FilterThumbnailResult> GenerateAllThumbnails(byte[] sourceImage, int width, int height);
}
Passando para a implementação, suponha a implementação da interface IThumbnailGenerator usando a biblioteca System.Drawing. Será parecido com o próximo trecho de código:
///<summary>
/// Implementação da interface IThumbnailGenerator usando System.Drawing.
///</summary>
public class ThumbnailGenerator
: IThumbnailGenerator
{
///<summary>
/// Um conjunto de processadores de miniaturas.
///</summary>
private static readonly FilterThumbnailProcessor[] Processors = new FilterThumbnailProcessor[]
{
ApplyRedFilter,
ApplyGreenFilter,
ApplyBlueFilter,
ApplyGrayFilter,
ApplyNegativeFilter,
ApplySepiaFilter,
};
///<summary>
/// Delegado para processamento de miniaturas.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private delegate FilterThumbnailResult FilterThumbnailProcessor(Bitmap thumbnail);
///<summary>
/// Gera um conjunto de miniaturas para todos os filtros disponíveis.
///</summary>
///<param name="sourceImage"> Bytes da imagem de origem.</param>
///<param name="width"> Largura solicitada das imagens de visualização.</param>
///<param name="height"> Altura solicitada das imagens de visualização.</param>
///<returns> Um conjunto de miniaturas.</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>
/// Aplica um filtro vermelho à miniatura.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private static FilterThumbnailResult ApplyRedFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Aplica um filtro verde à miniatura.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private static FilterThumbnailResult ApplyGreenFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Aplica um filtro azul à miniatura.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private static FilterThumbnailResult ApplyBlueFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Aplica um filtro cinza à miniatura.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private static FilterThumbnailResult ApplyGrayFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Aplica um filtro negativo à miniatura.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private static FilterThumbnailResult ApplyNegativeFilter(Bitmap thumbnail)
{
...
}
///<summary>
/// Aplica um filtro sépia à miniatura.
///</summary>
///<param name="thumbnail"> Miniatura da imagem original.</param>
///<returns> Resultado da geração de miniaturas filtradas.</returns>
private static FilterThumbnailResult ApplySepiaFilter(Bitmap thumbnail)
{
...
}
}
O código funcionará bem, mas tem uma desvantagem - ele gera todas as miniaturas sequencialmente. A biblioteca System.Drawing é baseada na biblioteca GDI+ bastante antiga, que foi projetada como uma biblioteca de thread único para que possa desperdiçar recursos quando houver vários núcleos de CPU.
O uso do Aspose.Drawing pode ajudar a melhorar significativamente o desempenho, pois não possui limitações relacionadas a um único thread. Por favor, tente alterar apenas uma função:
///<summary>
/// Gera um conjunto de miniaturas para todos os filtros disponíveis.
///</summary>
///<param name="sourceImage"> Bytes da imagem de origem.</param>
///<param name="width"> Largura solicitada das imagens de visualização.</param>
///<param name="height"> Altura solicitada das imagens de visualização.</param>
///<returns> Um conjunto de miniaturas.</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;
}
}
Esse código agora pode usar vários núcleos de CPU sem alterações significativas no código-fonte original. Substituir System.Drawing por Aspose.Drawing agiliza o desempenho de seus aplicativos e serviços.
Baixar código fonte
Você pode baixar o Código-fonte relacionado a este exemplo para sua referência.
Licença de avaliação de API gratuita
Você pode solicitar uma Licença Temporária Gratuita para testar a API em sua capacidade total.
Conclusão
Concluindo, você aprendeu com o exemplo como é simples usar a biblioteca Aspose.Drawing em seus serviços ASP.NET e ASP.NET Core. Além disso, Aspose.Drawing não tem problemas ou dependências externas que existem em System.Drawing. Além disso, você pode explorar a API em detalhes acessando a Documentação. Sinta-se à vontade para entrar em contato conosco a qualquer momento através do Fórum de suporte gratuito para qualquer dúvida!