diff --git a/.gitignore b/.gitignore
index d0596f3..93d25c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,8 @@
build/*
dist/*
+src/Tesseract-OCR4/*
+src/downloads/*
+src/config/*
+src/logs/*
+signtool_8.1/*
diff --git a/VERSIONS.LST b/VERSIONS.LST
index 856ab09..64b66ab 100644
--- a/VERSIONS.LST
+++ b/VERSIONS.LST
@@ -1,2 +1,2 @@
# ver|url|checksum, and | as separator, one version per ||
-3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||
+3.0.4|https://github.com/neox95/CNIRevelator/releases/download/3.0.4/CNIRevelator.zip|d03a18b35dfbb20d90664dc2c0f990adc5522e46||3.0.5|https://github.com/neox95/CNIRevelator/releases/download/3.0.5/CNIRevelator.zip|8b52290fb0910d8b9c4ec43293b08017e0031ca2||3.0.6|https://github.com/neox95/CNIRevelator/releases/download/3.0.6/CNIRevelator.zip|4bb4606dc9310d7b34b1fb38f9a0c2daf9518dc5||3.0.7|https://github.com/neox95/CNIRevelator/releases/download/3.0.7/CNIRevelator.zip|9aea1627c0b75610225a02458d5705563ca0d6af||3.0.8|https://github.com/neox95/CNIRevelator/releases/download/3.0.8/CNIRevelator.zip|8e849f8fcb5c952c09bdd4eb3392456ec9c6cf8f||
diff --git a/id-card.ico b/id-card.ico
deleted file mode 100644
index efa86e4..0000000
Binary files a/id-card.ico and /dev/null differ
diff --git a/make.bat b/make.bat
index eefda6d..5d6414b 100644
--- a/make.bat
+++ b/make.bat
@@ -4,15 +4,15 @@ title Compilation de CNIRevelator
-call pyinstaller -w -D --exclude-module PyQt5 --bootloader-ignore-signals --add-data "C:\Users\pf04950\AppData\Local\Continuum\anaconda3\Lib\site-packages\tld\res\effective_tld_names.dat.txt";"tld\res" --add-data "id-card.ico";"id-card.ico" -i "id-card.ico" -n CNIRevelator src\CNIRevelator.py
+call pyinstaller -w -D --exclude-module PyQt5 --bootloader-ignore-signals --add-data "C:\Users\adrie\Anaconda3\Lib\site-packages\tld\res\effective_tld_names.dat.txt";"tld\res" --add-data "src\id-card.ico";"id-card.ico" -i "src\id-card.ico" -n CNIRevelator src\CNIRevelator.py
copy LICENSE dist\CNIRevelator\LICENSE
copy src\id-card.ico dist\CNIRevelator\id-card.ico
-copy src\background.png dist\CNIRevelator\background.png
+copy src\*.png dist\CNIRevelator\*.png
-D:\Public\CNIRevelator-master\CNIRevelator-master\signtool_8.1\signtool\signtool.exe sign /n "CNIRevelator by Adrien Bourmault (neox95)" dist\CNIRevelator\CNIRevelator.exe
+signtool_8.1\signtool\signtool.exe sign /n "CNIRevelator by Adrien Bourmault (neox95)" dist\CNIRevelator\CNIRevelator.exe
pause
diff --git a/src/CNIRevelator.py b/src/CNIRevelator.py
index 9e9e088..3fe7fb0 100644
--- a/src/CNIRevelator.py
+++ b/src/CNIRevelator.py
@@ -31,7 +31,7 @@ import threading
import traceback
import psutil
-import launcher # launcher.py
+import launcher # launcher.py"
import updater # updater.py
import globs # globs.py
import pytesseract # pytesseract.py
diff --git a/src/Invert.png b/src/Invert.png
new file mode 100644
index 0000000..f9b3fb3
Binary files /dev/null and b/src/Invert.png differ
diff --git a/src/OCR.png b/src/OCR.png
new file mode 100644
index 0000000..6fc81ea
Binary files /dev/null and b/src/OCR.png differ
diff --git a/src/globs.py b/src/globs.py
index 674104c..42b1e6c 100644
--- a/src/globs.py
+++ b/src/globs.py
@@ -25,18 +25,13 @@
import os
# CNIRevelator version
-verType = "alpha"
-version = [3, 0, 6]
+verType = "final release"
+version = [3, 1, 0]
verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType)
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- 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" + \
-"Version 3.0.2 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement d'icône de l'exécutable\n- Correction d'un bug affectant le logging\n- Correction d'un bug affectant la détection de documents\n- Et autres modifications mineures\n\n" + \
-"Version 3.0.1 \nMise-à-jour majeure avec les corrections suivantes :\n- Renouvellement de la signature numérique de l'exécutable\n- Amélioration de présentation du log en cas d'erreur\n- Refonte totale du code source et désobfuscation\n- Téléchargements en HTTPS fiables avec somme de contrôle\n- Nouveaux terminaux d'entrées : un rapide (731) et un complet\n- Détection des documents améliorée, possibilité de choix plus fin\nEt les regressions suivantes :\n- Suppression temporaire de la fonction de lecture OCR. Retour planifié pour une prochaine version"
+changelog = "Version 3.1.0 \nMise-à-jour majeure avec les progressions suivantes :\n- Modifications cosmétiques de l'interface utilisateur\n- Stabilisation des changements effectués sur la version mineure 3.0 : interface utilisateur, OCR, VISA A et B, logging"
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
CNIRFolder = os.getcwd()
@@ -46,6 +41,7 @@ CNIRCryptoKey = '82Xh!efX3#@P~2eG'
CNIRNewVersion = False
CNIRConfig = CNIRFolder + '\\config\\conf.ig'
+CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\'
CNIRErrLog = CNIRFolder + '\\logs\\error.log'
CNIRMainLog = CNIRFolder + '\\logs\\main.log'
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
diff --git a/src/ihm.py b/src/ihm.py
index e254cfe..9c7622c 100644
--- a/src/ihm.py
+++ b/src/ihm.py
@@ -32,7 +32,6 @@ 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"]
@@ -69,7 +68,45 @@ class DocumentAsk(Toplevel):
self.choice = 1
def ok(self):
self.destroy()
+
+
+class OpenScanDialog(Toplevel):
+ def __init__(self, parent, text):
+ super().__init__(parent)
+ self.parent = parent
+ self.title('Validation de la MRZ détectée par OCR')
+ self.resizable(width=False, height=False)
+ self.termtext = Text(self, state='normal', width=45, height=2, wrap='none', font='Terminal 17', fg='#121f38')
+ self.termtext.grid(column=0, row=0, sticky='NEW', padx=5, pady=5)
+ self.termtext.insert('end', text + '\n')
+ self.button = Button(self, text='Valider', command=(self.valid))
+ self.button.grid(column=0, row=1, 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.validatedtext = self.termtext.get('1.0', 'end')
+ texting = self.parent.validatedtext.replace(' ', '').replace('\r', '').split('\n')
+ for i in range(len(texting)):
+ for char in texting[i]:
+ if char not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789<':
+ showerror('Erreur de validation', 'La MRZ soumise contient des caractères invalides', parent=self)
+ self.parent.validatedtext = ''
+
+ self.destroy()
+
class LoginDialog(Toplevel):
def __init__(self, parent):
@@ -178,21 +215,6 @@ class LauncherWindow(Tk):
def exit(self):
self.after(1000, self.destroy)
-class AutoScrollbar(ttk.Scrollbar):
-
- def set(self, lo, hi):
- if float(lo) <= 0.0:
- if float(hi) >= 1.0:
- self.grid_remove()
- self.grid()
- ttk.Scrollbar.set(self, lo, hi)
-
- def pack(self, **kw):
- raise TclError('Cannot use pack with the widget ' + self.__class__.__name__)
-
- def place(self, **kw):
- raise TclError('Cannot use place with the widget ' + self.__class__.__name__)
-
class ResizeableCanvas(Canvas):
def __init__(self,parent,**kwargs):
Canvas.__init__(self,parent,**kwargs)
@@ -208,7 +230,7 @@ class ResizeableCanvas(Canvas):
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
deleted file mode 100644
index 3afca8e..0000000
--- a/src/image.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""
-********************************************************************************
-* CNIRevelator *
-* *
-* Desc: Image calculation for CNI printing *
-* *
-* Copyright © 2018-2019 Adrien Bourmault (neox95) *
-* *
-* This file is part of CNIRevelator. *
-* *
-* CNIRevelator 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 of the License, or *
-* any later version. *
-* *
-* CNIRevelator 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 CNIRevelator. If not, see . *
-********************************************************************************
-"""
-
diff --git a/src/main.py b/src/main.py
index fd53870..b921838 100644
--- a/src/main.py
+++ b/src/main.py
@@ -35,13 +35,14 @@ import re
import traceback
import cv2
import PIL.Image, PIL.ImageTk
+import os, shutil
+import webbrowser
import ihm # ihm.py
import logger # logger.py
import mrz # mrz.py
import globs # globs.py
import pytesseract # pytesseract.py
-from image import * # image.py
# Global handler
logfile = logger.logCur
@@ -53,10 +54,12 @@ class mainWindow(Tk):
self.initialize()
def initialize(self):
- self.mrzChar = ''
+ self.mrzChar = ""
self.mrzDecided = False
self.Tags = []
self.compliance = True
+ self.corners = []
+ self.validatedtext = ""
# Hide during construction
self.withdraw()
@@ -89,6 +92,9 @@ class mainWindow(Tk):
self.lecteur_ci.grid_rowconfigure(5, weight=1)
# Fill the data sections
+ ttk.Label((self.lecteur_ci), text='Statut : ').grid(column=0, row=0, padx=5, pady=5)
+ self.STATUStxt = ttk.Label((self.lecteur_ci), text='EN ATTENTE', font=("TkDefaultFont", 13, "bold"), foreground="orange", anchor=CENTER)
+ self.STATUStxt.grid(column=1, row=0, padx=5, pady=5)
ttk.Label((self.lecteur_ci), text='Nom : ').grid(column=0, row=1, padx=5, pady=5)
self.nom = ttk.Label((self.lecteur_ci), text=' ')
self.nom.grid(column=1, row=1, padx=5, pady=5)
@@ -146,18 +152,110 @@ class mainWindow(Tk):
"INDIC" : self.indic,
}
- # 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.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 the image viewer
+ self.imageViewer = ttk.Labelframe(self, text='Affichage et traitement de documents')
+ self.imageViewer.grid_columnconfigure(0, weight=1)
+ self.imageViewer.grid_columnconfigure(1, weight=0)
+ self.imageViewer.grid_rowconfigure(0, weight=1)
+ self.imageViewer.grid_rowconfigure(1, weight=1)
+ self.imageViewer.grid_rowconfigure(2, weight=1)
+ self.imageViewer.frame = Frame(self.imageViewer)
+ self.imageViewer.frame.grid(column=0, row=0, sticky='NSEW')
+ self.imageViewer.frame.grid_columnconfigure(0, weight=1)
+ self.imageViewer.frame.grid_rowconfigure(0, weight=1)
+ # + toolbar
+ self.toolbar = ttk.Frame(self.imageViewer)
+ self.toolbar.grid_columnconfigure(0, weight=1)
+ self.toolbar.grid_columnconfigure(1, weight=1)
+ self.toolbar.grid_columnconfigure(2, weight=1)
+ self.toolbar.grid_columnconfigure(3, weight=1)
+ self.toolbar.grid_columnconfigure(4, weight=1)
+ self.toolbar.grid_columnconfigure(5, weight=1)
+ self.toolbar.grid_columnconfigure(6, weight=1, minsize=10)
+ self.toolbar.grid_columnconfigure(7, weight=1)
+ self.toolbar.grid_columnconfigure(8, weight=1, minsize=10)
+ self.toolbar.grid_columnconfigure(9, weight=1)
+ self.toolbar.grid_columnconfigure(10, weight=1)
+ self.toolbar.grid_columnconfigure(11, weight=1)
+ self.toolbar.grid_columnconfigure(12, weight=1)
+ self.toolbar.grid_columnconfigure(13, weight=1, minsize=10)
+ self.toolbar.grid_columnconfigure(14, weight=1)
+ self.toolbar.grid_columnconfigure(15, weight=1, minsize=10)
+ self.toolbar.grid_columnconfigure(16, weight=1)
+ self.toolbar.grid_rowconfigure(0, weight=1)
+
+ self.toolbar.zoomIn50Img = ImageTk.PhotoImage(PIL.Image.open("zoomIn50.png"))
+ self.toolbar.zoomIn50 = ttk.Button(self.toolbar, image=self.toolbar.zoomIn50Img, command=self.zoomInScan50)
+ self.toolbar.zoomIn50.grid(column=0, row=0)
+
+ self.toolbar.zoomIn20Img = ImageTk.PhotoImage(PIL.Image.open("zoomIn20.png"))
+ self.toolbar.zoomIn20 = ttk.Button(self.toolbar, image=self.toolbar.zoomIn20Img, command=self.zoomInScan20)
+ self.toolbar.zoomIn20.grid(column=1, row=0)
+
+ self.toolbar.zoomInImg = ImageTk.PhotoImage(PIL.Image.open("zoomIn.png"))
+ self.toolbar.zoomIn = ttk.Button(self.toolbar, image=self.toolbar.zoomInImg, command=self.zoomInScan)
+ self.toolbar.zoomIn.grid(column=2, row=0)
+
+ self.toolbar.zoomOutImg = ImageTk.PhotoImage(PIL.Image.open("zoomOut.png"))
+ self.toolbar.zoomOut = ttk.Button(self.toolbar, image=self.toolbar.zoomOutImg, command=self.zoomOutScan)
+ self.toolbar.zoomOut.grid(column=3, row=0)
+
+ self.toolbar.zoomOut20Img = ImageTk.PhotoImage(PIL.Image.open("zoomOut20.png"))
+ self.toolbar.zoomOut20 = ttk.Button(self.toolbar, image=self.toolbar.zoomOut20Img, command=self.zoomOutScan20)
+ self.toolbar.zoomOut20.grid(column=4, row=0)
+
+ self.toolbar.zoomOut50Img = ImageTk.PhotoImage(PIL.Image.open("zoomOut50.png"))
+ self.toolbar.zoomOut50 = ttk.Button(self.toolbar, image=self.toolbar.zoomOut50Img, command=self.zoomOutScan50)
+ self.toolbar.zoomOut50.grid(column=5, row=0)
+
+ self.toolbar.invertImg = ImageTk.PhotoImage(PIL.Image.open("invert.png"))
+ self.toolbar.invert = ttk.Button(self.toolbar, image=self.toolbar.invertImg, command=self.negativeScan)
+ self.toolbar.invert.grid(column=7, row=0)
+
+ self.toolbar.rotateLeftImg = ImageTk.PhotoImage(PIL.Image.open("rotateLeft.png"))
+ self.toolbar.rotateLeft = ttk.Button(self.toolbar, image=self.toolbar.rotateLeftImg, command=self.rotateLeft)
+ self.toolbar.rotateLeft.grid(column=9, row=0)
+
+ self.toolbar.rotateLeft1Img = ImageTk.PhotoImage(PIL.Image.open("rotateLeft1.png"))
+ self.toolbar.rotateLeft1 = ttk.Button(self.toolbar, image=self.toolbar.rotateLeft1Img, command=self.rotateLeft1)
+ self.toolbar.rotateLeft1.grid(column=10, row=0)
+
+ self.toolbar.rotateRight1Img = ImageTk.PhotoImage(PIL.Image.open("rotateRight1.png"))
+ self.toolbar.rotateRight1 = ttk.Button(self.toolbar, image=self.toolbar.rotateRight1Img, command=self.rotateRight1)
+ self.toolbar.rotateRight1.grid(column=11, row=0)
+
+ self.toolbar.rotateRightImg = ImageTk.PhotoImage(PIL.Image.open("rotateRight.png"))
+ self.toolbar.rotateRight = ttk.Button(self.toolbar, image=self.toolbar.rotateRightImg, command=self.rotateRight)
+ self.toolbar.rotateRight.grid(column=12, row=0)
+
+ self.toolbar.goOCRImg = ImageTk.PhotoImage(PIL.Image.open("OCR.png"))
+ self.toolbar.goOCR = ttk.Button(self.toolbar, image=self.toolbar.goOCRImg, command=self.goOCRDetection)
+ self.toolbar.goOCR.grid(column=14, row=0)
+
+ self.toolbar.pagenumber = StringVar()
+ self.toolbar.pageChooser = ttk.Combobox(self.toolbar, textvariable=self.toolbar.pagenumber)
+ self.toolbar.pageChooser.bind("<>", self.goPageChoice)
+ self.toolbar.pageChooser['values'] = ('1')
+ self.toolbar.pageChooser.current(0)
+ self.toolbar.pageChooser.grid(column=16, row=0)
+
+ self.toolbar.grid(column=0, row=2, padx=0, pady=0)
+
+ # + image with scrollbars
+ self.imageViewer.hbar = ttk.Scrollbar(self.imageViewer, orient='horizontal')
+ self.imageViewer.vbar = ttk.Scrollbar(self.imageViewer, orient='vertical')
+ self.imageViewer.hbar.grid(row=1, column=0, sticky="NSEW")
+ self.imageViewer.vbar.grid(row=0, column=1, sticky="NSEW")
+
+ self.imageViewer.ZONE = ihm.ResizeableCanvas(self.imageViewer.frame, bg=self["background"], xscrollcommand=(self.imageViewer.hbar.set),
+ yscrollcommand=(self.imageViewer.vbar.set))
+ self.imageViewer.ZONE.grid(sticky="NSEW")
+
+ self.imageViewer.hbar.config(command=self.imageViewer.ZONE.xview)
+ self.imageViewer.vbar.config(command=self.imageViewer.ZONE.yview)
+
+ self.STATUSimg = self.imageViewer.ZONE.create_image(0,0, image=None, anchor="nw")
+
# The terminal to enter the MRZ
self.terminal = ttk.Labelframe(self, text='Terminal de saisie de MRZ complète')
@@ -191,9 +289,9 @@ class mainWindow(Tk):
self.speed731.grid_columnconfigure(9, weight=1)
self.speed731.grid_rowconfigure(0, weight=1)
self.speed731text = Entry(self.speed731, font='Terminal 14')
- self.speed731text.grid(column=0, row=0, sticky='NEW', padx=5)
+ self.speed731text.grid(column=0, row=0, sticky='NEW', padx=5, pady=5)
self.speedResult = Text((self.speed731), state='disabled', width=1, height=1, wrap='none', font='Terminal 14')
- self.speedResult.grid(column=2, row=0, sticky='NEW')
+ self.speedResult.grid(column=2, row=0, sticky='NEW', padx=5, pady=5)
# The monitor that indicates some useful infos
self.monitor = ttk.Labelframe(self, text='Moniteur')
@@ -206,8 +304,8 @@ class mainWindow(Tk):
self.monitor.grid_rowconfigure(0, weight=1)
# All the items griding
- self.lecteur_ci.grid(column=0, row=0, sticky='EWNS', columnspan=2, padx=5, pady=5)
- self.STATUT.grid(column=2, row=0, sticky='EWNS', columnspan=1, padx=5, pady=5)
+ self.lecteur_ci.grid(column=2, row=0, sticky='EWNS', columnspan=1, padx=5, pady=5)
+ self.imageViewer.grid(column=0, row=0, sticky='EWNS', columnspan=2, padx=5, pady=5)
self.terminal.grid(column=0, row=2, sticky='EWNS', columnspan=2, padx=5, pady=5)
self.terminal2.grid(column=0, row=1, sticky='EWNS', columnspan=2, padx=5, pady=5)
self.monitor.grid(column=2, row=1, sticky='EWNS', columnspan=1, rowspan=2, padx=5, pady=5)
@@ -222,6 +320,8 @@ class mainWindow(Tk):
menubar.add_cascade(label='Fichier', menu=menu1)
menu3 = Menu(menubar, tearoff=0)
menu3.add_command(label='Commandes au clavier', command=(self.helpbox))
+ menu3.add_command(label='Signaler un problème', command=(self.openIssuePage))
+ menu3.add_separator()
menu3.add_command(label='A propos de CNIRevelator', command=(self.infobox))
menubar.add_cascade(label='Aide', menu=menu3)
self.config(menu=menubar)
@@ -248,36 +348,119 @@ class mainWindow(Tk):
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)
-
+
+ # Set image
+ self.imageViewer.image = None
+ self.imageViewer.imagePath = None
+ self.imageViewer.imgZoom = 1
+ self.imageViewer.rotateCount = 0
+ self.imageViewer.blackhat = False
+ self.imageViewer.pagenumber = 0
# Some bindings
self.termtext.bind('', self.entryValidation)
self.termtext.bind('<>', self.pasteValidation)
self.speed731text.bind('', self.speedValidation)
+ self.imageViewer.ZONE.bind("", self.rectangleSelectScan)
+
logfile.printdbg('Initialization successful')
- def statusUpdate(self, msg, color, image=None, setplace=False):
+ def statusUpdate(self, image=None, setplace=False):
if image:
- self.STATUT.image = image
+ self.imageViewer.image = image
+ self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image))
+ self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all"))
+
+ def rectangleSelectScan(self, event):
+ if self.imageViewer.image:
+ canvas = event.widget
+ print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y))
+
+ self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)])
+ if len(self.corners) == 2:
+ self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2)
+ print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1]))
+ if len(self.corners) > 2:
+ self.corners = []
+ self.imageViewer.ZONE.delete(self.select)
- self.STATUT.ZONE.itemconfigure(self.STATUSimg, image=(self.STATUT.image))
- self.STATUT.ZONE.itemconfigure(self.STATUStxt, text=(msg), fill=color)
+ def goOCRDetection(self):
+ if self.imageViewer.image:
+ cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
+ if self.imageViewer.blackhat:
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
+ cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
+ cv_img = cv2.bitwise_not(cv_img)
+ try:
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ except ValueError:
+ # 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
+ # Rotate
+ rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1)
+ cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height))
+ # Resize
+ dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100))
+ cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
+
+ x0 = int(self.corners[0][0])
+ y0 = int(self.corners[0][1])
+ x1 = int(self.corners[1][0])
+ y1 = int(self.corners[1][1])
+
+ crop_img = cv_img[y0:y1, x0:x1]
+
+ # Get the text by OCR
+ try:
+ os.environ['PATH'] = globs.CNIRTesser
+ os.environ['TESSDATA_PREFIX'] = globs.CNIRTesser + '\\tessdata'
+
+ text = pytesseract.image_to_string(crop_img, lang='ocrb', boxes=False, config='--psm 6 --oem 0 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890<')
+
+ # manual validation
+ # the regex
+ regex = re.compile("[^A-Z0-9<\n]")
+ text = re.sub(regex, '', text)
+ self.validatedtext = ''
+ invite = ihm.OpenScanDialog(self, text)
+ invite.transient(self)
+ invite.grab_set()
+ invite.focus_force()
+ self.wait_window(invite)
+
+ print("text : {}".format(self.validatedtext))
+
+ self.mrzChar = ""
+
+ # Get that
+ for char in self.validatedtext:
+ self.termtext.delete("1.0","end")
+ self.termtext.insert("1.0", self.mrzChar)
+ self.mrzChar = self.mrzChar + char
+
+ self.stringValidation("")
+ print(self.mrzChar)
+
+ # Reinstall tesseract
+ except pytesseract.TesseractNotFoundError as e:
+ try:
+ shutil.rmtree(globs.CNIRTesser)
+ except Exception:
+ pass
+ showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution'), parent=self)
+ logfile.printerr("Tesseract error : {}. Will be reinstallated".format(e))
+
+ # Tesseract error
+ except pytesseract.TesseractError as e:
+ logfile.printerr("Tesseract error : {}".format(e))
+ showerror('Erreur de module OCR', ("Le module Tesseract a rencontré un problème : {}".format(e)), parent=self)
- 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
@@ -427,9 +610,11 @@ class mainWindow(Tk):
# Get that
for char in lines:
+ self.termtext.delete("1.0","end")
self.termtext.insert("1.0", self.mrzChar)
self.mrzChar = self.mrzChar + char
self.stringValidation("")
+ self.termtext.insert("1.0", self.mrzChar)
return "break"
@@ -459,15 +644,175 @@ class mainWindow(Tk):
self.speedResult.insert('end', text)
self.speedResult['state'] = 'disabled'
-
+ def goPageChoice(self, event):
+ self.imageViewer.pagenumber = int(self.toolbar.pageChooser.get()) - 1
+ self.resizeScan()
+
def openingScan(self):
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 = {}
+ # Load an image using OpenCV
+ self.imageViewer.imagePath = path
+ self.imageViewer.imgZoom = 1
+ self.imageViewer.blackhat = False
+ self.imageViewer.rotateCount = 0
+ self.imageViewer.pagenumber = 0
+
+ # Determine how many pages
+ self.toolbar.pageChooser['values'] = ('1')
+ total = len(cv2.imreadmulti(self.imageViewer.imagePath)[1])
+
+ for i in range(2, total + 1):
+ self.toolbar.pageChooser['values'] += tuple(str(i))
+
+ # Open the first page
+ cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
+
+ try:
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ except ValueError:
+ # 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(photo)
+
+ def zoomInScan50(self, quantity = 50):
+ if self.imageViewer.image:
+ self.imageViewer.imgZoom += quantity
+ self.resizeScan()
+
+ def zoomOutScan50(self, quantity = 50):
+ if self.imageViewer.image:
+ self.imageViewer.imgZoom -= quantity
+ self.resizeScan()
+
+ def zoomInScan20(self, quantity = 20):
+ if self.imageViewer.image:
+ self.imageViewer.imgZoom += quantity
+ self.resizeScan()
+
+ def zoomOutScan20(self, quantity = 20):
+ if self.imageViewer.image:
+ self.imageViewer.imgZoom -= quantity
+ self.resizeScan()
+
+ def zoomInScan(self, quantity = 1):
+ if self.imageViewer.image:
+ self.imageViewer.imgZoom += quantity
+ self.resizeScan()
+
+ def zoomOutScan(self, quantity = 1):
+ if self.imageViewer.image:
+ self.imageViewer.imgZoom -= quantity
+ self.resizeScan()
+
+ def rotateRight(self):
+ if self.imageViewer.image:
+ self.imageViewer.rotateCount -= 1
+ if self.imageViewer.rotateCount < 0:
+ self.imageViewer.rotateCount = 4
+ self.resizeScan()
+
+ def rotateLeft(self):
+ if self.imageViewer.image:
+ self.imageViewer.rotateCount += 1
+ if self.imageViewer.rotateCount > 4:
+ self.imageViewer.rotateCount = 0
+ self.resizeScan()
+
+ def rotateLeft1(self):
+ if self.imageViewer.image:
+ self.imageViewer.rotateCount += 0.01
+ if self.imageViewer.rotateCount > 4:
+ self.imageViewer.rotateCount = 0
+ self.resizeScan()
+
+ def rotateRight1(self):
+ if self.imageViewer.image:
+ self.imageViewer.rotateCount -= 0.01
+ if self.imageViewer.rotateCount < 0:
+ self.imageViewer.rotateCount = 4
+ self.resizeScan()
+
+ def negativeScan(self):
+ if self.imageViewer.image:
+ # Load an image using OpenCV
+ cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
+ if not self.imageViewer.blackhat:
+ self.imageViewer.blackhat = True
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
+ cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
+ cv_img = cv2.bitwise_not(cv_img)
+ else:
+ self.imageViewer.blackhat = False
+ self.resizeScan(cv_img)
+
+ def resizeScan(self, cv_img = None):
+ if self.imageViewer.image:
+ try:
+ if not hasattr(cv_img, 'shape'):
+ # Load an image using OpenCV
+ cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
+ if self.imageViewer.blackhat:
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
+ cv_img = cv2.GaussianBlur(cv_img, (3, 3), 0)
+ cv_img = cv2.bitwise_not(cv_img)
+
+ try:
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ except ValueError:
+ # 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
+ # Rotate
+ rotationMatrix=cv2.getRotationMatrix2D((width/2, height/2),int(self.imageViewer.rotateCount*90),1)
+ cv_img=cv2.warpAffine(cv_img,rotationMatrix,(width,height))
+ # Resize
+ dim = (int(width * (self.imageViewer.imgZoom + 100) / 100), int(height * (self.imageViewer.imgZoom + 100) / 100))
+ cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
+ # Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
+ photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
+ self.statusUpdate( photo)
+ except Exception as e:
+ logfile.printerr("Error with opencv : {}".format(e))
+ traceback.print_exc(file=sys.stdout)
+ try:
+ # Reload an image using OpenCV
+ path = self.imageViewer.imagePath
+ self.imageViewer.imgZoom = 1
+ self.imageViewer.blackhat = False
+ self.imageViewer.rotateCount = 0
+ cv_img = cv2.imreadmulti(path)
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = cv_img.shape
+ # Get the image dimensions (OpenCV stores image data as NumPy ndarray)
+ height, width, channels_no = 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(photo)
+ except Exception as e:
+ logfile.printerr("Critical error with opencv : ".format(e))
+ traceback.print_exc(file=sys.stdout)
+ showerror("Erreur OpenCV (traitement d'images)", "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser")
+ self.initialize()
def newEntry(self):
self.initialize()
@@ -477,25 +822,27 @@ class mainWindow(Tk):
Tk().withdraw()
showinfo('A propos de CNIRevelator',
- ( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' +
- "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer " +
- "dans les termes de la GNU General Public License telle que publiée par " +
- "la Free Software Foundation, dans sa version 3 ou " +
- "ultérieure. " + "\n\n" +
- "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois " +
- "impliquer une quelconque garantie de " +
- "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la " +
- "GNU General Public License pour plus de détails à ce sujet. " +
- "\n\n" +
- "Vous devriez avoir reçu une copie de la GNU General Public License " +
- "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à '. " +
- "\n\n" +
- "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004" +
- "\n\n" +
- "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019" +
- "\n\n" +
- "Le code source de ce programme est disponible sur Github à l'adresse .\n" +
- " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !"
+ ( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n'
+ "Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
+ "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer "
+ "dans les termes de la GNU General Public License telle que publiée par "
+ "la Free Software Foundation, dans sa version 3 ou "
+ "ultérieure. " + "\n\n"
+ "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois "
+ "impliquer une quelconque garantie de "
+ "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la "
+ "GNU General Public License pour plus de détails à ce sujet. "
+ "\n\n"
+ "Vous devriez avoir reçu une copie de la GNU General Public License "
+ "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à . "
+ "\n\n"
+ "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004."
+ "\n\n"
+ "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019."
+ "\n\n"
+ "Le code source de ce programme est disponible sur Github à l'adresse .\n"
+ "Son fonctionnement est conforme aux normes et directives du document 9303 de l'OACI régissant les documents de voyages et d'identité." + '\n\n'
+ " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !\n\n"
),
parent=self)
@@ -520,6 +867,12 @@ class mainWindow(Tk):
),
parent=self)
+
+ def openIssuePage(self):
+ self.openBrowser("https://github.com/neox95/CNIRevelator/issues")
+
+ def openBrowser(self, url):
+ webbrowser.open_new(url)
def computeSigma(self):
"""
@@ -580,9 +933,11 @@ class mainWindow(Tk):
self.compliance = False
if self.compliance == True:
- self.statusUpdate("CONFORME", "chartreuse2")
+ self.STATUStxt["text"] = "CONFORME"
+ self.STATUStxt["foreground"] = "green"
else:
- self.statusUpdate("NON-CONFORME","red")
+ self.STATUStxt["text"] = "NON CONFORME"
+ self.STATUStxt["foreground"] = "red"
return
diff --git a/src/mrz.py b/src/mrz.py
index 4619d8a..e51fad6 100644
--- a/src/mrz.py
+++ b/src/mrz.py
@@ -640,27 +640,26 @@ AC = [
"Certificat de membre d'équipage"
]
-## XXXXXXXXXXX
-# VB = [
-# ["11222333333333333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCCCCCCCCCDE"],
-# {
-# "1": ["2", "CODE", "V."],
-# "2": ["3", "PAYS", "[A-Z]+"],
-# "3": ["39", "NOM", "[A-Z]+"],
-# "4": ["9", "NO", ".+"],
-# "5": ["1", "CTRL", "[0-9]","4"],
-# "6": ["3", "NAT", "[A-Z]+"],
-# "7": ["6", "BDATE", "[0-9]+"],
-# "8": ["1", "CTRL", "[0-9]", "7"],
-# "9": ["1", "SEX", "[A-Z]"],
-# "A": ["6", "EDATE", "[0-9]+"],
-# "B": ["1", "CTRL", "[0-9]", "A"],
-# "C": ["14", "FACULT", ".+"]
-# },
-# "Visa de type B"
-# ]
-
VA = [
+ ["11222333333333333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCCCCCCCCCCCCC"],
+ {
+ "1": ["2", "CODE", "V."],
+ "2": ["3", "PAYS", "[A-Z]+"],
+ "3": ["39", "NOM", "[A-Z]+"],
+ "4": ["9", "NO", ".+"],
+ "5": ["1", "CTRL", "[0-9]","4"],
+ "6": ["3", "NAT", "[A-Z]+"],
+ "7": ["6", "BDATE", "[0-9]+"],
+ "8": ["1", "CTRL", "[0-9]", "7"],
+ "9": ["1", "SEX", "[A-Z]"],
+ "A": ["6", "EDATE", "[0-9]+"],
+ "B": ["1", "CTRL", "[0-9]", "A"],
+ "C": ["16", "FACULT", ".+"]
+ },
+ "Visa de type A"
+]
+
+VB = [
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"],
{
"1": ["2", "CODE", "V."],
@@ -676,14 +675,14 @@ VA = [
"B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"]
},
- "Visa de type A"
+ "Visa de type B"
]
TSF = [
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"],
{
"1": ["2", "CODE", "TS"],
- "2": ["3", "PAYS", "[A-Z]+"],
+ "2": ["3", "PAYS", "FRA"],
"3": ["31", "NOM", "([A-Z]|<)+"],
"4": ["9", "NO", ".+"],
"5": ["1", "CTRL", "[0-9]","4"],
@@ -695,7 +694,7 @@ TSF = [
"B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"]
},
- "Titre de séjour"
+ "Carte de séjour"
]
I__ = [
@@ -752,8 +751,7 @@ DL = [
"Permis de conduire"
]
-#TYPES = [ID, I__, VB, VA, AC, I_, IP, P, DL]
-TYPES = [IDFR, I__, VA, AC, I_, IP, P, DL, TSF]
+TYPES = [IDFR, I__, VB, VA, AC, I_, IP, P, DL, TSF]
# longest document MRZ line
longest = max([len(x[0][0]) for x in TYPES])
diff --git a/src/rotateLeft.png b/src/rotateLeft.png
new file mode 100644
index 0000000..7653faa
Binary files /dev/null and b/src/rotateLeft.png differ
diff --git a/src/rotateLeft1.png b/src/rotateLeft1.png
new file mode 100644
index 0000000..9224963
Binary files /dev/null and b/src/rotateLeft1.png differ
diff --git a/src/rotateRight.png b/src/rotateRight.png
new file mode 100644
index 0000000..3e008dc
Binary files /dev/null and b/src/rotateRight.png differ
diff --git a/src/rotateRight1.png b/src/rotateRight1.png
new file mode 100644
index 0000000..a7de862
Binary files /dev/null and b/src/rotateRight1.png differ
diff --git a/src/updater.py b/src/updater.py
index b02ca37..b41c16b 100644
--- a/src/updater.py
+++ b/src/updater.py
@@ -56,7 +56,7 @@ def createShortcut(path, target='', wDir='', icon=''):
shortcut.close()
else:
shell = Dispatch('WScript.Shell')
- shortcut = shell.CreateShortCut(path)
+ shortcut = shell.CreateShortCut(shell.SpecialFolders("Desktop") + r"\{}".format(path))
shortcut.Targetpath = target
shortcut.WorkingDirectory = wDir
if icon == '':
@@ -192,7 +192,6 @@ def getLatestVersion(credentials):
return (finalver, finalurl, finalchecksum)
-# XXX Warning : when tesseracturl is not found, it seems to hang and freeze
def tessInstall(PATH, credentials):
# Global Handlers
logfile = logger.logCur
@@ -207,18 +206,43 @@ def tessInstall(PATH, credentials):
logfile.printdbg('Preparing download of Tesseract OCR 4...')
getTesseract = downloader.newdownload(credentials, tesseracturl, PATH + '\\downloads\\TsrtPackage.zip', "Tesseract 4 OCR Module").download()
- # Unzip Tesseract
- logfile.printdbg("Unzipping the package")
- launcherWindow.printmsg('Installing the updates')
- zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r')
- zip_ref.extractall(PATH)
- zip_ref.close()
-
- # Cleanup
try:
- os.remove(UPATH + '\\downloads\\TsrtPackage.zip')
+ # CHECKSUM
+ BUF_SIZE = 65536 # lets read stuff in 64kb chunks!
+
+ sha1 = hashlib.sha1()
+
+ with open(globs.CNIRFolder + '\\downloads\\TsrtPackage.zip', 'rb') as f:
+ while True:
+ data = f.read(BUF_SIZE)
+ if not data:
+ break
+ sha1.update(data)
+
+ check = sha1.hexdigest()
+ logfile.printdbg("SHA1: {0}".format(check))
+
+ if not check == globs.CNIRTesserHash:
+ logfile.printerr("Checksum error")
+ return False
+
+ # Unzip Tesseract
+ logfile.printdbg("Unzipping the package")
+ launcherWindow.printmsg('Installing the updates')
+ zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r')
+ zip_ref.extractall(PATH)
+ zip_ref.close()
+ # Cleanup
+ try:
+ os.remove(UPATH + '\\downloads\\TsrtPackage.zip')
+ except:
+ pass
+ return True
+
except:
- pass
+ return False
+ else:
+ return True
## Main Batch Function
def batch(credentials):
@@ -284,6 +308,9 @@ def batch(credentials):
shutil.rmtree(UPATH + 'temp')
logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe')
+ # Make a shortcut
+ createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH)
+
launcherWindow.printmsg('Success !')
# Cleanup
@@ -366,8 +393,6 @@ def umain():
logfile.printerr(str(e))
launcherWindow.printmsg('Fail :{}'.format(e))
launcherWindow.printmsg('Starting...')
- else:
- tessInstall(globs.CNIRFolder, credentials)
try:
try:
@@ -386,9 +411,39 @@ def umain():
else:
logfile.printerr("An error occured. No effective update !")
launcherWindow.printmsg('An error occured. No effective update !')
- time.sleep(2)
+ time.sleep(2)
+ launcherWindow.exit()
+ return 0
+
+ if UPDATE_IS_MADE:
+ launcherWindow.exit()
+ return 0
+ except:
+ logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc()))
launcherWindow.exit()
- return 0
+ sys.exit(2)
+ return 2
+
+ try:
+ try:
+ # INSTALLING TESSERACT OCR
+ success = tessInstall(globs.CNIRFolder, credentials)
+ except Exception as e:
+ logfile.printerr("An error occured on the thread : " + str(traceback.format_exc()))
+ launcherWindow.printmsg('ERROR : ' + str(e))
+ time.sleep(3)
+ launcherWindow.exit()
+ return 1
+
+ if success:
+ logfile.printdbg("Software is up-to-date !")
+ launcherWindow.printmsg('Software is up-to-date !')
+ else:
+ logfile.printerr("An error occured. No effective update !")
+ launcherWindow.printmsg('An error occured. No effective update !')
+ time.sleep(2)
+ launcherWindow.exit()
+ return 0
except:
logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc()))
@@ -396,5 +451,6 @@ def umain():
sys.exit(2)
return 2
- return
-
+ time.sleep(2)
+ launcherWindow.exit()
+ return 0
diff --git a/src/zoomIn.png b/src/zoomIn.png
new file mode 100644
index 0000000..959aa41
Binary files /dev/null and b/src/zoomIn.png differ
diff --git a/src/zoomIn20.png b/src/zoomIn20.png
new file mode 100644
index 0000000..d341227
Binary files /dev/null and b/src/zoomIn20.png differ
diff --git a/src/zoomIn50.png b/src/zoomIn50.png
new file mode 100644
index 0000000..21acbdc
Binary files /dev/null and b/src/zoomIn50.png differ
diff --git a/src/zoomOut.png b/src/zoomOut.png
new file mode 100644
index 0000000..0eca4be
Binary files /dev/null and b/src/zoomOut.png differ
diff --git a/src/zoomOut20.png b/src/zoomOut20.png
new file mode 100644
index 0000000..fb97321
Binary files /dev/null and b/src/zoomOut20.png differ
diff --git a/src/zoomOut50.png b/src/zoomOut50.png
new file mode 100644
index 0000000..f753234
Binary files /dev/null and b/src/zoomOut50.png differ