본문 바로가기
프로그래밍/자바

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

by pentode 2018. 4. 9.
반응형

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

 

이번 예제에서는 "스프링프레임웍 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로 썸네일을 만드는 방법을 알아 보았습니다.갤러리의 목록 처럼 이미지를 한번에 많이 보여줘야 하는 경우 썸네일을 만들어서 전체 페이지를 데이터량을 줄이는것이 중요합니다.

 

반응형

댓글2