Manipulação de Imagens com Java: Uma Demonstração Prática

Este artigo demonstra operações comuns de manipulação de imagens usando a linguagem Java, focando em redimensionamento e recorte. A classe principal utiliza a API BufferedImage para processar os pixels da imagem.

import javax.imageio.ImageIO; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.*; import java.util.Iterator;

public class ManipuladorImagens {

/**
 * Redimensiona uma imagem mantendo a proporção original.
 * @param caminhoOrigem caminho do arquivo de imagem original
 * @param caminhoDestino caminho para salvar a imagem redimensionada
 * @param fatorProporcao fator de redução (ex: 2 para reduzir pela metade)
 */
public static void redimensionarProporcional(String caminhoOrigem, String caminhoDestino, int fatorProporcao) throws IOException {
    try (FileInputStream entrada = new FileInputStream(caminhoOrigem);
         FileOutputStream saida = new FileOutputStream(caminhoDestino)) {
        
        BufferedImage imagemOriginal = ImageIO.read(entrada);
        int larguraOriginal = imagemOriginal.getWidth();
        int alturaOriginal = imagemOriginal.getHeight();
        
        int novaLargura = larguraOriginal / fatorProporcao;
        int novaAltura = alturaOriginal / fatorProporcao;
        
        BufferedImage imagemRedimensionada = new BufferedImage(novaLargura, novaAltura, BufferedImage.TYPE_INT_RGB);
        Graphics2D graficos = imagemRedimensionada.createGraphics();
        graficos.drawImage(imagemOriginal, 0, 0, novaLargura, novaAltura, null);
        graficos.dispose();
        
        ImageIO.write(imagemRedimensionada, "jpg", saida);
    }
}

/**
 * Redimensiona uma imagem para dimensões específicas.
 * @param caminhoOrigem caminho da imagem de entrada
 * @param caminhoDestino caminho para a imagem de saída
 * @param larguraDesejada largura final em pixels
 * @param alturaDesejada altura final em pixels
 */
public static void redimensionarFixo(String caminhoOrigem, String caminhoDestino, int larguraDesejada, int alturaDesejada) throws IOException {
    try (FileInputStream entrada = new FileInputStream(caminhoOrigem);
         FileOutputStream saida = new FileOutputStream(caminhoDestino)) {
        
        BufferedImage imagemOriginal = ImageIO.read(entrada);
        
        BufferedImage novaImagem = new BufferedImage(larguraDesejada, alturaDesejada, BufferedImage.TYPE_INT_RGB);
        Graphics2D graficos = novaImagem.createGraphics();
        graficos.drawImage(imagemOriginal, 0, 0, larguraDesejada, alturaDesejada, null);
        graficos.dispose();
        
        ImageIO.write(novaImagem, "png", saida);
    }
}

/**
 * Recorta uma área específica de uma imagem.
 * @param caminhoOrigem caminho da imagem a ser recortada
 * @param caminhoDestino caminho para salvar o recorte
 * @param x coordenada X do canto superior esquerdo da área de recorte
 * @param y coordenada Y do canto superior esquerdo da área de recorte
 * @param larguraRecorte largura da área de recorte
 * @param alturaRecorte altura da área de recorte
 */
public static void recortarImagem(String caminhoOrigem, String caminhoDestino, int x, int y, int larguraRecorte, int alturaRecorte) throws IOException {
    try (FileInputStream entradaArquivo = new FileInputStream(caminhoOrigem)) {
        Iterator<ImageReader> leitores = ImageIO.getImageReadersByFormatName("jpg");
        if (!leitores.hasNext()) {
            throw new IOException("Nenhum leitor de imagem encontrado para o formato especificado.");
        }
        
        ImageReader leitor = leitores.next();
        try (ImageInputStream fluxoImagem = ImageIO.createImageInputStream(entradaArquivo)) {
            leitor.setInput(fluxoImagem, true);
            
            ImageReadParam parametros = leitor.getDefaultReadParam();
            Rectangle areaRecorte = new Rectangle(x, y, larguraRecorte, alturaRecorte);
            parametros.setSourceRegion(areaRecorte);
            
            BufferedImage imagemRecortada = leitor.read(0, parametros);
            ImageIO.write(imagemRecortada, "jpg", new File(caminhoDestino));
        } finally {
            leitor.dispose();
        }
    }
}

}


</div>Acima, a classe `ManipuladorImagens` oferece três métodos estáticos principais. A exceção de `redimensionarProporcional` é lançada quando o fator de proporção não é válido. Os métodos seguem um fluxo similar: ler a imagem original, criar um novo `BufferedImage`, usar `Graphics2D` para desenhar/redimensionar, e fnialmente escrever a saída.

### Conceitos Fundamentais do BufferedImage

O `BufferedImage` é uma classe fundamnetal na manipulação de imagens em memória. A criação de um objeto ocorre com base no tipo de cor desejado:

- `BufferedImage.TYPE_INT_RGB`: Cria uma imagem sem canal alfa (transparência).
- `BufferedImage.TYPE_INT_ARGB`: Cria uma imagem com canal alfa, permitindo transparência.

### Conversões Entre BufferedImage e Array de Bytes

É comum precisar converter uma imagem em memória (`BufferedImage`) para um array de bytes (`byte[]`), por exemplo, para enviar via rede ou armazenar em banco de dados.

**BufferedImage para byte\[\]:**

ByteArrayOutputStream fluxoBytes = new ByteArrayOutputStream(); ImageIO.write(imagemBuffer, "png", fluxoBytes); byte[] dadosDaImagem = fluxoBytes.toByteArray();


**byte\[\] para BufferedImage:**

ByteArrayInputStream fluxoEntrada = new ByteArrayInputStream(dadosDaImagem); BufferedImage imagem = ImageIO.read(fluxoEntrada);


Essas conversões são essenciais para integrar o processamento de imagens com outros sistemas, como APIs REST ou bibliotecas que manipulam dados binários.

Tags: java BufferedImage Manipulação de Imagens Java2D ImageIO

Publicado em 6-10 04:37 por Thomas