이미지 업로더 코드

hyuckhoon.ko·2021년 3월 11일
0

What I learned in first year

목록 보기
75/146

1. 주요 발생 에러

osError: cannot write mode RGBA as JPEG

JPEG 확장자를 갖는 이미지는 투명도(A)를 표현할 수 없는 RGB파일이다.
따라서, RGBA 이미지를 RGB 이미지로 변환시켜줘야 한다.

if main_img.mode == "RGBA":
    # RGBA 이미지를 JPEG으로 저장 불가하므로
    main_img = main_img.convert("RGB")




2. 코드

import os
import django
from datetime import datetime
from PIL import Image, ImageFont, ImageDraw, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
from io import BytesIO

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
django.setup()
from django.core.files import File

from core.models import *


# 이미지 폴더 경로
IMG_FOLDER_PATH = os.getcwd() + "/image_files/"


# 워터마크 적용
def paste_watermark(local_main_image, main_width, main_height):
    """
    1000 by 1000 인 경우 워터마크 적용 헬퍼함수
    """

    padding_right = 12
    padding_bottom = 16

    text = "쿠돈에서 직접 촬영한 사진입니다"
    PWD = os.getcwd() + "/core/management/Spoqa Han Sans Regular.ttf"
    font = ImageFont.truetype(PWD, 24)
    text_width, text_height = font.getsize(text)
    watermark = Image.new('RGBA', (text_width, text_height), 0)  # 투명 배경 생성
    draw = ImageDraw.Draw(watermark)
    draw.text((0, 0), text=text, fill=(153, 153, 153, 85), font=font)  # 투명 배경에 워터마크 반영

    # 메인 배경 우측 하단에 워터마크 paste
    local_main_image.paste(
        watermark,
        (main_width - text_width - padding_right,
         main_height - text_height - padding_bottom),
        mask=watermark)
    main_img = local_main_image.convert("RGB")
    # 워터마크 적용된 이미지 리턴
    return main_img


# 이미지 업로더
def local_image_download():
    """
    로컬 이미지를 DB로 업로드
    """

    image_cnt = 1
    img_file_list = []
    product_code_list = Product.objects.filter(id__gt=454).values_list("product_code", flat=True)

    last_index = ProductImage.objects.last().id
    cur_idx = last_index + 1
    total_file_list = []
    for img_name in os.listdir(IMG_FOLDER_PATH):
        if ".DS_Store" in img_name:
            continue
        product_code = img_name.split("_")[0]
        if product_code in product_code_list:
            product = Product.objects.get(product_code=product_code)
            main_img = Image.open(IMG_FOLDER_PATH + img_name)
            main_width, main_height = main_img.size
            if main_width <= 500 or main_height <= 500:  # 500 이하 이미지는 버린다. 
                continue
            if (main_width == main_height == 1000):  # 워터마크 적용 조건
                main_img = paste_watermark(main_img, main_width, main_height)

            # 장고 ImageField에 저장
            new_filename = f"{product_code}_{image_cnt}.jpg"  # 새롭게 저장할 이미지 이름
            image_io = BytesIO()  # BytesIO object 생성
            # RGBA 이미지의 경우, RGB 이미지로 변환
            if main_img.mode == "RGBA":
                # RGBA 이미지를 JPEG으로 저장 불가하므로
                main_img = main_img.convert("RGB")
            main_img.save(image_io, 'JPEG')  # 로컬 이미지를 BytesIO object로 저장
            product_image = File(image_io, name=new_filename)  # create a django friendly File object

            temp_dict = {
                "id": cur_idx,
                "product_image": product_image,
                "product_id": product.id
            }
            img_file_list.append(temp_dict)
            cur_idx += 1
            image_cnt += 1

    # bulk_create
    bulk_items= [ProductImage(id=i["id"], image_url=i['product_image'], product_id=i["product_id"]) for i in img_file_list]
    ProductImage.objects.bulk_create(bulk_items)


start_time = datetime.now()
print(start_time)
# 업로드 시작
local_image_download()
end_time = datetime.now()
print(end_time)
gap = end_time - start_time
print(gap)
# 24 분 소요

0개의 댓글