Gerar imagens dinâmicas com servlets

HTTP Servlets tem utilidade mais interessante do que apenas Front Controllers e gerar código HTML. Um dos recursos mais bacanas é a possibilidade de gerar conteúdo binário em tempo de execução. Nesse post demonstrarei como desenhar uma imagem dinâmica utilizando Servlets. A idéia veio da necessidade do Cássio em extrair páginas de PDF e exibir como imagens em uma aplicação Web.

Vamos criar uma Servlet onde o usuário poderá realizar uma requisição via GET da URL “imagem.png” passando um parâmetro “texto” e a Servlet irá retornar uma imagem com uma bolinha e o texto digitado.

Estou utilizando Servlet 3.0, mas o código do método get pode ser utilizado em qualquer outra versão de Servlets sem necessidade de alteração.

[sourcecode lang=”java” highlight=”35,56″]package br.com.thiagovespa.samples.imagem;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Gera uma imagem com um texto passado por parâmetro
*
* @author Thiago Galbiatti Vespa
*/
@WebServlet("/imagem.png")
public class ImagemServlet extends HttpServlet {

private static final long serialVersionUID = 201011231103L;

public ImagemServlet() {
super();
}

@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// A imagem é um png – Poderia ser qualquer outro tipo
response.setContentType("image/png");

// Recupera o parâmetro
String text = request.getParameter("texto");

// Cria uma imagem de tamanho 500×50
BufferedImage image = new BufferedImage(500, 50,
BufferedImage.TYPE_INT_ARGB);

// Cria o canvas pra desenho
Graphics2D canvas = image.createGraphics();
canvas.setColor(Color.BLUE);
// Desenha um círculo azul
canvas.fillOval(10, 10, 10, 10);
canvas.setColor(Color.RED);
canvas.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
// Desenha o texto em vermelho
canvas.drawString(text != null ? text : "Nenhum texto informado!", 25,
20);
OutputStream out = null;
try {
out = response.getOutputStream();
// Escreve a imagem no outputstream da response no formato png
ImageIO.write(image, "PNG", out);
} finally {
if (out != null) {
out.close();
}
}
}

}
[/sourcecode]

Fiz vários comentários no código para facilitar a compreensão de quem está começando e para eu não precisar explicar linha a linha o que o código está fazendo :). O código importante  para gerar qualquer conteúdo binário é o que está destacado na linha 35, que seta o mime-type correto para a servlet exibir e o da linha 56 que recupera o OutputStream (binário) para escrever algum conteúdo nele.

Para utilizar o mime-type correto pro seu tipo de conteúdo, você pode utilizar a tabela da W3School disponível nesse link: http://www.w3schools.com/media/media_mimeref.asp

Agora é só fazer o deploy de um projeto com essa Servlet e acessá-la passando um parâmetro. O resultado você pode ver na imagem abaixo:

imagem.png (500×50)
imagem.png (500×50)

Para exibir dentro de uma página HTML é só referenciar o endereço da Servlet no atributo src da tag img. Por exemplo:

[sourcecode lang=”html” highlight=”9″]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Exemplo imagem</title>
</head>
<body>
Olha minha imagem a&iacute; em baixo<br/>
<img src="imagem.png?texto=Imagem gerada!"/>
</body>
</html>
[/sourcecode]

O browser irá exibir o conteúdo da imagem gerada dinâmicamente:

Exemplo imagem
Exemplo imagem

Agora é só programar a Servlet para gerar o que você quiser!.

Esse conceito é utilizado para geração de CAPTCHAs, PDF, XLS, e outros arquivos binários dinamicamente.

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6