sábado, 8 de setembro de 2012

Redimensionar Imagem em Java

Salve galera,

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!

2 comentários: