From 6687437247074aaa5c281ea97c29ad4c44470baa Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Wed, 7 Aug 2019 15:30:22 +0200 Subject: [PATCH] Working on image display --- src/CNIRevelator.py | 5 +- src/globs.py | 2 +- src/ihm.py | 182 ++++++-------------------------- src/image.py | 250 -------------------------------------------- src/main.py | 66 +++++++++--- src/mrz.py | 2 +- src/updater.py | 21 ++-- 7 files changed, 98 insertions(+), 430 deletions(-) diff --git a/src/CNIRevelator.py b/src/CNIRevelator.py index ab73b40..9e9e088 100644 --- a/src/CNIRevelator.py +++ b/src/CNIRevelator.py @@ -64,7 +64,10 @@ def main(): if globs.CNIRNewVersion: showinfo('Changelog : résumé de mise à jour', ('Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' + globs.changelog), parent=mainw) logfile.printdbg('main() : **** Launching App_main() ****') - mainw.mainloop() + try: + mainw.mainloop() + except Exception as e: + showerror("CNIRevelator Fatal Error", "An error has occured : {}".format(e), parent=mainw) logfile.printdbg('main() : **** Ending App_main() ****') logfile.printdbg('*** CNIRevelator LOGFILE. Goodbye World ! ***') diff --git a/src/globs.py b/src/globs.py index 86a57f6..674104c 100644 --- a/src/globs.py +++ b/src/globs.py @@ -31,7 +31,7 @@ verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], v verstring = "{}.{}".format(version[0], version[1]) debug = True -changelog = "Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n\n" + \ +changelog = "Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \ "Version 3.0.5 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'icône de l'exécutable afin de refléter le changement de version majeur accompli en 3.0\n\n" + \ "Version 3.0.4 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le système de mise-à-jour\n\n" + \ "Version 3.0.3 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le changelog\n- Correction d'une erreur avec la touche Suppr Arrière et Suppr causant une perte de données\n\n" + \ diff --git a/src/ihm.py b/src/ihm.py index b80ab2f..2cb7b5a 100644 --- a/src/ihm.py +++ b/src/ihm.py @@ -27,9 +27,12 @@ from tkinter import * from tkinter.messagebox import * from tkinter import filedialog from tkinter import ttk +import cv2 +import PIL.Image, PIL.ImageTk import logger # logger.py import globs # globs.py +import image # image.py controlKeys = ["Escape", "Right", "Left", "Up", "Down", "Home", "End", "BackSpace", "Delete", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"] @@ -121,9 +124,18 @@ class LauncherWindow(Tk): self.geometry('%dx%d+%d+%d' % (wwidth, wheight, x, y)) # Creating objects - self.image = PhotoImage(file = "background.png") + # Load an image using OpenCV + cv_img = cv2.imread("background.png") + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) + cv_img = cv2.blur(cv_img, (15, 15)) + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, no_channels = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width, no_channels = cv_img.shape + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage + self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) self.mainCanvas = Canvas(self, width=wwidth, height=wheight, bg=globs.CNIRLColor, highlightthickness=0) - self.mainCanvas.create_image(wwidth /2, wheight /2, image=self.image) + self.mainCanvas.create_image(wwidth /2, wheight /2, image=self.photo) # Column self.mainCanvas.grid_rowconfigure(0, weight=1, minsize=(wheight / 10 * 9)) @@ -158,6 +170,9 @@ class LauncherWindow(Tk): def printmsg(self, msg): self.mainCanvas.itemconfigure(self.msg, text=(msg)) + def exit(self): + self.after(1000, self.destroy) + class AutoScrollbar(ttk.Scrollbar): def set(self, lo, hi): @@ -173,156 +188,21 @@ class AutoScrollbar(ttk.Scrollbar): def place(self, **kw): raise TclError('Cannot use place with the widget ' + self.__class__.__name__) -class OpenPageDialog(Toplevel): - - def __init__(self, parent, number): - super().__init__(parent) - self.parent = parent - self.title("Choisir la page à afficher de l'image selectionnée") - self.resizable(width=False, height=False) - self.termtext = Label(self, text='Merci de selectionner un numéro de page dans la liste ci-dessous.') - self.termtext.grid(column=0, row=0, sticky='N', padx=5, pady=5) - self.combotry = ttk.Combobox(self) - self.combotry['values'] = tuple(str(x) for x in range(1, number + 1)) - self.combotry.grid(column=0, row=1, sticky='N', padx=5, pady=5) - self.button = Button(self, text='Valider', command=(self.valid)) - self.button.grid(column=0, row=2, sticky='S', padx=5, pady=5) - self.update() - hs = self.winfo_screenheight() - w = int(self.winfo_width()) - h = int(self.winfo_height()) - ws = self.winfo_screenwidth() - hs = self.winfo_screenheight() - x = ws / 2 - w / 2 - y = hs / 2 - h / 2 - self.geometry('%dx%d+%d+%d' % (w, h, x, y)) - if getattr(sys, 'frozen', False): - self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico') - else: - self.iconbitmap('id-card.ico') - - def valid(self): - self.parent.page = self.combotry.current() - self.destroy() - - -class OpenScanWin(Toplevel): - - def __init__(self, parent, file, type, nframe=1): - super().__init__(parent) - self.parent = parent - app = OpenScan(self, file, type, nframe) - -class OpenScan(ttk.Frame): - def __init__(self, mainframe, fileorig, type, nframe=1, pagenum=0, file=None): - """ Initialize the main Frame """ - if file == None: - file = fileorig - self.file = file - self.fileorig = fileorig - self.nframe = nframe - self.pagenum = pagenum - self.parent = mainframe.parent - ttk.Frame.__init__(self, master=mainframe) - self.master.title('Ouvrir un scan... (Utilisez la roulette pour zoomer, clic gauche pour déplacer et clic droit pour sélectionner la MRZ)') - self.master.resizable(width=False, height=False) - hs = self.winfo_screenheight() - w = int(self.winfo_screenheight() / 1.5) - h = int(self.winfo_screenheight() / 2) - ws = self.winfo_screenwidth() - hs = self.winfo_screenheight() - x = ws / 2 - w / 2 - y = hs / 2 - h / 2 - self.master.geometry('%dx%d+%d+%d' % (w, h, x, y)) - if getattr(sys, 'frozen', False): - self.master.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico') - else: - self.master.iconbitmap('id-card.ico') - self.master.rowconfigure(0, weight=1) - self.master.columnconfigure(0, weight=1) - self.cadre = CanvasImage(self.master, self.file, type) - self.cadre.grid(row=0, column=0) - self.master.menubar = Menu(self.master) - if type == 1: - self.master.menubar.add_command(label='Page précédente', command=(self.pagep)) - self.master.menubar.add_command(label='Pivoter -90°', command=(self.cadre.rotatemm)) - self.master.menubar.add_command(label='Pivoter -1°', command=(self.cadre.rotatem)) - self.master.menubar.add_command(label='Pivoter +1°', command=(self.cadre.rotatep)) - self.master.menubar.add_command(label='Pivoter +90°', command=(self.cadre.rotatepp)) - if type == 1: - self.master.menubar.add_command(label='Page suivante', command=(self.pages)) - self.master.config(menu=(self.master.menubar)) - self.cadre.canvas.bind('', self.motionprep) - self.cadre.canvas.bind('', self.motionize) - self.cadre.canvas.bind('', self.motionend) - - def pages(self): - if self.pagenum + 1 < self.nframe: - im = Image.open(self.fileorig) - im.seek(self.pagenum + 1) - newpath = globs.CNIREnv + '\\temp' + str(random.randint(11111, 99999)) + '.tif' - im.save(newpath) - im.close() - self.cadre.destroy() - self.__init__(self.master, self.fileorig, 1, self.nframe, self.pagenum + 1, newpath) - - def pagep(self): - if self.pagenum - 1 >= 0: - im = Image.open(self.fileorig) - im.seek(self.pagenum - 1) - newpath = globs.CNIREnv + '\\temp' + str(random.randint(11111, 99999)) + '.tif' - im.save(newpath) - im.close() - self.cadre.destroy() - self.__init__(self.master, self.fileorig, 1, self.nframe, self.pagenum - 1, newpath) - - def motionprep(self, event): - if hasattr(self, 'rect'): - self.begx = event.x - self.begy = event.y - self.ix = self.cadre.canvas.canvasx(event.x) - self.iy = self.cadre.canvas.canvasy(event.y) - self.cadre.canvas.coords(self.rect, self.cadre.canvas.canvasx(event.x), self.cadre.canvas.canvasy(event.y), self.ix, self.iy) - else: - self.begx = event.x - self.begy = event.y - self.ix = self.cadre.canvas.canvasx(event.x) - self.iy = self.cadre.canvas.canvasy(event.y) - self.rect = self.cadre.canvas.create_rectangle((self.cadre.canvas.canvasx(event.x)), (self.cadre.canvas.canvasy(event.y)), (self.ix), (self.iy), outline='red') - - def motionize(self, event): - event.x - event.y - self.cadre.canvas.coords(self.rect, self.ix, self.iy, self.cadre.canvas.canvasx(event.x), self.cadre.canvas.canvasy(event.y)) - - def motionend(self, event): - self.endx = event.x - self.endy = event.y - self.imtotreat = self.cadre.resizedim.crop((min(self.begx, self.endx), min(self.begy, self.endy), max(self.endx, self.begx), max(self.endy, self.begy))) - im = self.imtotreat - import CNI_pytesseract as pytesseract - try: - os.environ['PATH'] = globs.CNIREnv + '\\Tesseract-OCR4\\' - os.environ['TESSDATA_PREFIX'] = globs.CNIREnv + '\\Tesseract-OCR4\\tessdata' - self.text = pytesseract.image_to_string(im, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<') - except pytesseract.TesseractNotFoundError as e: - try: - os.remove(globs.CNIREnv + '\\Tesseract-OCR4\\*.*') - except Exception: - pass - - showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable. Il sera réinstallé à la prochaine exécution'), parent=self) - except pytesseract.TesseractError as e: - pass - - self.master.success = False - dialogconf = OpenScanDialog(self.master, self.text) - dialogconf.transient(self) - dialogconf.grab_set() - self.wait_window(dialogconf) - if self.master.success: - self.master.destroy() +class ResizeableCanvas(Canvas): + def __init__(self,parent,**kwargs): + Canvas.__init__(self,parent,**kwargs) + self.bind("", self.on_resize) + self.height = self.winfo_reqheight() + self.width = self.winfo_reqwidth() + def on_resize(self,event): + # determine the ratio of old width/height to new width/height + wscale = float(event.width)/self.width + hscale = float(event.height)/self.height + self.width = event.width + self.height = event.height + # rescale all the objects tagged with the "all" tag + self.scale("all",0,0,wscale,hscale) ## Global Handler launcherWindowCur = LauncherWindow() diff --git a/src/image.py b/src/image.py index db67367..3afca8e 100644 --- a/src/image.py +++ b/src/image.py @@ -23,253 +23,3 @@ ******************************************************************************** """ -class CanvasImage: - - def __init__(self, placeholder, file, type): - """ Initialize the ImageFrame """ - self.type = type - self.angle = 0 - self.imscale = 1.0 - self._CanvasImage__delta = 1.3 - self._CanvasImage__filter = Image.ANTIALIAS - self._CanvasImage__previous_state = 0 - self.path = file - self._CanvasImage__imframe = ttk.Frame(placeholder) - self.placeholder = placeholder - hbar = AutoScrollbar((self._CanvasImage__imframe), orient='horizontal') - vbar = AutoScrollbar((self._CanvasImage__imframe), orient='vertical') - hbar.grid(row=1, column=0, sticky='we') - vbar.grid(row=0, column=1, sticky='ns') - self.canvas = Canvas((self._CanvasImage__imframe), highlightthickness=0, xscrollcommand=(hbar.set), - yscrollcommand=(vbar.set)) - self.canvas.grid(row=0, column=0, sticky='nswe') - self.canvas.update() - hbar.configure(command=(self._CanvasImage__scroll_x)) - vbar.configure(command=(self._CanvasImage__scroll_y)) - self.canvas.bind('', lambda event: self._CanvasImage__show_image()) - self.canvas.bind('', self._CanvasImage__move_from) - self.canvas.bind('', self._CanvasImage__move_to) - self.canvas.bind('', self._CanvasImage__wheel) - self._CanvasImage__huge = False - self._CanvasImage__huge_size = 14000 - self._CanvasImage__band_width = 1024 - Image.MAX_IMAGE_PIXELS = 1000000000 - with warnings.catch_warnings(): - warnings.simplefilter('ignore') - self._CanvasImage__image = Image.open(self.path) - self.imwidth, self.imheight = self._CanvasImage__image.size - if self.imwidth * self.imheight > self._CanvasImage__huge_size * self._CanvasImage__huge_size: - if self._CanvasImage__image.tile[0][0] == 'raw': - self._CanvasImage__huge = True - self._CanvasImage__offset = self._CanvasImage__image.tile[0][2] - self._CanvasImage__tile = [self._CanvasImage__image.tile[0][0], - [ - 0, 0, self.imwidth, 0], - self._CanvasImage__offset, - self._CanvasImage__image.tile[0][3]] - self._CanvasImage__min_side = min(self.imwidth, self.imheight) - self._CanvasImage__pyramid = [self.smaller()] if self._CanvasImage__huge else [Image.open(self.path)] - self._CanvasImage__ratio = max(self.imwidth, self.imheight) / self._CanvasImage__huge_size if self._CanvasImage__huge else 1.0 - self._CanvasImage__curr_img = 0 - self._CanvasImage__scale = self.imscale * self._CanvasImage__ratio - self._CanvasImage__reduction = 2 - w, h = self._CanvasImage__pyramid[(-1)].size - while w > 512 and h > 512: - w /= self._CanvasImage__reduction - h /= self._CanvasImage__reduction - try: - self._CanvasImage__pyramid.append(self._CanvasImage__pyramid[(-1)].resize((int(w), int(h)), self._CanvasImage__filter)) - except TypeError: - showerror(title='Erreur de fichier', message="Image incompatible. Merci d'utiliser une autre image ou de la convertir dans un format standard accepté!", parent=(self.placeholder)) - self.placeholder.parent.openerrored = True - self.placeholder.destroy() - self.destroy() - return - - self.container = self.canvas.create_rectangle((0, 0, self.imwidth, self.imheight), width=0) - self._CanvasImage__show_image() - self.canvas.focus_set() - - def rotatem(self): - self.angle += 1 - self._CanvasImage__show_image() - - def rotatep(self): - self.angle -= 1 - self._CanvasImage__show_image() - - def rotatemm(self): - self.angle += 90 - self._CanvasImage__show_image() - - def rotatepp(self): - self.angle -= 90 - self._CanvasImage__show_image() - - def smaller(self): - """ Resize image proportionally and return smaller image """ - w1, h1 = float(self.imwidth), float(self.imheight) - w2, h2 = float(self._CanvasImage__huge_size), float(self._CanvasImage__huge_size) - aspect_ratio1 = w1 / h1 - aspect_ratio2 = w2 / h2 - if aspect_ratio1 == aspect_ratio2: - image = Image.new('RGB', (int(w2), int(h2))) - k = h2 / h1 - w = int(w2) - else: - if aspect_ratio1 > aspect_ratio2: - image = Image.new('RGB', (int(w2), int(w2 / aspect_ratio1))) - k = h2 / w1 - w = int(w2) - else: - image = Image.new('RGB', (int(h2 * aspect_ratio1), int(h2))) - k = h2 / h1 - w = int(h2 * aspect_ratio1) - i, j, n = 0, 1, round(0.5 + self.imheight / self._CanvasImage__band_width) - while i < self.imheight: - band = min(self._CanvasImage__band_width, self.imheight - i) - self._CanvasImage__tile[1][3] = band - self._CanvasImage__tile[2] = self._CanvasImage__offset + self.imwidth * i * 3 - self._CanvasImage__image.close() - self._CanvasImage__image = Image.open(self.path) - self._CanvasImage__image.size = (self.imwidth, band) - self._CanvasImage__image.tile = [self._CanvasImage__tile] - cropped = self._CanvasImage__image.crop((0, 0, self.imwidth, band)) - image.paste(cropped.resize((w, int(band * k) + 1), self._CanvasImage__filter), (0, int(i * k))) - i += band - j += 1 - - return image - - def redraw_figures(self): - """ Dummy function to redraw figures in the children classes """ - pass - - def grid(self, **kw): - """ Put CanvasImage widget on the parent widget """ - (self._CanvasImage__imframe.grid)(**kw) - self._CanvasImage__imframe.grid(sticky='nswe') - self._CanvasImage__imframe.rowconfigure(0, weight=1) - self._CanvasImage__imframe.columnconfigure(0, weight=1) - - def __scroll_x(self, *args, **kwargs): - """ Scroll canvas horizontally and redraw the image """ - (self.canvas.xview)(*args) - self._CanvasImage__show_image() - - def __scroll_y(self, *args, **kwargs): - """ Scroll canvas vertically and redraw the image """ - (self.canvas.yview)(*args) - self._CanvasImage__show_image() - - def __show_image(self): - """ Show image on the Canvas. Implements correct image zoom almost like in Google Maps """ - box_image = self.canvas.coords(self.container) - box_canvas = (self.canvas.canvasx(0), - self.canvas.canvasy(0), - self.canvas.canvasx(self.canvas.winfo_width()), - self.canvas.canvasy(self.canvas.winfo_height())) - box_img_int = tuple(map(int, box_image)) - box_scroll = [ - min(box_img_int[0], box_canvas[0]), min(box_img_int[1], box_canvas[1]), - max(box_img_int[2], box_canvas[2]), max(box_img_int[3], box_canvas[3])] - if box_scroll[0] == box_canvas[0]: - if box_scroll[2] == box_canvas[2]: - box_scroll[0] = box_img_int[0] - box_scroll[2] = box_img_int[2] - if box_scroll[1] == box_canvas[1] and box_scroll[3] == box_canvas[3]: - box_scroll[1] = box_img_int[1] - box_scroll[3] = box_img_int[3] - self.canvas.configure(scrollregion=(tuple(map(int, box_scroll)))) - x1 = max(box_canvas[0] - box_image[0], 0) - y1 = max(box_canvas[1] - box_image[1], 0) - x2 = min(box_canvas[2], box_image[2]) - box_image[0] - y2 = min(box_canvas[3], box_image[3]) - box_image[1] - if int(x2 - x1) > 0: - if int(y2 - y1) > 0: - if self._CanvasImage__huge: - if self._CanvasImage__curr_img < 0: - h = int((y2 - y1) / self.imscale) - self._CanvasImage__tile[1][3] = h - self._CanvasImage__tile[2] = self._CanvasImage__offset + self.imwidth * int(y1 / self.imscale) * 3 - self._CanvasImage__image.close() - self._CanvasImage__image = Image.open(self.path) - self._CanvasImage__image.size = (self.imwidth, h) - self._CanvasImage__image.tile = [self._CanvasImage__tile] - image = self._CanvasImage__image.crop((int(x1 / self.imscale), 0, int(x2 / self.imscale), h)) - image = self._CanvasImage__pyramid[max(0, self._CanvasImage__curr_img)].crop(( - int(x1 / self._CanvasImage__scale), int(y1 / self._CanvasImage__scale), - int(x2 / self._CanvasImage__scale), int(y2 / self._CanvasImage__scale))) - self.resizedim = image.resize((int(x2 - x1), int(y2 - y1)), self._CanvasImage__filter).rotate((self.angle), resample=(Image.BICUBIC), expand=1) - imagetk = ImageTk.PhotoImage((self.resizedim), master=(self.placeholder)) - imageid = self.canvas.create_image((max(box_canvas[0], box_img_int[0])), (max(box_canvas[1], box_img_int[1])), - anchor='nw', - image=imagetk) - self.canvas.lower(imageid) - self.canvas.imagetk = imagetk - - def __move_from(self, event): - """ Remember previous coordinates for scrolling with the mouse """ - self.canvas.scan_mark(event.x, event.y) - - def __move_to(self, event): - """ Drag (move) canvas to the new position """ - self.canvas.scan_dragto((event.x), (event.y), gain=1) - self._CanvasImage__show_image() - - def outside(self, x, y): - """ Checks if the point (x,y) is outside the image area """ - bbox = self.canvas.coords(self.container) - if bbox[0] < x < bbox[2]: - if bbox[1] < y < bbox[3]: - pass - return False - else: - return True - - def __wheel(self, event): - """ Zoom with mouse wheel """ - x = self.canvas.canvasx(event.x) - y = self.canvas.canvasy(event.y) - if self.outside(x, y): - return - scale = 1.0 - if event.delta == -120: - if round(self._CanvasImage__min_side * self.imscale) < int(self.placeholder.winfo_screenheight()): - return - self.imscale /= self._CanvasImage__delta - scale /= self._CanvasImage__delta - if event.delta == 120: - i = min(self.canvas.winfo_width(), self.canvas.winfo_height()) >> 1 - if i < self.imscale: - return - self.imscale *= self._CanvasImage__delta - scale *= self._CanvasImage__delta - k = self.imscale * self._CanvasImage__ratio - self._CanvasImage__curr_img = min(-1 * int(math.log(k, self._CanvasImage__reduction)), len(self._CanvasImage__pyramid) - 1) - self._CanvasImage__scale = k * math.pow(self._CanvasImage__reduction, max(0, self._CanvasImage__curr_img)) - self.canvas.scale('all', x, y, scale, scale) - self.redraw_figures() - self._CanvasImage__show_image() - - def crop(self, bbox): - """ Crop rectangle from the image and return it """ - if self._CanvasImage__huge: - band = bbox[3] - bbox[1] - self._CanvasImage__tile[1][3] = band - self._CanvasImage__tile[2] = self._CanvasImage__offset + self.imwidth * bbox[1] * 3 - self._CanvasImage__image.close() - self._CanvasImage__image = Image.open(self.path) - self._CanvasImage__image.size = (self.imwidth, band) - self._CanvasImage__image.tile = [self._CanvasImage__tile] - return self._CanvasImage__image.crop((bbox[0], 0, bbox[2], band)) - else: - return self._CanvasImage__pyramid[0].crop(bbox) - - def destroy(self): - """ ImageFrame destructor """ - self._CanvasImage__image.close() - map(lambda i: i.close, self._CanvasImage__pyramid) - del self._CanvasImage__pyramid[:] - del self._CanvasImage__pyramid - self.canvas.destroy() \ No newline at end of file diff --git a/src/main.py b/src/main.py index 01e7232..fd53870 100644 --- a/src/main.py +++ b/src/main.py @@ -32,6 +32,9 @@ from tkinter import ttk import threading from datetime import datetime import re +import traceback +import cv2 +import PIL.Image, PIL.ImageTk import ihm # ihm.py import logger # logger.py @@ -143,13 +146,18 @@ class mainWindow(Tk): "INDIC" : self.indic, } - # The STATUS indicator - self.STATUT = ttk.Labelframe(self, text='Statut') + # The STATUS indicator + image display + self.STATUT = ttk.Labelframe(self, text='Affichage de documents et statut') self.STATUT.grid_columnconfigure(0, weight=1) self.STATUT.grid_rowconfigure(0, weight=1) - self.STATUStxt = Label((self.STATUT), text='', font='Times 24', fg='#FFBF00') - self.STATUStxt.grid(column=0, row=0, padx=0, pady=0, sticky='EWNS') - self.STATUStxt['text'] = 'EN ATTENTE' + self.STATUT.frame = Frame(self.STATUT) + self.STATUT.frame.grid(column=0, row=0, sticky='NSEW') + self.STATUT.frame.grid_columnconfigure(0, weight=1) + self.STATUT.frame.grid_rowconfigure(0, weight=1) + self.STATUT.ZONE = ihm.ResizeableCanvas(self.STATUT.frame, bg=self["background"]) + self.STATUT.ZONE.pack(fill="both", expand=True) + self.STATUSimg = self.STATUT.ZONE.create_image(0,0, image=None) + self.STATUStxt = self.STATUT.ZONE.create_text(0,0, text='', font='Times 24', fill='#FFBF00') # The terminal to enter the MRZ self.terminal = ttk.Labelframe(self, text='Terminal de saisie de MRZ complète') @@ -229,7 +237,6 @@ class mainWindow(Tk): # Make this window resizable and set her size self.resizable(width=True, height=True) - self.minsize(self.winfo_width(), self.winfo_height()) self.update() w = int(self.winfo_reqwidth()) h = int(self.winfo_reqheight()) @@ -240,6 +247,20 @@ class mainWindow(Tk): self.geometry('%dx%d+%d+%d' % (w, h, x, y)) self.update() self.deiconify() + self.minsize(self.winfo_width(), self.winfo_height()) + + # Load an image using OpenCV + cv_img = cv2.imread("background.png") + cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) + cv_img = cv2.blur(cv_img, (15, 15)) + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Get the image dimensions (OpenCV stores image data as NumPy ndarray) + height, width = cv_img.shape + # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage + photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img)) + self.statusUpdate("EN ATTENTE", "#FFBF00", photo, setplace=True) + # Some bindings self.termtext.bind('', self.entryValidation) @@ -247,6 +268,17 @@ class mainWindow(Tk): self.speed731text.bind('', self.speedValidation) logfile.printdbg('Initialization successful') + def statusUpdate(self, msg, color, image=None, setplace=False): + if image: + self.STATUT.image = image + + self.STATUT.ZONE.itemconfigure(self.STATUSimg, image=(self.STATUT.image)) + self.STATUT.ZONE.itemconfigure(self.STATUStxt, text=(msg), fill=color) + + if setplace: + self.STATUT.ZONE.move(self.STATUSimg, self.STATUT.ZONE.winfo_reqwidth() / 2, self.STATUT.ZONE.winfo_reqheight() / 2) + self.STATUT.ZONE.move(self.STATUStxt, self.STATUT.ZONE.winfo_reqwidth() / 2, self.STATUT.ZONE.winfo_reqheight() / 2) + def stringValidation(self, keysym): # analysis # If we must decide the type of the document @@ -429,8 +461,13 @@ class mainWindow(Tk): def openingScan(self): - pass - # OPEN A SCAN + path = '' + path = filedialog.askopenfilename(parent=self, title='Ouvrir un scan de CNI...', filetypes=(('TIF files', '*.tif'), + ('TIF files', '*.tiff'), + ('JPEG files', '*.jpg'), + ('JPEG files', '*.jpeg'))) + self.mrzdetected = '' + self.mrzdict = {} def newEntry(self): self.initialize() @@ -524,13 +561,6 @@ class mainWindow(Tk): self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white") self.compliance = False - if self.compliance == True: - self.STATUStxt['text'] = 'CONFORME' - self.STATUStxt['fg'] = "green" - else: - self.STATUStxt['text'] = 'NON CONFORME' - self.STATUStxt['fg'] = "red" - # get the infos docInfos = mrz.getDocInfos(self.mrzDecided, code) #print(docInfos) @@ -547,6 +577,12 @@ class mainWindow(Tk): self.infoList[key]['background'] = "red" self.infoList[key]['foreground'] = "white" self.infoList[key]['text'] = "NC" + self.compliance = False + + if self.compliance == True: + self.statusUpdate("CONFORME", "chartreuse2") + else: + self.statusUpdate("NON-CONFORME","red") return diff --git a/src/mrz.py b/src/mrz.py index c9d55bf..4619d8a 100644 --- a/src/mrz.py +++ b/src/mrz.py @@ -989,7 +989,7 @@ def getDocInfos(doc, code): try: datetime.datetime.strptime(value,"%d/%m/%y") except ValueError: - print(value) + #print(value) if value != "": res[field[0]] = False else: diff --git a/src/updater.py b/src/updater.py index 727705e..4dbbf39 100644 --- a/src/updater.py +++ b/src/updater.py @@ -42,6 +42,8 @@ import downloader # downloader.py UPDATE_IS_MADE = False UPATH = ' ' +launcherWindow = ihm.launcherWindowCur + def createShortcut(path, target='', wDir='', icon=''): """ Creates a shortcut for a program or an internet link @@ -127,7 +129,7 @@ def getLatestVersion(credentials): # Global Handlers logfile = logger.logCur - launcherWindow = ihm.launcherWindowCur + # First retrieving the urls ! while True: @@ -194,7 +196,7 @@ def getLatestVersion(credentials): def tessInstall(PATH, credentials): # Global Handlers logfile = logger.logCur - launcherWindow = ihm.launcherWindowCur + # Verifying that Tesseract is installed if not os.path.exists(PATH + '\\Tesseract-OCR4\\'): @@ -222,7 +224,7 @@ def tessInstall(PATH, credentials): def batch(credentials): # Global Handlers logfile = logger.logCur - launcherWindow = ihm.launcherWindowCur + # Get the latest version of CNIRevelator finalver, finalurl, finalchecksum = getLatestVersion(credentials) @@ -300,7 +302,7 @@ def umain(): # Global Handlers logfile = logger.logCur - launcherWindow = ihm.launcherWindowCur + credentials = downloader.newcredentials() @@ -308,8 +310,7 @@ def umain(): logfile.printerr("Credentials Error. No effective update !") launcherWindow.printmsg('Credentials Error. No effective update !') time.sleep(2) - launcherWindow = ihm.launcherWindowCur - launcherWindow.destroy() + launcherWindow.exit() return 0 # Cleaner for the old version if detected @@ -376,7 +377,7 @@ def umain(): logfile.printerr("An error occured on the thread : " + str(traceback.format_exc())) launcherWindow.printmsg('ERROR : ' + str(e)) time.sleep(3) - launcherWindow.destroy() + launcherWindow.exit() return 1 if success: @@ -386,14 +387,12 @@ def umain(): logfile.printerr("An error occured. No effective update !") launcherWindow.printmsg('An error occured. No effective update !') time.sleep(2) - launcherWindow = ihm.launcherWindowCur - launcherWindow.destroy() + launcherWindow.exit() return 0 except: logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc())) - launcherWindow = ihm.launcherWindowCur - launcherWindow.destroy() + launcherWindow.exit() sys.exit(2) return 2