이전까진 블로그에 이미지 올리기 전에 워터마크 작업과 이미지 크기를 수작업으로 했는데 워드프레스가 업그레이드(?)되면서 사이즈 별로 자동 생성하기 때문에 워터마크 작업만 하면됩니다.
물론 PHP로 이미지 등록시 자동으로 워터마크를 박을 수 있겠지만 아직 할줄 모르기 때문에 업로드할 이미지를 폴더에 몰아놓고 실행하면 자동으로 워터마크를 박아주는 앱을 하나 만들어 봤습니다.
파이썬 3.8에서 작업함
import sys from PIL import Image from PIL import ImageDraw from PIL import ImageFont import re import os import errno ################################################################################ text_Watermark = 'Linsoo.co.kr `' text_Font = './Goyang.ttf' ################################################################################ #확장자 찾는 정규식 re_findEXT = re.compile('.+.(w+)?$') #파일 이름만 찾는 정규식 (.+[\/](w+)?..+$) #파일 이름+확장자 까지 구하는 정규식 re_findFileName = re.compile('.+[\/]([^\/:*?"<>|]+.[^\/:*?"<>|]+)?$') ################################################################################ ################################################################################ #이미지 컨버트 함수 def convertImage(srcFilePath, outputPath): extName = '' #확장자 srcFileName = '' #원본 파일이름 dstFileName = '' #저장할 파일이름 dstFilePath = '' #저장할 경로(파일명 포함) #확장자 못찾으면 패스 match = re_findEXT.match(srcFilePath) if match == None: return None else: extName = match.group(1) match = re_findFileName.match(srcFilePath) if match == None: print('파일 이름 못찾음') return None else: srcFileName = match.group(1) dstFileName ='linsoo_'+srcFileName dstFilePath = outputPath+'/'+dstFileName #dstFilePath = srcFilePath.replace(srcFileName, dstFileName) ################################################################################ #여기부터 이미지 컨버팅 #워터마크 텍스트 색상 colorText = (255,255,255,255) #아웃라인 색상 colorOutline = (128,128,128,255) #그림자 색상 colorShadow = (0,0,0,90) #그림자 위치 shadowX = 3 shadowY = 2 #워터마크 폰트크기 비율 (이미지 크기의 몇%를 차지 하는가) waterMarkHeightRatio = 0.071 ########################################################################### imgSrc= Image.open(srcFilePath).convert("RGBA") imgOutput = Image.new( "RGBA", imgSrc.size) # #워터마크 폰트 크기 이미지 높이에 비례한다. fontSize = round(imgSrc.height * waterMarkHeightRatio) #아웃라인 두께 outlineAmount = round(fontSize*0.013) #외곽선 굵기가 0 나오면 1 줌 outlineAmount = 1 if outlineAmount < 1 else outlineAmount fontWatermark = ImageFont.truetype(font=text_Font, size = fontSize) fontWidth,fontHeight = fontWatermark.getsize(text_Watermark) #워터마크 이미지와 원본이미지와 떨어짐 간격 offsetX = int(imgSrc.width * 0.01) offsetY = int(imgSrc.height * 0.02) #워터마크 x위치 posWatermarkStartX = imgSrc.width - fontWidth - offsetX posWatermarkStartY = imgSrc.height - fontHeight - offsetY ########################################################################### #그림자 ImageDraw.Draw(imgOutput).text( (posWatermarkStartX - outlineAmount +shadowX, posWatermarkStartY +shadowY ), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX + outlineAmount +shadowX, posWatermarkStartY +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX +shadowX, posWatermarkStartY - outlineAmount +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX +shadowX, posWatermarkStartY + outlineAmount +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX - outlineAmount +shadowX, posWatermarkStartY - outlineAmount +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX + outlineAmount +shadowX, posWatermarkStartY - outlineAmount +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX - outlineAmount +shadowX, posWatermarkStartY + outlineAmount +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) ImageDraw.Draw(imgOutput).text( (posWatermarkStartX + outlineAmount +shadowX, posWatermarkStartY + outlineAmount +shadowY), text_Watermark,fill=colorShadow, font=fontWatermark) # 그림자용 메인 텍스트 ImageDraw.Draw(imgOutput).text( (posWatermarkStartX+shadowX, posWatermarkStartY+shadowY ), text_Watermark,fill=colorShadow, font=fontWatermark) ################################################################################################################################ #외곽선 #left ImageDraw.Draw(imgOutput).text( (posWatermarkStartX - outlineAmount, posWatermarkStartY ), text_Watermark,fill=colorOutline, font=fontWatermark) #right ImageDraw.Draw(imgOutput).text( (posWatermarkStartX + outlineAmount, posWatermarkStartY ), text_Watermark,fill=colorOutline, font=fontWatermark) #up ImageDraw.Draw(imgOutput).text( (posWatermarkStartX, posWatermarkStartY - outlineAmount ), text_Watermark,fill=colorOutline, font=fontWatermark) # #down ImageDraw.Draw(imgOutput).text( (posWatermarkStartX, posWatermarkStartY + outlineAmount ), text_Watermark,fill=colorOutline, font=fontWatermark) #left up ImageDraw.Draw(imgOutput).text( (posWatermarkStartX - outlineAmount, posWatermarkStartY - outlineAmount ), text_Watermark,fill=colorOutline, font=fontWatermark) # #right up ImageDraw.Draw(imgOutput).text( (posWatermarkStartX + outlineAmount, posWatermarkStartY - outlineAmount ), text_Watermark,fill=colorOutline, font=fontWatermark) # #left down ImageDraw.Draw(imgOutput).text( (posWatermarkStartX - outlineAmount, posWatermarkStartY + outlineAmount ), text_Watermark,fill=colorOutline, font=fontWatermark) # #right down ImageDraw.Draw(imgOutput).text( (posWatermarkStartX + outlineAmount, posWatermarkStartY + outlineAmount ), text_Watermark,fill=colorOutline, font=fontWatermark) #메인 텍스트 ImageDraw.Draw(imgOutput).text( (posWatermarkStartX, posWatermarkStartY ), text_Watermark,fill=colorText, font=fontWatermark) out = Image.alpha_composite(imgSrc, imgOutput) # 파일 옵션에 관한건 아래 링크를 참고 # https://pillow.readthedocs.io/en/5.1.x/handbook/image-file-formats.html #파일을 저장한다. if(extName.lower() == 'png'): out.convert('RGB').save(dstFilePath, 'png') elif(extName.lower() == 'jpg'): out.convert('RGB').save(dstFilePath, 'jpeg',quality=95,optimize=True) print('-----------------------------------------------------------------') print(srcFilePath +' ==> '+dstFilePath) print("ImgWidth: "+str(imgSrc.width)+" ImgHeight: "+ str(imgSrc.height)+" FontSize: "+ str(fontSize)+" OutlineAmount: "+ str(outlineAmount)) ################################################################################ #특정 폴더 경로안에 파일 리스트 가져옴 regex = re.compile('^.+.(jpg|png|bmp)$', re.IGNORECASE) def convertFolder(srcPath, outputPath): outputPath = os.path.abspath(outputPath) try: if not(os.path.isdir(outputPath)): os.makedirs(os.path.join(outputPath)) except OSError as e: if e.errno != errno.EEXIST: print("Failed to create directory!!!!!") raise try: filenames = os.listdir(srcPath) for filename in filenames: full_filename = os.path.join(srcPath, filename) mo = regex.search(full_filename) if mo != None: if os.path.isfile(mo.group()): filePath = mo.group(0) convertImage(filePath, outputPath) except PermissionError: pass ################################################################################ #실행부분 convertFolder('./', './output') print('-----------------------------------------------------------------') var = input ('엔터키를 누르면 종료합니다.')
답글 남기기