Created
December 16, 2018 04:47
-
-
Save oiehot/9758d78c01b60f95134a8c33642b81b3 to your computer and use it in GitHub Desktop.
copyrighter.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import re | |
from PIL import Image, ImageDraw, ImageFont | |
from PyQt5.QtWidgets import * | |
from PyQt5.QtCore import pyqtSignal | |
from PyQt5.QtCore import QEvent | |
from datetime import datetime | |
from os.path import getmtime | |
DEFAULT_ARTIST = "Taewoo Lee ([email protected])" | |
DEFAULT_COPYRIGHT = "(C) AZ/GG/SKB/DW" | |
DEFAULT_COMMENT = "No comment.\nAll copyrights are auto-generated." | |
DEFAULT_FONT = './arial.ttf' | |
TITLE_FONT_SIZE = 0.02 | |
COPYRIGHT_FONT_SIZE = 0.01 | |
COMMENT_FONT_SIZE = 0.01 | |
MARGIN_RATE = 0.05 # ex) height * 0.05 | |
# 파일명에 이미 날짜가 들어가 있는 경우의 처리 | |
def filename_has_date(filePath): | |
'파일명 앞에 yyymmdd 형태의 날짜가 적혀져 있으면 True를 리턴한다' | |
yyyymmdd_re = re.compile('[0-9]{8}_.*') | |
filename = os.path.splitext(os.path.basename(filePath))[0] | |
if yyyymmdd_re.match(filename): | |
return True | |
else: | |
return False | |
def stamp(filePath, artist, comment, copyright, logger): | |
try: | |
img = Image.open(filePath) | |
except: | |
logger.log('%s 는 이미지 파일이 아닙니다.' % filePath) | |
return | |
# 배경색을 얻는다. | |
bg_color = img.getpixel( (0,0) ) | |
fg_color = (255-bg_color[0], 255-bg_color[1], 255-bg_color[2], 255) | |
_orgn_bbox = img.getbbox() | |
_orgn_width = _orgn_bbox[2] | |
_orgn_height = _orgn_bbox[3] | |
# 여백 계산 | |
margin_v = round(_orgn_height * MARGIN_RATE) | |
margin = { | |
'top': margin_v, | |
'left': 0, | |
'right': 0, | |
'bottom': round(margin_v * 0.5) | |
} | |
# 여백을 포함하여 Crop 하기 | |
crop_bbox = ( | |
_orgn_bbox[0] - margin['left'], | |
_orgn_bbox[1] - margin['top'], | |
_orgn_bbox[2] + margin['right'], | |
_orgn_bbox[3] + margin['bottom'] | |
) | |
img = img.crop(crop_bbox) | |
# Crop 이후 | |
bbox = img.getbbox() | |
# fix bbox !! | |
bbox = (bbox[0], bbox[1]-margin['top'], bbox[2], bbox[3]+margin['bottom']) | |
top_area = ( 0, 0, bbox[2], margin['top'] ) | |
bottom_area = ( 0, bbox[3] - margin['bottom'], bbox[2], bbox[3] ) | |
draw = ImageDraw.Draw(img) | |
draw.rectangle(top_area, outline=None, fill=bg_color) | |
draw.rectangle(bottom_area, outline=None, fill=bg_color) | |
# 폰트 사이즈 결정 | |
title_fnt_size = round(min(_orgn_width, _orgn_height) * TITLE_FONT_SIZE) | |
title_fnt = ImageFont.truetype(DEFAULT_FONT, title_fnt_size) | |
copyright_fnt_size = round(min(_orgn_width, _orgn_height) * COPYRIGHT_FONT_SIZE) | |
copyright_fnt = ImageFont.truetype(DEFAULT_FONT, copyright_fnt_size) | |
comment_fnt_size = round(min(_orgn_width, _orgn_height) * COMMENT_FONT_SIZE) | |
comment_fnt = ImageFont.truetype(DEFAULT_FONT, comment_fnt_size) | |
# 타이틀 그리기 | |
title_text = '' | |
if filename_has_date(filePath): | |
title_text = '[%s]' % os.path.splitext(os.path.basename(filePath))[0] | |
else: | |
yyyymmdd = datetime.fromtimestamp(getmtime(filePath)).strftime('%Y%m%d') | |
filename = os.path.splitext( os.path.basename(filePath) )[0] | |
title_text = '[%s_%s]' % (yyyymmdd, filename) | |
draw.text((50,50), title_text, font=title_fnt, fill=fg_color ) | |
# 카피 라이트 그리기 | |
copyright_text = copyright | |
copyright_w, copyright_h = draw.textsize(copyright_text, copyright_fnt) | |
copyright_x = round(_orgn_width/2 - copyright_w/2) | |
copyright_y = bbox[3] - margin['bottom'] + round(copyright_h/2) | |
draw.text( (copyright_x, copyright_y), copyright_text, font=copyright_fnt, fill=fg_color ) | |
# 추가 정보 그리기 | |
add_text = 'Artist: %s\nComment:\n%s' % (artist, comment) | |
add_text_w, add_text_h = draw.textsize(add_text, comment_fnt) | |
add_text_x = bbox[2] - add_text_w - 50 | |
add_text_y = bbox[0] + 50 | |
draw.text( (add_text_x, add_text_y), add_text, font=comment_fnt, fill=fg_color ) | |
# 저장하기 | |
pre, ext = os.path.splitext(filePath) | |
output = pre + '_Sealed.png' | |
try: | |
img.save(output) | |
except: | |
logger.log('%s 저장에 실패했습니다.' % filePath) | |
return | |
logger.log('%s 성공.' % filePath) | |
class FileListView(QListWidget): | |
def __init__(self, parent): | |
super().__init__(parent) | |
self.setAcceptDrops(True) | |
def dragEnterEvent(self, event): | |
if event.mimeData().hasUrls(): | |
event.accept() | |
else: | |
event.ignore() | |
def dragMoveEvent(self, event): | |
event.accept() | |
def dropEvent(self, event): | |
if event.mimeData().hasUrls(): | |
event.accept() | |
for url in event.mimeData().urls(): | |
filePath = str(url.toLocalFile()) | |
self.addItem(filePath) | |
else: | |
event.ignore() | |
def removeSelected(self): | |
for item in self.selectedItems(): | |
n = self.row(item) | |
self.takeItem(n) | |
def getFileList(self): | |
result = [] | |
max = self.count() | |
for i in range(max): | |
item = self.item(i) | |
result.append(item.text()) | |
return result | |
class CopyrighterWindow(QWidget): | |
def __init__(self): | |
super().__init__() | |
self.setWindowTitle("Copyrighter") | |
self.setGeometry(300, 300, 900, 450) | |
self.hLayout = QHBoxLayout() | |
self.setLayout(self.hLayout) | |
# Left VLayout | |
self.vLayout = QVBoxLayout() | |
self.hLayout.addLayout(self.vLayout) | |
# Right VLayout | |
self.vLayoutR = QVBoxLayout() | |
self.hLayout.addLayout(self.vLayoutR) | |
self.logForm = QPlainTextEdit('', self) | |
self.vLayoutR.addWidget(self.logForm) | |
# Files list | |
self.fileListView = FileListView(self) | |
self.vLayout.addWidget(self.fileListView) | |
# Remove File Button | |
self.removeFileButton = QPushButton("Remove", self) | |
self.removeFileButton.clicked.connect(self.fileListView.removeSelected) | |
self.vLayout.addWidget(self.removeFileButton) | |
# Grid Layout | |
self.gridLayout = QGridLayout() | |
self.vLayout.addLayout(self.gridLayout) | |
# Title Form | |
self.titleCheckbox = QCheckBox("Title", self) | |
self.titleCheckbox.setChecked(True) | |
# self.titleForm = QLineEdit("", self) | |
self.gridLayout.addWidget(self.titleCheckbox,0,0) | |
# self.gridLayout.addWidget(self.titleForm,0,1) | |
# Artist Form | |
self.artistCheckbox = QCheckBox("Artist", self) | |
self.artistCheckbox.setChecked(True) | |
self.artistForm = QLineEdit(DEFAULT_ARTIST) | |
self.gridLayout.addWidget(self.artistCheckbox,1,0) | |
self.gridLayout.addWidget(self.artistForm,1,1) | |
# Copyright Form | |
self.copyrightCheckbox = QCheckBox("Copyright", self) | |
self.copyrightCheckbox.setChecked(True) | |
self.copyrightForm = QLineEdit(DEFAULT_COPYRIGHT, self) | |
self.gridLayout.addWidget(self.copyrightCheckbox,2,0) | |
self.gridLayout.addWidget(self.copyrightForm,2,1) | |
# Comment Form | |
self.commentCheckbox = QCheckBox("Comment", self) | |
self.commentCheckbox.setChecked(True) | |
# self.commentForm = QLineEdit(DEFAULT_COMMENT, self) | |
self.commentForm = QPlainTextEdit(DEFAULT_COMMENT, self) | |
self.gridLayout.addWidget(self.commentCheckbox,3,0) | |
self.gridLayout.addWidget(self.commentForm,3,1) | |
# Start Button | |
self.startButton = QPushButton("Start", self) | |
self.startButton.clicked.connect(self.startButtonClicked) | |
self.vLayout.addWidget(self.startButton) | |
def drawTitleCheckboxChanged(self): | |
if self.drawTitleCheckbox.isChecked() == True: | |
QMessageBox.about(self, "Info", "Checked") | |
def startButtonClicked(self): | |
self.run() | |
def log(self, text): | |
self.logForm.insertPlainText(text + '\n') | |
def run(self): | |
# self.title = filename | |
artist = self.artistForm.text() | |
comment = self.commentForm.toPlainText() | |
copyright = self.copyrightForm.text() | |
files = self.fileListView.getFileList() | |
for file in files: | |
stamp(file, artist, comment, copyright, self) | |
if __name__ == "__main__": | |
app = QApplication(sys.argv) | |
win = CopyrighterWindow() | |
win.show() | |
app.exec_() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment