![[문제 해결] Node.js sharp 이용, Crop 후 합성 문제](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsnDrL%2FbtsDnySF5sP%2FUGWigDuUui3kKHEQQsYsok%2Fimg.jpg)
[문제 해결] Node.js sharp 이용, Crop 후 합성 문제Software Development/Trial-and-error2024. 1. 12. 15:33
Table of Contents
AWS Lambda에서 돌아갈 이미지 크롭 API 수정을 맡게 되었다.
로직은 다음과 같았다.
1. 먼저 Image를 받아온 후, 1080으로 변환한다.
2. 사용자가 Screen 안에서 이미지를 재배치 한 것(확대/축소, 상하좌우 이동)을, Resize 한 후 Crop한다.
3. Crop 한 Image를, 검은색 여백 페이지와 합친다.
이 때 받게되는 정보는, resizedImage, offset 이고,
resizedImage에서 offset은 계산되어 넘어오기 때문에, offset을 추가로 계산할 필요는 없다.
검은색 여백 페이지와 합칠 때, top, left를 offset과 resizedImage를 활용해 계산하는 것이 문제였다.
기존에 작성된 Crop에 문제는 없었고,
processImage 부분에서 left, top 설정에 오류가 있다는 점을 확인한 뒤
기존 코드를 바탕으로 고치려고 했었다.
기존 코드는 아래와 같았다.
async function processImage(croppedBuffer, screenSize, resizedImageSize, offset, croppedInfo){
if(croppedBuffer == null) {
return await sharp({
create: {
width: screenSize.w,
height: screenSize.h,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0}
}
}).jpeg().toBuffer();
}
const metadata = await sharp(croppedBuffer).metadata();
let croppedImageSize = {w: metadata.width, h: metadata.height};
const centerX = Math.round(screenSize.w / 2);
const centerY = Math.round(screenSize.h / 2);
const isCropped = resizedImageSize.w > croppedImageSize.w || resizedImageSize.h > croppedImageSize.h;
let top = Math.round(centerY - (croppedImageSize.h / 2) + offset.y);
let left = Math.round(centerX - (croppedImageSize.w / 2) + offset.x);
if(isCropped) {
if(resizedImageSize.w <= screenSize.w) {
left = Math.round(centerX - (resizedImageSize.w / 2) + offset.x);
}
if(resizedImageSize.h <= screenSize.h) {
top = Math.round(centerY - (resizedImageSize.h / 2) + offset.y);
}
}
console.log(`screenSize.w=> ${screenSize.w}`);
console.log(`screenSize.h=> ${screenSize.h}`);
console.log(`top=> ${top}`);
console.log(`left=> ${left}`);
return await sharp({
create: {
width: Math.round(screenSize.w),
height: Math.round(screenSize.h),
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0}
}
}).composite([{
input: croppedBuffer,
top : top,
left : left
}]).jpeg().toBuffer();
}
async function processImage(croppedBuffer, screenSize, resizedImageSize, offset, croppedInfo){
if(croppedBuffer == null) {
return await sharp({
create: {
width: screenSize.w,
height: screenSize.h,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0}
}
}).jpeg().toBuffer();
}
const metadata = await sharp(croppedBuffer).metadata();
let croppedImageSize = {w: metadata.width, h: metadata.height};
const centerX = Math.round(screenSize.w / 2);
const centerY = Math.round(screenSize.h / 2);
let left = Math.round(centerX + offset.x - resizedImageSize.w/2);
let top = Math.round(centerY + offset.y - resizedImageSize.h/2);
if(left < 0){
left = Math.max(left, 0);
}
if(top < 0){
top = Math.max(top, 0);
}
console.log(`screenSize.w=> ${screenSize.w}`);
console.log(`screenSize.h=> ${screenSize.h}`);
console.log(`top=> ${top}`);
console.log(`left=> ${left}`);
return await sharp({
create: {
width: Math.round(screenSize.w),
height: Math.round(screenSize.h),
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0}
}
}).composite([{
input: croppedBuffer,
top : top,
left : left
}]).jpeg().toBuffer();
}
수정한 코드는 다음과 같다.
기존 코드를 바탕으로 여러 예외를 생각하려니 머리가 아파서,
핵심 로직만 다시 생각하고 코드를 작성하니 30분만에 끝날 문제였다.
수정한다고 보낸 이틀이 아깝다. 끝.
이 아닌, 수정하고 보니 Resize 후 Crop 하는 과정에서 램을 지나치게 많이 먹는 부분을 확인했다.
전체적인 이미지 API 고도화에 이번 주말을 보내볼 예정이다.
끝.
'Software Development > Trial-and-error' 카테고리의 다른 글
@찐빵1 :: 위기주도학습
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!