Programming/Java

java image resize library 이미지 리사이즈 라이브러리 비교해보기

Jan92 2023. 7. 15. 00:33

Compare java image resizing libraries

java 이미지 리사이징 라이브러리 비교

해당 포스팅에서는 썸네일 생성 등, 이미지의 사이즈를 조절하는 기능을 java에서 구현하기 위해 사용할 수 있는 몇 가지 라이브러리와 해당 라이브러리들의 사용 방법에 대해 살펴봅니다.

+ 마지막에는 각 라이브러리들을 사용한 image resizing 결과를 비교해 보는 내용도 포함되어 있습니다.

 

  • java.awt.Graphics2D
  • Image.getScaledInstance()
  • thumbnailator
  • Imgscalr

1. java.awt.Graphics2D

'Graphics2D Class'는 graphics contexts에 대한 추상화를 제공하는 기본 클래스인 Graphics Class를 확장한 것으로 java 플랫폼에서 2차원 텍스트나 모양, 이미지를 렌더링 하기 위한 기본 클래스입니다.

(해당 클래스는 BufferedImage에 있는 데이터를 2D 좌표에서 연산하기 위해 사용됩니다.)

 

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
    BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D graphics2D = resizedImage.createGraphics();
    graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
    graphics2D.dispose();
    return resizedImage;
}

(Graphics2D를 사용한 기본적인 이미지 리사이징 코드)

 

Graphics2D 클래스를 통한 기본적인 이미지 리사이징은 다음과 같이 진행되며, 여기서 핵심인 drawImage() 메서드는 지정된 사각형의 크기에 맞게 이미지를 그리는 역할을 합니다.

drawImage() 메서드의 마지막 매개변수로 사용되는 ImageObserver는 비동기적으로 로드되는 이미지에 대한 업데이트를 애플리케이션에 알려주는 역할을 하며 일반적으로 null이 들어갑니다.

 

이어서 사용되는 dispose() 메서드의 경우 해당 graphics context를 사용하고 있는 모든 시스템 리소스를 해제하는 기능을 하며, dispose()가 호출된 이후에는 해당 그래픽 개체를 사용할 수 없습니다.

(garbage collector에서도 해당 리소스에 대한 처리를 하지만, 직접 dispose 메서드를 호출해서 처리하는 것이 효율성 측면에서 좋습니다.)

 

 

Graphics2D graphics2D = resizedImage.createGraphics();

//RenderingHints
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT);

graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);

(RenderingHints를 적용하는 코드)

 

추가로 Graphics2D 클래스에서는 다음과 같이 java.awt.RenderingHints 속성을 사용하여 이미지 렌더링 품질을 제어할 수 있는데요.

RenderingHints 속성을 통해 렌더링 품질을 우선으로 하거나 속도를 우선으로 하는 등의 지정을 할 수 있으며, 자세한 옵션은 아래 'Controlling Rendering Quality'에 대한 글을 참고하시면 좋을 것 같습니다.

 

https://docs.oracle.com/javase/tutorial/2d/advanced/quality.html

 

* 참고사항으로 모든 플랫폼에서 렌더링 품질 제어를 지원하는 것은 아니기 때문에 RenderingHints 속성을 설정하더라도 동작하지 않는 경우가 발생할 수 있습니다.

 

 

***

new BufferedImage() 생성자 메서드의 BufferedImage.TYPE_INT_RGB 매개변수는 이미지의 색상 모델을 나타내는데요.

이 외에 사용 가능한 이미지 색상 모델은 아래 'BufferedImage Class' oracle java 공식 문서에서 확인할 수 있습니다.

 

https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/java/awt/image/BufferedImage.html

 

 


2. Image.getScaledInstance()

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
    Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_DEFAULT);
    BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
    outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);
    return outputImage;
}

(Image 클래스의 getScaledInstacne 메서드를 사용한 기본적인 이미지 리사이징 코드)

 

java.awt 패키지의 'Image' 추상 클래스는 그래픽 이미지를 작성 또는 수정하기 위한 클래스들의 최상위 클래스입니다.

getScaledInstance() 메서드를 통해 대상 이미지의 크기가 조정된 새 이미지 개체를 반환하는데요.

해당 메서드에서 이미지 개체 생성 시 사용할 수 있는 알고리즘은 아래와 같습니다.

 

Image.SCALE_AREA_AVERAGING   //Area Averaging 이미지 스케일링 알고리즘 사용
Image.SCALE_DEFAULT          //기본 이미지 스케일링 알고리즘 사용
Image.SCALE_FAST             //생성되는 이미지의 품질보다 이미지 생성 속도를 우선으로 하는 알고리즘 사용
Image.SCALE_REPLICATE        //ReplicateScaleFilter 클래스에 구현된 이미지 스케일링 알고리즘 사용
Image.SCALE_SMOOTH           //이미지 생성 속도보다 생성되는 이미지의 품질을 우선으로 하는 알고리즘 사용

 

 


3. thumbnailator

<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.20</version>
</dependency>
// https://mvnrepository.com/artifact/net.coobird/thumbnailator
implementation group: 'net.coobird', name: 'thumbnailator', version: '0.4.20'

(maven 및 gradle 의존성 추가)

 

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException {
    return Thumbnails.of(originalImage)
            .size(targetWidth, targetHeight)
            .asBufferedImage();
}

(thumbnailator 라이브러리를 사용한 기본적인 이미지 리사이징 코드)

 

thumbnailator는 최근까지도 업데이트가 진행되고 있는 라이브러리인데요.

(2023년 6월 28일 0.4.20 버전 출시)

 

예시와 같이 BufferedImage를 통해 이미지 리사이징도 수행할 수 있지만, 아래와 같이 BufferedImage 또는 Graphics2D 개체를 직접 다루지 않고 'Thumbnails' 만을 사용해서 이미지 리사이징을 수행할 수 있다는 특징이 있습니다.

 

 

void resizeImage(int targetWidth, int targetHeight) throws IOException {
    Thumbnails.of(new File("original.jpg"))
            .size(targetWidth, targetHeight)
            .toFile(new File("thumbnail.jpg"));
}

(BufferedImage가 아닌 File을 직접 사용하는 코드)

 

아래 thumbnailator의 github 예시를 살펴보면 단순한 이미지 리사이징 외에도 이미지 리사이징 시 이미지를 회전하거나 워터마크를 삽입하는 등의 기능을 수행할 수 있습니다.

 

https://github.com/coobird/thumbnailator/wiki/Examples 

 

 


4. Imgscalr

<!-- https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib -->
<dependency>
    <groupId>org.imgscalr</groupId>
    <artifactId>imgscalr-lib</artifactId>
    <version>4.2</version>
</dependency>
// https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib
implementation group: 'org.imgscalr', name: 'imgscalr-lib', version: '4.2'

(maven 및 gradle 의존성 추가)

 

BufferedImage resizeImage5(BufferedImage originalImage, int targetWidth, int targetHeight) {
    return Scalr.resize(originalImage, targetWidth, targetHeight);
}

(imgscalr 라이브러리를 사용한 기본적인 이미지 리사이징 코드)

 

'Imgscalr'를 사용한 기본적인 이미지 리사이징은 다음과 같이 간단하게 사용할 수 있는데요.

Imgscalr의 경우 내부 동작 과정을 살펴보면 내부적으로 Graphics2D를 사용하여 동작한다는 것을 알 수 있습니다.

 

 

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
    return Scalr.resize(originalImage, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC
        ,targetWidth, targetHeight, Scalr.OP_ANTIALIAS);
}

(이미지 스케일링 옵션을 설정한 코드)

 

이미지 리사이징 시 스케일링 옵션을 설정하고 싶은 경우에는 다음과 같이 사용할 수도 있는데요.

Scalr.Method의 경우 이미지 스케일링의 품질 또는 속도를 우선으로 지정할 수 있으며, Scalr.Mode는 리사이징 모드를 설정하는 것으로 이미지를 지정된 너비 또는 높이에 맞추거나 둘 다에 맞추는 등의 모드를 지정할 수 있습니다.

 

Scalr.Method 옵션  =>  AUTOMATIC, SPEED, BALANCED, QUALITY, ULTRA_QUALITY

Scalr.Mode 옵션  =>  AUTOMATIC, FIT_EXACT, FIT_TO_WIDTH, FIT_TO_HEIGHT

 

 


5. 비교

java 이미지 리사이징 비교

다음 이미지는 3024 x 3024 사이즈의 이미지를 각 라이브러리를 통해 300 x 300 이미지로 리사이징 한 결과인데요.

높은 품질의 이미지 리사이징을 대략적인 기준으로 잡아 작업한 결과이며, 각각의 라이브러리에 대한 리사이징 옵션에 따라 결과가 다를 수 있습니다.

 

리사이징 평균 동작 시간으로는 'Graphics2D를 사용했을 때 47ms'가 나왔으며, 'Image.getScaledInstance()를 사용했을 때 539ms', 'thumbnailator 라이브러리를 사용했을 때 282ms', 'Scalr 라이브러리를 사용했을 때 1468ms'가 나왔습니다.

 

리사이징 품질로 봤을 때는 Graphics2D와 Scalr(내부적으로 Graphics2D를 사용)가 나머지에 비해 떨어지는 것을 볼 수 있는데요.

필요한 용도에 따라 다르겠지만 일반적으로 시간 대비 품질로는 thumbnailator 라이브러리가 가장 효율적인 것 같습니다.

 

 

 

< 참고 자료 >

https://www.baeldung.com/java-resize-image

https://babble-dev.tistory.com/39