Java, IntelliJ/Spring

JAVA 이미지 리사이징, 가로세로 크기 줄이기

고로케 2021. 8. 24.
반응형

이미지 리사이징 코드 예시입니다.

작성한 코드가 더 이상 쓰이지 않아 저장용으로 업로드 합니다.

 

    // 유저 프로필 수정
    @Transactional
    public UserInfoResponseDto updateUserInfo(MultipartFile files, String username, String comment, UserDetailsImpl userDetails, String age, String gender) {
        if (userDetails != null) {
            User user = userRepository.findById(userDetails.getUser().getId())
                    .orElseThrow(() -> new IllegalArgumentException("유저가 존재하지 않습니다."));
            String filename;
            // 파일이 존재한다면
            if (files != null) {
                try {
                // 이미지 확장자 검사
                    String originFilename = Objects.requireNonNull(files.getOriginalFilename()).replaceAll(" ", "");
                    String formatName = originFilename.substring(originFilename.lastIndexOf(".") + 1).toLowerCase();
                    String[] supportFormat = { "bmp", "jpg", "jpeg", "png" };
                    if (!Arrays.asList(supportFormat).contains(formatName)) {
                        throw new IllegalArgumentException("지원하지 않는 format 입니다.");
                    }
                // 저장할 파일 이름 중복 방지 uuid 적용
                    String nameToMD5 = new MD5Generator(originFilename).toString();
                    // 랜덤 키 생성
                    String uuid = UUID.randomUUID().toString();
                    // 랜덤 키와 파일명을 합쳐 파일명 중복을 피함
                    filename = nameToMD5 + "_" + uuid + originFilename;
                    // 해당 위치에 이미지 저장
                    String savePath = System.getProperty("user.dir") + "/image";
                    // 파일이 저장되는 폴더가 없으면 폴더를 생성
                    if (!new java.io.File(savePath).exists()) {
                        try {
                            new java.io.File(savePath).mkdir();
                        } catch (Exception e) {
                            throw new IllegalArgumentException("디렉토리 생성에 실패하였습니다.");
                        }
                    }
                 // 디폴트 이미지 혹은 카카오프사 이외의 프로필 이미지는 기존 이미지 파일 삭제
                    String defaultImg = "https://####/image/profileDefaultImg.jpg"; 
                    if (!user.getProfileImg().contains("k.kakaocdn.net/dn/") && !user.getProfileImg().contains(defaultImg)) {
                        String[] deleteImg = userDetails.getUser().getProfileImg().split("/image");
                        File deleteFile = new File(System.getProperty("user.dir") + "/image" + deleteImg[1]);
                        if (deleteFile.exists()) {
                            try {
                                deleteFile.delete();
                            } catch (Exception e) {
                                throw new IllegalArgumentException("기존 파일 삭제를 실패하였습니다.");
                            }
                        }
                    }
                 // 경로 + 파일 이름 설정
                    String filePath = savePath + "/" + filename;
                 // 이미지 리사이징
                    resizeImageFile(files, filePath, formatName);
                 // 유저 정보에 포함 될 이미지 url
                    filename = "https://####/image/" + filename;   // AWS EC2
                } catch (Exception e) {
                    throw new IllegalArgumentException("파일 업로드에 실패하였습니다.");
                }
            } else { // 업로드 이미지가 없다면 기존 url 사용
                filename = user.getProfileImg();
            }

            if (username == null) {
                username = user.getUsername();
            }
            if (comment == null) {
                comment = user.getComment();
            }
            if (user.getAge() == null) {
                user.updateAge(age);
            }
            if (user.getGender() == null) {
                user.updateGender(gender);
            }

            user.updateUserInfo(username, comment, filename);
            return new UserInfoResponseDto(user);
        } else {
            throw new IllegalArgumentException("로그인 하지 않았습니다.");
        }
    }

    // 이미지 크기 줄이기
    private void resizeImageFile(MultipartFile files, String filePath, String formatName) throws Exception {
	    // 이미지 읽어 오기
        BufferedImage inputImage = ImageIO.read(files.getInputStream());
		// 이미지 세로 가로 측정
        int originWidth = inputImage.getWidth();
        int originHeight = inputImage.getHeight();
        // 변경할 가로 길이
        int newWidth = 500;

        if (originWidth > newWidth) {
            // 기존 이미지 비율을 유지하여 세로 길이 설정
            int newHeight = (originHeight * newWidth) / originWidth;
   // 이미지 품질 설정         
// Image.SCALE_DEFAULT : 기본 이미지 스케일링 알고리즘 사용
// Image.SCALE_FAST : 이미지 부드러움보다 속도 우선
// Image.SCALE_REPLICATE : ReplicateScaleFilter 클래스로 구체화 된 이미지 크기 조절 알고리즘
// Image.SCALE_SMOOTH : 속도보다 이미지 부드러움을 우선
// Image.SCALE_AREA_AVERAGING : 평균 알고리즘 사용
            Image resizeImage = inputImage.getScaledInstance(newWidth, newHeight, Image.SCALE_FAST);
            BufferedImage newImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            Graphics graphics = newImage.getGraphics();
            graphics.drawImage(resizeImage, 0, 0, null);
            graphics.dispose();
          // 이미지 저장
            File newFile = new File(filePath);
            ImageIO.write(newImage, formatName, newFile);
        } else { 
                files.transferTo(new java.io.File(filePath));
        }
    }

 

결과물

이미지 픽셀이 줄어들고 파일 용량도 크게 감소했다.

 

위와 같이 

이미지 리사이징 코드를 작성해봤는데,

프로젝트 작업 중에 쓰다가 프론트쪽에서 이미지 크기를 줄여서 주기로 했다.

서버에서 작업시에 요청이 몰릴 경우 느려지는 현상이 있어서

response 가 느리게 내려가는 현상이 간헐적으로 발생함.

thread 가 완전히 돌고나서 진행하기엔 부담이 크다는 결론이 나서

프론트에서 작업하기로 했다.

 

반응형

댓글