Quem aqui nunca precisou pegar uma imagem de 2000x1800 e colocar em um espaço de 500x500? É exatamente esse problema que esse post vem resolver. Na verdade, precisamos fazer um calculo ninja jedi para conseguir escalar a imagem.
Esse calculo consiste em:
- Descobrir o que é menor na imagem, se é a altura ou a largura.
- Caso existir um lado menor, descobir seu percentual em relação ao lado maior.
- Agora em cima do espaço disponível (500x500)temos que tirar o percentual calculado anteriormente do menor lado da imagem.
Se a imagem já tiver altura igual a largura, nada será feito.
Então aqui está ele, o calculo, pronto para uso.
class ImageResizerService {
public byte[] read(String file) {
byte[] buffer = new byte[1024];
InputStream is = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
while (is.read(buffer) != -1) {
out.write(buffer);
}
try {
return out.toByteArray();
}finally {
is.close()
out.close()
}
}
public byte[] read(String file, double requiredWidth, double requiredHeight) {
BufferedImage imagem = ImageIO.read(new File(file));
double originalWidth = imagem.getWidth();
double originalHeight = imagem.getHeight();
double newWidth = 0;
double newHeight = 0;
double diff = 0;
if (requiredHeight == 0) {
requiredHeight = requiredWidth;
}
if (requiredWidth == 0) {
requiredWidth = requiredHeight;
}
if(originalWidth < requiredWidth && originalHeight < requiredHeight){
return read(file)
}
if(requiredWidth == 0 && requiredHeight == 0){
return read(file)
}
if (originalWidth > originalHeight) {
diff = originalWidth - originalHeight;
newWidth = requiredWidth;
diff = diff / originalWidth;
newHeight = newWidth - (newWidth * diff);
} else if (originalWidth < originalHeight) {
diff = originalHeight - originalWidth;
newHeight = requiredHeight;
diff = diff / originalHeight;
newWidth = newHeight - (newHeight * diff);
} else {
if (requiredHeight > requiredWidth) {
requiredHeight = requiredWidth;
} else if (requiredHeight < requiredWidth) {
requiredWidth = requiredHeight;
}
newHeight = requiredHeight;
newWidth = requiredWidth;
}
int type = BufferedImage.TYPE_INT_RGB;
boolean isPng = file.toUpperCase().endsWith("PNG")
if (isPng) {
type = BufferedImage.BITMASK;
}
BufferedImage new_img = new BufferedImage((int) newWidth, (int) newHeight, type);
Graphics2D g = new_img.createGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(imagem, 0, 0, (int) newWidth, (int) newHeight, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (isPng) {
ImageIO.write(new_img, "PNG", out);
}else{
ImageIO.write(new_img, "JPG", out);
}
try {
return out.toByteArray();
} finally {
out.close();
}
}
}
Se esse é o melhor ou mais fácil algoritimo não sei, desenvolvi ele apartir da minha necessidade, e até o momento não tive problemas com "deformação" de imagens. Ah, e notem que caso seja solicitada uma um tamanho maior do que o tamanho da imagem existente, ele não faz nada, pois o objetivo é não perder a qualidade da imagem. E caso o tamanho solicitado seja menor do que a imagem existente mas não obedeça suas proporções, ele manterá a proporção, não obedecendo as medidas silicitadas, sempre nivelando por um dos valores (altura ou largura). Nesse caso, pomos sempre passar ou só largura, ou só altura.
Até a próxima!
Obrigado por compartilhar
ResponderExcluirExcelente algoritmo, deu certinho
ResponderExcluirMuito obrigado por compartilhar!