Início > Programação > Como Escrever Imagens em um Servlet com o Pacote imageio

Como Escrever Imagens em um Servlet com o Pacote imageio

Quando preciso apresentar uma imagem em uma página web à partir da leitura de um arquivo em disco, utilizo um Servlet e um código mais ou menos assim para ler o arquivo e escrever seus bytes no Servlet:

BufferedInputStream input = new BufferedInputStream(image.getContent());
BufferedOutputStream output = 
   new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[8192];
for (int length = 0; (length = input.read(buffer)) > 0) {
   output.write(buffer, 0, length);
}

Sempre me incomodei com essa história de ter que escrever a imagem byte a byte na response. O problema é que além de não ser performático, não temos controle sobre a qualidade da imagem. Quando trabalhei com Swing e Java 2D, utilizei a classe JPEGImageEncoder do pacote com.sun.image.codec.jpeg para controlar a qualidade das imagens. É possível utilizar essa API na web, mas o Java 7 tem o pacote imageio. Quem ainda utiliza o JPEGImageEncoder deve migrar para ImageIO.

Depois de pesquisar um pouco e de fazer algumas tentativas de como fazer a mesma implementação com o Java 7, o resultado não ficou muito bom. As imagens JPEG estavam perdendo resolução. Encontrei uma implementação do Spring que me inspirou a fazer a minha. Nessa implementação, utilizo a classe ImageWriteParam para controlar a qualidade da imagem:

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
   String filePath = request.getParameter("filePath");
   File file = new File(filePath);
   BufferedImage read = ImageIO.read(file);
   ImageOutputStream imageOutputStream = imageOutputStream = 
      new MemoryCacheImageOutputStream(response.getOutputStream());
   String mimeType = getServletContext().getMimeType(file.getName());
   Iterator<ImageWriter> imageWriters = 
      ImageIO.getImageWritersByMIMEType(mimeType);
   if (imageWriters.hasNext()) {
      response.setContentType(mimeType);
      response.setHeader("Content-Disposition", 
         "inline; filename=\"" + file.getName() + "\"");
      ImageWriter imageWriter = imageWriter = imageWriters.next();
      ImageWriteParam iwp = imageWriter.getDefaultWriteParam();
      iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
      iwp.setCompressionQuality(1.0f);
      imageWriter.setOutput(imageOutputStream);
      imageWriter.write(null, new IIOImage(read, null, null), iwp);
   }
   file.delete();
}

Na implementação do Spring utiliza-se a classe MemoryCacheImageOutputStream, que faz bufferização da escrita e da leitura do stream. A implementação funcionou bem para arquivos JPEG, mas vi uma UnsupportedOperationException quando tentei escrever uma imagem PNG. Como a exceção explicava, o problema era a compressão do arquivo.

No stackoverflow foi indicado que se utilizasse o métoddo canWriteCompressed() da classe ImageWriteParam para verificar se o objeto writer de determinado tipo de imagem suporta compressão. Sendo assim, basta substituir as linhas (18) e (19) do código acima pelas linhas abaixo:

if (iwp.canWriteCompressed()) { 
   iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
   iwp.setCompressionQuality(1.0f);
}
Anúncios
  1. Nenhum comentário ainda.
  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: