guetzli-recursively-gui/dist/Guetzli-R.app/Contents/Resources/Guetzli-R.py
2017-04-20 00:57:59 +02:00

148 lines
5.3 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from os import path, walk, remove, rename
from imghdr import what
from subprocess import call
from tkinter import Frame, Tk, Button, Label, filedialog, ttk, font, PhotoImage
import threading
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
master.title('Guetzli recursively GUI')
master.minsize(width=500, height=140)
master.maxsize(width=500, height=140)
self.font_general = font.Font(family='Helvetica', size=14)
self.font_run = font.Font(family='Helvetica', size=18)
self.center(master)
self.pack()
self.create_widgets()
self.top_dir = ''
self.TEMP_FILE = 'temp.jpg'
self.TYPES = ('jpeg',)
self.num_images = 0
def create_widgets(self):
# Button select folder
self.button_select_folder = Button(self)
self.button_select_folder['text'] = 'Choose folder'
self.button_select_folder['pady'] = 10
self.button_select_folder['font'] = self.font_general
self.button_select_folder['command'] = self.open_folder
self.button_select_folder.pack(side='top')
# Label path folder
self.label_path = Label(self)
self.label_path['text'] = ''
self.label_path['pady'] = 10
self.label_path['font'] = self.font_general
# Button run
self.button_run = Button(self)
self.button_run['text'] = 'Optimize'
self.button_run['font'] = self.font_run
self.button_run['pady'] = 10
self.button_run['state'] = 'disabled'
self.button_run['command'] = self._start_optimize
self.button_run.pack(side='top')
# Progressbar
self.progress_bar = ttk.Progressbar(self)
self.progress_bar['length'] = 500
def center(self, toplevel):
toplevel.update_idletasks()
w = toplevel.winfo_screenwidth()
h = toplevel.winfo_screenheight()
size = tuple(
int(_) for _ in toplevel.geometry().split('+')[0].split('x')
)
x = w/2 - size[0]/2
y = h/2 - size[1]/2
toplevel.geometry('%dx%d+%d+%d' % (size + (x, y)))
def open_folder(self):
self.button_run['state'] = 'disabled'
self.top_dir = filedialog.askdirectory(initialdir='.')
self.label_path['text'] = 'Looking for images to optimize... Please, wait'
self._start_count_images()
def _update_label_num_files(self):
self.label_path['text'] = f'{self.num_images} images found'
if self.num_images > 0:
self.button_run['state'] = 'normal'
self.button_run.pack_forget()
self.label_path.pack(side='top')
self.button_run.pack(side='top')
def _start_count_images(self):
newthread = threading.Thread(target=self.count_images)
newthread.start()
def _start_optimize(self):
newthread = threading.Thread(target=self.run_guetzli)
newthread.start()
def count_images(self):
num = 0
for dirpath, dirnames, files in walk(self.top_dir):
for name in files:
url = path.join(dirpath, name)
# Check type
if what(url) in self.TYPES:
num += 1
self.num_images = num
self._update_label_num_files()
def run_guetzli(self):
# Show progress bar
self.progress_bar['value'] = 0
self.progress_bar['maximum'] = self.num_images
self.progress_bar.pack(side='bottom')
self.button_run['state'] = 'disabled'
self.button_select_folder['state'] = 'disabled'
# Run guetzli
for dirpath, dirnames, files in walk(self.top_dir):
for name in files:
# Info
self.label_path['text'] = 'Preparing file'
url = path.join(dirpath, name)
# Check type
if what(url) in self.TYPES:
# Info
self.label_path['text'] = f'Working... {name}'
# Get urls
url_out = path.join(self.top_dir, self.TEMP_FILE)
# Remove temp image
try:
remove(url_out)
except:
pass
# Execute guetzli
call(['guetzli-osx', url, url_out])
# Check if it is cost effective to replace it
size_source = path.getsize(url)
size_out = 0
try:
size_out = path.getsize(url_out)
except:
size_out = size_source
size_acurate = 100 * size_out / size_source
if size_acurate < 100:
# Remove source
try:
remove(url)
except:
pass
# Move temp to source
rename(url_out, url)
# Increment progress bar
self.progress_bar['value'] += 1
# Message finish
self.button_select_folder['state'] = 'normal'
self.label_path['text'] = 'Finish!'
self.progress_bar.pack_forget()
root = Tk()
app = Application(master=root)
app.mainloop()