반응형

0. 들어가기

-. 앞 포스팅의 S3 기본 이용법에서 발전해서, 이미지를 변환 후 로컬에 저장하지 않고 메모리에서 바로 S3로 업로드 할 계획.

-. 현재 내가 가지고 있는 파일 (원본)은 *.png 형태이고, 이를 용량 감소를 위해 *.jpg로 변환해서 S3에 업로드 하려고 한다. 왜냐면... PNG 대비 JPG는 약 20% (quality에 따라 달라짐)의 용량을 가지기 때문에 이미지 호스팅에 훨씬 유리하기 때문이다.

1. PNG to JPG 변환

-. python 패키지인 pillow를 이용해서 아주 쉽게 변환 가능하다.

from PIL import Image
im = Image.open("testimage.png")
rgb_im = im.convert('RGB')
rgb_im.save('testimage_100.jpg', quality=100)
rgb_im.save('testimage_95.jpg', quality=95)
rgb_im.save('testimage_90.jpg', quality=90)

-. quality는 jpg의 화질 관련된 숫자..인거같은데, 내가 보기에 90까지는 별 차이가 없어서 90으로 변환했다. 위 방식으로 변환한 이미지를 배열해봤는데, 뭐가 다른지 사실 잘 모르겠다. (세세한 색 연속성 등에서 차이가 있다고 함)

2. 변환 이미지를 메모리에 저장

-. 위 파이썬 코드에선 .save를 이용해 파일로 저장했는데, 이번엔 S3로 바로 업로드를 할 것이다. 로컬에 임시파일을 만들고, 그 파일을 업로드 해도 결과물은 같지만, 하드에 파일을 한번 쓰는 작업이 불필요하게 소요된다.

-. 앞 포스팅에서 upload_file 함수를 사용했는데, 이번엔 upload_fileobj라는 비슷한 함수를 사용한다.

import io
from PIL import Image
im = Image.open("testimage.png")
rgb_im = im.convert('RGB')

TEMP = io.BytesIO()
rgb_im.save(TEMP, format="jpeg", quality=90) 
TEMP.seek(0)
client.upload_fileobj(TEMP, Bucket="movics", Key='testimage.jpeg', ExtraArgs={'ContentType': 'image/jpeg'})

-. 요 간단한 코드 짜는 것에 한시간 정도 소요했는데, 내가 시간을 많이 뺏긴 부분이 TEMP.seek(0) 요 한줄을 몰라서였다.  이미지가 자꾸 0B로 올라가더라...

-. 다행히 stack overflow의 한 문답글에서 답을 찾았는데, PIL.Image.save() 함수로 BytesIO 객체에 할당된 메모리에 이미지 데이터를 저장하면 커서가 해당 데이터의 가장 마지막에서 멈춘다. 이후, 다시 TEMP를 호출하게 되면 가장 마지막 자리만 출력, 즉 0B의 이미지가 올라가게 된다. 아래 예시처럼 seek(0) 을 한 경우와 하지 않은 경우를 비교해 봤다.

TEMP1 = copy.copy(TEMP)
client.upload_fileobj(TEMP1, Bucket="movics", Key='testimage_noseek(0).jpeg', ExtraArgs={'ContentType': 'image/jpeg'})
TEMP.seek(0)
client.upload_fileobj(TEMP, Bucket="movics", Key='testimage.jpeg', ExtraArgs={'ContentType': 'image/jpeg'})

-. 아무튼 클리어.

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기