갤러리와 같은 웹애플리케이션을 만들게 되면 이미지의 썸네일을 만들게 됩니다. 가끔 보면 썸네일 없이 원본이미지를 줄여서 보여주고 있는곳이 있는데, 모바일 환경이라면 시간과 데이터 사용량이 많이 소비가 될 것입니다.
이번 예제에서는 "스프링프레임웍 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로 썸네일을 만드는 방법을 알아 보았습니다.갤러리의 목록 처럼 이미지를 한번에 많이 보여줘야 하는 경우 썸네일을 만들어서 전체 페이지를 데이터량을 줄이는것이 중요합니다.
'프로그래밍 > 자바' 카테고리의 다른 글
Eclipse scratchpad 사용하기(code snippets 즉시 실행) (0) | 2018.04.09 |
---|---|
jsoup : 자바 HTML 파서(Java HTML Parser) (5) | 2018.04.09 |
lombok 라이브러리 - Getter, Setter, toString 자동 생성 (0) | 2018.04.09 |
자바 문법 - 기본타입(basic type), 리터럴(literal), 변수(variable), 상수(constant) (0) | 2018.04.09 |
자바 문법 - 프로그램 기본구조 (0) | 2018.04.08 |