#!/usr/bin/env python3 ################################################ # 2022 by Paul Sherman # last updated Saturday, 04/09/2022 # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ################################################ import tkinter.filedialog as filedialog from tkinter import * import tkinter.messagebox import os, imghdr, re, subprocess, base64, sys from PIL import ImageTk, Image from shutil import copyfile def showMessage(message, type='info', timeout=4000): import tkinter as tk from tkinter import messagebox as msgb root = tk.Tk() root.withdraw() try: root.after(timeout, root.destroy) msgb.showinfo('Colors Reduced', message, master=root) except: pass APP_ICON = """ R0lGODlhEAAQAMZmALgBGAAswAEtwLkDGgIuwLkEHAQvwbkFHAUwwQYxwQcywggzwgkzwgs1w7wQ JRA5xBE6xBQ9xRU9xRY+xRpCxhxDxx1Exx5Fxx9GyCtPy8QsPsUwQzFVzTNWzTRXzTpczj1ez0Bh 0EFi0MtDVEtq085OX1Fv1FNx1VZz1Vp21lx412F82GN+2GaA2WmC2m2G226G29hwfXOL3HSM3dh1 gtt/in+V34KY4N2FkN6Hkoec4Yid4omd4t+Nl5ao5eKXoZmr5pus5pyt5+Wgqae26aq56q+96+my uLK/7Oq0u7bD7bfD7bjE7bvH7sDL78jR8cnS8srT8uPQ387W89La9PPU2N/l9+Dl9+Ln+Ofr+ent +uvu+vP1/PT2/Pf4/fj5/f34+f77+/v8/v39//7+/////1YAkVYAkVYAkVYAkVYAkVYAkVYAkVYA kVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkVYAkSH5 BAEKAH8ALAAAAAAQABAAAAfGgFonExCFhocRJFgmHUZNj5CRSCAiD0ZlPilIZZydnE4GDEpKCScI V546TGVPAaJBE0UCUZ1ABA1TraJcIQYrZJxQCkAqFUauSpxjnVoWLGVeHxPIZVcvXWViIh5eVTRS GMhfHgIpZTMRqD8ASVQnojwUSwsoBk2c60mcollWZUIBZHTKx0kCEU8rLmwpg2PEgBI9yrSwcGOH RRsIQDCJUQDAgRpl/sDgkKGkSRdgNADYECbkn5cwYZYZ4uAIp5g4/3DK0SkQADs=""" top = Tk() icondata= base64.b64decode(APP_ICON) tempFile= "/tmp/icon.gif" iconfile= open(tempFile,"wb") iconfile.write(icondata) iconfile.close() try: img = PhotoImage(file='/tmp/icon.gif') top.tk.call('wm', 'iconphoto', top._w, img) except: pass os.remove(tempFile) # this section bails from program if something is amiss --------------------------------------------- # first, we check if the cwebp program is present: f = subprocess.getoutput('type -path cwebp') if not f: top.withdraw() tkinter.messagebox.showinfo("Error", "libwebp needs to be installed to use this utility") sys.exit(0) # if we are not passed a filename, pop up a file open dialog if len(sys.argv) < 2: file_name = filedialog.askopenfilename(title='Select a JPEG file', filetypes=[('JPEG files', '.jpg')]) if not file_name: sys.exit(0) else: file_name = ' '.join(sys.argv[1:]) if not os.path.isfile(file_name): top.withdraw() tkinter.messagebox.showinfo("Error", "This script is meant to be passed a single JPEG file") sys.exit(0) # if the file name passed does not exist if not os.path.isfile(file_name): top.withdraw() tkinter.messagebox.showinfo("Error", "This script is meant to be passed a JPEG file") sys.exit(0) # if the filename passed is not a jpg x = imghdr.what(file_name) if not x == 'jpeg': top.withdraw() tkinter.messagebox.showinfo("Error", "file_name does not appear to be a valid JPEG image") sys.exit(0) #---------------------------------------------------------------------------------------------------------------- pattern = re.compile(".jpg", re.IGNORECASE) newname = pattern.sub("ORIGINAL.jpg", file_name) if newname == file_name: pattern = re.compile(".jpeg", re.IGNORECASE) newname = pattern.sub("ORIGINAL.jpeg", file_name) print (newname) def convert_it(ev=None): # copy original for backup first copyfile(file_name,newname) subprocess.call(['mogrify','-quality', str(scale.get()) + '%', file_name]) file_size = os.path.getsize(file_name) new_size = os.path.getsize(newname) if new_size < 2024: oSIZE = str(new_size) + " bytes" nSIZE = str(file_size) + " bytes" if 2024 < new_size < 1050000: oSIZE = str(round(new_size / 1024)) + " kb" nSIZE = str(round(file_size / 1024)) + " kb" if new_size > 1050000: oSIZE = str(round(new_size / 1048576)) + " mb" nSIZE = str(round(file_size / 1048576)) + " mb" print("File Size was :", oSIZE) print("New File Size :", nSIZE) sizeMESG = "File Size was : " + oSIZE + "\nNew File Size : " + nSIZE showMessage(sizeMESG) if deletebackup.get() == True: os.remove(newname) sys.exit(0) top.title("JPG-Reduce") subprocess.call(['convert', '-resize', '260x210', '-strip', file_name, '/tmp/88.jpg']) img = Image.open("/tmp/88.jpg") tk_img = ImageTk.PhotoImage(img) os.remove("/tmp/88.jpg") imagepanel=Label(top,image = tk_img) imagepanel.grid(row =0, column=0,rowspan=1,columnspan=2, padx=2,pady=10) label1 = Label(top, text='Output Quality', font='Sans -12 bold',width=16) label1.grid(row=1, column=0,columnspan=2,padx=2,pady=2) scale = Scale(top,from_=30,to=100,orient=HORIZONTAL,resolution=5,tickinterval=10,sliderlength=15,length=380) scale.config(width=20) scale.set(90) scale.grid(row =2, column=0,columnspan=2,padx=2,pady=2) deletebackup = BooleanVar() deletebackup.set(True) delCheckbox = Checkbutton(top, var=deletebackup, text="Delete Backup Automatically") delCheckbox.grid(row =3, column=0,columnspan=2,padx=2,pady=2) quit = Button(top, text='Never Mind', command=top.quit, activeforeground='white', activebackground='red',width=14) quit.grid(row =4, column=0, padx=16,pady=10) commit = Button(top, text='Reduce', command=convert_it, activeforeground='white', activebackground='green',width=16) commit.grid(row =4, column=1, padx=2,pady=10) # Gets the requested values of the height and widht. windowWidth = top.winfo_reqwidth() windowHeight = top.winfo_reqheight() # Gets both half the screen width/height and window width/height positionRight = int(top.winfo_screenwidth()/2 - windowWidth/2) positionDown = int(top.winfo_screenheight()/2 - windowHeight/2) # Positions the window in the center of the page. top.geometry("+{}+{}".format(positionRight, positionDown)) top.resizable(False, False) mainloop()