update ui, fix a bug that can not save cropped pdf to target directory
This commit is contained in:
parent
681af4b36a
commit
c47e7c9a07
15
cropper.py
15
cropper.py
@ -16,6 +16,12 @@ def clip(value, min_value, max_value):
|
|||||||
value = max_value
|
value = max_value
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def parse_workdir(filepath):
|
||||||
|
workdir = '/'.join('/'.join(filepath.split('\\')).split('/')[:-1])
|
||||||
|
if workdir == '':
|
||||||
|
workdir = '.'
|
||||||
|
return workdir
|
||||||
|
|
||||||
def crop(args):
|
def crop(args):
|
||||||
infile = args.input
|
infile = args.input
|
||||||
# process filepath
|
# process filepath
|
||||||
@ -31,9 +37,8 @@ def crop(args):
|
|||||||
thresh = args.thresh
|
thresh = args.thresh
|
||||||
|
|
||||||
# parse working dir.
|
# parse working dir.
|
||||||
workdir = '/'.join('/'.join(infile.split('\\')).split('/')[:-1])
|
inworkdir = parse_workdir(infile)
|
||||||
if workdir == '':
|
outworkdir = parse_workdir(outfile)
|
||||||
workdir = '.'
|
|
||||||
|
|
||||||
if infile.split('.')[-1].lower() in ['ppt', 'pptx']:
|
if infile.split('.')[-1].lower() in ['ppt', 'pptx']:
|
||||||
# lets process pptx.
|
# lets process pptx.
|
||||||
@ -119,7 +124,7 @@ def crop(args):
|
|||||||
names = ['{0}_{1}.pdf'.format(outbase, i+1) for i in range(len(pdf))]
|
names = ['{0}_{1}.pdf'.format(outbase, i+1) for i in range(len(pdf))]
|
||||||
if args.names is not None:
|
if args.names is not None:
|
||||||
names = args.names
|
names = args.names
|
||||||
namesfile = os.path.join(workdir, names)
|
namesfile = os.path.join(inworkdir, names)
|
||||||
if os.path.isfile(namesfile) and names.split('.')[-1] == 'txt':
|
if os.path.isfile(namesfile) and names.split('.')[-1] == 'txt':
|
||||||
with open(namesfile, 'r', encoding='utf-8') as f:
|
with open(namesfile, 'r', encoding='utf-8') as f:
|
||||||
names = f.read()
|
names = f.read()
|
||||||
@ -131,7 +136,7 @@ def crop(args):
|
|||||||
names = [n + '.pdf' if n[:-4] != '.pdf' else n for n in names]
|
names = [n + '.pdf' if n[:-4] != '.pdf' else n for n in names]
|
||||||
if len(names) < len(pdf):
|
if len(names) < len(pdf):
|
||||||
names += ['{0}_{1}.pdf'.format(outbase, i+1) for i in range(len(names), len(pdf))]
|
names += ['{0}_{1}.pdf'.format(outbase, i+1) for i in range(len(names), len(pdf))]
|
||||||
names = [os.path.join(workdir, name) for name in names]
|
names = [os.path.join(outworkdir, name) for name in names]
|
||||||
for i, (name, page) in enumerate(zip(names, pdf)):
|
for i, (name, page) in enumerate(zip(names, pdf)):
|
||||||
page_pdf = fitz.Document()
|
page_pdf = fitz.Document()
|
||||||
page_pdf.insertPDF(pdf, from_page=i, to_page=i)
|
page_pdf.insertPDF(pdf, from_page=i, to_page=i)
|
||||||
|
|||||||
26
main.py
26
main.py
@ -85,13 +85,15 @@ def parse_and_crop(conf):
|
|||||||
# parser.add_argument('--visual', '-v', default=False, action='store_true', help='display cropbox.')
|
# parser.add_argument('--visual', '-v', default=False, action='store_true', help='display cropbox.')
|
||||||
# parser.add_argument('--mute', '-m', default=False, action='store_true', help='do not display output file path.')
|
# parser.add_argument('--mute', '-m', default=False, action='store_true', help='do not display output file path.')
|
||||||
# args = parser.parse_args()
|
# args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
from ui import Loader
|
from ui import Loader
|
||||||
defaults = {
|
defaults = {
|
||||||
"input": "",
|
"input": "",
|
||||||
"output": "",
|
"output": "",
|
||||||
"background_color": "",
|
"background_color": "255,255,255",
|
||||||
"border": "0.0",
|
"border": "0.0",
|
||||||
"zoom": "1.0",
|
"zoom": "1.0",
|
||||||
"thresh": "1.0",
|
"thresh": "1.0",
|
||||||
@ -111,7 +113,7 @@ else:
|
|||||||
|
|
||||||
conf = {
|
conf = {
|
||||||
"input": {"name": "源文件", "type": "readfile", "extension": ("PDF & PPT", ".pdf .pptx")},
|
"input": {"name": "源文件", "type": "readfile", "extension": ("PDF & PPT", ".pdf .pptx")},
|
||||||
"output": {"name": "保存路径", "type": "savefile"},
|
"output": {"name": "保存路径", "type": "savefile", "initial": "output.pdf"},
|
||||||
"background_color": {"name": "背景颜色", "type": "color", "default": "255,255,255"},
|
"background_color": {"name": "背景颜色", "type": "color", "default": "255,255,255"},
|
||||||
"border": {"name": "留白", "type": "str", "default": "0.0"},
|
"border": {"name": "留白", "type": "str", "default": "0.0"},
|
||||||
"zoom": {"name": "缩放等级", "type": "str", "default": "1.0"},
|
"zoom": {"name": "缩放等级", "type": "str", "default": "1.0"},
|
||||||
@ -122,9 +124,27 @@ conf = {
|
|||||||
"mute": {"name": "显示保存文件", "type": "str", "default": "false"},
|
"mute": {"name": "显示保存文件", "type": "str", "default": "false"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
introduction = [
|
||||||
|
"==== 使用说明 ====",
|
||||||
|
"- 源文件:输入的文件,可以为PDF或者PPT,如果是PPT,会首先自动调用PowerPoint将给定的PPT转变为PDF然后进行裁剪(PPT裁剪第一次需要调用COM对象因此速度稍慢,建议耐心等待,裁切一次后速度会恢复到正常水平",
|
||||||
|
"- 保存路径:保存的文件名,仅适用于非拆分模式。如果留空,则保存路径为源文件所在目录,保存的文件名为\"源文件名_crop.pdf\"",
|
||||||
|
"- 背景颜色:哪一种颜色会被认为是背景",
|
||||||
|
"- 留白:不紧贴有效内容裁切,预留一个给定大小的白边。",
|
||||||
|
"- 缩放等级:裁切是基于视觉裁切的,因此裁切过程中会首先渲染PDF,采用默认值即可,更高的缩放会将PDF渲染为更高分辨率的图片从而提高裁剪精度,但计算时间也会相应增加。",
|
||||||
|
"- 阈值:像素值差异多少会被认为是前景。",
|
||||||
|
"- 拆分:是否将源文件自动拆分为每页一个的单个文件。默认文件名采取下划线+数字命名。如果源文件是PPT且PPT备注不为空,则首先采用PPT的备注作为当前页保存的文件名。",
|
||||||
|
"- 页名称:手动指定拆分模式下每一页的名称,具有最高优先级,用逗号分隔。留空则使用默认的文件名或者PPT中备注的文件名。",
|
||||||
|
"- 显示裁切框:在右侧的日志区域输出裁切框坐标",
|
||||||
|
"- 显示保存文件:显示保存的文件名。",
|
||||||
|
]
|
||||||
|
help_msg = '\n'.join(introduction)
|
||||||
|
|
||||||
# write defaults.
|
# write defaults.
|
||||||
for key in defaults:
|
for key in defaults:
|
||||||
conf[key]['default'] = defaults[key]
|
conf[key]['default'] = defaults[key]
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
Loader(master=root, conf=conf, execution=parse_and_crop, title="PDF/PPT自动裁边")
|
Loader(master=root, conf=conf, execution=parse_and_crop, title="PDF/PPT自动裁边", help_msg=help_msg)
|
||||||
|
|
||||||
|
|
||||||
|
print(help_msg)
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
36
ui.py
36
ui.py
@ -29,7 +29,7 @@ def text_on_image(img, text, pos, size=16, color='#000000'):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
class Loader(tk.Frame):
|
class Loader(tk.Frame):
|
||||||
def __init__(self, master=None, conf={}, execution=None, title=None):
|
def __init__(self, master=None, conf={}, execution=None, title=None, help_msg=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
self.master = master
|
self.master = master
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
@ -44,7 +44,7 @@ class Loader(tk.Frame):
|
|||||||
# self.font = tk.Font(family='', size=40,weight='',slant='',underline='',overstrike='')
|
# self.font = tk.Font(family='', size=40,weight='',slant='',underline='',overstrike='')
|
||||||
if self.title is not None:
|
if self.title is not None:
|
||||||
self.master.title(self.title)
|
self.master.title(self.title)
|
||||||
|
self.help_msg = help_msg
|
||||||
def add_resource(self, obj, name):
|
def add_resource(self, obj, name):
|
||||||
if name in self.resources:
|
if name in self.resources:
|
||||||
print('Name [{0}] Repeated.'.format(name))
|
print('Name [{0}] Repeated.'.format(name))
|
||||||
@ -137,6 +137,12 @@ class Loader(tk.Frame):
|
|||||||
conf[name] = self.resources[key].get()
|
conf[name] = self.resources[key].get()
|
||||||
self.execution(conf)
|
self.execution(conf)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.resources['textbox_log'].delete("1.0", 'end')
|
||||||
|
|
||||||
|
def showhelp(self):
|
||||||
|
print(self.help_msg)
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
self.rowcount = 0
|
self.rowcount = 0
|
||||||
for key, value in self.conf.items():
|
for key, value in self.conf.items():
|
||||||
@ -153,7 +159,7 @@ class Loader(tk.Frame):
|
|||||||
destination = 'entry_' + key
|
destination = 'entry_' + key
|
||||||
if dtype in ['readfile', 'savefile', 'directory']:
|
if dtype in ['readfile', 'savefile', 'directory']:
|
||||||
extension = value.get('extension', None)
|
extension = value.get('extension', None)
|
||||||
initialfile = default
|
initialfile = value.get('initial', None)
|
||||||
args = {
|
args = {
|
||||||
"dst": destination,
|
"dst": destination,
|
||||||
"choose_type": dtype,
|
"choose_type": dtype,
|
||||||
@ -161,7 +167,7 @@ class Loader(tk.Frame):
|
|||||||
"initial_file": initialfile
|
"initial_file": initialfile
|
||||||
}
|
}
|
||||||
self.add_button(
|
self.add_button(
|
||||||
text="选择文件",
|
text="<选择文件",
|
||||||
command=lambda args=args:self.choose_file(**args),
|
command=lambda args=args:self.choose_file(**args),
|
||||||
size=(16, 16),
|
size=(16, 16),
|
||||||
layout={"row":self.rowcount, "column": 2, "padx": 5},
|
layout={"row":self.rowcount, "column": 2, "padx": 5},
|
||||||
@ -171,7 +177,7 @@ class Loader(tk.Frame):
|
|||||||
self.conf[key]['type'] = 'str'
|
self.conf[key]['type'] = 'str'
|
||||||
elif dtype == 'color':
|
elif dtype == 'color':
|
||||||
self.add_button(
|
self.add_button(
|
||||||
text="选择颜色",
|
text="<选择颜色",
|
||||||
command=lambda dst=destination:self.choose_color(dst),
|
command=lambda dst=destination:self.choose_color(dst),
|
||||||
size=(16, 16),
|
size=(16, 16),
|
||||||
layout={"row":self.rowcount, "column": 2, "padx": 5},
|
layout={"row":self.rowcount, "column": 2, "padx": 5},
|
||||||
@ -181,15 +187,29 @@ class Loader(tk.Frame):
|
|||||||
|
|
||||||
self.rowcount += 1
|
self.rowcount += 1
|
||||||
self.add_button(
|
self.add_button(
|
||||||
text=" 裁剪 ",
|
text="清空输出>",
|
||||||
|
command=self.clear,
|
||||||
|
size=(16, 16),
|
||||||
|
layout={"row":self.rowcount-2, "column": 2, "pady": 5, "sticky": "e"},
|
||||||
|
name='clear_output'
|
||||||
|
)
|
||||||
|
self.add_button(
|
||||||
|
text="显示帮助>",
|
||||||
|
command=self.showhelp,
|
||||||
|
size=(16, 16),
|
||||||
|
layout={"row":self.rowcount-1, "column": 2, "pady": 5, "sticky": "e"},
|
||||||
|
name='show_help'
|
||||||
|
)
|
||||||
|
self.add_button(
|
||||||
|
text=" 开始裁剪 ",
|
||||||
command=self.execute,
|
command=self.execute,
|
||||||
size=(16, 16),
|
size=(16, 16),
|
||||||
layout={"row":self.rowcount, "column": 0, "columnspan": 2, "pady": 5},
|
layout={"row":self.rowcount, "column": 0, "columnspan": "3", "pady": 5},
|
||||||
name='execute_final'
|
name='execute_final'
|
||||||
)
|
)
|
||||||
self.add_textbox(
|
self.add_textbox(
|
||||||
width=40,
|
width=40,
|
||||||
layout={"row":0, "column": 3, "rowspan": self.rowcount, "padx": 5, "pady": 0},
|
layout={"row":0, "column": 3, "rowspan": self.rowcount + 1, "padx": 5, "pady": 5, "sticky": "ns"},
|
||||||
name="textbox_log"
|
name="textbox_log"
|
||||||
)
|
)
|
||||||
sys.stdout = StdSimulator(self.resources['textbox_log'])
|
sys.stdout = StdSimulator(self.resources['textbox_log'])
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user