3535__copyright__ = '(c) 2024-2025 Ilya Razmanov'
3636__credits__ = 'Ilya Razmanov'
3737__license__ = 'unlicense'
38- __version__ = '1.20.1.1 '
38+ __version__ = '1.20.7.14 '
3939__maintainer__ = 'Ilya Razmanov'
4040__email__ = 'ilyarazmanov@gmail.com'
4141__status__ = 'Production'
4242
4343from copy import deepcopy
4444from pathlib import Path
4545from random import randbytes # Used for random icon only
46- from tkinter import Button , Frame , IntVar , Label , Menu , Menubutton , PhotoImage , Spinbox , Tk , filedialog
46+ from time import ctime
47+ from tkinter import Button , Frame , IntVar , Label , Menu , Menubutton , PhotoImage , Spinbox , Tk
48+ from tkinter .filedialog import askopenfilename , asksaveasfilename
4749from tkinter .messagebox import showinfo
4850
49- from export import linen , stitch
50- from filter import avgrow
5151from pypng .pnglpng import png2list
5252from pypnm .pnmlpnm import list2bin , pnm2list
5353
54+ from export import linen , stitch
55+ from filter import avgrow
56+
5457""" ┌────────────┐
5558 │ GUI events │
5659 └────-───────┘ """
@@ -68,30 +71,34 @@ def ShowMenu(event) -> None:
6871
6972def ShowInfo (event = None ) -> None :
7073 """Show image information"""
74+ file_size = Path (sourcefilename ).stat ().st_size
75+ file_size_str = f'{ file_size / 1024 :.2f} Kb' if (file_size > 1024 ) else f'{ file_size } bytes'
76+ modification_str = ctime (Path (sourcefilename ).stat ().st_mtime )
77+ channels_str = f'{ Z } channel' if Z == 1 else f'{ Z } channels'
7178 showinfo (
7279 title = 'Image information' ,
73- message = f'File: { sourcefilename } ' ,
74- detail = f'Image: X= { X } , Y= { Y } , Z= { Z } , maxcolors= { maxcolors } ' ,
80+ message = f'File properties: \n Location: { sourcefilename } \n Size: { file_size_str } \n Last modified: { modification_str } ' ,
81+ detail = f'Image properties, as internally represented by program: \n Width: { X } px \n Height: { Y } px \n Channels: { channels_str } \n Color depth: { maxcolors + 1 } gradations/channel ' ,
7582 )
7683
7784
7885def UINormal () -> None :
7986 """Normal UI state, buttons enabled"""
8087 for widget in frame_top .winfo_children ():
8188 if widget .winfo_class () in ('Label' , 'Button' , 'Spinbox' ):
82- widget . config ( state = 'normal' )
89+ widget [ ' state' ] = 'normal'
8390 if widget .winfo_class () == 'Button' :
84- widget . config ( cursor = 'hand2' )
91+ widget [ ' cursor' ] = 'hand2'
8592 info_string .config (text = info_normal ['txt' ], foreground = info_normal ['fg' ], background = info_normal ['bg' ])
8693
8794
8895def UIBusy () -> None :
8996 """Busy UI state, buttons disabled"""
9097 for widget in frame_top .winfo_children ():
9198 if widget .winfo_class () in ('Label' , 'Button' , 'Spinbox' ):
92- widget . config ( state = 'disabled' )
99+ widget [ ' state' ] = 'disabled'
93100 if widget .winfo_class () == 'Button' :
94- widget . config ( cursor = 'arrow' )
101+ widget [ ' cursor' ] = 'arrow'
95102 info_string .config (text = info_busy ['txt' ], foreground = info_busy ['fg' ], background = info_busy ['bg' ])
96103 sortir .update ()
97104
@@ -106,12 +113,12 @@ def ShowPreview(preview_name: PhotoImage, caption: str) -> None:
106113 preview = preview .zoom (
107114 zoom_factor + 1 ,
108115 )
109- label_zoom . config ( text = f'Zoom { zoom_factor + 1 } :1' )
116+ label_zoom [ ' text' ] = f'Zoom { zoom_factor + 1 } :1'
110117 else :
111118 preview = preview .subsample (
112119 1 - zoom_factor ,
113120 )
114- label_zoom . config ( text = f'Zoom 1:{ 1 - zoom_factor } ' )
121+ label_zoom [ ' text' ] = f'Zoom 1:{ 1 - zoom_factor } '
115122
116123 zanyato .config (text = caption , font = ('helvetica' , 8 ), image = preview , compound = 'top' , padx = 0 , pady = 0 , justify = 'center' , background = zanyato .master ['background' ], relief = 'flat' , borderwidth = 1 , state = 'normal' )
117124
@@ -129,7 +136,7 @@ def GetSource(event=None) -> None:
129136 is_filtered = False
130137 is_saved = False
131138
132- sourcefilename = filedialog . askopenfilename (title = 'Open image file' , filetypes = [('Supported formats' , '.png .ppm .pgm .pbm' ), ('Portable network graphics' , '.png' ), ('Portable network map' , '.ppm .pgm .pbm' )])
139+ sourcefilename = askopenfilename (title = 'Open image file' , filetypes = [('Supported formats' , '.png .ppm .pgm .pbm' ), ('Portable network graphics' , '.png' ), ('Portable network map' , '.ppm .pgm .pbm' )])
133140 if sourcefilename == '' :
134141 return
135142
@@ -203,7 +210,7 @@ def GetSource(event=None) -> None:
203210 butt_plus .config (state = 'normal' , cursor = 'hand2' )
204211 butt_minus .config (state = 'normal' , cursor = 'hand2' )
205212 # updating zoom label display
206- label_zoom . config ( text = 'Zoom 1:1' )
213+ label_zoom [ ' text' ] = 'Zoom 1:1'
207214 # enabling "Filter"
208215 UINormal ()
209216
@@ -223,9 +230,7 @@ def RunFilter(event=None) -> None:
223230 """ ┌─────────────────┐
224231 │ Filtering image │
225232 └─────────────────┘ """
226- image3D = avgrow .filter (source_image3D , threshold_x , threshold_y )
227-
228- UINormal ()
233+ image3D = avgrow .filter (source_image3D , threshold_x , threshold_y , wrap_around = False , keep_alpha = True )
229234
230235 # preview result
231236 preview_data = list2bin (image3D , maxcolors , show_chessboard = True )
@@ -238,10 +243,11 @@ def RunFilter(event=None) -> None:
238243 ShowPreview (preview_filtered , 'Result' )
239244
240245 # enabling zoom
241- label_zoom . config ( state = 'normal' )
246+ label_zoom [ ' state' ] = 'normal'
242247 butt_plus .config (state = 'normal' , cursor = 'hand2' )
243248 # binding switch on preview click
244249 zanyato .bind ('<Button-1>' , SwitchView ) # left click
250+ UINormal ()
245251
246252
247253def zoomIn (event = None ) -> None :
@@ -300,7 +306,7 @@ def SwitchView(event=None) -> None:
300306
301307def SaveAsLinen () -> None :
302308 """Once pressed on Linen"""
303- savefilename = filedialog . asksaveasfilename (
309+ savefilename = asksaveasfilename (
304310 title = 'Save POV-Ray file' ,
305311 filetypes = [
306312 ('POV-Ray file' , '.pov' ),
@@ -325,7 +331,7 @@ def SaveAsLinen() -> None:
325331
326332def SaveAsStitch () -> None :
327333 """Once pressed on Linen"""
328- savefilename = filedialog . asksaveasfilename (
334+ savefilename = asksaveasfilename (
329335 title = 'Save POV-Ray file' ,
330336 filetypes = [
331337 ('POV-Ray file' , '.pov' ),
@@ -398,7 +404,7 @@ def SaveAsStitch() -> None:
398404menu02 .add_separator ()
399405menu02 .add_command (label = 'Exit' , state = 'normal' , command = DisMiss , accelerator = 'Ctrl+Q' )
400406
401- butt01 . config ( menu = menu02 )
407+ butt01 [ ' menu' ] = menu02
402408
403409# Filter section begins
404410info00 = Label (frame_top , text = 'Filtering \n Threshold:' , font = ('helvetica' , 8 , 'italic' ), justify = 'right' , foreground = 'brown' , state = 'disabled' )
0 commit comments