-1

is it possible to keep the image quality when resize it in java? this is my code:

package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;

@Slf4j
public class DemoApplicationSlim {
    public static void main(String[] args) throws Exception {
        String filePath = "/Users/john/Downloads/zj/test.jpeg";
        Path path = Paths.get(filePath);
        byte[] bytes = Files.readAllBytes(path);
        String base64Origin = Base64.getEncoder().encodeToString(bytes);
        BufferedImage resizedIdPhoto = new BufferedImage(300, 400, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = resizedIdPhoto.createGraphics();
        BufferedImage img = Base64ToBufferImage(base64Origin);
        graphics.drawImage(img, 0, 0, 300, 400, null);
        String b64Resize = bufferImageToBase64(resizedIdPhoto, "png");
        saveImage(base64Origin,"/Users/john/Downloads/hr-origin.jpeg");
        saveImage(b64Resize,"/Users/john/Downloads/hr-resize.jpeg");
    }

    private static void saveImage(String base64Image, String imagePath) {
        try {
            byte[] imageBytes = Base64Coder.decode(base64Image);
            File imageFile = new File(imagePath);
            if (!imageFile.exists()) {
                imageFile.createNewFile();
            }
            FileOutputStream outputStream = new FileOutputStream(imageFile);
            outputStream.write(imageBytes);
            outputStream.flush();
            outputStream.close();
            System.out.println("save success:" + imagePath);
        } catch (IOException e) {
            log.error("save file failed",e);
        }
    }

    public static BufferedImage Base64ToBufferImage(String base64) {
        BufferedImage image = null;
        byte[] imageBytes;
        imageBytes = Base64.getDecoder().decode(base64);
        try (ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes)) {
            image = ImageIO.read(bis);
        } catch (IOException ex) {
            log.error("read  image error", ex);
        }
        return image;
    }

    public static String bufferImageToBase64(BufferedImage image, String format) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        javax.imageio.ImageIO.write(image, format, baos);
        byte[] bytes = baos.toByteArray();
        String base64 = Base64.getEncoder().encodeToString(bytes);
        return base64;
    }
}

now I found a issue it that when I resized the image, the resized output image loss so much quality. is it possible to keep original quality when resize? I have found this lib https://github.com/rkalla/imgscalr but it stop maintain for 5 years.

spark
  • 663
  • 1
  • 5
  • 18
  • Why are you using base64 at all in your code? I don't see anything in there which requires it... – Jon Skeet May 13 '23 at 12:00
  • this image I will send to the cloud service to remove background, the cloud service api that accept base64 string. @JonSkeet – spark May 13 '23 at 12:14
  • 1
    Right, but none of that's relevant to the aspect of resizing the image, right? You'd only need to encode it as base64 after doing everything else - which means it's irrelevant to this question. (I'd also recommend avoiding base64 encoding until the final step in your real code, too - it'll make your code much simpler and cleaner.) – Jon Skeet May 13 '23 at 14:14
  • yes, you are correct. I just use this code to show the issue. the resize will happen in the step flow because I need to generate different size of photo, it will used by different countries id card. each countries has there own specification. – spark May 13 '23 at 14:50
  • "I just use this code to show the issue." But the base64 part is irrelevant to the issue, and so shouldn't be in the question. Ideally, Stack Overflow questions should show minimal but complete code required to reproduce the issue - anything irrelevant is a distraction. – Jon Skeet May 13 '23 at 14:53

1 Answers1

0

Finally I found thumbnailator https://github.com/coobird/thumbnailator can handle this, first import the dependencies:

implementation 'net.coobird:thumbnailator:0.4.19'

then resize the image like this:

Thumbnails.of("/Users/John/Downloads/zj/test.jpeg")
                .size(300,400)
                .toFile("/Users/John/Downloads/hr-thumbnail.jpeg");

the resized image quality are perfect.

spark
  • 663
  • 1
  • 5
  • 18
  • 1
    You may also want to have a look at the discussion in [this question](https://stackoverflow.com/questions/14115950/quality-of-image-after-resize-very-low-java) – MadProgrammer May 13 '23 at 12:42