Skip to content

Commit

Permalink
Merge pull request #137 from Ong-gi-Jong-gi/dev
Browse files Browse the repository at this point in the history
Merging dev branch into main branch
  • Loading branch information
minjoon-98 authored Aug 6, 2024
2 parents 2273cad + 0c72b2c commit 382a3f2
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ GitHub Secrets에 다음 정보를 설정해야 합니다:
- LOG_GROUP_NAME: AWS Cloudwatch 로그 그룹 이름
- LOG_STREAM_NAME: AWS Cloudwatch 로그 스트림 이름

자세한 정보는 `.github/workflows/ci-cd.yml` 파일을 참고해주시길 바랍니다.
자세한 정보는 `.github/workflows/Spring Boot CI-CD.yml` 파일을 참고해주시길 바랍니다.

<!--
## 기여
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies {

// thumbnailator for merging image
implementation 'net.coobird:thumbnailator:0.4.20'
implementation 'com.drewnoakes:metadata-extractor:2.18.0'

//ffmpeg
implementation ('net.bramp.ffmpeg:ffmpeg:0.8.0')
Expand Down
130 changes: 106 additions & 24 deletions src/main/java/ongjong/namanmoo/service/AwsS3Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -70,7 +73,7 @@ public AwsS3Service(
* @return 업로드된 파일의 URL
* @throws IOException 파일 변환 또는 업로드 중 발생하는 예외
*/
public String uploadFile(MultipartFile multipartFile) throws IOException {
public String uploadFile(MultipartFile multipartFile) throws IOException, InterruptedException {
log.info("Converting MultipartFile to File...");
File uploadFile = convertFile(multipartFile)
.orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File convert fail"));
Expand All @@ -81,6 +84,11 @@ public String uploadFile(MultipartFile multipartFile) throws IOException {
uploadFile = optimizeImageFile(uploadFile);
}

// else if (determineFileType(multipartFile).equals("video")) {
// log.info("Optimizing video file...");
// uploadFile = resizeVideo(multipartFile);
// }

String fileType = determineFileType(multipartFile);
String fileName = generateFileName(uploadFile, fileType);

Expand Down Expand Up @@ -116,6 +124,38 @@ public String uploadOriginalFile(MultipartFile multipartFile, Long memberId) thr
return uploadFileUrl;
}

// // FFmpeg 명령어를 실행하여 동영상을 리사이즈하는 메소드
// public File resizeVideo(MultipartFile videoFile) throws IOException, InterruptedException {
// // 고유한 파일명을 생성하기 위해 UUID와 원래 파일명을 결합
// String uniqueFileName = UUID.randomUUID() + "_" + videoFile.getOriginalFilename();
// String outputFileName = System.getProperty("java.io.tmpdir") + "/" + uniqueFileName;
//
// File inputFile = new File(System.getProperty("java.io.tmpdir") + "/" + videoFile.getOriginalFilename());
// videoFile.transferTo(inputFile);
//
// // FFmpeg 명령어를 통해 동영상 리사이즈
// String[] command = {
// "ffmpeg",
// "-i", inputFile.getAbsolutePath(),
// "-vf", "scale=854:480", // 원하는 해상도로 조정
// "-b:v", "1000k", // 비트레이트 설정
// "-preset", "ultrafast",
// outputFileName
// };
//
// ProcessBuilder processBuilder = new ProcessBuilder(command);
// processBuilder.redirectErrorStream(true);
//
// Process process = processBuilder.start();
// int exitCode = process.waitFor();
//
// if (exitCode != 0) {
// throw new RuntimeException("FFmpeg command failed");
// }
//
// return new File(outputFileName);
// }

/**
* 이미지를 최적화하는 메소드.
*
Expand All @@ -127,29 +167,71 @@ private File optimizeImageFile(File originalFile) throws IOException {
BufferedImage originalImage = ImageIO.read(originalFile);
File optimizedFile = new File("optimized_" + originalFile.getName());

// 원본 이미지의 크기
int originalWidth = originalImage.getWidth();
int originalHeight = originalImage.getHeight();

// 원하는 최대 크기
int maxWidth = (int) (originalWidth * 0.85);
int maxHeight = (int) (originalHeight * 0.85);

// 비율 유지하면서 리사이징할 크기 계산
double aspectRatio = (double) originalWidth / originalHeight;
int newWidth = maxWidth;
int newHeight = (int) (maxWidth / aspectRatio);
if (newHeight > maxHeight) {
newHeight = maxHeight;
newWidth = (int) (maxHeight * aspectRatio);
// EXIF 데이터를 읽어 Orientation 정보를 가져옴
// EXIF Orientation의 기본값 = 1
int orientation = 1;
try {
Metadata metadata = ImageMetadataReader.readMetadata(originalFile);
ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
// EXIF 정보가 없거나 기본값이 1인 경우 orientation = 1
if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
}
} catch (Exception e) {
log.warn("Could not read EXIF metadata: {}", e.getMessage());
}

// 이미지 회전 처리
BufferedImage rotatedImage;
switch (orientation) {
// EXIF Orientation의 값 = 6 : 90도 시계방향
case 6:
log.info("11111");
rotatedImage = Thumbnails.of(originalImage).rotate(90).scale(1).asBufferedImage();
log.info("22222");
break;
// EXIF Orientation의 값 = 3 : 180도 시계방향
case 3:
rotatedImage = Thumbnails.of(originalImage).rotate(180).scale(1).asBufferedImage();
break;
// EXIF Orientation의 값 = 8 : 270도 시계방향
case 8:
rotatedImage = Thumbnails.of(originalImage).rotate(270).scale(1).asBufferedImage();
break;
default:
rotatedImage = originalImage;
break;
}

// 원본 이미지의 크기
int originalWidth = rotatedImage.getWidth();
int originalHeight = rotatedImage.getHeight();

// 이미지 리사이즈 및 압축
Thumbnails.of(originalImage)
.size(newWidth, newHeight) // 비율을 유지하면서 리사이즈
.outputQuality(0.5) // 이미지 품질 설정 (0.0 ~ 1.0)
.toFile(optimizedFile);

Thumbnails.Builder<BufferedImage> thumbnailBuilder = Thumbnails.of(rotatedImage);
if (originalWidth > 512 || originalHeight > 512) {

double aspectRatio = (double) originalWidth / originalHeight;

int newWidth = 512;
int newHeight = (int) (512 / aspectRatio);

if (newHeight > 512) {
newHeight = 512;
newWidth = (int) (512 * aspectRatio);
}
// 비율을 유지하면서 리사이즈
thumbnailBuilder.size(newWidth, newHeight)
.outputQuality(0.85)
.toFile(optimizedFile);
log.info("Optimized Image Dimensions: {}x{}",newWidth, newHeight);
} else {
// 원본 크기로 유지하고 압축
thumbnailBuilder.scale(1)
.outputQuality(0.85)
.toFile(optimizedFile);
}

// 원본 이미지 파일의 크기
long originalFileSize = originalFile.length();
// 최적화된 이미지 파일의 크기
Expand All @@ -158,13 +240,12 @@ private File optimizeImageFile(File originalFile) throws IOException {
// 로그 출력
log.info("Original Image Dimensions: {}x{}", originalWidth, originalHeight);
log.info("Original File Size: {} bytes", originalFileSize);
log.info("Optimized Image Dimensions: {}x{}", newWidth, newHeight);
log.info("Optimized File Size: {} bytes", optimizedFileSize);


return optimizedFile;
}


/**
* 파일 타입을 결정하는 메소드.
*
Expand All @@ -186,7 +267,7 @@ private String determineFileType(MultipartFile multipartFile) {
}

/**
* MultipartFile을 File 객체로 변환하는 메소드.
* MultipartFile을 File 객체로 변환하는 메소드.x
*
* @param file 변환할 MultipartFile
* @return Optional<File> 변환된 File 객체를 포함하는 Optional
Expand Down Expand Up @@ -221,6 +302,7 @@ private String generateFileName(File uploadFile, String fileType) {

// return fileType + "/" + UUID.randomUUID() + "_" + formattedDate + "_" + uploadFile.getName();
return fileType + "/" + formattedDate + "_" + uploadFile.getName();

}

// generateFileName 메소드에 멤버 ID 추가
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/ongjong/namanmoo/service/FFmpegService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import net.bramp.ffmpeg.builder.FFmpegBuilder;
import org.checkerframework.checker.index.qual.SameLen;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -98,4 +101,5 @@ public void mergeAudiosWithSilence(List<String> inputPaths, String outputPath, d
log.info("Executing FFmpeg command with filter: {}", filterComplex);
ffmpegExecutor.createJob(builder).run();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ public Map<String, String> uploadImageFile(Challenge challenge, MultipartFile ph

try {
// S3에 파일 업로드 및 URL 저장
// String uploadedUrl = awsS3Service.uploadFile(photo);
String uploadedUrl = awsS3Service.uploadOriginalFile(photo, member.getMemberId());
// String uploadedUrl = awsS3Service.uploadFile(photo);
// String uploadedUrl = awsS3Service.uploadFileWithRetry(photo, 3);

Optional<Lucky> optionalLucky = luckyRepository.findByFamilyFamilyIdAndRunningTrue(family.getFamilyId());
Expand Down

0 comments on commit 382a3f2

Please sign in to comment.