티스토리 뷰

JavaScript & TypeScript

sharp image rotate 문제

kingsubin 2023. 3. 12. 18:00

문제

이미지 업로드 시 버킷에 업로드된 이미지의 너비와 높이가 데이터베이스에 저장한 이미지 객체의 너비와 높이와 일치하지 않음.

/**
 기존 구조
1. `sharpInstance` 생성
2. `sharpInstance.rotate()`
3. 버킷에 이미지 업로드
4. `metadata.width`, `metadata.height` 를 `DB` 에 저장
*/

const sharpInstance = sharp(buffer);

sharpInstance.rotate();

const metadata = await sharpInstance.metadata();

const image = {
    // ... 
    width: metadata.width,
    height: metadata.height,
}

bucket.upload(buffer);
database.save(image);
  • 이미지 처리는 sharp 라이브러리를 사용함.
  • 대략 위와 같은 구조로 버킷에 업로드, 이미지 정보를 데이터베이스에 저장함.
  • 데이터베이스에 저장된 width, height 의 값이 원본 이미지와 맞지 않는 문제가 있음.

해결 과정

1

  • 원본 이미지의 width, heightimage 객체에 할당하기 전에 sharp.roate() 사용하는데 이 함수가 작동하지 않을까 생각함.
  • 인자를 주지 않으면 exif.orientation 을 보고 auto-rotated 된다고 알고 있어서 문제가 없지 않을까 해서 auto-rotate 를 확인했는데 함수의 문제가 아닌 것 같음.

2

  • 문서 설명을 다시 보니 이렇게 적혀있음.
    "Rotate the output image by either an explicit angle or auto-orient based on the EXIF Orientation tag."
  • 즉, 기존 코드에서 사용하는 width, height 는 그전에 rotate 를 하더라도 roated 된 이미지의 width, height 가 아니라 원본 이미지의 width, height 를 쓰고 있었음.

결론

width, height 를 이미지 업로드보다 먼저 사용해야 해서 직접 orientation을 보고 width, height를 사용하도록 수정

https://sirv.com/help/articles/rotate-photos-to-be-upright/

  • orientation 이 5~8일 때 width, height 를 뒤집어주면 됨.
const metadata = await sharpInstance.metadata();

const getNormalSize = (  
  width: number,  
  height: number,  
  orientation?: number,  
): { width: number; height: number } => {  
  return orientation && orientation >= 5  
    ? { width: height, height: width }  
    : { width, height };  
};

const width = getNormalSize(metadata.width, metadata.heigth, metadata.orientation);
const height = getNormalSize(metadata.width, metadata.heigth, metadata.orientation);

const image = {
    // ... 
    width,
    height,
}

bucket.upload(buffer);
database.save(image);