Gerando Thumbnails com HttpHandler

Como prometi em um post anterior, vou detalhar aqui alguns dos conceitos e motivações por trás do gerador de thumbnails que disponibilizei no CodePlex como parte integrante de uma biblioteca para agilizar desenvolvimento ASP.NET chamada CNZK Web Library. O código que está no CodePlex não contém ainda uma documentação formal mas está bem comentado. Vou mostrar o motivo de algumas das decisões que tomei no desenvolvimento dessa classe e tentar explicar o funcionamento de alguns trechos de código.

Para começar: As Motivações

Eu coordeno um time de desenvolvimento responsável por diversos projetos dos nossos clientes. Para poder dar conta de todos os projetos de desenvolvimento ou manutenção de sites com eficiência e agilidade foi necessário desenvolver e aplicar metodologias e padrões. Durante algumas reuniões nós tentamos identificar pontos em comum entre os projetos que pudessem ser padronizados e transformados em uma biblioteca para evitar que o trabalho fosse refeitos todas as vezes. Um ponto que era muito importante para mim era que a utilização dessa biblioteca fosse o mais simples possível, para encorajar o seu uso e aperfeiçoamento.

A geração de thumbnails de imagens pode não parecer muito óbvia quando se analisa os pontos em comum entre sites, até o momento em que você começa a olhar o código das áreas de administração do site e vê a complexidade que é embutida no código para fazer upload de 2 ou 3 imagens para cada produto ou item de uma página. Além disso, tem mais outros 2 fatores que foram muito importantes na decisão de fazer o gerador de thumbnails: Gerenciamento de muitos arquivos em disco no webserver; Facilidade e agilidade de uso da área administrativa do site.

Essa biblioteca do Codeplex não contemplará apenas o gerador de thumbnails. Há diversas outras classes que já tenho prontas ou parcialmente prontas que estão apenas passando por uma limpeza de código antes de fazerem parte da biblioteca. A classe de thumbnail foi escolhida para ser a primeira por ser a que estava em estado mais maduro e por ter sido a melhor testada e mais utilizada da biblioteca até agora em nossos projetos.

Segundo passo: Decisões Técnicas e Arquitetura

A idéia inicial era fazer uma classe que tornasse possível redimensionar facilmente as imagens no momento do upload, para que o usuário não precisasse fazer upload de2 ou 3 imagens diferente apenas por causa do tamanho. Após fazer uma primeira versão eu notei que isso não agilizaria muito o processo de desenvolvimento e também não seria um componente muito reutilizável.

Então eu encontrei um capítulo em um livro que mostrava como fazer um HttpHandler para redimensionamento de imagem. O código no livro trabalhava de forma semelhante ao código que eu gerei, mas o tamanho final das imagens não era parametrizável e as miniaturas geradas eram armazenadas em disco. Essas duas características ainda não eram exatamente o que eu queria, então eu fiz a minha versão.

HttpHandlers são um recurso extremamente interessante do ASP.NET, pois nos possibilitam criar a nossa própria extensão de arquivo e tratá-la da forma que precisarmos, como se fosse um novo tipo de arquivo. O único problema em se criar sua própria extensão de arquivo é que será necessário regitrar essa extensão no IIS e informar que ela deverá ser processada pelo ASP.NET para que o código do seu handler seja executado (aliás, é isso que o ASP.NET faz com as extensões aspx, ascx e axd). A extensão axd já é utilizada pelo ASP.NET justamente para processamento de handlers (um exemplo disso é o trace.axd).

Então, o que eu fiz foi implementar uma classe extendendo IHttpHandler e registrar a minha classe como sendo o handler para qualquer chamada que for feita para arquivos com a extensão ".thumb.axd". Para o IIS, o que interessa é a extensão axd, que indica que o ASP.NET deve processar a requisição. Eu poderia ter usado apenas a extensão ".thumb", mas teria que registrá-la no IIS do servidor do site, o que não seria muito prático, principalmente levando em consideração a quantidade de ambiente que precisariam ser configurados (desenvolvimento, homologação, produção, etc...).

