Preciso redimensionar arquivos PNG, JPEG e GIF. Como posso fazer isso usando Java?
Preciso redimensionar arquivos PNG, JPEG e GIF. Como posso fazer isso usando Java?
Respostas:
Depois de carregar a imagem, você pode tentar:
BufferedImage createResizedCopy(Image originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
System.out.println("resizing...");
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
FWIW Acabei de lançar (Apache 2, hospedado no GitHub) uma biblioteca simples de dimensionamento de imagens para Java chamada imgscalr (disponível no Maven central ).
A biblioteca implementa algumas abordagens diferentes para o dimensionamento de imagens (incluindo a abordagem incremental de Chris Campbell com alguns aprimoramentos menores) e escolherá a melhor abordagem para você, se você pedir, ou fornecerá a aparência mais rápida ou bonita (se você peça isso).
O uso é simples, apenas um monte de métodos estáticos. O caso de uso mais simples é:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
Todas as operações mantêm as proporções originais da imagem; portanto, neste caso, você está solicitando ao imgscalr que redimensione sua imagem dentro de limites de 200 pixels de largura e 200 pixels de altura e, por padrão, selecionará automaticamente a abordagem mais rápida e bonita para isso, pois não foi possível. não especificado.
Percebo desde o início que isso se parece com autopromoção (é), mas gastei minha parte justa do tempo pesquisando exatamente esse mesmo assunto e continuei apresentando diferentes resultados / abordagens / pensamentos / sugestões e decidi sentar e escrever uma implementação simples que abordaria os casos de uso de 80 a 85% em que você tem uma imagem e provavelmente deseja uma miniatura para ela - o mais rápido possível ou o mais bonito possível (para aqueles que tentaram, você notará fazendo uma Graphics.drawImage, mesmo com interpolação BICUBIC em uma imagem pequena o suficiente, ainda parece lixo).
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. Também gosto do seu jeito e acho que é mais simples.
Thumbnailator é uma biblioteca de redimensionamento de imagem de código aberto para Java com uma interface fluente, distribuída sob a licença MIT.
Eu escrevi esta biblioteca porque criar miniaturas de alta qualidade em Java pode ser surpreendentemente difícil e o código resultante pode ser bastante confuso. Com o Thumbnailator, é possível expressar tarefas bastante complicadas usando uma API fluente simples.
Um exemplo simples
Para um exemplo simples, é possível obter uma imagem e redimensioná-la para 100 x 100 (preservando a proporção da imagem original) e salvando-a em um arquivo em uma única declaração:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
Um exemplo avançado
A execução de tarefas complexas de redimensionamento é simplificada com a interface fluente do Thumbnailator.
Vamos supor que queremos fazer o seguinte:
0.85
,thumbnail.
anexados ao inícioTraduzido para o Thumbnailator, poderíamos executar o acima com o seguinte:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Uma observação sobre a qualidade e velocidade da imagem
Essa biblioteca também usa o método de dimensionamento bilinear progressivo destacado em Filthy Rich Clients por Chet Haase e Romain Guy, a fim de gerar miniaturas de alta qualidade e garantir um desempenho de tempo de execução aceitável.
Você não precisa de uma biblioteca para fazer isso. Você pode fazer isso com o próprio Java.
Chris Campbell tem um excelente e detalhado artigo sobre dimensionamento de imagens - consulte este artigo .
Chet Haase e Romain Guy também têm uma descrição detalhada e muito informativa do dimensionamento de imagens em seu livro Filthy Rich Clients .
O Java Advanced Imaging agora é de código aberto e fornece as operações necessárias.
Se você está lidando com imagens grandes ou deseja um resultado bonito, não é uma tarefa trivial em java. Simplesmente fazê-lo através de uma operação de revenda via Graphics2D não criará uma miniatura de alta qualidade. Você pode fazer isso usando JAI, mas requer mais trabalho do que você imagina para obter algo que pareça bom e a JAI tem o hábito desagradável de explodir nossa JVM com erros OutOfMemory.
Eu sugiro usar o ImageMagick como um executável externo, se você puder se safar. É simples de usar e faz o trabalho corretamente para que você não precise.
A API Java não fornece um recurso de escala padrão para imagens e redução da qualidade da imagem.
Por causa disso, tentei usar o cvResize do JavaCV, mas parece causar problemas.
Encontrei uma boa biblioteca para dimensionamento de imagens: basta adicionar a dependência para "java-image-scaling" no seu pom.xml.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
No repositório maven, você obterá a versão recente para isso.
Ex. No seu programa java
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Você pode tentar usar o GraphicsMagick Image Processing System com o im4java como uma interface de linha de para Java.
Existem muitas vantagens do GraphicsMagick, mas uma por todas:
Image Magick foi mencionado. Existe um projeto de front end da JNI chamado JMagick. Não é um projeto particularmente estável (e se sabe que o Image Magick muda muito e até quebra a compatibilidade). Dito isso, tivemos uma boa experiência usando o JMagick e uma versão compatível do Image Magick em um ambiente de produção para executar o dimensionamento com alta taxa de transferência e baixa latência. A velocidade foi substancialmente melhor do que com uma biblioteca de gráficos Java que tentamos anteriormente.
Basta usar a resposta de Burkhard, mas adicione esta linha depois de criar os gráficos:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Você também pode definir o valor como BICUBIC, ele produzirá uma imagem de melhor qualidade, mas é uma operação mais cara. Existem outras dicas de renderização que você pode definir, mas eu descobri que a interpolação produz o efeito mais notável. Lembre-se de que, se você quiser aumentar bastante o zoom, o código java provavelmente será muito lento. Acho que imagens maiores começam a produzir lag em torno de 300% de zoom, mesmo com todas as dicas de renderização definidas para otimizar a velocidade sobre a qualidade.
Você pode usar o Marvin (estrutura de processamento de imagem Java pura) para esse tipo de operação: http://marvinproject.sourceforge.net
Escala de plug-in: http://marvinproject.sourceforge.net/en/plugins/scale.html
Acontece que escrever um scaler de desempenho não é trivial. Eu fiz isso uma vez para um projeto de código aberto: ImageScaler .
Em princípio, 'java.awt.Image # getScaledInstance (int, int, int)' também faria o trabalho, mas há um bug desagradável com isso - consulte meu link para obter detalhes.
Eu desenvolvi uma solução com as classes disponíveis gratuitamente (AnimatedGifEncoder, GifDecoder e LWZEncoder) disponíveis para lidar com animação GIF.
Você pode fazer o download do jar jgifcode e executar a classe GifImageUtil. Link: http://www.jgifcode.com
você pode usar o seguinte produto popular: thumbnailator
Se você não deseja importar o imgScalr como a resposta de @Riyad Kalla acima da qual eu testei também funciona bem, você pode fazer isso com Peter Walser, responda a @ Peter Walser em outra questão:
/**
* utility method to get an icon from the resources of this class
* @param name the name of the icon
* @return the icon, or null if the icon wasn't found.
*/
public Icon getIcon(String name) {
Icon icon = null;
URL url = null;
ImageIcon imgicon = null;
BufferedImage scaledImage = null;
try {
url = getClass().getResource(name);
icon = new ImageIcon(url);
if (icon == null) {
System.out.println("Couldn't find " + url);
}
BufferedImage bi = new BufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
// paint the Icon to the BufferedImage.
icon.paintIcon(null, g, 0,0);
g.dispose();
bi = resizeImage(bi,30,30);
scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
imgicon = new ImageIcon(scaledImage);
} catch (Exception e) {
System.out.println("Couldn't find " + getClass().getName() + "/" + name);
e.printStackTrace();
}
return imgicon;
}
public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
float scaleX = (float) areaWidth / image.getWidth();
float scaleY = (float) areaHeight / image.getHeight();
float scale = Math.min(scaleX, scaleY);
int w = Math.round(image.getWidth() * scale);
int h = Math.round(image.getHeight() * scale);
int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
boolean scaleDown = scale < 1;
if (scaleDown) {
// multi-pass bilinear div 2
int currentW = image.getWidth();
int currentH = image.getHeight();
BufferedImage resized = image;
while (currentW > w || currentH > h) {
currentW = Math.max(w, currentW / 2);
currentH = Math.max(h, currentH / 2);
BufferedImage temp = new BufferedImage(currentW, currentH, type);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(resized, 0, 0, currentW, currentH, null);
g2.dispose();
resized = temp;
}
return resized;
} else {
Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = resized.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(image, 0, 0, w, h, null);
g2.dispose();
return resized;
}
}
Tente este método a seguir:
ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);