JAVA 이미지 리사이징 유틸 개발 / 썸네일 및 워터마크 이미지 생성 방법

썸네일 및 워터마크 이미지 생성

JAVA 이미지 리사이징 유틸

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

@Slf4j
@Component
public class ImageUtil {

    // 이미지 리사이징 함수
    public File makeResizeImg(File sourceFile, Integer width, Integer height) throws Exception {

        // 확장자
        String fileExt = getFileExt(sourceFile);

        BufferedImage sourceImage = ImageIO.read(sourceFile);

        // 원본 이미지 너비, 높이
        int sourceWidth = sourceImage.getWidth();
        int sourceHeight = sourceImage.getHeight();

        // 높이 고정, 원본 이미지 비율로 width 생성
        if(width == null) {
            width = (sourceWidth * height) / sourceHeight;
        }

        // 가로 고정, 원본 이미지 비율로 height 생성
        if(height == null) {
            height = (sourceHeight * width) / sourceWidth;
        }

        // 이미지 품질 Image.SCALE_SMOOTH : 리사이징 속도가 느리더라도 부드럽게
        // 리사이징 시 화질이 어느정도 깨지는 것은 감안해야 합니다.
        Image resizeImage = sourceImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);

        // 원본 이미지 타입이 0(커스텀)이면 Unknown image type 0 에러 발생하니 5(TYPE_3BYTE_RGR)로 변경하여 BufferedImage 생성
        Integer sourceType = sourceImage.getType();

        if(sourceType.equals(0)) {
            sourceType = BufferedImage.TYPE_3BYTE_BGR;
        }

        BufferedImage newImage = new BufferedImage(width, height, sourceType);
        Graphics graphics = newImage.getGraphics();
        graphics.drawImage(resizeImage, 0, 0, null);
        graphics.dispose();

        File thumbnailFile = new File("thumbnailImage."+fileExt);

        ImageIO.write(newImage, fileExt, thumbnailFile);

        return thumbnailFile;
    }

    // 워터마크 이미지 생성 함수
    public File makeWatermarkImg(File sourceFile, File watermarkSourceFile) throws Exception {

        // 확장자
        String fileExt = getFileExt(sourceFile);

        BufferedImage sourceImage = ImageIO.read(sourceFile);
        BufferedImage watermarkSourceImage = ImageIO.read(watermarkSourceFile);

        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        // 투명도 설정
        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
        g2d.setComposite(alphaChannel);

        // 워터마크 위치 (중앙)
        //int topLeftX = (sourceImage.getWidth() - watermarkSourceImage.getWidth()) / 2;
        //int topLeftY = (sourceImage.getHeight() - watermarkSourceImage.getHeight()) / 2;

        // 워터마크 위치 (중앙 하단)
        int topLeftX = (sourceImage.getWidth() - watermarkSourceImage.getWidth()) / 2;
        int topLeftY = (sourceImage.getHeight() - watermarkSourceImage.getHeight()) - 30;

        // 워터마크 그리기
        g2d.drawImage(watermarkSourceImage, topLeftX, topLeftY, null);

        File watermarkImageFile = new File("watermarkImage."+fileExt);

        ImageIO.write(sourceImage, fileExt, watermarkImageFile);
        g2d.dispose();

        return watermarkImageFile;
    }

    // 이미지 확장자 추출 함수
    public String getFileExt(File file) {
        String sourceFileName = file.getName();
        return sourceFileName.substring(sourceFileName.lastIndexOf(".") + 1);
    }
    // 확장자 추출 방법2
    // String fileExt = FilenameUtils.getExtension(sourceFile.getName());
}

JPG, PNG는 썸네일 및 워터마크 파일이 정상적으로 생성되는 것을 확인했습니다.
GIF는 멈춘 검은 배경으로 생성되어 다른 방법으로 개발해야할 것 같습니다.

썸네일 이미지 생성 예시

File sourceFile = new File(원본파일경로);

// 이미지 리사이징 : Width 자동, Height 200px 고정
File thumbnailFile = imageUtil.makeResizeImg(sourceFile, null, 200);

// S3 버킷에 썸네일 이미지 업로드 (생략)

// 삭제
thumbnailFile.delete();

이미지 리사이징하여 썸네일 이미지 생성 예시입니다.

워터마크 이미지 생성 예시

File sourceFile = new File(원본파일경로);

// 이미지 리사이징 : Width 자동, Height 700px 고정
File resizeSourceFile = imageUtil.makeResizeImg(sourceFile, null, 700);

File watermarkSourceFile = new File(워터마크로 합성할 이미지 파일경로);

// 워터마크 이미지 생성
File watermarkImageFile = imageUtil.makeWatermarkImg(resizeSourceFile, watermarkSourceFile);

// S3 버킷에 워터마크 이미지 업로드 (생략)

// 삭제
resizeSourceFile.delete();
watermarkImageFile.delete();

이미지 리사이징 후 워터마크 이미지 생성 예시입니다.


Unsupported Image Type 에러 해결

ImageIO.read 시 에러메세지

javax.imageio.IIOException: Unsupported Image Type
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1156)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1127)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1470)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1317)

ImageIO는 CMYK가 아니라 RGB 색상 모드의 이미지만 읽을 수 있기 때문에 발생하는 에러입니다.

imageio-jpeg 추가

implementation 'com.twelvemonkeys.imageio:imageio-jpeg:3.9.4'

build.gradle 파일에 imageio-jpeg 라이브러리 의존성 추가 후 Gradle 재빌드합니다.
톰캣 재시작 시 소스 변경 없이 에러가 해결됩니다.

imageio-jpeg 3.7.0 버전 에러

javax.imageio.IIOException: No SOF segment in stream
at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.getSOF(JPEGImageReader.java:886)
at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:293)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1470)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1317)

imageio-jpeg 라이브러리 3.7.0 사용 시 발생할 수 있는 에러입니다. 3.9.4 버전 사용하면 됩니다.

Leave a comment