Como Funciona

Eu tentei tornar a utilização simples, rápida e pouco intrusiva. Uma das vantagens de utilizar a extensão .axd, é que o IIS está configurado para simplesmente repassar qualquer requisição feita à arquivos com essa extensão para o ASP.NET, sem sequer verificar se o arquivo realmente existe. Isso tornou possível que eu utilizasse a extensão que escolhi (.thumb.axd) como sufixo das imagens originais. Assim eu poderia chamar um thumb para uma imagem usando a seguinte URI: "/img/foto.jpg.thumb.axd".

Agora tudo que eu precisava era passar alguns parâmetros para que o handler soubesse qual deveria ser o novo tamanho da imagem. Como eu não queria que a url ficasse poluída, fiz com que os parâmetros de tamanho (que são obrigatórios) fossem passados como se fizessem parte do nome do arquivo, da seguinte forma: "/img/foto.jpg.200x150.thumb.axd". Pronto, agora posso redimensionar qualquer imagem nos meus sites. Outra vantagem é que os profissionais de interface podem utilizar esse controle sem nenhuma interferência dos programadores, poupando trabalho dos 2 lados.

Superficialmente, a lógica que o código segue é a seguinte:

  • Verifica se a URI solicitada está no formato correto, utilizando Expressão Regular.
  • Obtém a imagem que será redimensionada. Verifica se a imagem original existe.
    • Se existir, abre o arquivo e obtém suas dimensões. Nesse momento é configurado o cache, vinculado ao arquivo original.
    • Se não existir, verifica se está configurado um arquivo padrão para imagem não disponível e o abre.
    • Se não houver arquivo padrão, cria uma imagem em memória com os dizeres "Imagem não disponível".
  • Faz o cálculo das proporções da imagem, para verificar se o tamanho solicitado é proporcional ao original.
    • Se o tamanho solicitado for proporcional, redimensiona a imagem para o novo tamanho.
    • Se não for proporcional, calcula o redimensionamento da imagem para que caiba no novo tamanho.
  • Cria uma nova imagem em memória com o tamanho solicitado.
  • Redimensiona a imagem obtida (original ou de aviso) para o tamanho proporcional calculado.
  • Coloca a imagem redimensionada centralizada dentro da nova imagem.
  • Define qual será o tipo de output (se o original for gif, a saída será gif. se não for gif, a saída será jpg).
  • Faz o output da imagem, codificada no formato correto.

Alguns pontos interessantes desse handler:

Os thumbnails gerados são armazenados em cache para evitar sobrecarga de processamento no servidor. Esse cache está vinculado ao arquivo da imagem original, ou seja, se a imagem original for alterada o cache expira.

Sempre será retornada uma imagem, existindo ou não a original. Isso poupa bastante código de verificação nas páginas e problemas de layout.

A imagem redimensionada não será distorcida. Se a imagem original não estiver nas mesmas proporções da solicitada, ela será redimensionada proporcionalmente para caber no tamanho solicitado.

O peso das páginas vai diminuir, poupando banda dos usuários do site e tornando o carregamento da página mais rápido.

Outros parâmetros

Esse controle não faz apenas redimensionamento de imagens. Conforme as necessidades foram surgindo, novas funcionalidades foram desenvolvidas. Abaixo tem uma lista do que o controle faz, além de redimensionar imagens:

  • Definição da cor de fundo. É possível definir a cor de fundo utilizando o parâmetro "bg" na URI. Essa cor será visível quando a imagem for de proporções diferentes da solicitada ou quando for gerada a "imagem não diponível".
  • Definição da cor de frente. Parâmetro "fg". É a cor que será utilizada no texto de "imagem não disponível".
  • Definição de texto. Parâmetro "txt". É o texto que aparecerá em "Imagem não disponível".
  • Definição do método do cálculo de proporção. Parâmetro "inside". Define se a imagem deve ser redimensionada para caber inteira dentro da nova proporção ou se haverá cortes nas bordas. Os cortes são feitos em apenas 2 lados, no caso de inside=false.
  • Definição de máscara. Parâmetro "mask". É possível colocar uma máscara translúcida sobre a imagem. A cor e opacidade da máscara são fornecidas no formato ARGB, em um hexadecimal de 8 caracteres. Ex.: mask=88FF0000 é igual a uma máscara vermelha com 50% de opacidade.
  • Definições globais no web.config. É possível definir valores padrão para todos os parâmetros acima, exceto a máscara, no web.config da aplicação.

