1
0
mirror of https://gitlab.os-k.eu/neox/CNIRevelator.git synced 2023-08-25 14:03:10 +02:00

Merge pull request #13 from neox95/v3.0

V3.0.8 release and now working on 3.1
This commit is contained in:
Adrien Bourmault 2019-08-12 00:00:28 +02:00 committed by GitHub
commit 1548fae87b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 567 additions and 160 deletions

5
.gitignore vendored
View File

@ -8,3 +8,8 @@
build/* build/*
dist/* dist/*
src/Tesseract-OCR4/*
src/downloads/*
src/config/*
src/logs/*
signtool_8.1/*

View File

@ -1,2 +1,2 @@
# ver|url|checksum, and | as separator, one version per || # 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||

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -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 LICENSE dist\CNIRevelator\LICENSE
copy src\id-card.ico dist\CNIRevelator\id-card.ico 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 pause

View File

@ -31,7 +31,7 @@ import threading
import traceback import traceback
import psutil import psutil
import launcher # launcher.py import launcher # launcher.py"
import updater # updater.py import updater # updater.py
import globs # globs.py import globs # globs.py
import pytesseract # pytesseract.py import pytesseract # pytesseract.py

BIN
src/Invert.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

BIN
src/OCR.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

View File

@ -25,18 +25,13 @@
import os import os
# CNIRevelator version # CNIRevelator version
verType = "alpha" verType = "final release"
version = [3, 0, 6] version = [3, 1, 0]
verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType) verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType)
verstring = "{}.{}".format(version[0], version[1]) verstring = "{}.{}".format(version[0], version[1])
debug = True 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" + \ 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"
"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"
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8' CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
CNIRFolder = os.getcwd() CNIRFolder = os.getcwd()
@ -46,6 +41,7 @@ CNIRCryptoKey = '82Xh!efX3#@P~2eG'
CNIRNewVersion = False CNIRNewVersion = False
CNIRConfig = CNIRFolder + '\\config\\conf.ig' CNIRConfig = CNIRFolder + '\\config\\conf.ig'
CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\'
CNIRErrLog = CNIRFolder + '\\logs\\error.log' CNIRErrLog = CNIRFolder + '\\logs\\error.log'
CNIRMainLog = CNIRFolder + '\\logs\\main.log' CNIRMainLog = CNIRFolder + '\\logs\\main.log'
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig' CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'

View File

@ -32,7 +32,6 @@ import PIL.Image, PIL.ImageTk
import logger # logger.py import logger # logger.py
import globs # globs.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"] 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 self.choice = 1
def ok(self): def ok(self):
self.destroy() 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): class LoginDialog(Toplevel):
def __init__(self, parent): def __init__(self, parent):
@ -178,21 +215,6 @@ class LauncherWindow(Tk):
def exit(self): def exit(self):
self.after(1000, self.destroy) 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): class ResizeableCanvas(Canvas):
def __init__(self,parent,**kwargs): def __init__(self,parent,**kwargs):
Canvas.__init__(self,parent,**kwargs) Canvas.__init__(self,parent,**kwargs)
@ -208,7 +230,7 @@ class ResizeableCanvas(Canvas):
self.height = event.height self.height = event.height
# rescale all the objects tagged with the "all" tag # rescale all the objects tagged with the "all" tag
self.scale("all",0,0,wscale,hscale) self.scale("all",0,0,wscale,hscale)
## Global Handler ## Global Handler
launcherWindowCur = LauncherWindow() launcherWindowCur = LauncherWindow()

View File

@ -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 <https:*www.gnu.org/licenses/>. *
********************************************************************************
"""

View File

@ -35,13 +35,14 @@ import re
import traceback import traceback
import cv2 import cv2
import PIL.Image, PIL.ImageTk import PIL.Image, PIL.ImageTk
import os, shutil
import webbrowser
import ihm # ihm.py import ihm # ihm.py
import logger # logger.py import logger # logger.py
import mrz # mrz.py import mrz # mrz.py
import globs # globs.py import globs # globs.py
import pytesseract # pytesseract.py import pytesseract # pytesseract.py
from image import * # image.py
# Global handler # Global handler
logfile = logger.logCur logfile = logger.logCur
@ -53,10 +54,12 @@ class mainWindow(Tk):
self.initialize() self.initialize()
def initialize(self): def initialize(self):
self.mrzChar = '' self.mrzChar = ""
self.mrzDecided = False self.mrzDecided = False
self.Tags = [] self.Tags = []
self.compliance = True self.compliance = True
self.corners = []
self.validatedtext = ""
# Hide during construction # Hide during construction
self.withdraw() self.withdraw()
@ -89,6 +92,9 @@ class mainWindow(Tk):
self.lecteur_ci.grid_rowconfigure(5, weight=1) self.lecteur_ci.grid_rowconfigure(5, weight=1)
# Fill the data sections # 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) 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 = ttk.Label((self.lecteur_ci), text=' ')
self.nom.grid(column=1, row=1, padx=5, pady=5) self.nom.grid(column=1, row=1, padx=5, pady=5)
@ -146,18 +152,110 @@ class mainWindow(Tk):
"INDIC" : self.indic, "INDIC" : self.indic,
} }
# The STATUS indicator + image display # The the image viewer
self.STATUT = ttk.Labelframe(self, text='Affichage de documents et statut') self.imageViewer = ttk.Labelframe(self, text='Affichage et traitement de documents')
self.STATUT.grid_columnconfigure(0, weight=1) self.imageViewer.grid_columnconfigure(0, weight=1)
self.STATUT.grid_rowconfigure(0, weight=1) self.imageViewer.grid_columnconfigure(1, weight=0)
self.STATUT.frame = Frame(self.STATUT) self.imageViewer.grid_rowconfigure(0, weight=1)
self.STATUT.frame.grid(column=0, row=0, sticky='NSEW') self.imageViewer.grid_rowconfigure(1, weight=1)
self.STATUT.frame.grid_columnconfigure(0, weight=1) self.imageViewer.grid_rowconfigure(2, weight=1)
self.STATUT.frame.grid_rowconfigure(0, weight=1) self.imageViewer.frame = Frame(self.imageViewer)
self.STATUT.ZONE = ihm.ResizeableCanvas(self.STATUT.frame, bg=self["background"]) self.imageViewer.frame.grid(column=0, row=0, sticky='NSEW')
self.STATUT.ZONE.pack(fill="both", expand=True) self.imageViewer.frame.grid_columnconfigure(0, weight=1)
self.STATUSimg = self.STATUT.ZONE.create_image(0,0, image=None) self.imageViewer.frame.grid_rowconfigure(0, weight=1)
self.STATUStxt = self.STATUT.ZONE.create_text(0,0, text='', font='Times 24', fill='#FFBF00') # + 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("<<ComboboxSelected>>", 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 # The terminal to enter the MRZ
self.terminal = ttk.Labelframe(self, text='Terminal de saisie de MRZ complète') 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_columnconfigure(9, weight=1)
self.speed731.grid_rowconfigure(0, weight=1) self.speed731.grid_rowconfigure(0, weight=1)
self.speed731text = Entry(self.speed731, font='Terminal 14') 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 = 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 # The monitor that indicates some useful infos
self.monitor = ttk.Labelframe(self, text='Moniteur') self.monitor = ttk.Labelframe(self, text='Moniteur')
@ -206,8 +304,8 @@ class mainWindow(Tk):
self.monitor.grid_rowconfigure(0, weight=1) self.monitor.grid_rowconfigure(0, weight=1)
# All the items griding # All the items griding
self.lecteur_ci.grid(column=0, row=0, sticky='EWNS', columnspan=2, padx=5, pady=5) self.lecteur_ci.grid(column=2, row=0, sticky='EWNS', columnspan=1, padx=5, pady=5)
self.STATUT.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.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.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) 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) menubar.add_cascade(label='Fichier', menu=menu1)
menu3 = Menu(menubar, tearoff=0) menu3 = Menu(menubar, tearoff=0)
menu3.add_command(label='Commandes au clavier', command=(self.helpbox)) 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)) menu3.add_command(label='A propos de CNIRevelator', command=(self.infobox))
menubar.add_cascade(label='Aide', menu=menu3) menubar.add_cascade(label='Aide', menu=menu3)
self.config(menu=menubar) self.config(menu=menubar)
@ -248,36 +348,119 @@ class mainWindow(Tk):
self.update() self.update()
self.deiconify() self.deiconify()
self.minsize(self.winfo_width(), self.winfo_height()) self.minsize(self.winfo_width(), self.winfo_height())
# Load an image using OpenCV # Set image
cv_img = cv2.imread("background.png") self.imageViewer.image = None
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) self.imageViewer.imagePath = None
cv_img = cv2.blur(cv_img, (15, 15)) self.imageViewer.imgZoom = 1
# Get the image dimensions (OpenCV stores image data as NumPy ndarray) self.imageViewer.rotateCount = 0
height, width = cv_img.shape self.imageViewer.blackhat = False
# Get the image dimensions (OpenCV stores image data as NumPy ndarray) self.imageViewer.pagenumber = 0
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 # Some bindings
self.termtext.bind('<Key>', self.entryValidation) self.termtext.bind('<Key>', self.entryValidation)
self.termtext.bind('<<Paste>>', self.pasteValidation) self.termtext.bind('<<Paste>>', self.pasteValidation)
self.speed731text.bind('<Control_R>', self.speedValidation) self.speed731text.bind('<Control_R>', self.speedValidation)
self.imageViewer.ZONE.bind("<Button-1>", self.rectangleSelectScan)
logfile.printdbg('Initialization successful') logfile.printdbg('Initialization successful')
def statusUpdate(self, msg, color, image=None, setplace=False): def statusUpdate(self, image=None, setplace=False):
if image: 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)) def goOCRDetection(self):
self.STATUT.ZONE.itemconfigure(self.STATUStxt, text=(msg), fill=color) 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): def stringValidation(self, keysym):
# analysis # analysis
@ -427,9 +610,11 @@ class mainWindow(Tk):
# Get that # Get that
for char in lines: for char in lines:
self.termtext.delete("1.0","end")
self.termtext.insert("1.0", self.mrzChar) self.termtext.insert("1.0", self.mrzChar)
self.mrzChar = self.mrzChar + char self.mrzChar = self.mrzChar + char
self.stringValidation("") self.stringValidation("")
self.termtext.insert("1.0", self.mrzChar)
return "break" return "break"
@ -459,15 +644,175 @@ class mainWindow(Tk):
self.speedResult.insert('end', text) self.speedResult.insert('end', text)
self.speedResult['state'] = 'disabled' self.speedResult['state'] = 'disabled'
def goPageChoice(self, event):
self.imageViewer.pagenumber = int(self.toolbar.pageChooser.get()) - 1
self.resizeScan()
def openingScan(self): def openingScan(self):
path = '' path = ''
path = filedialog.askopenfilename(parent=self, title='Ouvrir un scan de CNI...', filetypes=(('TIF files', '*.tif'), path = filedialog.askopenfilename(parent=self, title='Ouvrir un scan de CNI...', filetypes=(('TIF files', '*.tif'),
('TIF files', '*.tiff'), ('TIF files', '*.tiff'),
('JPEG files', '*.jpg'), ('JPEG files', '*.jpg'),
('JPEG files', '*.jpeg'))) ('JPEG files', '*.jpeg')))
self.mrzdetected = '' # Load an image using OpenCV
self.mrzdict = {} 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): def newEntry(self):
self.initialize() self.initialize()
@ -477,25 +822,27 @@ class mainWindow(Tk):
Tk().withdraw() Tk().withdraw()
showinfo('A propos de CNIRevelator', showinfo('A propos de CNIRevelator',
( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' + ( '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 " + "Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
"dans les termes de la GNU General Public License telle que publiée par " + "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer "
"la Free Software Foundation, dans sa version 3 ou " + "dans les termes de la GNU General Public License telle que publiée par "
"ultérieure. " + "\n\n" + "la Free Software Foundation, dans sa version 3 ou "
"CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois " + "ultérieure. " + "\n\n"
"impliquer une quelconque garantie de " + "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois "
"QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la " + "impliquer une quelconque garantie de "
"GNU General Public License pour plus de détails à ce sujet. " + "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la "
"\n\n" + "GNU General Public License pour plus de détails à ce sujet. "
"Vous devriez avoir reçu une copie de la GNU General Public License " + "\n\n"
"avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à '<https://www.gnu.org/licenses/>. " + "Vous devriez avoir reçu une copie de la GNU General Public License "
"\n\n" + "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à <https://www.gnu.org/licenses/>. "
"Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004" + "\n\n"
"\n\n" + "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004."
"Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019" + "\n\n"
"\n\n" + "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019."
"Le code source de ce programme est disponible sur Github à l'adresse <https://github.com/neox95/CNIRevelator>.\n" + "\n\n"
" En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !" "Le code source de ce programme est disponible sur Github à l'adresse <https://github.com/neox95/CNIRevelator>.\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) parent=self)
@ -520,6 +867,12 @@ class mainWindow(Tk):
), ),
parent=self) parent=self)
def openIssuePage(self):
self.openBrowser("https://github.com/neox95/CNIRevelator/issues")
def openBrowser(self, url):
webbrowser.open_new(url)
def computeSigma(self): def computeSigma(self):
""" """
@ -580,9 +933,11 @@ class mainWindow(Tk):
self.compliance = False self.compliance = False
if self.compliance == True: if self.compliance == True:
self.statusUpdate("CONFORME", "chartreuse2") self.STATUStxt["text"] = "CONFORME"
self.STATUStxt["foreground"] = "green"
else: else:
self.statusUpdate("NON-CONFORME","red") self.STATUStxt["text"] = "NON CONFORME"
self.STATUStxt["foreground"] = "red"
return return

View File

@ -640,27 +640,26 @@ AC = [
"Certificat de membre d'équipage" "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 = [ 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"], ["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"],
{ {
"1": ["2", "CODE", "V."], "1": ["2", "CODE", "V."],
@ -676,14 +675,14 @@ VA = [
"B": ["1", "CTRL", "[0-9]", "A"], "B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"] "C": ["8", "FACULT", ".+"]
}, },
"Visa de type A" "Visa de type B"
] ]
TSF = [ TSF = [
["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"], ["112223333333333333333333333333333333", "444444444566677777789AAAAAABCCCCCC"],
{ {
"1": ["2", "CODE", "TS"], "1": ["2", "CODE", "TS"],
"2": ["3", "PAYS", "[A-Z]+"], "2": ["3", "PAYS", "FRA"],
"3": ["31", "NOM", "([A-Z]|<)+"], "3": ["31", "NOM", "([A-Z]|<)+"],
"4": ["9", "NO", ".+"], "4": ["9", "NO", ".+"],
"5": ["1", "CTRL", "[0-9]","4"], "5": ["1", "CTRL", "[0-9]","4"],
@ -695,7 +694,7 @@ TSF = [
"B": ["1", "CTRL", "[0-9]", "A"], "B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"] "C": ["8", "FACULT", ".+"]
}, },
"Titre de séjour" "Carte de séjour"
] ]
I__ = [ I__ = [
@ -752,8 +751,7 @@ DL = [
"Permis de conduire" "Permis de conduire"
] ]
#TYPES = [ID, I__, VB, VA, AC, I_, IP, P, DL] TYPES = [IDFR, I__, VB, VA, AC, I_, IP, P, DL, TSF]
TYPES = [IDFR, I__, VA, AC, I_, IP, P, DL, TSF]
# longest document MRZ line # longest document MRZ line
longest = max([len(x[0][0]) for x in TYPES]) longest = max([len(x[0][0]) for x in TYPES])

BIN
src/rotateLeft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

BIN
src/rotateLeft1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

BIN
src/rotateRight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

BIN
src/rotateRight1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

View File

@ -56,7 +56,7 @@ def createShortcut(path, target='', wDir='', icon=''):
shortcut.close() shortcut.close()
else: else:
shell = Dispatch('WScript.Shell') shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(path) shortcut = shell.CreateShortCut(shell.SpecialFolders("Desktop") + r"\{}".format(path))
shortcut.Targetpath = target shortcut.Targetpath = target
shortcut.WorkingDirectory = wDir shortcut.WorkingDirectory = wDir
if icon == '': if icon == '':
@ -192,7 +192,6 @@ def getLatestVersion(credentials):
return (finalver, finalurl, finalchecksum) return (finalver, finalurl, finalchecksum)
# XXX Warning : when tesseracturl is not found, it seems to hang and freeze
def tessInstall(PATH, credentials): def tessInstall(PATH, credentials):
# Global Handlers # Global Handlers
logfile = logger.logCur logfile = logger.logCur
@ -207,18 +206,43 @@ def tessInstall(PATH, credentials):
logfile.printdbg('Preparing download of Tesseract OCR 4...') logfile.printdbg('Preparing download of Tesseract OCR 4...')
getTesseract = downloader.newdownload(credentials, tesseracturl, PATH + '\\downloads\\TsrtPackage.zip', "Tesseract 4 OCR Module").download() 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: 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: except:
pass return False
else:
return True
## Main Batch Function ## Main Batch Function
def batch(credentials): def batch(credentials):
@ -284,6 +308,9 @@ def batch(credentials):
shutil.rmtree(UPATH + 'temp') shutil.rmtree(UPATH + 'temp')
logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe') logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe')
# Make a shortcut
createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH)
launcherWindow.printmsg('Success !') launcherWindow.printmsg('Success !')
# Cleanup # Cleanup
@ -366,8 +393,6 @@ def umain():
logfile.printerr(str(e)) logfile.printerr(str(e))
launcherWindow.printmsg('Fail :{}'.format(e)) launcherWindow.printmsg('Fail :{}'.format(e))
launcherWindow.printmsg('Starting...') launcherWindow.printmsg('Starting...')
else:
tessInstall(globs.CNIRFolder, credentials)
try: try:
try: try:
@ -386,9 +411,39 @@ def umain():
else: else:
logfile.printerr("An error occured. No effective update !") logfile.printerr("An error occured. No effective update !")
launcherWindow.printmsg('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() 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: except:
logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc())) logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc()))
@ -396,5 +451,6 @@ def umain():
sys.exit(2) sys.exit(2)
return 2 return 2
return time.sleep(2)
launcherWindow.exit()
return 0

BIN
src/zoomIn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

BIN
src/zoomIn20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/zoomIn50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/zoomOut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 B

BIN
src/zoomOut20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1013 B

BIN
src/zoomOut50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB