Java로 썸네일(Thumbnail) 이미지 만들기

프로그래밍/자바 2018. 4. 9. 21:00
반응형

갤러리와 같은 웹애플리케이션을 만들게 되면 이미지의 썸네일을 만들게 됩니다. 가끔 보면 썸네일 없이 원본이미지를 줄여서 보여주고 있는곳이 있는데, 모바일 환경이라면 시간과 데이터 사용량이 많이 소비가 될 것입니다.


이번 예제에서는 "스프링프레임웍 ajax 파일업로드 - jQuery, FormData, jQuery Form Plugin 사용" 에서 사용한 이미지 업로드 프로젝트에 썸네일 생성 기능을 추가해 봅니다. Java 환경에서 썸네일을 만들기 위해서 Scalr 라이브러리를 사용합니다. 이 라이브러리는 다음 URL에서 다운로드 할 수 있습니다.


https://github.com/rkalla/imgscalr


메이븐을 사용중이라면 pom.xml 파일에 다음 의존성을 추가하면 됩니다.

 

<dependency>
    <groupId>org.imgscalr</groupId>
    <artifactId>imgscalr-lib</artifactId>
    <version>4.2</version>
</dependency>

 

썸네일을 만들때는 다음과 같은 문제를 고려해야 만합니다.


가로, 세로 이미지일 경우



위의 이미지에서 보는 것과 같이 원본 이미지의 너비와 높이의 비율이 우리가 화면에 보여 주고자 하는 썸네일의 비율과 다를 수 있다는 것 입니다. 이것을 처리하는 여러가지 방법이 있을 수 있는데, 여기서는 만들려고하는 썸네일 이미지의 비율과 같으면서 원본 이미지를 꽉 채울 수 있는 크기로 원본 이미지를 크롭한 후 그것으로 썸네일을 생성합니다. 만약, 원본 이미지가 썸네일 보다 작다면 확대가 될 것입니다.


코드를 보겠습니다. 샘플 프로젝트의 HomeController.java 파일에 추가된 내용 입니다. upload 메소드에서 업로드된 파일을 저장하는 부분에서 저장후 썸네일을 만들도록 하였습니다.

 

import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import org.imgscalr.Scalr;

...

for(int i = 0; i < mpf.size(); i++) {
    String originalFileName =  mpf.get(i).getOriginalFilename();
    int index = originalFileName.lastIndexOf(".");
    String fileName = originalFileName.substring(0, index);
    String fileExt = originalFileName.substring(index + 1);

    File file = new File(PATH + originalFileName);
    logger.info(file.getAbsolutePath());
    
    mpf.get(i).transferTo(file);
    
    // 썸네일을 생성하는 메소드를 호출합니다.
    makeThumbnail(file.getAbsolutePath(), originalFileName, fileExt);
    
}

 

썸네일 생성을 담당하고 있는 메소드 입니다.

 

/** * 썸네일을 생성합니다. * 250 x 150 크기의 썸네일을 만듭니다. */ private void makeThumbnail(String filePath, String fileName, String fileExt) throws Exception { // 저장된 원본파일로부터 BufferedImage 객체를 생성합니다. BufferedImage srcImg = ImageIO.read(new File(filePath)); // 썸네일의 너비와 높이 입니다. int dw = 250, dh = 150; // 원본 이미지의 너비와 높이 입니다. int ow = srcImg.getWidth(); int oh = srcImg.getHeight(); // 원본 너비를 기준으로 하여 썸네일의 비율로 높이를 계산합니다. int nw = ow; int nh = (ow * dh) / dw; // 계산된 높이가 원본보다 높다면 crop이 안되므로 // 원본 높이를 기준으로 썸네일의 비율로 너비를 계산합니다. if(nh > oh) { nw = (oh * dw) / dh; nh = oh; } // 계산된 크기로 원본이미지를 가운데에서 crop 합니다. BufferedImage cropImg = Scalr.crop(srcImg, (ow-nw)/2, (oh-nh)/2, nw, nh); // crop된 이미지로 썸네일을 생성합니다. BufferedImage destImg = Scalr.resize(cropImg, dw, dh); // 썸네일을 저장합니다. 이미지 이름 앞에 "THUMB_" 를 붙여 표시했습니다. String thumbName = PATH + "THUMB_" + fileName; File thumbFile = new File(thumbName); ImageIO.write(destImg, fileExt.toUpperCase(), thumbFile); }

 

makeThumbnail() 메소드의 인자의 의미는 다음과 같습니다.

- String filePath : 원본 파일이 저장된 경로입니다.

- String fileName : 원본 파일이 저장된 이름입니다.

- String fileExt : 원본 파일의 확장자 입니다.


Scalr.crop() 메소드의 인자의 의미는 다음과 같습니다.

- 첫 번째 srcImg : 원본 이미지의 BufferedImage 객체 입니다.

- 두 번째 (ow-nw)/2 : crop할 좌상단의 x 좌표 입니다.

- 세 번째 (oh-nh)/2 : crop할 좌상단의 y 좌표 입니다.

- 네 번째 nw : crop될 너비 입니다.

- 다섯 번째 nh : crop될 높이 입니다.

- 여섯 번째 null : crop에 사용될 옵션 정보가 들어가는데, 여기서는 사용하지 않습니다.


Scalr.resize() 메소드의 인자의 의미는 다음과 같습니다.

- 첫 번째 cropImg : 리사이즈할 이미지의 BufferedImage 객체 입니다.

- 두 번째 dw : 썸네일의 너비 입니다.

- 세 번째 dh : 썸네일의 높이 입니다.

- 네 번째 null : resize에 필요한 옵션 정보인데, 여기서는 사용하지 않습니다.



이 메소드를 사용하여 생성한 썸네일의 샘플 입니다. 썸네일은 가로로 긴 이미지 인데, 원본 이미지는 세로로 긴 이미지이므로 썸네일의 비율로 가운데를 crop 하여 썸네일이 만들어진것을 확인할 수 있습니다.


실행결과



다른 방법으로 원본 이미지의 비율을 유지하면서 높이를 150px로 하여 썸네일을 만들려면 아래와 같이 사용합니다.

 

BufferedImage destImg = Scalr.resize(srcImg, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_HEIGHT, 150);

 

원본 이미지의 비율을 유지하면서 너비를 250px로 하여 썸네일을 만들려면 다음과 같이 하면 됩니다.

 

BufferedImage destImg = Scalr.resize(srcImg, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_WIDTH, 250);

 

이것으로 Java로 썸네일을 만드는 방법을 알아 보았습니다.갤러리의 목록 처럼 이미지를 한번에 많이 보여줘야 하는 경우 썸네일을 만들어서 전체 페이지를 데이터량을 줄이는것이 중요합니다.


반응형

댓글을 달아 주세요

  • 지나가는사람 2019.02.21 09:10  댓글주소  수정/삭제  댓글쓰기

    글 잘봤습니다~! 저.. 질문이 있는데요
    저런 라이브러리는 직접 찾으시는건가요?
    다른 라이브러리 같은거도 찾는 방법을 알고 싶어서 질문드립니다

    • pentode 2019.02.21 23:53 신고  댓글주소  수정/삭제

      필요한 라이브러가 있을때 가장 먼저하는 것이 구글 검색입니다. java thumbnail library 이런 식으로 검색하면 대부분 라이브러리들을 찾을 수 있습니다. 여러개가 검색이 되면 라이센스, 활발하게 개발이 되고 있는지 등을 따져서 사용할 라이브러리를 결정을 하면 될것 같습니다.