####################################################################################################################################### SOF import curses import os import shutil import sys from curses import (A_REVERSE, KEY_DOWN, KEY_ENTER, KEY_LEFT, KEY_RIGHT, KEY_UP, ascii, wrapper) from imghdr import what as is_file_an_image from os import chdir, listdir, path from pathlib import Path from random import randint, shuffle from time import sleep from tkinter import * from tkinter import filedialog, ttk from tkinter.filedialog import askopenfile from PIL import Image, ImageTk SHOWHELP=True MOTD=[0,1] MOTD[0]=f"""hotkeys: m: shuffle on/off p: autopump on/off r: cycle image-rendering modes t: display text on/off up: increase autopump inverval down: decrease autopump interval left: change image right: change image s: move image to _keep directory d: move image to _drop directory q: quit program Change SHOWHELP=True to SHOWHELP=False to remove this message. """ MOTD[1]=f"""base_picture_directory_path: ??: the directory you want to load images from string: path e.g. /home/user/Pictures starting_index: ??: index number you want to start from integer: index e.g. 3 rendering mode: ??: the rendering mode you want to use to start integer: index 0: image y screen-constrained - scales the image to the height of the screen 1: image x screen-constrained - scales the image to the width of the screen 2: image x,y screen-constrained - scales the image to the height,width of the screen 3: image x,y image-thumbnail - scales image within screen-resolution 4: image original - displays image at normal scale e.g. 3 pump_mode: ??: this changes images automatically integer: boolean 0: off 1: on e.g. 1 pump_interval: ??: the interval in seconds between pictures changing automatically float: value e.g. 3.5 shuffle: ??: randomize order that images are loaded integer: boolean e.g. 1 Change SHOWHELP=True to SHOWHELP=False to remove this message. command line: usage: {sys.argv[0]} base_picture_directory_path starting_index rendering_mode pump_mode pump_interval shuffle e.g. {sys.argv[0]} /home/dr1p/Pictures 0 4 1 3 1 """ ########################################################################################################################################### class DR1P1M4G3(): ######################################################################################################################################### def __init__(self,USERPATH=None,IMGINDEX=None,RENDMODE=None,PUMPMODE=None,PUMPTIME=None,USERSHUF=None): ####################################################################################################################################### if USERPATH: self.IMAGE_DIR=str(USERPATH) self.USER_USERPATH=USERPATH else: self.USER_USERPATH="" self.IMAGE_DIR="./" ####################################################################################################################################### if IMGINDEX: self.IMAGE_INDEX=IMGINDEX self.USER_IMGINDEX=IMGINDEX else: self.USER_IMGINDEX=0 self.IMAGE_INDEX=0 ####################################################################################################################################### if RENDMODE: self.REDIMENSION=RENDMODE self.USER_RENDMODE=RENDMODE else: self.USER_RENDMODE=0 self.REDIMENSION=0 ####################################################################################################################################### if PUMPMODE: self.PUMPMODE=PUMPMODE self.USER_PUMPMODE=PUMPMODE else: self.USER_PUMPMODE=False self.PUMP_AUTO=False ####################################################################################################################################### if not PUMPTIME==float(0.5): self.PUMPTIME=PUMPTIME self.USER_PUMPTIME=PUMPTIME self.PUMP_INTERVAL=0.5 else: self.USER_PUMPTIME=0 self.PUMP_INTERVAL=0.5 ####################################################################################################################################### if USERSHUF: self.USERSHUF=USERSHUF self.USER_USERSHUF=False else: self.USERSHUF=False self.USER_USERSHUF=False ####################################################################################################################################### self.RENDER_TEXT=True self.LAST_DIRECTION=-1 self.ISAVE_DIRECTORY=self.IMAGE_DIR+"_ISAVE" self.IDROP_DIRECTORY=self.IMAGE_DIR+"_IDROP" self.IMAGE_LIST=[] self.main() ######################################################################################################################################### def fliptext(self,s): self.RENDER_TEXT=not self.RENDER_TEXT if self.RENDER_TEXT: print(f"<<<<< text rendering enabled >>>>>") self.canvas.delete('all') self.loadimage() else: print(f"<<<<< text rendering disabled >>>>>") self.canvas.delete('all') self.loadimage() ######################################################################################################################################### def isave(self,s): if not os.path.exists(self.ISAVE_DIRECTORY): os.mkdir(self.ISAVE_DIRECTORY) shutil.move(self.IMAGE_LIST[self.IMAGE_INDEX],self.ISAVE_DIRECTORY) print(f"<<<<< moved {self.IMAGE_LIST[self.IMAGE_INDEX]} to {self.ISAVE_DIRECTORY} >>>>>") if self.LAST_DIRECTION: self.right(self) else: self.left(self) ######################################################################################################################################### def idrop(self,s): if not os.path.exists(self.IDROP_DIRECTORY): os.mkdir(self.IDROP_DIRECTORY) shutil.move(self.IMAGE_LIST[self.IMAGE_INDEX],self.IDROP_DIRECTORY) print(f"<<<<< moved {self.IMAGE_LIST[self.IMAGE_INDEX]} to {self.IDROP_DIRECTORY} >>>>>") if self.LAST_DIRECTION: self.right(self) else: self.left(self) ######################################################################################################################################### def up(self,s): self.PUMP_INTERVAL+=0.01 ######################################################################################################################################### def down(self,s): self.PUMP_INTERVAL-=0.01 ######################################################################################################################################### def shuffling(self,s): self.USER_USERSHUF=not self.USER_USERSHUF if self.USER_USERSHUF: self.getfilelist() self.loadimage() print(f"<<<<< image shuffling enabled >>>>>") else: print(f"<<<<< image shuffling disabled >>>>>") ######################################################################################################################################## def escaped(self,s): self.root.destroy() sys.exit(0) ######################################################################################################################################### def autopump(self,s): self.PUMP_AUTO = not self.PUMP_AUTO if self.PUMP_AUTO: while self.PUMP_AUTO: self.right(self) if self.PUMP_INTERVAL < 0.01: self.PUMP_INTERVAL+=0.5 sleep(self.PUMP_INTERVAL) print(self.PUMP_AUTO) ######################################################################################################################################### def redimension(self,s): self.canvas.delete('all') self.REDIMENSION+=1 if self.REDIMENSION>4: self.REDIMENSION=0 self.loadimage() ######################################################################################################################################### def loadimage(self): self.canvas.delete('all') try: try: self.image=Image.open(self.IMAGE_LIST[self.IMAGE_INDEX]) except: pass IMG_X_OG=self.image.width IMG_Y_OG=self.image.height x=self.root.winfo_screenwidth() y=self.root.winfo_screenheight() xx=self.image.width yy=self.image.height REDIMENSION="" ##################################################################################################################################### if self.REDIMENSION==0: self.canvas.delete('all') REDIMENSION="[ image x screen-constrained ]" xxx=xx+(x-xx) yyy=yy+(x-xx) if yyy>y: REDIMENSION="[ image y screen-constrained ]" yy=yyy-(yyy-y) if IMG_Y_OG < y: xx=xxx-(yyy-y) else: xx=xx-(self.image.height-y) try: self.resized_image=self.image.resize((xx,yy),Image.LANCZOS) self.photo_resized=ImageTk.PhotoImage(self.resized_image) self.canvas.create_image(x/2-xx/2,0,anchor=NW,image=self.photo_resized) except: if self.LAST_DIRECTION: self.right(self) else: self.left(self) ##################################################################################################################################### elif self.REDIMENSION==1: self.canvas.delete('all') REDIMENSION="[ image x screen-constrained ]" if xxself.root.winfo_screenheight(): for i in range(100): if not self.REDIMENSION==1: self.canvas.delete('all') sleep(0.1) self.loadimage() break offset=int(i*(yy-self.root.winfo_screenheight())/100) self.resized_image=self.image.resize((xx,yy),Image.LANCZOS) self.cropped_image=self.resized_image.crop([0,0+offset,x,y+offset]) self.photo_resized=ImageTk.PhotoImage(self.cropped_image) self.canvas.create_image(0,0,anchor=NW,image=self.photo_resized) self.canvas.configure(bg='black') Buffer = 'filename: {}\nredimension: {} - screen: {}x{} - image: {}x{} - diff: {}x{} - resize: {}x{}\nfile: {}/{} - interval: {}'.format(self.IMAGE_LIST[self.IMAGE_INDEX],REDIMENSION,self.root.winfo_screenwidth(),self.root.winfo_screenheight(),self.image.width,self.image.height,x-IMG_X_OG,y-IMG_Y_OG,xx,yy,self.IMAGE_INDEX,len(self.IMAGE_LIST)-1,self.PUMP_INTERVAL) if self.RENDER_TEXT: self.canvas.create_text(self.root.winfo_screenwidth()/2, 55, text=Buffer,fill='red',justify='center') self.root.title(Buffer) print(f"{offset} / {x} - {i}") self.root.update() else: self.resized_image=self.image.resize((xx,yy),Image.LANCZOS) self.photo_resized=ImageTk.PhotoImage(self.resized_image) self.canvas.create_image(0,0,anchor=NW,image=self.photo_resized) self.canvas.delete('all') self.canvas.configure(bg='black') Buffer = 'filename: {}\nredimension: {} - screen: {}x{} - image: {}x{} - diff: {}x{} - resize: {}x{}\nfile: {}/{} - interval: {}'.format(self.IMAGE_LIST[self.IMAGE_INDEX],REDIMENSION,self.root.winfo_screenwidth(),self.root.winfo_screenheight(),self.image.width,self.image.height,x-IMG_X_OG,y-IMG_Y_OG,xx,yy,self.IMAGE_INDEX,len(self.IMAGE_LIST)-1,self.PUMP_INTERVAL) if self.RENDER_TEXT: self.canvas.create_text(self.root.winfo_screenwidth()/2, 55, text=Buffer,fill='red',justify='center') self.root.title(Buffer) print(f"{offset} / {x} - {i}") self.root.update() ##################################################################################################################################### elif self.REDIMENSION==2: self.canvas.delete('all') REDIMENSION="[ image x,y screen-stretched ]" self.resized_image=self.image.resize((self.root.winfo_screenwidth(),self.root.winfo_screenheight()),Image.LANCZOS) self.photo_resized=ImageTk.PhotoImage(self.resized_image) self.canvas.create_image(0,0,anchor=NW,image=self.photo_resized) ##################################################################################################################################### elif self.REDIMENSION==3: self.canvas.delete('all') REDIMENSION="[ screen x,y image-thumbnail ]" self.image.thumbnail((1680,1050),resample=Image.LANCZOS) self.image.save('thumbnail.jpg') self.image=Image.open('thumbnail.jpg') self.photo=ImageTk.PhotoImage(self.image) xx=self.image.width yy=self.image.height self.canvas.create_image(x/2-xx/2,0,anchor=NW,image=self.photo) ##################################################################################################################################### elif self.REDIMENSION==4: self.canvas.delete('all') REDIMENSION="[ image-original ]" self.photo=ImageTk.PhotoImage(self.image) self.canvas.create_image(x/2-xx/2,0,anchor=NW,image=self.photo) ##################################################################################################################################### self.canvas.configure(bg='black') global Name Name = 'filename: {}\nredimension: {} - screen: {}x{} - image: {}x{} - diff: {}x{} - resize: {}x{}\nfile: {}/{} - interval: {}'.format(self.IMAGE_LIST[self.IMAGE_INDEX],REDIMENSION,self.root.winfo_screenwidth(),self.root.winfo_screenheight(),self.image.width,self.image.height,x-IMG_X_OG,y-IMG_Y_OG,xx,yy,self.IMAGE_INDEX,len(self.IMAGE_LIST)-1,self.PUMP_INTERVAL) if self.RENDER_TEXT: self.canvas.create_text(self.root.winfo_screenwidth()/2, 55, text=Name,fill='red',justify='center') self.root.title(Name) self.root.update() except IOError: print(f"error: non-picture, skipping past - {self.IMAGE_LIST[self.IMAGE_INDEX]}") if self.LAST_DIRECTION: self.right(self) else: self.left(self) pass print('<< dr1p1m4g3 >> screen: {}x{} - image: {}x{} - file: {}/{} - interval: {} - filename: {}'.format(self.root.winfo_screenwidth(),self.root.winfo_screenheight(),self.image.width,self.image.height,self.IMAGE_INDEX,len(self.IMAGE_LIST)-1,self.PUMP_INTERVAL,self.IMAGE_LIST[self.IMAGE_INDEX])) ######################################################################################################################################### def getfilelist(self): # self.IMAGE_LIST=[ x for x in Path(self.IMAGE_DIR+'/').rglob('*') if not str(x).endswith('.txt') and not "intermediates" in x.name ] print(f'<<< generating image list recursively from base directory: {self.IMAGE_DIR}/* >>>') FILE_LIST=[ x for x in Path(self.IMAGE_DIR+'/').rglob('*') ] self.IMAGE_LIST=[] for x in FILE_LIST: try: if is_file_an_image(str(x)): self.IMAGE_LIST.append(x) print(f'added: {str(x)}') except Exception as e: print(f'skipped: {str(x)} - reason: {e}') if self.USER_USERSHUF: shuffle(self.IMAGE_LIST) self.IMAGE_INDEX=randint(0,len(self.IMAGE_LIST)-1) print(f'index:{self.IMAGE_LIST[self.IMAGE_INDEX]}/{len(self.IMAGE_LIST)} - filename:{self.IMAGE_LIST[self.IMAGE_INDEX]} - size:{self.image.size}: [ width:{self.image.width} / height:{self.image.height} ]') self.IMAGE_LIST=sorted(self.IMAGE_LIST) ######################################################################################################################################### def right(self,s): self.LAST_DIRECTION=True self.IMAGE_INDEX+=1 if self.IMAGE_INDEX==len(self.IMAGE_LIST): self.IMAGE_INDEX=0 self.getfilelist() self.loadimage() ######################################################################################################################################### def left(self,s): self.LAST_DIRECTION=False self.IMAGE_INDEX-=1 self.getfilelist() if self.IMAGE_INDEX<0: self.IMAGE_INDEX=len(self.IMAGE_LIST)-1 self.loadimage() ######################################################################################################################################### def main(self): ####################################################################################################################################### try: Name='<< dr1p1m4g3 >>' self.root=Tk(className=Name) self.root.attributes('-fullscreen',True) self.root.eval('tk::PlaceWindow . center') # self.root.overrideredirect(True) #self.root.wm_attributes("-topmost",True) #self.root.wm_attributes("-transparent",True) #self.root.config(bg='systemTransparent') self.image=Image.new(mode='RGB', size=(self.root.winfo_screenwidth(),self.root.winfo_screenheight())) self.photo=ImageTk.PhotoImage(self.image) self.canvas=Canvas(self.root,width=self.root.winfo_screenwidth(),height=self.root.winfo_screenheight(),bd=0,highlightthickness=0) self.canvas.pack(fill="both",expand=True) self.REDIMENSION+=self.USER_RENDMODE self.IMAGE_INDEX=(0+int(self.USER_IMGINDEX)) self.PUMP_AUTO=self.USER_PUMPMODE self.getfilelist() self.canvas.bind("",self.shuffling) self.canvas.bind("

