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.