Documentação

Estou finalizando uma documentação completa do código, com exemplos e detalhes de todos os parâmetros. Essa documentação será disponibilizada no Codeplex ainda nesta semana.

Resumo

Expliquei um pouco sobre o motivo da criação dessa biblioteca e detalhei melhor o funcionamento do gerador de thumbnails. Achei melhor não colocar nenhum código neste post pois o objetivo aqui não era ser técnico. Quem quiser mais detalhes, pode baixar o código fonte no projeto CNZK Web Library no Codeplex e dar uma olhada. Se houver qualquer dúvida ou sugestão, basta postar um comentário no Codeplex neste blog.

Tags: ASP.NET

CNZK Web Library no CodePlex - Agilizando o desenvolvimento em ASP.NET

Acabo de criar um projeto no CodePlex para desenvolvimento de uma biblioteca de componentes reutilizáveis para agilizar o desenvolvimento de web sites utilizando ASP.NET 2.0 e superior.

CNZK Web Library

Jà disponibilizei uma primeira versão para download contendo um HttpHandler para gerar miniaturas de imagens de uma forma extremamente simples. Segue abaixo um exemplo:

URI da imagem original:
img/imagem-original.jpg

URI da imagem redimensionada para 200 x 150:
img/imagem-original.jpg.200x150.thumb.axd

A imagem redimensionada fica armazenada em cache para evitar sobrecarga no processador do servidor. Além disso, se for solicitado o redimensionamento de uma imagem inexistente, será gerada uma imagem com o texto "Imagem não disponível". Isso nos poupa o trabalho de ficar verificando se uma imagem existe ou não antes de escrever sua url na página.

Em breve vou fazer um post entrando em maiores detalhes do código e explicando os conceitos envolvidos. Até lá, façam download, utilizem e me deixem saber o que acham.

Tags: ASP.NET

Webcast sobre Silverlight 2.0 para Aplicações de Negócios

Como eu já comentei em um post anterior, Silverlight não é só para Internet e pode ser utilizado para o desenvolvimento de aplicativos também. Pois esse é justamente o tema de um webcast ao vivo da Microsoft que será realizado hoje (19/03/2008), às 15:00 horas (horário de Brasilia, -3:00).

O webcast é gratuído, terá 90 minutos de duração e será apresentado em inglês. Para obter mais informações ou assistir ao webcast, basta seguir o link abaixo:


Microsoft Webcast : Silverlight 2.0 for Business Applications


Para quem não puder assistir ao vivo, esses webcasts são disponibilizados para download em até 5 dias após a realização (normalmente são disponibilizados em menos de 1 dia). O download será disponibilizado na mesma página acima.

Para assistir ao vivo é aconselhavel acessar o link com uns 10 minutos de antecedência para seja instalado e configurado o software necessário (Live Meeting). Há a opção de utilizar a versão web (um applet Java) mas a experiência com o software instalado é um pouco melhor.

IE8 Beta 1 Disponível para download

Hoje é realmente o dia da novidade. Além de disponibilizar para download toda a família do Silverlight 2 (SDK, tools, runtime, documentação, Blend 2 March, ....), a Microsoft disponibilizou para download o beta 1 do IE8. Pelo pouco que eu vi no streaming do Keynote de abertura, vale a pena o download.

 

Internet Explorer 8 Readiness Toolkit

 

Hoje eu não durmo !!

Tags: MIX08 IE IE8