",self.autopump) self.canvas.bind("",self.redimension) self.canvas.bind("",self.fliptext) self.canvas.bind("",self.up) self.canvas.bind("",self.down) self.canvas.bind("",self.left) self.canvas.bind("",self.right) self.canvas.bind("",self.isave) self.canvas.bind("",self.idrop) self.canvas.bind("",self.escaped) self.canvas.focus_set() self.loadimage() self.root.mainloop() ####################################################################################################################################### except Exception as err: print(f"main(): {err}") ########################################################################################################################################### def main(screen): curses.start_color() curses.use_default_colors() curses.init_pair(1,5,0) curses.init_pair(2,4,0) curses.init_pair(3,6,0) curses.init_pair(4,3,0) ch, first, selected, paths = 0, 0, 0, [ x for x in listdir() if os.path.isdir(x) ] screen.erase() if SHOWHELP: try: screen.addstr(0,0,'SELECT A BASE DIRECTORY',curses.color_pair(2)) screen.addstr(': ',curses.color_pair(1)) screen.addstr('<< ',curses.color_pair(4)) screen.addstr('LEFT',curses.color_pair(3)) screen.addstr('/',curses.color_pair(1)) screen.addstr('RIGHT',curses.color_pair(3)) screen.addstr('/',curses.color_pair(1)) screen.addstr('ENTER',curses.color_pair(3)) screen.addstr(' >>',curses.color_pair(4)) screen.addstr(1,0,'[ ',curses.color_pair(1)) screen.addstr("THE CURRENT DIRECTORY",curses.color_pair(2)) screen.addstr(': ',curses.color_pair(1)) screen.addstr(f"{os.getcwd()}",curses.color_pair(3)) screen.addstr(' ]',curses.color_pair(1)) screen.addstr(2,0,'',curses.color_pair(1)) screen.addstr(3,0,'Change SHOWHELP=True to SHOWHELP=False to remove this message.',curses.color_pair(3)) except Exception as e: pass screen.refresh() sleep(6) while ch != ascii.ESC: height, _ = screen.getmaxyx() screen.erase() screen.refresh() try: paths=sorted(paths) for y, filename in enumerate(paths[first : first+height]): screen.addstr(y, 0, filename, A_REVERSE * (selected == first + y)) except: pass ch = screen.getch() selected += (ch == KEY_DOWN) - (ch == KEY_UP) selected = max(0, min(len(paths)-1, selected)) first += (first <= selected - height) - (first > selected) if ch in [KEY_LEFT, KEY_RIGHT, KEY_ENTER, 10, 13]: if not ch==10: new_dir = '..' if ch == KEY_LEFT else paths[selected] if path.isdir(new_dir): chdir(new_dir) first, selected, paths = 0, 0, [ x for x in listdir() if os.path.isdir(x) ] paths=sorted(paths) else: curses.nocbreak() curses.endwin() return str(os.getcwd()) ########################################################################################################################################### if __name__=="__main__": ######################################################################################################################################### if SHOWHELP: print(MOTD[0]) print('press enter key to continue') input() print(MOTD[1]) print('press enter key to continue') input() ######################################################################################################################################### DEBUG=False if DEBUG: USERPATH=str("") IMGINDEX=int(0) RENDMODE=int(0) PUMPMODE=int(1) PUMPTIME=10 USERSHUF=True else: USERPATH=str("") IMGINDEX=int(0) RENDMODE=int(0) PUMPMODE=int(0) PUMPTIME=float(0.5) USERSHUF=False ######################################################################################################################################### if not DEBUG: try: USERPATH=str(sys.argv[1]) print(f'[ specified user path: {USERPATH} ]') except: USERPATH=str(wrapper(main)) print(f'[ no directory path was specified: defaulting to current directory and recursively ]') ######################################################################################################################################### if not DEBUG: try: IMGINDEX=int(sys.argv[2]) print(f'[ specified user index: {IMGINDEX} ]') except: IMGINDEX=0 print(f'[ no image index was specificed: defaulting to 0 ]') ######################################################################################################################################### if not DEBUG: try: RENDMODE=int(sys.argv[3]) print(f'[ specified rendering mode: {RENDMODE} ]') except: RENDMODE=0 print(f'[ no render mode specified: defaulting to image x,y screen-constrained ]') ######################################################################################################################################### if not DEBUG: try: PUMPMODE=int(sys.argv[4]) print(f'[ specified user pump mode: {PUMPMODE} ]') try: PUMPTIME=float(sys.argv[5]) print(f'[ specified user pump interval: {PUMPTIME} ]') except: PUMPTIME=0 print(f'[ no pump mode interval: default to 0.5 second interval ]') except: print(f'[ no pump mode specified: defaulting to being turned off ]') ######################################################################################################################################### if not DEBUG: try: USERSHUF=int(sys.argv[6]) print(f'[ specified user image shuffle mode: {USERSHUF} ]') except: USERSHUF=False print(f'[ no shuffle mode specified: defaulting to being turned off ]') ######################################################################################################################################### dr1p1m4g3=DR1P1M4G3(USERPATH,IMGINDEX,RENDMODE,PUMPMODE,PUMPTIME,USERSHUF) ######################################################################################################################################### ####################################################################################################################################### EOF