pycodeocr-main Mailing List for PyCodeOCR
Status: Beta
Brought to you by:
drtrigon
You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
(3) |
Apr
(8) |
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
(9) |
Oct
(1) |
Nov
(2) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
|
Feb
(8) |
Mar
(4) |
Apr
(9) |
May
|
Jun
|
Jul
(4) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(2) |
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2014 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(8) |
Sep
(1) |
Oct
|
Nov
|
Dec
|
From: <la...@us...> - 2014-09-05 08:08:04
|
Revision: 71 http://sourceforge.net/p/pycodeocr/code/71 Author: laserb Date: 2014-09-05 08:08:01 +0000 (Fri, 05 Sep 2014) Log Message: ----------- Fix old output not removed. Modified Paths: -------------- branches/redesign/PyCodeOCR.py branches/redesign/gtkGUI/ImagePreview.py Modified: branches/redesign/PyCodeOCR.py =================================================================== --- branches/redesign/PyCodeOCR.py 2014-08-28 14:57:01 UTC (rev 70) +++ branches/redesign/PyCodeOCR.py 2014-09-05 08:08:01 UTC (rev 71) @@ -115,6 +115,7 @@ # run recognition self.progressbar.resetProgress("") + self.imagePreview.removeAll() runRecognition = Recognition.RunRecognition(self.source, sourceProperties, self.imageRecognition, recognitionProperties) runRecognition.connect("updateRecognition", self.onProgressUpdate) runRecognition.connect("recognized", self.on_recognized) Modified: branches/redesign/gtkGUI/ImagePreview.py =================================================================== --- branches/redesign/gtkGUI/ImagePreview.py 2014-08-28 14:57:01 UTC (rev 70) +++ branches/redesign/gtkGUI/ImagePreview.py 2014-09-05 08:08:01 UTC (rev 71) @@ -122,6 +122,10 @@ self.output.addText(text, self.res_color[mode]) else: self.output.addText(content, self.res_color[mode]) + + def removeAll(self): + self.output.removeAll() + self.main_image.set_from_file( "PyCodeOCR.png" ) def setRecognitionData(self, recognitionData): self.recognitionData = recognitionData @@ -131,7 +135,7 @@ # @see http://stackoverflow.com/questions/7906814/converting-pil-image-to-gtk-pixbuf def image_to_pixbuf(self, image): fd = StringIO.StringIO() - self.recognitionData.getImage().save(fd, "png") + image.save(fd, "png") contents = fd.getvalue() fd.close() loader = gtk.gdk.PixbufLoader("png") @@ -192,9 +196,11 @@ self.remove(self.button[text]) def removeAll(self): - for button in self.button: - self.remove(button[0]) - + children = self.get_children() + for child in children: + self.remove(child) + self.button = {} + def copyClipboard(self, widget): label = widget.get_label() label = label.split("\n")[0] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-28 14:57:09
|
Revision: 70 http://sourceforge.net/p/pycodeocr/code/70 Author: laserb Date: 2014-08-28 14:57:01 +0000 (Thu, 28 Aug 2014) Log Message: ----------- Update tests and add missing files. Modified Paths: -------------- branches/redesign/Recognition/__init__.py branches/redesign/Test/Tests.py Added Paths: ----------- branches/redesign/Test/TestGUI.py branches/redesign/Test/TestScannerGUI.py branches/redesign/gtkGUI/Chooser.py branches/redesign/gtkGUI/ImagePreview.glade branches/redesign/gtkGUI/PropertyWidgets/ branches/redesign/gtkGUI/PropertyWidgets/Coordinates.py branches/redesign/gtkGUI/PropertyWidgets/Filechooser.py branches/redesign/gtkGUI/PropertyWidgets/ListChooser.py branches/redesign/gtkGUI/PropertyWidgets/PropertyWidgetBase.py branches/redesign/gtkGUI/PropertyWidgets/__init__.py branches/redesign/gtkGUI/test.py Removed Paths: ------------- branches/redesign/Source/Sources.py Modified: branches/redesign/Recognition/__init__.py =================================================================== --- branches/redesign/Recognition/__init__.py 2014-08-28 14:37:06 UTC (rev 69) +++ branches/redesign/Recognition/__init__.py 2014-08-28 14:57:01 UTC (rev 70) @@ -1,4 +1,5 @@ from Recognition.ImageRecognition import RunRecognition +from Recognition.ImageRecognition import RecognitionData from Recognition.Barcode import Barcode from Recognition.DataMatrix import DataMatrix from Recognition.DTMX import DTMX Deleted: branches/redesign/Source/Sources.py =================================================================== --- branches/redesign/Source/Sources.py 2014-08-28 14:37:06 UTC (rev 69) +++ branches/redesign/Source/Sources.py 2014-08-28 14:57:01 UTC (rev 70) @@ -1,33 +0,0 @@ -# -*- coding: utf8 -*- - -import sane -from Source import Scanner - -class Sources(object): - def __init__(self): - self.sources = [] - - def searchScanner(self): - sane.init() - srcs = sane.get_devices() - for src in srcs: - self.sources.append(Scanner(src)) - - def getSources(self): - return self.sources - - def getSource(self, name): - for src in self.sources: - if src.getName() == name: - return src - - def addSource(self, source): - self.sources.append(source) - - def removeSource(self, source): - i = 0 - for src in self.sources: - if src.equals(source): - self.sources.pop(i); - return - i = i + 1 Added: branches/redesign/Test/TestGUI.py =================================================================== --- branches/redesign/Test/TestGUI.py (rev 0) +++ branches/redesign/Test/TestGUI.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,114 @@ +# @see http://www.python-kurs.eu/threads.php + +import gtk +from gtkGUI.ProgressBar import ProgressBar +from gtkGUI.ImagePreview import ImagePreview +import threading, time +from PIL import Image +import Recognition + + +class TestGUI(threading.Thread): + def __init__(self, widget, on_button_pressed): + threading.Thread.__init__(self) + self.widget = widget + self.on_button_pressed = on_button_pressed + + # @see https://git.gnome.org/browse/pygtk/tree/examples/gtk/widget.py + def run(self): + self.win = gtk.Window() + self.win.set_border_width(5) + self.win.set_title('Widget test') + self.win.connect('delete-event', gtk.main_quit) + + frame = gtk.Frame("Example frame") + self.win.add(frame) + + hbox = gtk.HBox() + frame.add(hbox) + + button = gtk.Button("Click") + button.connect("pressed",self.on_button_pressed) + hbox.add(button) + hbox.add(self.widget) + + self.win.show_all() + gtk.main() + + + ## Refresh window during running processes. + def refresh(self): + self.win.queue_draw() + time.sleep(0.1) # give also some time to the user... :) + while gtk.events_pending(): + gtk.main_iteration() + +def progressbar_on_button_pressed(event): + for i in range(10): + progressbar.nextProgress("clicked " + str(progressbar.getProgress())) + t.refresh() + print progressbar.getProgress() == 10 + progressbar.resetProgress("reset") + print progressbar.getProgress() == 0 + + +def imagePreview_on_button_pressed(event): + imagePreview.setOutput("Recognition failed.", False) + for i in range(10): + t.refresh() + imagePreview.setOutput("Success", True) + for i in range(10): + t.refresh() + imagePreview.setOutput("Reset") + +def complete_on_button_pressed(event): + imagePreview.setOutput("Recognition failed.", False) + for i in range(10): + progressbar.nextProgress("clicked " + str(progressbar.getProgress())) + t.refresh() + imagePreview.setOutput("Success", True) + for i in range(10): + t.refresh() + imagePreview.setOutput("Reset") + progressbar.resetProgress("reset") + for i in range(10): + t.refresh() + + image = Image.open("/home/rf/Firefox_wallpaper.png") + recognitionData = Recognition.RecognitionData(image) + recognitionData.setContent("Data recognized", True) + imagePreview.setRecognitionData(recognitionData) + + +# main routin +if __name__ == '__main__': + errors = 0 + # init tests + progressbar = ProgressBar(10) + t = TestGUI(progressbar, progressbar_on_button_pressed) + t.start() + t.join() + + # init tests + imagePreview = ImagePreview() + image = Image.open("/home/rf/bin/pyCodeOCR/PyCodeOCR.png") + imagePreview.setImage(image) + t = TestGUI(imagePreview, imagePreview_on_button_pressed) + t.start() + t.join() + + vbox = gtk.VBox() + imagePreview = ImagePreview() + image = Image.open("/home/rf/bin/pyCodeOCR/PyCodeOCR.png") + imagePreview.setImage(image) + progressbar = ProgressBar(10) + vbox.pack_start(imagePreview,True,True,0) + vbox.pack_end(progressbar,False,False,0) + vbox.show_all() + t = TestGUI(vbox, complete_on_button_pressed) + t.start() + t.join() + + + + Added: branches/redesign/Test/TestScannerGUI.py =================================================================== --- branches/redesign/Test/TestScannerGUI.py (rev 0) +++ branches/redesign/Test/TestScannerGUI.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,81 @@ +# @see http://www.python-kurs.eu/threads.php + +import gtk +from gtkGUI.ProgressBar import ProgressBar +from gtkGUI.ImagePreview import ImagePreview +import threading, time +from PIL import Image +import Recognition, Source + + +class TestGUI(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + + # @see https://git.gnome.org/browse/pygtk/tree/examples/gtk/widget.py + def run(self): + srcs = Source.Scanner() + srcs.searchScanner() + self.source = srcs.activated()[0][1] + + self.win = gtk.Window() + self.win.set_border_width(5) + self.win.set_title('Widget test') + self.win.connect('delete-event', gtk.main_quit) + + frame = gtk.Frame("Example frame") + self.win.add(frame) + + hbox = gtk.HBox() + frame.add(hbox) + + button = gtk.Button("Click") + button.connect("pressed",self.on_button_pressed) + hbox.add(button) + + vbox = gtk.VBox() + self.imagePreview = ImagePreview() + self.progressbar = ProgressBar(10) + vbox.pack_start(self.imagePreview,True,True,0) + vbox.pack_end(self.progressbar,False,False,0) + + hbox.add(vbox) + + self.win.show_all() + gtk.main() + + + ## Refresh window during running processes. + def refresh(self): + self.win.queue_draw() + time.sleep(0.1) # give also some time to the user... :) + while gtk.events_pending(): + gtk.main_iteration() + + def on_button_pressed(self, event): + esr = Recognition.ESR() + esr.setRotate([180]) + + stdScannerData = Source.StdScannerData() + scannerData = stdScannerData.getStdScannerData("180 deg") + + + runRecognition = Recognition.RunRecognition(self.source, scannerData, esr) + runRecognition() + self.imagePreview.setRecognitionData(esr.getRecognitionData()) + + +# main routin +if __name__ == '__main__': + errors = 0 + # init tests + + + + t = TestGUI() + t.start() + t.join() + + + + Modified: branches/redesign/Test/Tests.py =================================================================== --- branches/redesign/Test/Tests.py 2014-08-28 14:37:06 UTC (rev 69) +++ branches/redesign/Test/Tests.py 2014-08-28 14:57:01 UTC (rev 70) @@ -43,9 +43,9 @@ ## Look for some scanners. def Scanners(self): print "Test search scanners ..." - srcs = Source.Sources() + srcs = Source.Scanner() srcs.searchScanner() - if len(srcs.getSources()) == 0: + if len(srcs.activated()[0][1]) == 0: print "Test failed." return False else: @@ -91,8 +91,9 @@ def TestRecognition(self, source, imageRecognition, image, expected): print "Test image recognition from file for %s ..." % imageRecognition.getName() scannerData = Source.ScannerData("default") - runRecognition = Recognition.RunRecognition(source, scannerData, imageRecognition) + runRecognition = Recognition.RunRecognition(source, scannerData, imageRecognition, "") (check, text) = runRecognition.recognize(image) + text = text[0][1] if check and text == expected: print "Test passed." return True @@ -105,9 +106,9 @@ # @pre A source, an imageRecognition and some parameters # @post The image gets scanned by the source and recognized by the method specified in imageRecognition. # The result is checked with what we expected. - def TestRunRecognition(self, source, parameters, imageRecognition): + def TestRunRecognition(self, source, parameters, imageRecognition, recognitionParameters): print "Test image recognition from %s for %s ..." % (source.getName(),imageRecognition.getName()) - runRecognition = Recognition.RunRecognition(source, parameters, imageRecognition) + runRecognition = Recognition.RunRecognition(source, parameters, imageRecognition, recognitionParameters) (check, msg) = runRecognition() if check: print "Test passed." @@ -130,16 +131,6 @@ if not tests.Scanners(): exit() - # test reading and storing of scanner properties - srcs = Source.Sources() - srcs.searchScanner() - source = srcs.getSources()[0] - errors += not tests.SourceProperties(source) - - # test adding another source to the source-list - fileSource = Source.File("./TestImage.jpg","TestImage","file") - errors += not tests.AddSource(fileSource, "TestImage", "./TestImage.jpg") - # test image recognition without using source esr = Recognition.ESR() image = Image.open("./TestImage.jpg") @@ -150,14 +141,14 @@ # test image recognition with ESR from file source esr = Recognition.ESR() stdScannerData = Source.StdScannerData() - errors += not tests.TestRunRecognition(fileSource, "", esr) + fileSource = Source.File() + errors += not tests.TestRunRecognition(fileSource, ["./TestImage.jpg"], esr, "") # test image recognition with ESR form scanner source # esr = Recognition.ESR() -# esr.setRotate([180]) # stdScannerData = Source.StdScannerData() # scannerData = stdScannerData.getStdScannerData("180 deg") -# errors += not tests.TestRunRecognition(source, scannerData, esr) +# errors += not tests.TestRunRecognition(source, scannerData, esr, "") print "All test done." print "Errors: %s" % errors Added: branches/redesign/gtkGUI/Chooser.py =================================================================== --- branches/redesign/gtkGUI/Chooser.py (rev 0) +++ branches/redesign/gtkGUI/Chooser.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,82 @@ +import inspect +import gtk +import PropertyWidgets + +class Chooser(gtk.VBox): + def __init__(self, members, ignore): + #Initialize the VBox + gtk.VBox.__init__(self,False,0) + self.combobox = gtk.ComboBox() + self.add(self.combobox) + self.selection = None + self.members = members + self.ignore = ignore + self.list = {} + + self.selectionWidgets = [] + self.propertyVBox = gtk.VBox() + self.add(self.propertyVBox) + + self.propertyWidgets = {} + for name, obj in inspect.getmembers(PropertyWidgets): + self.propertyWidgets[name] = obj + + + # init ComboBox + self.initComboBox() + + # get list of available classes + self.getList() + + def initComboBox(self): + self.liststore = gtk.ListStore(str) + self.cell = gtk.CellRendererText() + self.combobox.set_model(self.liststore) + self.combobox.pack_start(self.cell, True) + self.combobox.add_attribute(self.cell, 'text', 0) + self.combobox.connect("changed", self.getActive) + + + def getSelection(self): + return self.selection + + def getProperties(self): + properties = [] + for widget in self.selectionWidgets: + properties.append(widget.getSelection()) + return properties + + def getList(self): + self.list = {} + self.liststore.clear() + for name, obj in inspect.getmembers(self.members): + if name[0] != '_' and not name in self.ignore: + self.list[name] = obj + + keys = self.list.keys() + keys.sort() + for key in keys: + self.liststore.append([key]) + self.combobox.set_active(0) + return self.list + + def getActive(self, widget = None): + text = self.combobox.get_active_text() + self.selection = self.list[text] + self.selection = self.selection() + + for widget in self.selectionWidgets: + self.propertyVBox.remove(widget) + + self.selectionWidgets = [] + widgets = self.selection.activated() + if widgets: + for options in widgets: + if options[0] in self.propertyWidgets.keys(): + widget = self.propertyWidgets[options[0]] + widget = widget(options[1]) + self.selectionWidgets.append(widget) + self.propertyVBox.add(widget) + widget.show_all() + return self.selection + \ No newline at end of file Added: branches/redesign/gtkGUI/ImagePreview.glade =================================================================== (Binary files differ) Index: branches/redesign/gtkGUI/ImagePreview.glade =================================================================== --- branches/redesign/gtkGUI/ImagePreview.glade 2014-08-28 14:37:06 UTC (rev 69) +++ branches/redesign/gtkGUI/ImagePreview.glade 2014-08-28 14:57:01 UTC (rev 70) Property changes on: branches/redesign/gtkGUI/ImagePreview.glade ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/xml \ No newline at end of property Added: branches/redesign/gtkGUI/PropertyWidgets/Coordinates.py =================================================================== --- branches/redesign/gtkGUI/PropertyWidgets/Coordinates.py (rev 0) +++ branches/redesign/gtkGUI/PropertyWidgets/Coordinates.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,94 @@ +from PropertyWidgetBase import PropertyWidgetBase +from Source.Scanner import ScannerData +from Source.Scanner import StdScannerData +import gtk + +class Coordinates(PropertyWidgetBase): + def __init__(self, options): + super(Coordinates,self).__init__(options) + self.stdScannerData = StdScannerData() + + self.profile = gtk.HBox() + self.position = gtk.HBox() + self.size = gtk.HBox() + self.rotation = gtk.HBox() + + self.add(self.profile) + self.add(self.position) + self.add(self.size) + self.add(self.rotation) + + self.initPosition() + self.initSize() + self.initRotation() + self.initprofile() + + self.setProfile("default") + + def initprofile(self): + label = gtk.Label("Profiles") + self.profileCombobox = gtk.ComboBox() + self.liststore = gtk.ListStore(str) + self.cell = gtk.CellRendererText() + self.profileCombobox.set_model(self.liststore) + self.profileCombobox.pack_start(self.cell, True) + self.profileCombobox.add_attribute(self.cell, 'text', 0) + self.liststore.clear() + for data in self.stdScannerData.getStdScannerDatas(): + self.liststore.append([data.getName()]) + self.profileCombobox.set_active(0) + self.profileCombobox.connect("changed",self.on_profile_changed) + + self.profile.add(label) + self.profile.add(self.profileCombobox) + + def on_profile_changed(self, widget = None): + profile = self.profileCombobox.get_active_text() + self.setProfile(profile) + + def initPosition(self): + label = gtk.Label("Position") + self.position_x = gtk.SpinButton(None,1,0) + self.position_x.get_adjustment().set_all(0,0,1000,1,10,0) + self.position_y = gtk.SpinButton(None,1,0) + self.position_y.get_adjustment().set_all(0,0,1000,1,10,0) + + self.position.add(label) + self.position.add(self.position_x) + self.position.add(self.position_y) + + def initSize(self): + label = gtk.Label("Size") + self.size_x = gtk.SpinButton(None,1,0) + self.size_x.get_adjustment().set_all(0,0,1000,1,10,0) + self.size_y = gtk.SpinButton(None,1,0) + self.size_y.get_adjustment().set_all(0,0,1000,1,10,0) + + self.size.add(label) + self.size.add(self.size_x) + self.size.add(self.size_y) + + def initRotation(self): + label = gtk.Label("Rotation") + self.rotate = gtk.SpinButton(None,1,0) + self.rotate.get_adjustment().set_all(0,0,360,10,90,0) + + self.rotation.add(label) + self.rotation.add(self.rotate) + + def setProfile(self, profile): + self.scannerData = self.stdScannerData.getStdScannerData(profile) + (position_x, position_y) = self.scannerData.getPosition() + (size_x, size_y) = self.scannerData.getSize() + self.position_x.set_value(position_x) + self.position_y.set_value(position_y) + self.size_x.set_value(size_x) + self.size_y.set_value(size_y) + self.rotate.set_value(self.scannerData.getRotation()) + + def getSelection(self): + selection = ScannerData("custom") + selection.setPosition(self.position_x.get_value_as_int(), self.position_y.get_value_as_int()) + selection.setSize(self.size_x.get_value_as_int(), self.size_y.get_value_as_int()) + selection.setRotation(self.rotate.get_value_as_int()) + return selection \ No newline at end of file Added: branches/redesign/gtkGUI/PropertyWidgets/Filechooser.py =================================================================== --- branches/redesign/gtkGUI/PropertyWidgets/Filechooser.py (rev 0) +++ branches/redesign/gtkGUI/PropertyWidgets/Filechooser.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,13 @@ +from PropertyWidgetBase import PropertyWidgetBase +import gtk + +class Filechooser(PropertyWidgetBase): + def __init__(self, options): + super(Filechooser,self).__init__(options) + self.widget = gtk.FileChooserButton("File") + self.widget.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) + #self.widget = gtk.Label("test") + self.add(self.widget) + + def getSelection(self): + return self.widget.get_filename() \ No newline at end of file Added: branches/redesign/gtkGUI/PropertyWidgets/ListChooser.py =================================================================== --- branches/redesign/gtkGUI/PropertyWidgets/ListChooser.py (rev 0) +++ branches/redesign/gtkGUI/PropertyWidgets/ListChooser.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,30 @@ +from PropertyWidgetBase import PropertyWidgetBase +import gtk + +class ListChooser(PropertyWidgetBase): + def __init__(self, options): + super(ListChooser,self).__init__(options) + self.combobox = gtk.ComboBox() + self.add(self.combobox) + + self.initComboBox() + self.getList() + + def initComboBox(self): + self.liststore = gtk.ListStore(str) + self.cell = gtk.CellRendererText() + self.combobox.set_model(self.liststore) + self.combobox.pack_start(self.cell, True) + self.combobox.add_attribute(self.cell, 'text', 0) + + + def getList(self): + self.liststore.clear() + for option in self.options: + self.liststore.append([option]) + self.combobox.set_active(0) + return + + def getSelection(self): + selection = self.combobox.get_active_text() + return selection \ No newline at end of file Added: branches/redesign/gtkGUI/PropertyWidgets/PropertyWidgetBase.py =================================================================== --- branches/redesign/gtkGUI/PropertyWidgets/PropertyWidgetBase.py (rev 0) +++ branches/redesign/gtkGUI/PropertyWidgets/PropertyWidgetBase.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,10 @@ +import gtk + +class PropertyWidgetBase(gtk.VBox): + def __init__(self, options): + #Initialize the VBox + gtk.VBox.__init__(self,False,0) + self.options = options + + def getSelection(self): + pass \ No newline at end of file Added: branches/redesign/gtkGUI/PropertyWidgets/__init__.py =================================================================== --- branches/redesign/gtkGUI/PropertyWidgets/__init__.py (rev 0) +++ branches/redesign/gtkGUI/PropertyWidgets/__init__.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,3 @@ +from Filechooser import Filechooser +from Coordinates import Coordinates +from ListChooser import ListChooser \ No newline at end of file Added: branches/redesign/gtkGUI/test.py =================================================================== --- branches/redesign/gtkGUI/test.py (rev 0) +++ branches/redesign/gtkGUI/test.py 2014-08-28 14:57:01 UTC (rev 70) @@ -0,0 +1,81 @@ +import gtk, sys + +class ComboButton(gtk.HBox): + + def __init__(self,menuitems): + gtk.HBox.__init__(self,False,0) + """ + if( !(isinstance(menuitems,types.TupleType) or + isinstance(menuitems,type.ListType))): + raise(ComboButtonException()) + """ + self.set_border_width(2) + self.entry = gtk.Entry() + menu = gtk.Menu() + for i in menuitems: + item = gtk.MenuItem(i) + item.show() + menu.append(item) + item.connect( "activate",self.menu_response,i) + + button = gtk.Button() + arrow = gtk.Arrow(gtk.ARROW_DOWN,gtk.SHADOW_IN) + button.add(arrow) + self.progressbar = gtk.ProgressBar() + self.pack_start(button,False,False,0) + self.pack_end(self.entry,True,True,0) + self.pack_end(self.progressbar,True,True,0) + + button.connect("event",self.button_popup,menu) + + + self.show_all() + + def button_popup(self,widget,event,menu): + if event.type == gtk.gdk.BUTTON_PRESS: + menu.popup(None,None,None,event.button,event.time) + return True + return False + + def menu_response(self,widget,str): + print "%s was clicked" % str + buffer = self.entry.get_text() + self.entry.set_text(buffer + str ) + + + def entry_call(self,widget,event): + print "event is of %s type" % event.type + + def set_active(self,number): + pass + + def get_text(self): + return self.entry.get_text() + + def set_text(self,text): + self.entry.set_text(text) + +def main(args): + win = gtk.Window() + win.set_border_width(5) + win.set_title('Widget test') + win.connect('delete-event', gtk.main_quit) + + frame = gtk.Frame("Example frame") + win.add(frame) + + w = ComboButton(["a","b"]) + frame.add(w) + + win.show_all() + + gtk.main() + + + +# main routin +if __name__ == '__main__': + errors = 0 + + # init tests + sys.exit(main(sys.argv)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-28 14:37:11
|
Revision: 69 http://sourceforge.net/p/pycodeocr/code/69 Author: laserb Date: 2014-08-28 14:37:06 +0000 (Thu, 28 Aug 2014) Log Message: ----------- Add possibility to have more than one output. Modified Paths: -------------- branches/redesign/Recognition/ESR.py branches/redesign/Recognition/ImageRecognition.py branches/redesign/gtkGUI/ImagePreview.py Modified: branches/redesign/Recognition/ESR.py =================================================================== --- branches/redesign/Recognition/ESR.py 2014-08-27 06:55:49 UTC (rev 68) +++ branches/redesign/Recognition/ESR.py 2014-08-28 14:37:06 UTC (rev 69) @@ -33,25 +33,22 @@ ## @overwrite verification def doVerification(self): - # correct for common char recognition errors - self.recognitionData.setContent(self.char_correction(self.recognitionData.getContent())) - # get data data = self.recognitionData.getContent() + code = data[0][1] + # correct for common char recognition errors + code = self.char_correction(code) + + # check for invalid characters - check = (not "?" in data) or (not "!" in data) # any unrecognized char in code? - check = check and ( len(data) in self.valid_code_len ) # correct code len? + check = (not "?" in code) or (not "!" in code) # any unrecognized char in code? + check = check and ( len(code) in self.valid_code_len ) # correct code len? if not check: return (False, "Invalid length or invalid characters") - # extract amount, reference and account from codeline - tmp = data[:-1].split(">") - amount = tmp[0] - tmp = tmp[1].split("+ ") - reference = tmp[0] - account = tmp[1] - + (amount, reference, account) = self.split(code) + # do checksum for amount, reference and account if not self.checksum(amount): return (False, "Checksum for amount failed.") @@ -60,9 +57,27 @@ if not self.checksum(account): return (False, "Checksum for account failed.") + # save data in split form + account = account[0:2]+"-"+account[2:-1]+"-"+account[-1] + amount = str(float(amount[2:-1])/100) + self.setContent(code, account, amount, reference) + # return true if all checks are positive return (True, "") + def split(self, data): + try: + # extract amount, reference and account from codeline + tmp = data[:-1].split(">") + amount = tmp[0] + tmp = tmp[1].split("+ ") + reference = tmp[0] + account = tmp[1] + return (amount, reference, account) + except: + return ("","","") + + # thanks to http://www.hosang.ch/modulo10.aspx # much more details http://www.sic.ch/de/dl_tkicch_dta.pdf ( page 51 ) # @see http://www.bundesbank.de/download/zahlungsverkehr/zv_pz201012.pdf @@ -112,8 +127,10 @@ os.remove(self.temp_name + "tesseract.txt") # clean-up os.remove(self.temp_name + ".png") # clean-up + # set content - self.recognitionData.setContent(data) + (amount, reference, account) = self.split(data) + self.setContent(data, account, amount, reference) # check if data is valid (check, msg) = self.verify() @@ -123,6 +140,11 @@ # return the data return self.recognitionData.getContent() + def setContent(self, all, account, amount, reference): + data = [["All",all],["Account",account],["Amount",amount],["Reference",reference]] + self.recognitionData.setContent(data) + + ## Character correction after recogition (on basis that there should be numbers and few special chars). # # @test Add unittest to check correct operation of this important module/function. Modified: branches/redesign/Recognition/ImageRecognition.py =================================================================== --- branches/redesign/Recognition/ImageRecognition.py 2014-08-27 06:55:49 UTC (rev 68) +++ branches/redesign/Recognition/ImageRecognition.py 2014-08-28 14:37:06 UTC (rev 69) @@ -95,7 +95,7 @@ def __init__(self, image): self.image = image self.temp_name = "image_object_temp_file" - self.content = "" + self.content = [] self.valid = None ## get image @@ -135,6 +135,15 @@ def getContent(self): return self.content + def getContentString(self): + if isinstance(self.content, list): + content = "" + for i in len(self.content): + content += " "+str(self.content[i][1]) + return content + return self.content + + def setValid(self, valid): self.valid = valid @@ -144,11 +153,18 @@ ## save content to clipboard # @pre information set # @post information saved in clipboard - def saveClipboard(self): - # set the clipboard text data - pyperclip.setcb(self.content) - # make our data available to other applications - pyperclip.getcb() + def saveClipboard(self): + if isinstance(self.content, list): + for content in self.content: + # set the clipboard text data + pyperclip.setcb(content[1]) + # make our data available to other applications + pyperclip.getcb() + else: + # set the clipboard text data + pyperclip.setcb(self.content) + # make our data available to other applications + pyperclip.getcb() ## Run the recognition and verify the information class RunRecognition(gobject.GObject): @@ -183,7 +199,7 @@ # if data is valid, save to clipboard and return data self.emit("recognized") if check: - self.emit("updateRecognition","Data is valid. Save to clipboard.") + self.emit("updateRecognition","Data is valid. Click to save to clipboard.") self.imageRecognition.getRecognitionData().saveClipboard() return (True, self.imageRecognition.getRecognitionData().getContent()) Modified: branches/redesign/gtkGUI/ImagePreview.py =================================================================== --- branches/redesign/gtkGUI/ImagePreview.py 2014-08-27 06:55:49 UTC (rev 68) +++ branches/redesign/gtkGUI/ImagePreview.py 2014-08-28 14:37:06 UTC (rev 69) @@ -1,4 +1,4 @@ -import gtk, os +import gtk, os, pyperclip, pango import StringIO # PIL/Pillow image library and it's SANE bindings @@ -9,8 +9,10 @@ def __init__(self): #Initialize the VBox gtk.VBox.__init__(self,False,0) - self.res_color = { True: gtk.gdk.color_parse("#00FF00"), - False: gtk.gdk.color_parse("#FF0000"), + self.recognitionData = None + + self.res_color = { True: gtk.gdk.color_parse("#006600"), + False: gtk.gdk.color_parse("#660000"), None: gtk.gdk.color_parse("#FFFFFF"), } # # retrieve widgets @@ -38,12 +40,12 @@ self.img_popup = self.builder.get_object('img_popup') ## output line - self.output = self.builder.get_object('output') + self.output = Output() # connect eventbox to close image window (self.new_width, self.new_height ) = (0,0) self.main_image.set_tooltip_text("Click for original image") - #self.main_image.connect('expose-event', self.on_image_resize, "") # high cpu usage + #self.main_image.connect('motion-notify-event', self.on_image_resize, "") # high cpu usage self.popup_image.set_tooltip_text("Click to close") self.pack_start(self.scanned_code_label,False,False,0) @@ -113,11 +115,13 @@ self.setOutputHelper() def setOutputHelper(self): - self.output.set_text(self.recognitionData.getContent()) + content = self.recognitionData.getContent() mode = self.recognitionData.isValid() - - # widget color - self.output.modify_base(gtk.STATE_NORMAL, self.res_color[mode]) + if isinstance(content, list): + for text in content: + self.output.addText(text, self.res_color[mode]) + else: + self.output.addText(content, self.res_color[mode]) def setRecognitionData(self, recognitionData): self.recognitionData = recognitionData @@ -138,6 +142,8 @@ def on_image_resize(self, widget, event, window): allocation = widget.get_allocation() + if not self.recognitionData: + return image = self.recognitionData.getImage() pixbuf = self.image_to_pixbuf(image) image = gtk.Image() @@ -164,4 +170,39 @@ # set new pixbuf widget.set_from_pixbuf(pixbuf) + +class Output(gtk.HBox): + def __init__(self): + #Initialize the VBox + gtk.HBox.__init__(self,False,0) + self.button = {} + + def addText(self, text, color): + labelText = text[0] + "\n" + text[1] + button = gtk.Button(labelText) + label = button.get_child() + label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) + label.modify_fg(gtk.STATE_NORMAL, color) + button.connect("clicked",self.copyClipboard) + self.button[text[0]] = [button, text] + self.add(button) + self.show_all() + + def removeText(self, text): + self.remove(self.button[text]) + + def removeAll(self): + for button in self.button: + self.remove(button[0]) + + def copyClipboard(self, widget): + label = widget.get_label() + label = label.split("\n")[0] + text = self.button[label][1][1] + # set the clipboard text data + pyperclip.setcb(text) + # make our data available to other applications + pyperclip.getcb() + + \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-27 06:55:59
|
Revision: 68 http://sourceforge.net/p/pycodeocr/code/68 Author: laserb Date: 2014-08-27 06:55:49 +0000 (Wed, 27 Aug 2014) Log Message: ----------- Add options for source and recognition. Modified Paths: -------------- branches/redesign/PyCodeOCR.py branches/redesign/Recognition/ESR.py branches/redesign/Recognition/ImageRecognition.py branches/redesign/Recognition/__init__.py branches/redesign/Source/File.py branches/redesign/Source/Scanner.py branches/redesign/Source/SourceBase.py branches/redesign/gtkGUI/ImagePreview.py Modified: branches/redesign/PyCodeOCR.py =================================================================== --- branches/redesign/PyCodeOCR.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/PyCodeOCR.py 2014-08-27 06:55:49 UTC (rev 68) @@ -107,17 +107,15 @@ def on_button_pressed(self, event): # get image recognition and initialize self.imageRecognition = self.recognitionChooser.getSelection() - option = self.recognitionChooser.getOption() - self.imageRecognition.setRotate([180]) + recognitionProperties = self.recognitionChooser.getProperties() # get source and initialize self.source = self.sourceChooser.getSelection() - self.source.setAddress(self.source.scanners[0][0]) - stdScannerData = Source.StdScannerData() - scannerData = stdScannerData.getStdScannerData("180 deg") + sourceProperties = self.sourceChooser.getProperties() # run recognition - runRecognition = Recognition.RunRecognition(self.source, scannerData, self.imageRecognition) + self.progressbar.resetProgress("") + runRecognition = Recognition.RunRecognition(self.source, sourceProperties, self.imageRecognition, recognitionProperties) runRecognition.connect("updateRecognition", self.onProgressUpdate) runRecognition.connect("recognized", self.on_recognized) t = threading.Thread(target=runRecognition) Modified: branches/redesign/Recognition/ESR.py =================================================================== --- branches/redesign/Recognition/ESR.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/Recognition/ESR.py 2014-08-27 06:55:49 UTC (rev 68) @@ -87,12 +87,9 @@ return str(uebertrag) == number[-1] # @overwrite recognizeImage - def recognizeImage(self, image, rotate = None): - super(ESR,self).recognizeImage(image) - - # if no rotation is set, use default: [0, 90, 90, 90] - if rotate == None: - rotate = self.rotate + def recognizeImage(self, image, recognitionProperties): + rotate = self.rotate + super(ESR,self).recognizeImage(image, recognitionProperties) # try all rotation and test if data is valid for angle in rotate: @@ -126,9 +123,6 @@ # return the data return self.recognitionData.getContent() - def activated(self): - return ["0 deg", "90 deg", "180 deg", "270 deg"] - ## Character correction after recogition (on basis that there should be numbers and few special chars). # # @test Add unittest to check correct operation of this important module/function. Modified: branches/redesign/Recognition/ImageRecognition.py =================================================================== --- branches/redesign/Recognition/ImageRecognition.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/Recognition/ImageRecognition.py 2014-08-27 06:55:49 UTC (rev 68) @@ -33,7 +33,7 @@ self.depth = 8 self.rotate = [0,90,90,90] self.recognitionData = None - + ## Verify if data is valid. # @pre image acquired and recognized # @post information extracted @@ -42,7 +42,7 @@ def verify(self): (check, msg) = self.doVerification() self.recognitionData.setValid(check) - return (True, msg) + return (check, msg) ## get image and associated data # @pre image recognized @@ -55,13 +55,13 @@ # @param image # @post information is extracted # @return extracted information - def recognizeImage(self,image): + def recognizeImage(self,image, recognitionProperties): recognitionData = RecognitionData(image) self.recognitionData = recognitionData return self.recognitionData.getContent() def activated(self): - print "is activated" + return [] ## get name # @return name @@ -153,10 +153,11 @@ ## Run the recognition and verify the information class RunRecognition(gobject.GObject): ## init - def __init__(self, source, data, imageRecognition): + def __init__(self, source, sourceProperties, imageRecognition, recognitionProperties): self.__gobject_init__() self.source = source - self.data = data + self.sourceProperties = sourceProperties + self.recognitionProperties = recognitionProperties self.imageRecognition = imageRecognition ## call @@ -164,7 +165,7 @@ # data if the acquired data is image, error-message otherwise def __call__(self): self.emit("updateRecognition","Get Image ...") - image = self.source.getImage(self.data) + image = self.source.getImage(self.sourceProperties) return self.recognize(image) ## recognize image @@ -173,7 +174,7 @@ def recognize(self, image): # do recognition self.emit("updateRecognition","Recognize image ...") - self.imageRecognition.recognizeImage(image) + self.imageRecognition.recognizeImage(image, self.recognitionProperties) # verify data self.emit("updateRecognition","Verify data ...") @@ -187,7 +188,7 @@ return (True, self.imageRecognition.getRecognitionData().getContent()) # if data is invalid return error message - self.emit("updateRecognition","Data is not valid.") + self.emit("updateRecognition","Data is not valid. "+msg) return (False, msg) gobject.type_register(RunRecognition) Modified: branches/redesign/Recognition/__init__.py =================================================================== --- branches/redesign/Recognition/__init__.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/Recognition/__init__.py 2014-08-27 06:55:49 UTC (rev 68) @@ -1,5 +1,3 @@ -from Recognition.ImageRecognition import ImageRecognitionBase -from Recognition.ImageRecognition import RecognitionData from Recognition.ImageRecognition import RunRecognition from Recognition.Barcode import Barcode from Recognition.DataMatrix import DataMatrix Modified: branches/redesign/Source/File.py =================================================================== --- branches/redesign/Source/File.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/Source/File.py 2014-08-27 06:55:49 UTC (rev 68) @@ -28,5 +28,9 @@ ## get a new image from file # @return image - def getImage(self,data = None): + def getImage(self, data): + self.address = data[0] return Image.open(self.address) + + def activated(self): + return [["Filechooser",[]]] Modified: branches/redesign/Source/Scanner.py =================================================================== --- branches/redesign/Source/Scanner.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/Source/Scanner.py 2014-08-27 06:55:49 UTC (rev 68) @@ -50,18 +50,22 @@ def searchScanner(self): sane.init() self.scanners = sane.get_devices() + + def getScanner(self,name): + for scanner in self.scanners: + if scanner[1] == name: + return scanner[0] + return None ## get a new image from a sane device # @param size and position of the image # @return image - def getImage(self,scannerData = None): - # if no data is given use predefined default. - if not scannerData: - stdScannerData = StdScannerData() - scannerData = stdScannerData.getStdScannerData("default") + def getImage(self, properties): + name = properties[0] + scannerData = properties[1] # open scanner - self.scanner=sane.open(self.address) + self.scanner=sane.open(self.getScanner(name)) # get an image, return an error if it failed try: @@ -95,11 +99,12 @@ return sys.exc_info()[1] + def activated(self): scanner_names = [] for scanner in self.scanners: scanner_names.append(scanner[1]) - return scanner_names + return [["ListChooser",scanner_names],["Coordinates",["Bottom", "Left", "Top", "Right"]]] ## @@ -120,6 +125,7 @@ self.size = [100,100] self.color = 'gray' self.resolution = 600 + self.rotation = 0 ## get name # @return name @@ -169,6 +175,12 @@ # @return resolution def getResolution(self): return self.resolution + + def setRotation(self, rotation): + self.rotation = rotation + + def getRotation(self): + return self.rotation ## @@ -184,7 +196,7 @@ # init def __init__(self): ## default scanning coordinates - self.stdScannerData = [ScannerData("default"),ScannerData("0 deg"),ScannerData("90 deg"),ScannerData("180 deg"),ScannerData("270 deg"),ScannerData("A4")] + self.stdScannerData = [ScannerData("default"),ScannerData("Bottom"),ScannerData("Left"),ScannerData("Top"),ScannerData("Right"),ScannerData("A4")] self.setInitialParameters() ## Generate a set of default scanning properties @@ -192,14 +204,17 @@ def setInitialParameters(self): self.getStdScannerData("default").setPosition(60,82) self.getStdScannerData("default").setSize(155,20) - self.getStdScannerData("0 deg").setPosition(60,82) - self.getStdScannerData("0 deg").setSize(155,20) - self.getStdScannerData("90 deg").setPosition(82,1) - self.getStdScannerData("90 deg").setSize(20,150) - self.getStdScannerData("180 deg").setPosition(1,3) - self.getStdScannerData("180 deg").setSize(150,20) - self.getStdScannerData("270 deg").setPosition(3,60) - self.getStdScannerData("270 deg").setSize(20,150) + self.getStdScannerData("Bottom").setPosition(60,82) + self.getStdScannerData("Bottom").setSize(155,20) + self.getStdScannerData("Left").setPosition(82,1) + self.getStdScannerData("Left").setSize(20,150) + self.getStdScannerData("Left").setRotation(90) + self.getStdScannerData("Top").setPosition(1,3) + self.getStdScannerData("Top").setSize(150,20) + self.getStdScannerData("Top").setRotation(180) + self.getStdScannerData("Right").setPosition(3,60) + self.getStdScannerData("Right").setSize(20,150) + self.getStdScannerData("Right").setRotation(270) # scan whole range (A4: http://www.cl.cam.ac.uk/~mgk25/iso-paper.html) self.getStdScannerData("A4").setPosition(0,0) self.getStdScannerData("A4").setSize(215,296) Modified: branches/redesign/Source/SourceBase.py =================================================================== --- branches/redesign/Source/SourceBase.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/Source/SourceBase.py 2014-08-27 06:55:49 UTC (rev 68) @@ -36,7 +36,7 @@ return image def activated(self): - print "is activated" + return [] ## return name of source # @return name Modified: branches/redesign/gtkGUI/ImagePreview.py =================================================================== --- branches/redesign/gtkGUI/ImagePreview.py 2014-08-26 18:12:03 UTC (rev 67) +++ branches/redesign/gtkGUI/ImagePreview.py 2014-08-27 06:55:49 UTC (rev 68) @@ -86,6 +86,24 @@ pixbuf = self.image_to_pixbuf(image) image = gtk.Image() image.set_from_pixbuf(pixbuf) + + width = pixbuf.get_width() + height = pixbuf.get_height() + + target_width = 300 + target_height = 50 + + # get current width and height + width, height = pixbuf.get_width(), pixbuf.get_height() + + # get scale for width and height + scale_width, scale_height = float(target_width)/width, float(target_height)/height + + # target scale is minimum scale for width and height + scale = min(scale_width,scale_height) + + # scale pixbuf + pixbuf = pixbuf.scale_simple(int(width*scale), int(height*scale), gtk.gdk.INTERP_BILINEAR) self.main_image.set_from_pixbuf( pixbuf ) self.on_image_resize(self.main_image, "", "") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-26 18:12:07
|
Revision: 67 http://sourceforge.net/p/pycodeocr/code/67 Author: laserb Date: 2014-08-26 18:12:03 +0000 (Tue, 26 Aug 2014) Log Message: ----------- Add source and recognition selection. Modified Paths: -------------- branches/redesign/PyCodeOCR.py branches/redesign/Recognition/Barcode.py branches/redesign/Recognition/DTMX.py branches/redesign/Recognition/DataMatrix.py branches/redesign/Recognition/ESR.py branches/redesign/Recognition/ImageRecognition.py branches/redesign/Recognition/PDF417.py branches/redesign/Source/File.py branches/redesign/Source/Scanner.py branches/redesign/Source/SourceBase.py branches/redesign/Source/__init__.py branches/redesign/gtkGUI/__init__.py Modified: branches/redesign/PyCodeOCR.py =================================================================== --- branches/redesign/PyCodeOCR.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/PyCodeOCR.py 2014-08-26 18:12:03 UTC (rev 67) @@ -52,10 +52,6 @@ class PyCodeOCR(object): def __init__(self): - srcs = Source.Sources() - srcs.searchScanner() - self.source = srcs.getSources()[0] - self.win = gtk.Window() self.win.set_border_width(5) self.win.set_title('PyCodeOCR') @@ -76,6 +72,20 @@ vboxProperties = gtk.VBox() hbox.add(vboxProperties) + sourceFrame = gtk.Frame("Source") + sourceVBox = gtk.VBox() + sourceFrame.add(sourceVBox) + self.sourceChooser = gtkGUI.Chooser(Source, ["SourceBase","ScannerData","StdScannerData"]) + sourceVBox.pack_start(self.sourceChooser,False,False,0) + vboxProperties.pack_start(sourceFrame, True,True,0) + + recognitionFrame = gtk.Frame("Recognition") + recognitionVBox = gtk.VBox() + recognitionFrame.add(recognitionVBox) + self.recognitionChooser = gtkGUI.Chooser(Recognition, ["ImageRecognition","ImageRecognitionBase","RecognitionData","RunRecognition"]) + recognitionVBox.pack_start(self.recognitionChooser,False,False,0) + vboxProperties.pack_start(recognitionFrame, True,True,0) + button = gtk.Button("Scan") button.connect("pressed",self.on_button_pressed) vboxProperties.pack_end(button, False, False, 0) @@ -95,21 +105,25 @@ def on_button_pressed(self, event): - self.imageRecognition = Recognition.ESR() + # get image recognition and initialize + self.imageRecognition = self.recognitionChooser.getSelection() + option = self.recognitionChooser.getOption() self.imageRecognition.setRotate([180]) + # get source and initialize + self.source = self.sourceChooser.getSelection() + self.source.setAddress(self.source.scanners[0][0]) stdScannerData = Source.StdScannerData() scannerData = stdScannerData.getStdScannerData("180 deg") + # run recognition runRecognition = Recognition.RunRecognition(self.source, scannerData, self.imageRecognition) runRecognition.connect("updateRecognition", self.onProgressUpdate) runRecognition.connect("recognized", self.on_recognized) t = threading.Thread(target=runRecognition) t.start() - #gtk.threads_enter() - #self.imagePreview.setRecognitionData(esr.getRecognitionData()) - #gtk.threads_leave() + def on_recognized(self, runRecognition): self.imagePreview.setRecognitionData(self.imageRecognition.getRecognitionData()) Modified: branches/redesign/Recognition/Barcode.py =================================================================== --- branches/redesign/Recognition/Barcode.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Recognition/Barcode.py 2014-08-26 18:12:03 UTC (rev 67) @@ -2,7 +2,7 @@ class Barcode(ImageRecognition.ImageRecognitionBase): def __init__(self): - super(Barcode,self).__init("Barcode") + super(Barcode,self).__init__("Barcode") def verify(self): data = self.content.getContent() Modified: branches/redesign/Recognition/DTMX.py =================================================================== --- branches/redesign/Recognition/DTMX.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Recognition/DTMX.py 2014-08-26 18:12:03 UTC (rev 67) @@ -2,7 +2,7 @@ class DTMX(ImageRecognition.ImageRecognitionBase): def __init__(self): - super(DTMX,self).__init("DTMX") + super(DTMX,self).__init__("DTMX") def verify(self): pass Modified: branches/redesign/Recognition/DataMatrix.py =================================================================== --- branches/redesign/Recognition/DataMatrix.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Recognition/DataMatrix.py 2014-08-26 18:12:03 UTC (rev 67) @@ -2,7 +2,7 @@ class DataMatrix(ImageRecognition.ImageRecognitionBase): def __init__(self): - super(DataMatrix,self).__init("DataMatrix") + super(DataMatrix,self).__init__("DataMatrix") def verify(self): return True Modified: branches/redesign/Recognition/ESR.py =================================================================== --- branches/redesign/Recognition/ESR.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Recognition/ESR.py 2014-08-26 18:12:03 UTC (rev 67) @@ -21,7 +21,7 @@ from Recognition import ImageRecognition import utils -import re, os +import re, os, gtk ## Extract information from ESR class ESR(ImageRecognition.ImageRecognitionBase): @@ -126,6 +126,9 @@ # return the data return self.recognitionData.getContent() + def activated(self): + return ["0 deg", "90 deg", "180 deg", "270 deg"] + ## Character correction after recogition (on basis that there should be numbers and few special chars). # # @test Add unittest to check correct operation of this important module/function. Modified: branches/redesign/Recognition/ImageRecognition.py =================================================================== --- branches/redesign/Recognition/ImageRecognition.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Recognition/ImageRecognition.py 2014-08-26 18:12:03 UTC (rev 67) @@ -60,6 +60,9 @@ self.recognitionData = recognitionData return self.recognitionData.getContent() + def activated(self): + print "is activated" + ## get name # @return name def getName(self): Modified: branches/redesign/Recognition/PDF417.py =================================================================== --- branches/redesign/Recognition/PDF417.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Recognition/PDF417.py 2014-08-26 18:12:03 UTC (rev 67) @@ -2,7 +2,7 @@ class PDF417(ImageRecognition.ImageRecognitionBase): def __init__(self): - super(PDF417,self).__init("PDF417") + super(PDF417,self).__init__("PDF417") def verify(self): return (True, "") Modified: branches/redesign/Source/File.py =================================================================== --- branches/redesign/Source/File.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Source/File.py 2014-08-26 18:12:03 UTC (rev 67) @@ -23,8 +23,8 @@ from PIL import Image class File(SourceBase): - def __init__(self,address, name, typename): - super(File,self).__init__(address, name, typename) + def __init__(self): + super(File,self).__init__() ## get a new image from file # @return image Modified: branches/redesign/Source/Scanner.py =================================================================== --- branches/redesign/Source/Scanner.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Source/Scanner.py 2014-08-26 18:12:03 UTC (rev 67) @@ -25,25 +25,32 @@ class Scanner(SourceBase): ## init - def __init__(self, dev): - super(Scanner,self).__init__(dev[0],dev[1],dev[3]) - - # open scanner - self.scanner=sane.open(self.address) - - # get parameters from scanner - parameters = self.scanner.get_parameters() - for i in range(len(parameters)): - self.addParameter(str(i), parameters[i]) + def __init__(self): + super(Scanner,self).__init__() + self.scanners = [] + self.searchScanner() +# +# # open scanner +# self.scanner = sane.open(self.address) +# +# # get parameters from scanner +# parameters = self.scanner.get_parameters() +# for i in range(len(parameters)): +# self.addParameter(str(i), parameters[i]) +# +# # get options from options +# options = self.scanner.get_options() +# for option in options: +# self.addOption(option[1], option) +# +# # close scanner +# self.scanner.close() + + + def searchScanner(self): + sane.init() + self.scanners = sane.get_devices() - # get options from options - options = self.scanner.get_options() - for option in options: - self.addOption(option[1], option) - - # close scanner - self.scanner.close() - ## get a new image from a sane device # @param size and position of the image # @return image @@ -87,6 +94,12 @@ self.scanner.close() return sys.exc_info()[1] + + def activated(self): + scanner_names = [] + for scanner in self.scanners: + scanner_names.append(scanner[1]) + return scanner_names ## Modified: branches/redesign/Source/SourceBase.py =================================================================== --- branches/redesign/Source/SourceBase.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Source/SourceBase.py 2014-08-26 18:12:03 UTC (rev 67) @@ -21,18 +21,47 @@ class SourceBase(object): ## init - def __init__(self,address, name, typename): - self.address = address - self.name = name - self.type = typename + def __init__(self): + self.address = "" + self.name = "" + self.type = "" self.parameters = {} self.options = {} + ## get a new image + # @param additional data required to get the image + # @return image + def getImage(self,data = None): + image = "" + return image + + def activated(self): + print "is activated" + ## return name of source # @return name def getName(self): return self.name + def setName(self, name): + self.name = name + + ## return address of source + # @return address + def getAddress(self): + return self.address + + def setAddress(self, address): + self.address = address + + ## return type of source + # @return type + def getType(self): + return self.type + + def setType(self, typename): + self.type = typename + ## set parameters for source # @param parameters dictionary # @post parameters set @@ -79,16 +108,6 @@ def getOption(self, optionName): return self.options[optionName] - ## return address of source - # @return address - def getAddress(self): - return self.address - - ## return type of source - # @return type - def getType(self): - return self.type - ## test if two sources are equal # two sources are equal, if address, name and type are equal # @param another source @@ -102,13 +121,6 @@ return False return True - ## get a new image - # @param additional data required to get the image - # @return image - def getImage(self,data = None): - image = "" - return image - ## print some info to the source # def printInfo(self): Modified: branches/redesign/Source/__init__.py =================================================================== --- branches/redesign/Source/__init__.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/Source/__init__.py 2014-08-26 18:12:03 UTC (rev 67) @@ -3,4 +3,3 @@ from Source.Scanner import StdScannerData from Source.SourceBase import SourceBase from Source.File import File -from Source.Sources import Sources Modified: branches/redesign/gtkGUI/__init__.py =================================================================== --- branches/redesign/gtkGUI/__init__.py 2014-08-26 13:07:59 UTC (rev 66) +++ branches/redesign/gtkGUI/__init__.py 2014-08-26 18:12:03 UTC (rev 67) @@ -1,3 +1,4 @@ from ImagePreview import ImagePreview from ProgressBar import ProgressBar +from Chooser import Chooser import ScanProperties \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-26 13:08:10
|
Revision: 66 http://sourceforge.net/p/pycodeocr/code/66 Author: laserb Date: 2014-08-26 13:07:59 +0000 (Tue, 26 Aug 2014) Log Message: ----------- Get some basic GUI to work. Modified Paths: -------------- branches/redesign/PyCodeOCR.py branches/redesign/Recognition/ESR.py branches/redesign/Recognition/ImageRecognition.py branches/redesign/gtkGUI/ImagePreview.py branches/redesign/gtkGUI/ProgressBar.py branches/redesign/gtkGUI/__init__.py Removed Paths: ------------- branches/redesign/blacklist branches/redesign/tests/ branches/redesign/utils/checksum.py branches/redesign/utils/ocr.py Modified: branches/redesign/PyCodeOCR.py =================================================================== --- branches/redesign/PyCodeOCR.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/PyCodeOCR.py 2014-08-26 13:07:59 UTC (rev 66) @@ -43,27 +43,80 @@ # @include "./CHANGES" # +import gtk, time import Source import Recognition +import gtkGUI +import threading class PyCodeOCR(object): def __init__(self): - self.sources = Source.Sources() - self.sources.searchScanner() + + srcs = Source.Sources() + srcs.searchScanner() + self.source = srcs.getSources()[0] + + self.win = gtk.Window() + self.win.set_border_width(5) + self.win.set_title('PyCodeOCR') + self.win.connect('delete-event', gtk.main_quit) + + hbox = gtk.HBox() + self.win.add(hbox) + + vboxImage = gtk.VBox() + self.imagePreview = gtkGUI.ImagePreview() + self.progressbar = gtkGUI.ProgressBar(4) + vboxImage.pack_start(self.imagePreview,True,True,0) + vboxImage.pack_end(self.progressbar,False,False,0) + + hbox.add(vboxImage) + + vboxProperties = gtk.VBox() + hbox.add(vboxProperties) + + button = gtk.Button("Scan") + button.connect("pressed",self.on_button_pressed) + vboxProperties.pack_end(button, False, False, 0) + + self.win.show_all() + def __call__(self): - self.runRecognition() + gtk.main() + - def runRecognition(self): - source = self.sources.getSources()[0] - imageRecognition = Recognition.ESR() - imageRecognition.setRotate([180]) + ## Refresh window during running processes. + def refresh(self): + self.win.queue_draw() + time.sleep(0.1) # give also some time to the user... :) + while gtk.events_pending(): + gtk.main_iteration() + + + def on_button_pressed(self, event): + self.imageRecognition = Recognition.ESR() + self.imageRecognition.setRotate([180]) + stdScannerData = Source.StdScannerData() scannerData = stdScannerData.getStdScannerData("180 deg") - runRecognition = Recognition.RunRecognition(source, scannerData, imageRecognition) - (check, msg) = runRecognition() - print msg - + + runRecognition = Recognition.RunRecognition(self.source, scannerData, self.imageRecognition) + runRecognition.connect("updateRecognition", self.onProgressUpdate) + runRecognition.connect("recognized", self.on_recognized) + t = threading.Thread(target=runRecognition) + t.start() + #gtk.threads_enter() + #self.imagePreview.setRecognitionData(esr.getRecognitionData()) + #gtk.threads_leave() + + def on_recognized(self, runRecognition): + self.imagePreview.setRecognitionData(self.imageRecognition.getRecognitionData()) + + def onProgressUpdate(self, runRecognition, message): + self.progressbar.nextProgress(message) + if __name__ == '__main__': + gtk.threads_init() main = PyCodeOCR() main() Modified: branches/redesign/Recognition/ESR.py =================================================================== --- branches/redesign/Recognition/ESR.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/Recognition/ESR.py 2014-08-26 13:07:59 UTC (rev 66) @@ -32,7 +32,7 @@ self.valid_code_len = [ 53, 43, 42, 32 ] # valid code lenghts ## @overwrite verification - def verify(self): + def doVerification(self): # correct for common char recognition errors self.recognitionData.setContent(self.char_correction(self.recognitionData.getContent())) @@ -69,6 +69,11 @@ # @see http://www.bundesbank.de/zahlungsverkehr/zahlungsverkehr_pruefziffernberechnung.php # @return True if checksum is valid, false otherwise def checksum(self, number): + try: + int(number) + except: + return False + tabelle = [0,9,4,6,8,2,7,1,3,5] uebertrag = 0 Modified: branches/redesign/Recognition/ImageRecognition.py =================================================================== --- branches/redesign/Recognition/ImageRecognition.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/Recognition/ImageRecognition.py 2014-08-26 13:07:59 UTC (rev 66) @@ -19,7 +19,8 @@ # @li Modules: utils # -import os, gtk +import os, gtk, threading, gobject +import pyperclip from PIL import Image import utils @@ -31,6 +32,7 @@ self.name = name self.depth = 8 self.rotate = [0,90,90,90] + self.recognitionData = None ## Verify if data is valid. # @pre image acquired and recognized @@ -38,7 +40,9 @@ # @return (boolean, data) True if data is valid, false otherwise # if data is valid return data, otherwise return error message def verify(self): - return (True, "") + (check, msg) = self.doVerification() + self.recognitionData.setValid(check) + return (True, msg) ## get image and associated data # @pre image recognized @@ -89,6 +93,7 @@ self.image = image self.temp_name = "image_object_temp_file" self.content = "" + self.valid = None ## get image # @return image @@ -118,29 +123,35 @@ # @pre image recognized # @param information from image # @post information set - def setContent(self, content): + def setContent(self, content, valid = None): self.content = content + self.valid = valid ## get information associated with image # @return information content def getContent(self): return self.content + def setValid(self, valid): + self.valid = valid + + def isValid(self): + return self.valid + ## save content to clipboard # @pre information set # @post information saved in clipboard def saveClipboard(self): - # get the clipboard - clipboard = gtk.clipboard_get() # set the clipboard text data - clipboard.set_text(self.content) + pyperclip.setcb(self.content) # make our data available to other applications - clipboard.store() + pyperclip.getcb() ## Run the recognition and verify the information -class RunRecognition(object): +class RunRecognition(gobject.GObject): ## init def __init__(self, source, data, imageRecognition): + self.__gobject_init__() self.source = source self.data = data self.imageRecognition = imageRecognition @@ -149,6 +160,7 @@ # @return (boolean, data), True if data is valid, False otherwise # data if the acquired data is image, error-message otherwise def __call__(self): + self.emit("updateRecognition","Get Image ...") image = self.source.getImage(self.data) return self.recognize(image) @@ -157,15 +169,24 @@ # data if the acquired data is image, error message otherwise def recognize(self, image): # do recognition + self.emit("updateRecognition","Recognize image ...") self.imageRecognition.recognizeImage(image) # verify data + self.emit("updateRecognition","Verify data ...") (check, msg) = self.imageRecognition.verify() # if data is valid, save to clipboard and return data + self.emit("recognized") if check: + self.emit("updateRecognition","Data is valid. Save to clipboard.") self.imageRecognition.getRecognitionData().saveClipboard() return (True, self.imageRecognition.getRecognitionData().getContent()) # if data is invalid return error message - return (False, msg) \ No newline at end of file + self.emit("updateRecognition","Data is not valid.") + return (False, msg) + +gobject.type_register(RunRecognition) +gobject.signal_new("recognized", RunRecognition, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) +gobject.signal_new("updateRecognition", RunRecognition, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)) Deleted: branches/redesign/blacklist =================================================================== --- branches/redesign/blacklist 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/blacklist 2014-08-26 13:07:59 UTC (rev 66) @@ -1 +0,0 @@ -Printer Name Modified: branches/redesign/gtkGUI/ImagePreview.py =================================================================== --- branches/redesign/gtkGUI/ImagePreview.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/gtkGUI/ImagePreview.py 2014-08-26 13:07:59 UTC (rev 66) @@ -3,20 +3,29 @@ # PIL/Pillow image library and it's SANE bindings from PIL import Image +import Recognition -class ImagePreview(gtk.Widget): +class ImagePreview(gtk.VBox): def __init__(self): - #Initialize the Widget - gtk.Widget.__init__(self) + #Initialize the VBox + gtk.VBox.__init__(self,False,0) + self.res_color = { True: gtk.gdk.color_parse("#00FF00"), + False: gtk.gdk.color_parse("#FF0000"), + None: gtk.gdk.color_parse("#FFFFFF"), } + # # retrieve widgets # # main_window - main window # ## gladefile raw_path.glade - self.gladefile = raw_path + ".glade" + self.gladefile = "/home/rf/Testing/pycodeocr/gtkGUI/ImagePreview.glade" # open GTKBuilder self.builder = gtk.Builder() self.builder.add_from_file(self.gladefile) # connect signal handlers self.builder.connect_signals(self) + + ## label + self.scanned_code_label = self.builder.get_object('scanned_code_label') + ## event box for image self.main_image_eventbox = self.builder.get_object('main_image_eventbox') ## event box for image window @@ -27,26 +36,37 @@ self.popup_image = self.builder.get_object('popup_image') ## image window self.img_popup = self.builder.get_object('img_popup') + + ## output line + self.output = self.builder.get_object('output') + # connect eventbox to close image window (self.new_width, self.new_height ) = (0,0) - self.main_image.set_tooltip_text("Click for bigger image") - self.popup_image.set_tooltip_text("Leave window to close") + self.main_image.set_tooltip_text("Click for original image") + #self.main_image.connect('expose-event', self.on_image_resize, "") # high cpu usage + self.popup_image.set_tooltip_text("Click to close") - + self.pack_start(self.scanned_code_label,False,False,0) + self.pack_start(self.main_image_eventbox,True,True,0) + self.pack_end(self.output,False,False,0) - def on_eventbox_button_press_event(self, source=None, event=None): + self.show_all() + + def on_popup_image_eventbox_button_press_event(self, source=None, event=None): if self.img_popup.get_visible(): # hide window self.img_popup.hide() + + def on_main_image_eventbox_button_press_event(self, source=None, event=None): + if self.img_popup.get_visible(): + # hide window + self.img_popup.hide() else: - pixbuf = self.image_to_pixbuf(self.image.getImage()) + image = self.recognitionData.getImage() + pixbuf = self.image_to_pixbuf(image) image = gtk.Image() image.set_from_pixbuf(pixbuf) - - scaled_pixbuf = pixbuf.scale_simple(300,300,gtk.gdk.INTERP_BILINEAR) - - # set image - self.popup_image.set_from_pixbuf( scaled_pixbuf ) + self.popup_image.set_from_pixbuf( pixbuf ) # show window self.img_popup.show() @@ -57,25 +77,73 @@ # @see http://www.daniweb.com/code/snippet216637.html # @see http://www.pythonware.com/products/pil/index.htm def setImage(self, image): - self.image = image - pixbuf = self.image_to_pixbuf(self.image.getImage()) + self.recognitionData = Recognition.RecognitionData(image) + self.setImageHelper() + + + def setImageHelper(self): + image = self.recognitionData.getImage() + pixbuf = self.image_to_pixbuf(image) image = gtk.Image() image.set_from_pixbuf(pixbuf) + + self.main_image.set_from_pixbuf( pixbuf ) + self.on_image_resize(self.main_image, "", "") - scaled_pixbuf = pixbuf.scale_simple(150,150,gtk.gdk.INTERP_BILINEAR) + def setOutput(self, output, mode = None): + self.recognitionData.setContent(output, mode) + self.setOutputHelper() + + def setOutputHelper(self): + self.output.set_text(self.recognitionData.getContent()) + mode = self.recognitionData.isValid() + + # widget color + self.output.modify_base(gtk.STATE_NORMAL, self.res_color[mode]) - - self.main_image.set_from_pixbuf( scaled_pixbuf ) + def setRecognitionData(self, recognitionData): + self.recognitionData = recognitionData + self.setImageHelper() + self.setOutputHelper() - - def image_to_pixbuf(self): + # @see http://stackoverflow.com/questions/7906814/converting-pil-image-to-gtk-pixbuf + def image_to_pixbuf(self, image): fd = StringIO.StringIO() - self.image.getImage().save(fd, "ppm") + self.recognitionData.getImage().save(fd, "png") contents = fd.getvalue() fd.close() - loader = gtk.gdk.PixbufLoader("pnm") + loader = gtk.gdk.PixbufLoader("png") loader.write(contents, len(contents)) pixbuf = loader.get_pixbuf() loader.close() return pixbuf + + def on_image_resize(self, widget, event, window): + allocation = widget.get_allocation() + image = self.recognitionData.getImage() + pixbuf = self.image_to_pixbuf(image) + image = gtk.Image() + image.set_from_pixbuf(pixbuf) + + width = pixbuf.get_width() + height = pixbuf.get_height() + if height != allocation.height or width != allocation.width: + # min width and height should be 10px + target_width = max(100,allocation.width) + target_height = max(100,allocation.height) + + # get current width and height + width, height = pixbuf.get_width(), pixbuf.get_height() + + # get scale for width and height + scale_width, scale_height = float(target_width)/width, float(target_height)/height + + # target scale is minimum scale for width and height + scale = min(scale_width,scale_height) + + # scale pixbuf + pixbuf = pixbuf.scale_simple(int(width*scale), int(height*scale), gtk.gdk.INTERP_BILINEAR) + + # set new pixbuf + widget.set_from_pixbuf(pixbuf) \ No newline at end of file Modified: branches/redesign/gtkGUI/ProgressBar.py =================================================================== --- branches/redesign/gtkGUI/ProgressBar.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/gtkGUI/ProgressBar.py 2014-08-26 13:07:59 UTC (rev 66) @@ -1,24 +1,23 @@ import gtk -class ProgressBar(gtk.Widget): +# @see http://bytes.com/topic/python/answers/579827-pygtk-custom-widgets +class ProgressBar(gtk.HBox): def __init__(self,maximum): - gtk.Widget.__init(self) -# # retrieve widgets -# # main_window - main window -# ## gladefile raw_path.glade - self.gladefile = raw_path + ".glade" - # open GTKBuilder - self.builder = gtk.Builder() - self.builder.add_from_file(self.gladefile) - # connect signal handlers - self.builder.connect_signals(self) - ## progressbar - self.progressbar = self.builder.get_object('progressbar') - self.progress = 0 - self.maximum = maximum + gtk.HBox.__init__(self,False,0) + self.maximum = 1.0*maximum + + self.set_border_width(2) + + # progressbar + self.progressbar = gtk.ProgressBar() + self.progress = 0.0 + self.pack_start(self.progressbar,True,True,0) + + self.show_all() def nextProgress(self, message): - self.progress += 1 + if self.progress < self.maximum: + self.progress += 1 self.setProgress(message) def resetProgress(self, message): @@ -28,10 +27,10 @@ def setProgress(self, message): self.progressbar.set_fraction(self.progress/self.maximum) self.progressbar.set_text(message) - self.refresh() +# self.refresh() def setMaximum(self, maximum): - self.maximum = maximum + self.maximum = 1.0*maximum self.progressbar.set_fraction(self.progress/self.maximum) def getMaximum(self): Modified: branches/redesign/gtkGUI/__init__.py =================================================================== --- branches/redesign/gtkGUI/__init__.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/gtkGUI/__init__.py 2014-08-26 13:07:59 UTC (rev 66) @@ -1,3 +1,3 @@ -import ImagePreview -import ProgressBar +from ImagePreview import ImagePreview +from ProgressBar import ProgressBar import ScanProperties \ No newline at end of file Deleted: branches/redesign/utils/checksum.py =================================================================== --- branches/redesign/utils/checksum.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/utils/checksum.py 2014-08-26 13:07:59 UTC (rev 66) @@ -1,47 +0,0 @@ -## -# @file utils/checksum.py -# @namespace utils::checksum -# @authors laserb, drtrigon -# @version 1.1 -# @brief Modulo 10 checksum for e-banking codes. -# -# @test Add unittest to check correct operation of this important module. -# -# $Id$ -# -# @section Description -# -# Modulo 10 checksum for e-banking codes -# - -class modulo10: - # thanks to http://www.hosang.ch/modulo10.aspx - # much more details http://www.sic.ch/de/dl_tkicch_dta.pdf ( page 51 ) - # @see http://www.bundesbank.de/download/zahlungsverkehr/zv_pz201012.pdf - # @see http://www.bundesbank.de/zahlungsverkehr/zahlungsverkehr_pruefziffernberechnung.php - def __init__(self, amount, account, reference): - self.tabelle = [0,9,4,6,8,2,7,1,3,5] - - self.account = account - self.reference = reference - - self.checksum_b = self._checksum(amount) - self.checksum_k = self._checksum(account) - self.checksum_r = self._checksum(reference) - self.checksum = self.checksum_b and self.checksum_k and self.checksum_r - - try: - self.amount = str(int(amount[2:-1])/100.) - except ValueError: - self.amount = amount + " [ERROR!]" - - def _run(self, nr): - self.uebertrag = 0 - # iterate over each character - for i in range(len(nr)): - self.uebertrag = self.tabelle[(self.uebertrag + int(nr[i]) )%10] - - return (10-self.uebertrag)%10 - - def _checksum(self, value): - return (int(value[-1]) == self._run(value[:-1]) ) Deleted: branches/redesign/utils/ocr.py =================================================================== --- branches/redesign/utils/ocr.py 2014-08-24 10:19:30 UTC (rev 65) +++ branches/redesign/utils/ocr.py 2014-08-26 13:07:59 UTC (rev 66) @@ -1,272 +0,0 @@ -# -*- coding: utf-8 -*- -## -# @file utils/ocr.py -# @namespace utils::ocr -# @authors laserb, drtrigon -# @version 1.1 -# @brief Character recogition (OCR) functions and classes. -# -# $Id$ -# -# @section Description -# -# Character recogition (OCR) functions. -# - -# python standard modules -import os, re, sys, subprocess, gobject, threading, gtk -from logging import logging - -# PIL image library and it's SANE bindings -import sane # f12: 'python-imaging-sane' - - -## Character correction after recogition (on basis that there should be numbers and few special chars). -# -# @test Add unittest to check correct operation of this important module/function. -# -def char_correction(data): - data = re.sub("\n", "", data) - print data - corrections = [ - # Zero - ("O", "0"), ("D", "0"), ("U", "0"), ("Q", "0"), ("\(\)", "0"), ("G", "0"), ("o", "0"), - # Two - ("Z", "2"), - # Three - ("\?>", "3"), - # Four - ("l\.", "4"), ("A", "4"), ("l»", "4"), ("h", "4"), ("i»", "4"), ("l\xe2\x80\xa2", "4"), ("&", "4"), ("l\+", "4"), - # Five - ("S", "5"), - # Six - ("c>", "6"), - # Seven - #("\?", "7"), - # One (critical, therefore done as last; has also Overlapps e.g. with Four) - (chr(226)+chr(128)+chr(153)+"I", "1"), - (chr(226)+chr(128)+chr(153)+"\|", "1"), - (chr(226)+chr(128)+chr(152)+"\|", "1"), - (chr(226)+chr(128)+chr(152)+"I", "1"), - (chr(39)+"I", "1"), - ("I", "1"), - (chr(153)+"l", "1"), - (chr(39)+"l", "1"), - ("l", "1"), - (chr(39)+"!", "1"), - (chr(39)+"\|", "1"), - ("'\|", "1"), - ("\|", "1"), - ("'\]", "1"), - ("'\}", "1"), - (r'\\', "1"), - # non-numbers - (" ", ""), - ("\xe2", ""), - ("\x80", ""), - ("\xbb", ""), - ("\x99", ""), - ("\x98", ""), - ("\x5f", ""), - ("\x60", ""), - ("'", ""), - #('\xbb', 187)('\x99', 153)('\x98', 152) - ("\+", "+ "), - ("\)", ">"), - ("\x92", "1"), # post correction - ] - for item in corrections: - olddata = data - data = re.sub(item[0], item[1], data) - if not (data == olddata): print 'subst: "%s" => "%s"' % (item[0], item[1]) - - return data - -## SANE/PIL interface python wrapper/bindings. -class RunSANE(threading.Thread): - # "scanimage --format=tif --resolution 300 --mode Gray > %s.tif" - # "scanimage --format=tif --resolution 600 --mode Gray -t 82 -y 20 -l 60 -x 155.9 > %s.tif" - #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s.tif" - - resolution = 600 - - ## Init of sane interface -> device. - def __init__(self, notebook, progress, device_chooser_button, BlacklistMgr,device_chooser_event,device_info_text): - print "init sane python interface ..." - self.device_chooser_event = device_chooser_event - self.notebook = notebook - self.progress = progress - self.device_chooser_button = device_chooser_button - self.BlacklistMgr = BlacklistMgr - self.device_info_text = device_info_text - - threading.Thread.__init__(self) - - def run(self): - - # get blacklist - self.blacklist = self.BlacklistMgr.read_blacklist() - - # init SANE - self.n = 4. - self.progress(0.,"init sane python interface ...") - try: - self.version = sane.init() - self.progress(1./self.n,"init sane python interface ... search devices") - # get sane devices - self.devices = sane.get_devices() - - # filter blacklisted devices - if len(self.devices) > 0 : - self.devices = self.BlacklistMgr.filter_devices(self.devices) - - # check how many devices we found - if len(self.devices) == 0: - self.progress(0./self.n,"No device found.") - self.device_chooser_button.set_visible(False) - self.found_scanner = False - gtk.gdk.threads_leave() - return - elif len(self.devices) > 1: - # simply continue and select device in GUI ( see init_sane ) - self.progress(2./self.n,"More than one device found.") - self.device_chooser_button.set_visible(True) - self.notebook.set_show_tabs(False) - self.found_scanner = None - self.BlacklistMgr.device_treeview.set_cursor(0) - - # show tab with device list - # choose device and press ok to initialize scanner - self.notebook.set_current_page(2) - - - gtk.gdk.threads_leave() - self.device_chooser_event.wait() - - # show main tab again - self.notebook.set_show_tabs(True) - self.notebook.set_current_page(0) - - # get selection from treeview - self.devnr = self.BlacklistMgr.device_treeview.get_cursor()[0][0] - - else: - # only one device found, continue - self.progress(2./self.n,"Device: %s" % self.devices[0][1]+" "+self.devices[0][2]) - self.device_chooser_button.set_visible(False) - self.devnr = 0 - - except: - # No device found at all - self.found_scanner = False - self.device_chooser_button.set_visible(False) - print "No sane device found. Retry again." - self.progress(0./self.n,"No sane device found. Retry again.") - gtk.gdk.threads_leave() - return - - - ## Init of sane interface -> scanner - print "Use device number: "+str(self.devnr) - try: - # finish init device - self.dev = self.devices[self.devnr][0] # choose device - print "%s" % self.dev - self.progress(3./self.n,"Device initialized. Open scanner...") - - # open scanner device - self.scanner = sane.open(self.dev) - self.params = self.scanner.get_parameters() - self.opts = self.scanner.get_options() - - self.found_scanner = True - - self.progress(4./self.n,"Ready: %s" % self.devices[self.devnr][1]+" "+self.devices[self.devnr][2]) -# self.info() - self.device_chooser_button.set_visible(False) - print "done." - - except: - # init scanner failed. maybe device has no scanner - self.found_scanner = False - print "Loading sane device failed. Retry again." - self.progress(0./self.n,"Loading sane device failed. Retry again.") - gtk.gdk.threads_leave() - - - self.info() - gtk.gdk.threads_leave() - - - ## Not init of sane and scanner, but of scan operation. - def post_init(self, coords, out_filename): - self.coords = coords - self.out_filename = out_filename - #self.info() - - ## call - def __call__(self): - (self.error, self.stdout, self.stderr) = self._run() - return self.error - - ## Scan and save the PIL image object to file. - # @see http://mail.python.org/pipermail/image-sig/1997-June/000307.html - # @see http://sane-pygtk.sourceforge.net/) - def _run(self): - try: - # Set scan parameters (also with higher resolution!) - (t, l, y, x) = self.coords - self.scanner.tl_y = float(t) - self.scanner.tl_x = float(l) - self.scanner.br_y = (float(y) + self.scanner.tl_y) - self.scanner.br_x = (float(x) + self.scanner.tl_x) - self.scanner.resolution = self.resolution - self.scanner.mode = "Gray" - - # Initiate the scan - self.scanner.start() - - # Get an Image object containing the scanned image - im = self.scanner.snap() - - # Write the image out as a TIFF file (or whatever) - im.save(self.out_filename) - - #self.scanner.stop() - except: - return (True, "error", sys.exc_info()[1]) - - return (False, "ok", "") - - ## Show some info about the scanner and SANE. - def info(self): - entrybuffer = self.device_info_text.get_buffer() - entrybuffer.delete(entrybuffer.get_start_iter(),entrybuffer.get_end_iter()) - # redirect print to device textbuffer - logdev = logging(entrybuffer) - sys.stdout = logdev - - print 'SANE version: %s' % repr(self.version).replace('array',' ') - print "\n" - print 'Available devices:' - for device in self.devices: - print device[1]+" "+device[2] - print "\n" - print 'Selected device: '+self.devices[self.devnr][1]+" "+self.devices[self.devnr][2] - print "\n" - print 'SaneDev object= %s' % self.scanner - print "\n" - print 'Device parameters: %s' % repr(self.params).replace('array',' ') - print "\n" - print 'Device options:' - for opt in self.opts: - print "%s: %s" % (opt[2], opt[3]) - - - def retry(self): - try: - self.scanner.close() - except: - pass - sane.exit() - self.run() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-24 10:19:39
|
Revision: 65 http://sourceforge.net/p/pycodeocr/code/65 Author: laserb Date: 2014-08-24 10:19:30 +0000 (Sun, 24 Aug 2014) Log Message: ----------- add more documentation Modified Paths: -------------- branches/redesign/Recognition/Barcode.py branches/redesign/Recognition/ESR.py branches/redesign/Recognition/ImageRecognition.py branches/redesign/Recognition/PDF417.py Modified: branches/redesign/Recognition/Barcode.py =================================================================== --- branches/redesign/Recognition/Barcode.py 2014-08-24 10:18:01 UTC (rev 64) +++ branches/redesign/Recognition/Barcode.py 2014-08-24 10:19:30 UTC (rev 65) @@ -9,7 +9,7 @@ check = not (data['type'] == "unknown") if check: check = check and ( int(data['crc']) == 0 ) # CRC error check? - check = check and (float(data['error']) < 0.15) # recognizion errors? + check = check and (float(data['error']) < 0.15) # recognition errors? print 'type:' +" "+ data['type'] print 'chars:' +" "+ data['chars'] print 'crc:' +" "+ data['crc'] @@ -17,7 +17,7 @@ data = data['code'] else: data = "type: " + data['type'] - return check + return (check, data) def setImage(self,image): self.image = image Modified: branches/redesign/Recognition/ESR.py =================================================================== --- branches/redesign/Recognition/ESR.py 2014-08-24 10:18:01 UTC (rev 64) +++ branches/redesign/Recognition/ESR.py 2014-08-24 10:19:30 UTC (rev 65) @@ -1,62 +1,104 @@ # -*- coding: utf8 -*- +## +# @file ESR.py +# @package ImageRecognition +# @authors drtrigon, laserb +# @version 2.0b +# @brief Recognize codeline from ESR +# +# $Id: $ +# +# +# @section Description +# +# Extract information from ESR. +# +# @section Dependencies +# +# @li Python modules needed are: os, re. +# @li Modules: utils, Recognition +# from Recognition import ImageRecognition import utils import re, os +## Extract information from ESR class ESR(ImageRecognition.ImageRecognitionBase): + ## init def __init__(self): super(ESR,self).__init__("ESR") self.temp_name = "image_object_temp_file" self.valid_code_len = [ 53, 43, 42, 32 ] # valid code lenghts - + ## @overwrite verification def verify(self): + # correct for common char recognition errors self.recognitionData.setContent(self.char_correction(self.recognitionData.getContent())) + # get data data = self.recognitionData.getContent() + + # check for invalid characters check = (not "?" in data) or (not "!" in data) # any unrecognized char in code? check = check and ( len(data) in self.valid_code_len ) # correct code len? if not check: return (False, "Invalid length or invalid characters") + # extract amount, reference and account from codeline tmp = data[:-1].split(">") amount = tmp[0] tmp = tmp[1].split("+ ") reference = tmp[0] account = tmp[1] + # do checksum for amount, reference and account if not self.checksum(amount): return (False, "Checksum for amount failed.") if not self.checksum(reference): return (False, "Checksum for reference failed.") if not self.checksum(account): return (False, "Checksum for account failed.") + + # return true if all checks are positive return (True, "") # thanks to http://www.hosang.ch/modulo10.aspx # much more details http://www.sic.ch/de/dl_tkicch_dta.pdf ( page 51 ) # @see http://www.bundesbank.de/download/zahlungsverkehr/zv_pz201012.pdf # @see http://www.bundesbank.de/zahlungsverkehr/zahlungsverkehr_pruefziffernberechnung.php + # @return True if checksum is valid, false otherwise def checksum(self, number): tabelle = [0,9,4,6,8,2,7,1,3,5] uebertrag = 0 + # iterate over each character for i in range(len(number)-1): uebertrag = tabelle[(uebertrag + int(number[i]) )%10] uebertrag = (10-uebertrag)%10 + + # check if last digit equals checksum return str(uebertrag) == number[-1] + # @overwrite recognizeImage def recognizeImage(self, image, rotate = None): super(ESR,self).recognizeImage(image) + + # if no rotation is set, use default: [0, 90, 90, 90] if rotate == None: rotate = self.rotate + + # try all rotation and test if data is valid for angle in rotate: + # convert image self.recognitionData.convert({"-depth":str(self.depth),"-rotate":str(angle)}, "convert: unable to open image") + + # do recognition with tesseract self.recognitionData.getImage().save(self.temp_name + ".png") runExternal = utils.RunExternal("tesseract %s %s" % (self.temp_name + ".png",self.temp_name+"tesseract"),error_msg="Couldn't find text") runExternal() + # Simple workaround: The program simply continuous if no text is found at all # and therefore no txt-file is generated. if not os.path.exists(self.temp_name+"tesseract.txt"): @@ -67,10 +109,16 @@ df.close() os.remove(self.temp_name + "tesseract.txt") # clean-up os.remove(self.temp_name + ".png") # clean-up + + # set content self.recognitionData.setContent(data) + + # check if data is valid (check, msg) = self.verify() if check: break + + # return the data return self.recognitionData.getContent() ## Character correction after recogition (on basis that there should be numbers and few special chars). Modified: branches/redesign/Recognition/ImageRecognition.py =================================================================== --- branches/redesign/Recognition/ImageRecognition.py 2014-08-24 10:18:01 UTC (rev 64) +++ branches/redesign/Recognition/ImageRecognition.py 2014-08-24 10:19:30 UTC (rev 65) @@ -1,70 +1,104 @@ # -*- coding: utf8 -*- ## -# @file File.py -# @package Source -# @extends SourceBase +# @file ImageRecognition.py +# @package ImageRecognition # @authors drtrigon, laserb # @version 2.0b -# @brief Base class for sources. +# @brief Base class for image recognition. # # $Id: $ # # # @section Description # -# Get an image from file. +# Extract information from image. # # @section Dependencies # +# @li Python modules needed are: os, gtk, PIL. +# @li Modules: utils # import os, gtk from PIL import Image import utils +## Base class for image recognition. This class is not useful by itself. +# Extend this class for a specific recognition technique. class ImageRecognitionBase(object): + ## init def __init__(self, name): self.name = name self.depth = 8 self.rotate = [0,90,90,90] + ## Verify if data is valid. + # @pre image acquired and recognized + # @post information extracted + # @return (boolean, data) True if data is valid, false otherwise + # if data is valid return data, otherwise return error message def verify(self): return (True, "") + ## get image and associated data + # @pre image recognized + # @return image and asscociated data def getRecognitionData(self): return self.recognitionData + ## recognize image + # @pre image acquired + # @param image + # @post information is extracted + # @return extracted information def recognizeImage(self,image): recognitionData = RecognitionData(image) self.recognitionData = recognitionData return self.recognitionData.getContent() + ## get name + # @return name def getName(self): return self.name + ## get rotate + # @return rotate def getRotate(self): return self.rotate + ## set rotate + # @param rotation angle def setRotate(self, rotate): self.rotate = rotate + ## get depth + # @return depth def getDepth(self): return self.depth + ## set depth + # @param depth def setDepth(self, depth): self.depth = depth - +## store for image and associated data class RecognitionData(object): + ## init def __init__(self, image): self.image = image self.temp_name = "image_object_temp_file" self.content = "" + ## get image + # @return image def getImage(self): return self.image + ## convert initial image to prepare it for recognition + # @pre image acquired + # @param convertion options, error message + # @post image optimized for recognition def convert(self,options,msg): path = os.path.abspath(".") orig = os.path.join(path,self.temp_name + ".png") @@ -80,12 +114,21 @@ os.remove(orig) # clean-up os.remove(new) # clean-up + ## set information content of image + # @pre image recognized + # @param information from image + # @post information set def setContent(self, content): self.content = content + ## get information associated with image + # @return information content def getContent(self): return self.content + ## save content to clipboard + # @pre information set + # @post information saved in clipboard def saveClipboard(self): # get the clipboard clipboard = gtk.clipboard_get() @@ -94,21 +137,35 @@ # make our data available to other applications clipboard.store() - +## Run the recognition and verify the information class RunRecognition(object): + ## init def __init__(self, source, data, imageRecognition): self.source = source self.data = data self.imageRecognition = imageRecognition + ## call + # @return (boolean, data), True if data is valid, False otherwise + # data if the acquired data is image, error-message otherwise def __call__(self): image = self.source.getImage(self.data) return self.recognize(image) + ## recognize image + # @return (boolean, data), True if data is valid, False otherwise + # data if the acquired data is image, error message otherwise def recognize(self, image): + # do recognition self.imageRecognition.recognizeImage(image) + + # verify data (check, msg) = self.imageRecognition.verify() + + # if data is valid, save to clipboard and return data if check: self.imageRecognition.getRecognitionData().saveClipboard() return (True, self.imageRecognition.getRecognitionData().getContent()) + + # if data is invalid return error message return (False, msg) \ No newline at end of file Modified: branches/redesign/Recognition/PDF417.py =================================================================== --- branches/redesign/Recognition/PDF417.py 2014-08-24 10:18:01 UTC (rev 64) +++ branches/redesign/Recognition/PDF417.py 2014-08-24 10:19:30 UTC (rev 65) @@ -5,7 +5,7 @@ super(PDF417,self).__init("PDF417") def verify(self): - return True + return (True, "") def setImage(self,image): self.image = image This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-24 10:18:11
|
Revision: 64 http://sourceforge.net/p/pycodeocr/code/64 Author: laserb Date: 2014-08-24 10:18:01 +0000 (Sun, 24 Aug 2014) Log Message: ----------- removed no longer needed stuff Modified Paths: -------------- branches/redesign/utils/RunExternal.py branches/redesign/utils/__init__.py branches/redesign/utils/blacklist_manager.py Modified: branches/redesign/utils/RunExternal.py =================================================================== --- branches/redesign/utils/RunExternal.py 2014-08-24 07:21:52 UTC (rev 63) +++ branches/redesign/utils/RunExternal.py 2014-08-24 10:18:01 UTC (rev 64) @@ -1,5 +1,6 @@ +# -*- coding: utf8 -*- ## Run external shell command/application. -import subprocess +import subprocess, os class RunExternal: error_msg = [ "/bin/sh: " ] Modified: branches/redesign/utils/__init__.py =================================================================== --- branches/redesign/utils/__init__.py 2014-08-24 07:21:52 UTC (rev 63) +++ branches/redesign/utils/__init__.py 2014-08-24 10:18:01 UTC (rev 64) @@ -13,9 +13,7 @@ # This is the utils package with important functions. # -import utils.checksum import utils.requirements -import utils.ocr from utils.blacklist_manager import blacklist_manager from utils.RunExternal import RunExternal from logging import logging Modified: branches/redesign/utils/blacklist_manager.py =================================================================== --- branches/redesign/utils/blacklist_manager.py 2014-08-24 07:21:52 UTC (rev 63) +++ branches/redesign/utils/blacklist_manager.py 2014-08-24 10:18:01 UTC (rev 64) @@ -34,7 +34,7 @@ # create self.treeview things self.blacklist_store = gtk.ListStore(gobject.TYPE_STRING) self.blacklist_treeview.set_model(self.blacklist_store) - blackcol = gtk.TreeViewColumn("Blacklisted Devices:", gtk.CellRendererText(),text=0) + blackcol = gtk.TreeViewColumn("Blacklisted Scanner:", gtk.CellRendererText(),text=0) self.blacklist_treeview.append_column(blackcol) return This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2014-08-24 07:11:34
|
Revision: 62 http://sourceforge.net/p/pycodeocr/code/62 Author: laserb Date: 2014-08-24 07:11:31 +0000 (Sun, 24 Aug 2014) Log Message: ----------- Branching from trunk to redesign at 61. Added Paths: ----------- branches/redesign/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2013-11-03 16:19:43
|
Revision: 61 http://sourceforge.net/p/pycodeocr/code/61 Author: drtrigon Date: 2013-11-03 16:19:40 +0000 (Sun, 03 Nov 2013) Log Message: ----------- * support for Pillow (PIL replacement) * add ')' -> '>' substitution for ocr Modified Paths: -------------- trunk/PyCodeOCR.py trunk/utils/ocr.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-12-22 23:07:40 UTC (rev 60) +++ trunk/PyCodeOCR.py 2013-11-03 16:19:40 UTC (rev 61) @@ -68,8 +68,8 @@ from utils.checksum import modulo10 -# PIL image library and it's SANE bindings -import Image, ImageDraw +# PIL/Pillow image library and it's SANE bindings +from PIL import Image, ImageDraw #from PIL import Image from time import gmtime, strftime Modified: trunk/utils/ocr.py =================================================================== --- trunk/utils/ocr.py 2011-12-22 23:07:40 UTC (rev 60) +++ trunk/utils/ocr.py 2013-11-03 16:19:40 UTC (rev 61) @@ -72,6 +72,7 @@ ("'", ""), #('\xbb', 187)('\x99', 153)('\x98', 152) ("\+", "+ "), + ("\)", ">"), ("\x92", "1"), # post correction ] for item in corrections: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-12-22 23:07:46
|
Revision: 60 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=60&view=rev Author: drtrigon Date: 2011-12-22 23:07:40 +0000 (Thu, 22 Dec 2011) Log Message: ----------- better bug handling; print trackebacks to terminal in case the GUI freezes Modified Paths: -------------- trunk/PyCodeOCR.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-12-22 22:42:28 UTC (rev 59) +++ trunk/PyCodeOCR.py 2011-12-22 23:07:40 UTC (rev 60) @@ -264,7 +264,6 @@ self.logging = utils.logging(self.textbuffer) if not debug: sys.stdout = self.logging - sys.stderr = self.logging # initialize treeviews in Blacklist Manager This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-12-22 22:42:34
|
Revision: 59 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=59&view=rev Author: drtrigon Date: 2011-12-22 22:42:28 +0000 (Thu, 22 Dec 2011) Log Message: ----------- bug fix; 'None' could not be converted into string in 'ocr.py' some additional minor changes for simpler debugging and others Modified Paths: -------------- trunk/PyCodeOCR.py trunk/utils/ocr.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-09-17 18:41:11 UTC (rev 58) +++ trunk/PyCodeOCR.py 2011-12-22 22:42:28 UTC (rev 59) @@ -56,7 +56,9 @@ utils.requirements.check_all_pycodeocr_requirements() sys.exit() +debug = ("--debug" in sys.argv) + # GTK, PyGTK, GLADE (GNOME) modules import pygtk pygtk.require('2.0') @@ -156,7 +158,7 @@ MDE = { 'invoices': 0, 'barcode': 1, 'DataMatrix': 2, 'PDF417': 3 } ## Initialize - def __init__(self): + def __init__(self, BlacklistMgr): # # retrieve widgets # # main_window - main window # ## gladefile raw_path.glade @@ -260,12 +262,14 @@ # redirect print self.logging = utils.logging(self.textbuffer) - sys.stdout = self.logging - sys.stderr = self.logging + if not debug: + sys.stdout = self.logging + sys.stderr = self.logging # initialize treeviews in Blacklist Manager - BlacklistMgr.post_init(self.device_treeview, self.blacklist_treeview, local_path) + self.BlacklistMgr = BlacklistMgr + self.BlacklistMgr.post_init(self.device_treeview, self.blacklist_treeview, local_path) print "---------",strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()),"----------" @@ -282,10 +286,11 @@ self.device_chooser_event = threading.Event() ## initialize sane - self.run_sane = utils.ocr.RunSANE(self.notebook, self.progress, self.device_chooser_button, BlacklistMgr,self.device_chooser_event,self.device_info_text) + self.run_sane = utils.ocr.RunSANE(self.notebook, self.progress, self.device_chooser_button, self.BlacklistMgr,self.device_chooser_event,self.device_info_text) self.run_sane.start() # redirect print again to old textbuffer - sys.stdout = self.logging + if not debug: + sys.stdout = self.logging gtk.main() @@ -374,11 +379,11 @@ ## add device to blacklist def blacklist_add(self, widget=None): - BlacklistMgr.blacklist_add() + self.BlacklistMgr.blacklist_add() ## remove device from blacklist def blacklist_remove(self, widget=None): - BlacklistMgr.blacklist_remove() + self.BlacklistMgr.blacklist_remove() ## one of the placement coordinates changed def on_placement_value_changed(self, source=None, event=None): @@ -808,11 +813,9 @@ self.refresh() if __name__ == '__main__': - global BlacklistMgr - global main ## initialize Blacklist Manager BlacklistMgr = utils.blacklist_manager() ## run main application - main = MainWindowGTK() + main = MainWindowGTK(BlacklistMgr) main.run() Modified: trunk/utils/ocr.py =================================================================== --- trunk/utils/ocr.py 2011-09-17 18:41:11 UTC (rev 58) +++ trunk/utils/ocr.py 2011-12-22 22:42:28 UTC (rev 59) @@ -259,7 +259,7 @@ print "\n" print 'Device options:' for opt in self.opts: - print opt[2]+ ": " + opt[3] + print "%s: %s" % (opt[2], opt[3]) def retry(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-09-17 18:41:19
|
Revision: 58 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=58&view=rev Author: drtrigon Date: 2011-09-17 18:41:11 +0000 (Sat, 17 Sep 2011) Log Message: ----------- PEP 8 Modified Paths: -------------- trunk/PyCodeOCR.py trunk/utils/RunExternal.py trunk/utils/RunLibdmtx.py trunk/utils/RunMagickWand.py trunk/utils/blacklist_manager.py trunk/utils/checksum.py trunk/utils/logging.py trunk/utils/ocr.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-07-27 13:51:33 UTC (rev 57) +++ trunk/PyCodeOCR.py 2011-09-17 18:41:11 UTC (rev 58) @@ -77,10 +77,10 @@ #from pythonmagickwand.image import Image # search optional pakages -if "LD_LIBRARY_PATH" not in os.environ: # patch/work-a-round for libdmtx bindings - os.environ["LD_LIBRARY_PATH"] = "/usr/local/lib" # - os.system('python %s' % sys.argv[0]) # - sys.exit() # +if "LD_LIBRARY_PATH" not in os.environ: # patch/work-a-round for libdmtx bindings + os.environ["LD_LIBRARY_PATH"] = "/usr/local/lib" # + os.system('python %s' % sys.argv[0]) # + sys.exit() # ## list of available pakages print "To check and install requirements run: 'python %s --install-deps'" % sys.argv[0] pakages = [] @@ -89,21 +89,21 @@ "dmtxread": utils.requirements.which("dmtxread"), "pdf417decode.exe": utils.requirements.which("pdf417decode.exe"), } if os.path.exists(paths["gocr"]): - pakages.append( "gocr" ) - print "gocr found." + pakages.append( "gocr" ) + print "gocr found." # libdmtx bindings #try: -# from pydmtx import DataMatrix -# pakages.append( "libdmtx" ) -# print "libdmtx and pydmtx found." -#except: pass +# from pydmtx import DataMatrix +# pakages.append( "libdmtx" ) +# print "libdmtx and pydmtx found." +#except: pass if os.path.exists(paths["dmtxread"]): - pakages.append( "libdmtx" ) - print "libdmtx and pydmtx found." + pakages.append( "libdmtx" ) + print "libdmtx and pydmtx found." # pdf417decode if os.path.exists(paths["pdf417decode.exe"]): - pakages.append( "pdf417decode" ) - print "pdf417decode.exe found." + pakages.append( "pdf417decode" ) + print "pdf417decode.exe found." # global variables and constants @@ -115,712 +115,704 @@ ## users home path /home/user home_path = os.path.expanduser('~') ## default scanning coordinates -std_scan_koords = { "0 deg": (( 82, 60, 20, 155 ), 0), # or with higher res. ( 820, 600, 200, 1559 ), +std_scan_koords = { "0 deg": (( 82, 60, 20, 155 ), 0), # or with higher res. ( 820, 600, 200, 1559 ), "90 deg": (( 1, 82, 150, 20 ), 90), "180 deg": (( 3, 1, 20, 150 ), 180), "270 deg": (( 60, 3, 150, 20 ), 270), - "A4": (( 0, 0, 296, 215 ), 0), } # scan whole range (A4: http://www.cl.cam.ac.uk/~mgk25/iso-paper.html) - #"A4": (( 0, 0, 290, 210 ), 0), } # (more secure; with small border) + "A4": (( 0, 0, 296, 215 ), 0), } # scan whole range (A4: http://www.cl.cam.ac.uk/~mgk25/iso-paper.html) + #"A4": (( 0, 0, 290, 210 ), 0), } # (more secure; with small border) ## MainWindow # The GUI was created/designed using GLADE # class MainWindowGTK: - """ - PyCodeOCR main GUI window and application class. - """ + """ + PyCodeOCR main GUI window and application class. + """ - # initialization - # (variables) - max_retry = 3 # max. scan attempts - valid_code_len = [ 53, 42, 32 ] # valid code lenghts - scan_koords = std_scan_koords["0 deg"][0] # default scan pos. - mode = std_scan_koords["0 deg"][1] # default scan orient. - res_color = { True: gtk.gdk.color_parse("#00FF00"), - False: gtk.gdk.color_parse("#FF0000"), - None: gtk.gdk.color_parse("#FFFFFF"), } - temp = os.path.join(home_path, "PyCodeOCR_tmp") - debug = ( os.path.join(home_path, "PyCodeOCR_debug"), - os.path.join(home_path, "PyCodeOCR_debug.txt"), ) - regex_gocr = re.compile('<barcode(.*?)/>') + # initialization + # (variables) + max_retry = 3 # max. scan attempts + valid_code_len = [ 53, 43, 42, 32 ] # valid code lenghts + scan_koords = std_scan_koords["0 deg"][0] # default scan pos. + mode = std_scan_koords["0 deg"][1] # default scan orient. + res_color = { True: gtk.gdk.color_parse("#00FF00"), + False: gtk.gdk.color_parse("#FF0000"), + None: gtk.gdk.color_parse("#FFFFFF"), } + temp = os.path.join(home_path, "PyCodeOCR_tmp") + debug = ( os.path.join(home_path, "PyCodeOCR_debug"), + os.path.join(home_path, "PyCodeOCR_debug.txt"), ) + regex_gocr = re.compile('<barcode(.*?)/>') - #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s" # SANE scan command - cmd_convert = "convert %s -depth 8 -rotate %d %s" # ImageMagick command - cmd_tesser = "tesseract %s.tif %s" # TesserAct command - cmd_gocr = paths["gocr"] + " -i %s.pnm" # GOCR command (local) - cmd_pdf417dec = "wine " + paths["pdf417decode.exe"] + " %s.png" # pdf417decode/wine command (local) + #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s" # SANE scan command + cmd_convert = "convert %s -depth 8 -rotate %d %s" # ImageMagick command + cmd_tesser = "tesseract %s.tif %s" # TesserAct command + cmd_gocr = paths["gocr"] + " -i %s.pnm" # GOCR command (local) + cmd_pdf417dec = "wine " + paths["pdf417decode.exe"] + " %s.png" # pdf417decode/wine command (local) - __stop = False + __stop = False - # (constants) - MDE = { 'invoices': 0, 'barcode': 1, 'DataMatrix': 2, 'PDF417': 3 } + # (constants) + MDE = { 'invoices': 0, 'barcode': 1, 'DataMatrix': 2, 'PDF417': 3 } - ## Initialize - def __init__(self): - - -# # retrieve widgets -# # main_window - main window -# ## gladefile raw_path.glade - self.gladefile = raw_path + ".glade" - # open GTKBuilder - self.builder = gtk.Builder() - self.builder.add_from_file(self.gladefile) - # connect signal handlers - self.builder.connect_signals(self) - - # get objects from glade/GTKBuilder - ## main window - self.main_window = self.builder.get_object('main_window') - self.main_window.set_icon_from_file(raw_path+".png") - ## notebok - self.notebook = self.builder.get_object('notebook') - ## image window - self.img_popup = self.builder.get_object('img_popup') - ## scan button - self.scan_button = self.builder.get_object('scan_button') - ## restart button - self.retry_button = self.builder.get_object('retry_button') - ## exit button - self.exit_button = self.builder.get_object('exit_button') - ## placement frame - self.placement_frame = self.builder.get_object('placement_frame') - ## image - self.main_image = self.builder.get_object('main_image') - ## image - self.popup_image = self.builder.get_object('popup_image') - ## output line - self.output = self.builder.get_object('output') - self.log_text = self.builder.get_object('log_text') - self.textbuffer = self.log_text.get_buffer() - self.device_info_text = self.builder.get_object('device_info_text') - ## progressbar - self.progressbar = self.builder.get_object('progressbar') - ## Orientation label - self.placement_label = self.builder.get_object('placement_label') - ## Orientation combobox - self.orientation = self.builder.get_object('orientation') - ## mode combobox - self.mode_combobox = self.builder.get_object('mode_combobox') - ## list with possible values for modes - self.mode_list = self.builder.get_object('mode_list') - ## x-position - self.position_x = self.builder.get_object('position_x') - ## y-position - self.position_y = self.builder.get_object('position_y') - ## x-size - self.size_x = self.builder.get_object('size_x') - ## y-size - self.size_y = self.builder.get_object('size_y') - ## file input - self.file_input_button = self.builder.get_object('file_input_button') - ## sane input - self.sane_input_button = self.builder.get_object('sane_input_button') - ## choose file - self.filechooserbutton = self.builder.get_object('filechooserbutton') - ## device list - self.device_treeview = self.builder.get_object('device_treeview') - ## blacklisted device list - self.blacklist_treeview = self.builder.get_object('blacklist_treeview') - ## OK button - self.device_chooser_button = self.builder.get_object('device_chooser_button') - ## event box for image - self.main_image_eventbox = self.builder.get_object('main_image_eventbox') - ## event box for image window - self.popup_image_eventbox = self.builder.get_object('popup_image_eventbox') + ## Initialize + def __init__(self): +# # retrieve widgets +# # main_window - main window +# ## gladefile raw_path.glade + self.gladefile = raw_path + ".glade" + # open GTKBuilder + self.builder = gtk.Builder() + self.builder.add_from_file(self.gladefile) + # connect signal handlers + self.builder.connect_signals(self) + + # get objects from glade/GTKBuilder + ## main window + self.main_window = self.builder.get_object('main_window') + self.main_window.set_icon_from_file(raw_path+".png") + ## notebok + self.notebook = self.builder.get_object('notebook') + ## image window + self.img_popup = self.builder.get_object('img_popup') + ## scan button + self.scan_button = self.builder.get_object('scan_button') + ## restart button + self.retry_button = self.builder.get_object('retry_button') + ## exit button + self.exit_button = self.builder.get_object('exit_button') + ## placement frame + self.placement_frame = self.builder.get_object('placement_frame') + ## image + self.main_image = self.builder.get_object('main_image') + ## image + self.popup_image = self.builder.get_object('popup_image') + ## output line + self.output = self.builder.get_object('output') + self.log_text = self.builder.get_object('log_text') + self.textbuffer = self.log_text.get_buffer() + self.device_info_text = self.builder.get_object('device_info_text') + ## progressbar + self.progressbar = self.builder.get_object('progressbar') + ## Orientation label + self.placement_label = self.builder.get_object('placement_label') + ## Orientation combobox + self.orientation = self.builder.get_object('orientation') + ## mode combobox + self.mode_combobox = self.builder.get_object('mode_combobox') + ## list with possible values for modes + self.mode_list = self.builder.get_object('mode_list') + ## x-position + self.position_x = self.builder.get_object('position_x') + ## y-position + self.position_y = self.builder.get_object('position_y') + ## x-size + self.size_x = self.builder.get_object('size_x') + ## y-size + self.size_y = self.builder.get_object('size_y') + ## file input + self.file_input_button = self.builder.get_object('file_input_button') + ## sane input + self.sane_input_button = self.builder.get_object('sane_input_button') + ## choose file + self.filechooserbutton = self.builder.get_object('filechooserbutton') + ## device list + self.device_treeview = self.builder.get_object('device_treeview') + ## blacklisted device list + self.blacklist_treeview = self.builder.get_object('blacklist_treeview') + ## OK button + self.device_chooser_button = self.builder.get_object('device_chooser_button') + ## event box for image + self.main_image_eventbox = self.builder.get_object('main_image_eventbox') + ## event box for image window + self.popup_image_eventbox = self.builder.get_object('popup_image_eventbox') - # initiate orientation and position - self.orientation.set_active(0) - self.position_x.set_value(self.scan_koords[0]) - self.position_y.set_value(self.scan_koords[1]) - self.size_x.set_value(self.scan_koords[2]) - self.size_y.set_value(self.scan_koords[3]) - - - self.mode_combobox.set_active(0) - if "gocr" not in pakages: - self.mode_combobox.remove_text(1) - self.mode_combobox.insert_text(1, "< not installed >") - if "libdmtx" not in pakages: - self.mode_combobox.remove_text(2) - self.mode_combobox.insert_text(2, "< not installed >") - if "pdf417decode" not in pakages: - self.mode_combobox.remove_text(3) - self.mode_combobox.insert_text(3, "< not installed >") - - - # connect eventbox to close image window - (self.new_width, self.new_height ) = (0,0) - - # set tooltips - self.retry_button.set_tooltip_text("Restart PyCodeOCR to search for a SANE device.") - self.retry_button.set_visible(True) - self.main_image.set_tooltip_text("Click for bigger image") - self.popup_image.set_tooltip_text("Leave window to close") - - - # redirect print - self.logging = utils.logging(self.textbuffer) - sys.stdout = self.logging - sys.stderr = self.logging - - - # initialize treeviews in Blacklist Manager - BlacklistMgr.post_init(self.device_treeview, self.blacklist_treeview, local_path) - - print "---------",strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()),"----------" - - - - - # display window - self.main_window.show() + # initiate orientation and position + self.orientation.set_active(0) + self.position_x.set_value(self.scan_koords[0]) + self.position_y.set_value(self.scan_koords[1]) + self.size_x.set_value(self.scan_koords[2]) + self.size_y.set_value(self.scan_koords[3]) + + + self.mode_combobox.set_active(0) + if "gocr" not in pakages: + self.mode_combobox.remove_text(1) + self.mode_combobox.insert_text(1, "< not installed >") + if "libdmtx" not in pakages: + self.mode_combobox.remove_text(2) + self.mode_combobox.insert_text(2, "< not installed >") + if "pdf417decode" not in pakages: + self.mode_combobox.remove_text(3) + self.mode_combobox.insert_text(3, "< not installed >") + + + # connect eventbox to close image window + (self.new_width, self.new_height ) = (0,0) + + # set tooltips + self.retry_button.set_tooltip_text("Restart PyCodeOCR to search for a SANE device.") + self.retry_button.set_visible(True) + self.main_image.set_tooltip_text("Click for bigger image") + self.popup_image.set_tooltip_text("Leave window to close") + + + # redirect print + self.logging = utils.logging(self.textbuffer) + sys.stdout = self.logging + sys.stderr = self.logging + + + # initialize treeviews in Blacklist Manager + BlacklistMgr.post_init(self.device_treeview, self.blacklist_treeview, local_path) + + print "---------",strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()),"----------" - return - - ## Run gtk mainloop and with it THIS APP. - def run(self): - gtk.gdk.threads_init() - - self.device_chooser_event = threading.Event() - - ## initialize sane - self.run_sane = utils.ocr.RunSANE(self.notebook, self.progress, self.device_chooser_button, BlacklistMgr,self.device_chooser_event,self.device_info_text) - self.run_sane.start() - # redirect print again to old textbuffer - sys.stdout = self.logging - - gtk.main() - - - def on_device_chooser_button_clicked(self, source=None): - self.device_chooser_button.set_visible(False) - self.device_chooser_event.set() - - - - ## set sensitivity of buttons the first time - def init_sensitivity(self): - # set sensitivity - if self.run_sane.found_scanner: - self.sane_input_button.set_active(True) - self.sane_input_button.set_sensitive(True) - else: - self.file_input_button.set_active(True) - self.sane_input_button.set_sensitive(False) - - # Try to set orientation and placement sensitive - self.toggle_orientation_sensitive(True) - self.toggle_placement_sensitive(True) - - ## toggle orientation sensitivity - def toggle_orientation_sensitive(self, value): - self.placement_label.set_sensitive(value) - self.orientation.set_sensitive(value) + + # display window + self.main_window.show() - ## toggle placement sensitivity - def toggle_placement_sensitive(self, value): - if self.sane_input_button.get_active(): - self.placement_frame.set_sensitive(value) - else: - self.placement_frame.set_sensitive(False) + return + + ## Run gtk mainloop and with it THIS APP. + def run(self): + gtk.gdk.threads_init() + + self.device_chooser_event = threading.Event() + + ## initialize sane + self.run_sane = utils.ocr.RunSANE(self.notebook, self.progress, self.device_chooser_button, BlacklistMgr,self.device_chooser_event,self.device_info_text) + self.run_sane.start() + # redirect print again to old textbuffer + sys.stdout = self.logging + + gtk.main() + + + def on_device_chooser_button_clicked(self, source=None): + self.device_chooser_button.set_visible(False) + self.device_chooser_event.set() + + + ## set sensitivity of buttons the first time + def init_sensitivity(self): + # set sensitivity + if self.run_sane.found_scanner: + self.sane_input_button.set_active(True) + self.sane_input_button.set_sensitive(True) + else: + self.file_input_button.set_active(True) + self.sane_input_button.set_sensitive(False) + + # Try to set orientation and placement sensitive + self.toggle_orientation_sensitive(True) + self.toggle_placement_sensitive(True) + + ## toggle orientation sensitivity + def toggle_orientation_sensitive(self, value): + self.placement_label.set_sensitive(value) + self.orientation.set_sensitive(value) + ## toggle placement sensitivity + def toggle_placement_sensitive(self, value): + if self.sane_input_button.get_active(): + self.placement_frame.set_sensitive(value) + else: + self.placement_frame.set_sensitive(False) + ## signals / glade callbacks + # + def on_pointer_motion(self, source=None, event=None): + pass +# (x,y,state) = self.main_window.window.get_pointer() +# (wxim, wyim ) = self.main_image.get_size_request() +# if x > 16+(wxim-self.new_width)/2 and x < 16+(wxim+self.new_width)/2 and y > 75+(wyim-self.new_height)/2 and y < 75+(wyim+self.new_height)/2: +# if not self.img_popup.get_visible(): +# self.on_main_image_eventbox_button_press_event() + + def on_main_image_eventbox_button_press_event(self, source=None, event=None): + if self.img_popup.get_visible(): + # clean-up + os.remove( self.image_file_big ) + # hide window + self.img_popup.hide() + else: + # load original image + im1 = Image.open(self.imageFile) + # adjust width and height to your needs and keep ratio + (im_width, im_height) = im1.size #get image size + # get size of shown image + width = self.main_image.allocation.width + height = self.main_image.allocation.height + + # make it bigger in window + # size should be at least 600 + if max(width,height) < 300: + ratio = min(600/float(width),600/float(height)) + width = ratio*width + height = ratio*height + # or 2x bigger + else: + width = 2*width + height = 2*height + + ratio = min(float(width)/im_width,float(height)/im_height) #calculate resizing ratio + new_width = int(im_width*ratio) + new_height = int(im_height*ratio) + # resize to fit popup window + im = im1.resize((new_width, new_height), Image.BILINEAR) + # save + self.image_file_big = self.temp+"06.jpg" + im.save( self.image_file_big ) + # set image + self.popup_image.set_from_file( self.image_file_big ) + # show window + self.img_popup.show() - ## signals / glade callbacks - # - def on_pointer_motion(self, source=None, event=None): - pass -# (x,y,state) = self.main_window.window.get_pointer() -# (wxim, wyim ) = self.main_image.get_size_request() -# if x > 16+(wxim-self.new_width)/2 and x < 16+(wxim+self.new_width)/2 and y > 75+(wyim-self.new_height)/2 and y < 75+(wyim+self.new_height)/2: -# if not self.img_popup.get_visible(): -# self.on_main_image_eventbox_button_press_event() - - def on_main_image_eventbox_button_press_event(self, source=None, event=None): - if self.img_popup.get_visible(): - # clean-up - os.remove( self.image_file_big ) - # hide window - self.img_popup.hide() - else: - # load original image - im1 = Image.open(self.imageFile) - # adjust width and height to your needs and keep ratio - (im_width, im_height) = im1.size #get image size - # get size of shown image - width = self.main_image.allocation.width - height = self.main_image.allocation.height - - # make it bigger in window - # size should be at least 600 - if max(width,height) < 300: - ratio = min(600/float(width),600/float(height)) - width = ratio*width - height = ratio*height - # or 2x bigger - else: - width = 2*width - height = 2*height - - ratio = min(float(width)/im_width,float(height)/im_height) #calculate resizing ratio - new_width = int(im_width*ratio) - new_height = int(im_height*ratio) - # resize to fit popup window - im = im1.resize((new_width, new_height), Image.BILINEAR) - # save - self.image_file_big = self.temp+"06.jpg" - im.save( self.image_file_big ) - # set image - self.popup_image.set_from_file( self.image_file_big ) - # show window - self.img_popup.show() + + ## add device to blacklist + def blacklist_add(self, widget=None): + BlacklistMgr.blacklist_add() + + ## remove device from blacklist + def blacklist_remove(self, widget=None): + BlacklistMgr.blacklist_remove() + + ## one of the placement coordinates changed + def on_placement_value_changed(self, source=None, event=None): + self.scan_koords = (self.position_x.get_value(),self.position_y.get_value(), + self.size_x.get_value(),self.size_y.get_value()) - - ## add device to blacklist - def blacklist_add(self, widget=None): - BlacklistMgr.blacklist_add() - - ## remove device from blacklist - def blacklist_remove(self, widget=None): - BlacklistMgr.blacklist_remove() - - ## one of the placement coordinates changed - def on_placement_value_changed(self, source=None, event=None): - self.scan_koords = (self.position_x.get_value(),self.position_y.get_value(), - self.size_x.get_value(),self.size_y.get_value()) + ## Orientation changed + def on_orientation_changed(self, source=None, event=None): + orient = self.orientation.get_model()[self.orientation.get_active()][0] - ## Orientation changed - def on_orientation_changed(self, source=None, event=None): - orient = self.orientation.get_model()[self.orientation.get_active()][0] + self.position_x.set_value(std_scan_koords[orient][0][0]) + self.position_y.set_value(std_scan_koords[orient][0][1]) + self.size_x.set_value(std_scan_koords[orient][0][2]) + self.size_y.set_value(std_scan_koords[orient][0][3]) - self.position_x.set_value(std_scan_koords[orient][0][0]) - self.position_y.set_value(std_scan_koords[orient][0][1]) - self.size_x.set_value(std_scan_koords[orient][0][2]) - self.size_y.set_value(std_scan_koords[orient][0][3]) + self.mode = std_scan_koords[orient][1] + + ## mode changed + def on_mode_changed(self, source=None): + op_mode = self.mode_combobox.get_active() + if (op_mode == self.MDE['invoices']): + self.toggle_placement_sensitive(True) + self.toggle_orientation_sensitive(True) + elif (op_mode == self.MDE['barcode']): + self.toggle_placement_sensitive(False) + self.toggle_orientation_sensitive(True) + elif (op_mode == self.MDE['DataMatrix']): + self.toggle_placement_sensitive(False) + self.toggle_orientation_sensitive(False) + elif (op_mode == self.MDE['PDF417']): + self.toggle_placement_sensitive(True) + self.toggle_orientation_sensitive(True) - self.mode = std_scan_koords[orient][1] - - ## mode changed - def on_mode_changed(self, source=None): - op_mode = self.mode_combobox.get_active() - if (op_mode == self.MDE['invoices']): - self.toggle_placement_sensitive(True) - self.toggle_orientation_sensitive(True) - elif (op_mode == self.MDE['barcode']): - self.toggle_placement_sensitive(False) - self.toggle_orientation_sensitive(True) - elif (op_mode == self.MDE['DataMatrix']): - self.toggle_placement_sensitive(False) - self.toggle_orientation_sensitive(False) - elif (op_mode == self.MDE['PDF417']): - self.toggle_placement_sensitive(True) - self.toggle_orientation_sensitive(True) + ## ToggleButton: 'scan'/'stop'. + def on_scan_button_clicked(self, source=None, event=None, *a): + if self.scan_button.get_active(): # scan ! + # test if we ask for a scanner, but there is none connected + if not self.run_sane.found_scanner and self.sane_input_button.get_active(): + self.__stop = True + self.scan_button.set_active(False) + return + + self.scan_button.set_label("stop") + self.__stop = False - ## ToggleButton: 'scan'/'stop'. - def on_scan_button_clicked(self, source=None, event=None, *a): - if self.scan_button.get_active(): # scan ! - # test if we ask for a scanner, but there is none connected - if not self.run_sane.found_scanner and self.sane_input_button.get_active(): - self.__stop = True - self.scan_button.set_active(False) - return - - self.scan_button.set_label("stop") - self.__stop = False + self.output.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) # widget color + self.refresh() - self.output.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) # widget color - self.refresh() + for i in range(self.max_retry): + check = self.scancode() + if check or (check == None) or self.__stop: break + if self.__stop: return - for i in range(self.max_retry): - check = self.scancode() - if check or (check == None) or self.__stop: break - if self.__stop: return + self.output.modify_base(gtk.STATE_NORMAL, self.res_color[check]) # widget color + self.refresh() - self.output.modify_base(gtk.STATE_NORMAL, self.res_color[check]) # widget color - self.refresh() + self.__stop = True # other way around; to be able to decide if it was stopped or ended correctly + self.scan_button.set_active(False) # (since this triggers THIS function again) + else: # stop/abort ! + self.scan_button.set_label("scan") + if self.__stop: return + self.__stop = True - self.__stop = True # other way around; to be able to decide if it was stopped or ended correctly - self.scan_button.set_active(False) # (since this triggers THIS function again) - else: # stop/abort ! - self.scan_button.set_label("scan") - if self.__stop: return - self.__stop = True + self.output.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) # widget color + self.progressbar.set_text("Stopped by user!") + self.refresh() + return - self.output.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) # widget color - self.progressbar.set_text("Stopped by user!") - self.refresh() - return + ## exit and restart + def on_retry_button_clicked(self, source=None, event=None): + self.device_chooser_event.clear() + self.run_sane.retry() - ## exit and restart - def on_retry_button_clicked(self, source=None, event=None): - self.device_chooser_event.clear() - self.run_sane.retry() + ## exit + def on_exit_button_clicked(self, source=None, event=None): + self.on_main_window_destroy() - ## exit - def on_exit_button_clicked(self, source=None, event=None): - self.on_main_window_destroy() + ## press x-button on window + def on_main_window_destroy(self, source=None, event=None): + try: + os.remove( self.temp+"04.jpg" ) # clean-up + os.remove( self.image_file_small ) + except: + pass + # exit + gtk.main_quit() - ## press x-button on window - def on_main_window_destroy(self, source=None, event=None): - try: - os.remove( self.temp+"04.jpg" ) # clean-up - os.remove( self.image_file_small ) - except: - pass - # exit - gtk.main_quit() + ## file selected + def on_filechooserbutton_file_set(self, source=None): + self.file_input_button.set_active(True) + self.inp_file = self.filechooserbutton.get_filename() + if not os.path.exists(self.inp_file): + self.progress(0., "File not found!") + return None + self.setimage(self.inp_file) - ## file selected - def on_filechooserbutton_file_set(self, source=None): - self.file_input_button.set_active(True) - self.inp_file = self.filechooserbutton.get_filename() - if not os.path.exists(self.inp_file): - self.progress(0., "File not found!") - return None - self.setimage(self.inp_file) + # helpers + # + ## Main scanning and number recognition procedure. + # + # @todo Put this function (may be as class with functions for each step) into utils::ocr + # + def scancode(self): + # Initialization of scanning process + # (0/7) + self.progress(0., "") + max_steps = 7 + op_mode = self.mode_combobox.get_active() + source_mode = self.sane_input_button.get_active() + if (op_mode == self.MDE['invoices']): # 0: invoices (tesser) + self.on_placement_value_changed() # scan selected range + self.on_orientation_changed() # orientation mode + opt = { 'tmp_file': "02.tif", + 'recog_class': utils.RunExternal, + 'recog_cmd': self.cmd_tesser % (self.temp+"02", self.temp+"03"), + 'recog_error_msg': [ "Unable" ], + 'valid_code_len': self.valid_code_len, + 'resolution': 600, } + elif (op_mode == self.MDE['barcode']): # 1: barcode (gocr) + self.on_orientation_changed() # orientation mode + self.scan_koords = std_scan_koords["A4"][0] + #self.mode = std_scan_koords["A4"][1] + opt = { 'tmp_file': "02.pnm", + 'recog_class': utils.RunExternal, + 'recog_cmd': self.cmd_gocr % (self.temp+"02",), + 'recog_error_msg': [ "\nERROR pnm.c" ], + 'valid_code_len': [ 13, 10, 9 ], + 'resolution': 300, } + elif (op_mode == self.MDE['DataMatrix']): # 2: DataMatrix (libdmtx) + #self.on_orientation_changed() # orientation mode + self.scan_koords = std_scan_koords["A4"][0] + self.mode = std_scan_koords["A4"][1] + #pydmtx recognition +# opt = { 'tmp_file': "02.jpg", # some issues with recogition +# 'recog_class': utils.RunLibdmtx, # . +# 'recog_cmd': self.temp+"02.jpg", # of different file formats +# 'recog_error_msg': [ None ], # . + #dmtxread recognition + opt = { 'tmp_file': "02.jpg", # some issues with recogition + 'recog_class': utils.RunExternal, # . + 'recog_cmd': "%s -v -D %s02.jpg"%(paths["dmtxread"],self.temp), # of different file formats + 'recog_error_msg': [ "error" ], # . + #opt = { 'tmp_file': "02.bmp", # and drawing/marking the + # 'recog_cmd': (self.temp+"02.bmp", [ None ], utils.ocr.RunLibdmtx), } # processed region(s)... + #opt = { 'tmp_file': "02.png", # (but this should work for 'tif') + # 'recog_cmd': (self.temp+"02.png", [ None ], utils.ocr.RunLibdmtx), } # + 'resolution': 150, } + elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) + self.on_placement_value_changed() # scan selected range + self.on_orientation_changed() # orientation mode + opt = { 'tmp_file': "02.png", + 'recog_class': utils.RunExternal, + 'recog_cmd': self.cmd_pdf417dec % (self.temp+"02",), + 'recog_error_msg': [ "wine: cannot find", "pdf417decode.exe imagefile|string.txt|-i", "Decoding failed." ], + 'resolution': 300, } - # helpers - # - ## Main scanning and number recognition procedure. - # - # @todo Put this function (may be as class with functions for each step) into utils::ocr - # - def scancode(self): - # Initialization of scanning process - # (0/7) - self.progress(0., "") - max_steps = 7 - op_mode = self.mode_combobox.get_active() - source_mode = self.sane_input_button.get_active() - if (op_mode == self.MDE['invoices']): # 0: invoices (tesser) - self.on_placement_value_changed() # scan selected range - self.on_orientation_changed() # orientation mode - opt = { 'tmp_file': "02.tif", - 'recog_class': utils.RunExternal, - 'recog_cmd': self.cmd_tesser % (self.temp+"02", self.temp+"03"), - 'recog_error_msg': [ "Unable" ], - 'valid_code_len': self.valid_code_len, - 'resolution': 600, } - elif (op_mode == self.MDE['barcode']): # 1: barcode (gocr) - self.on_orientation_changed() # orientation mode - self.scan_koords = std_scan_koords["A4"][0] - #self.mode = std_scan_koords["A4"][1] - opt = { 'tmp_file': "02.pnm", - 'recog_class': utils.RunExternal, - 'recog_cmd': self.cmd_gocr % (self.temp+"02",), - 'recog_error_msg': [ "\nERROR pnm.c" ], - 'valid_code_len': [ 13, 10, 9 ], - 'resolution': 300, } - elif (op_mode == self.MDE['DataMatrix']): # 2: DataMatrix (libdmtx) - #self.on_orientation_changed() # orientation mode - self.scan_koords = std_scan_koords["A4"][0] - self.mode = std_scan_koords["A4"][1] - #pydmtx recognition -# opt = { 'tmp_file': "02.jpg", # some issues with recogition -# 'recog_class': utils.RunLibdmtx, # . -# 'recog_cmd': self.temp+"02.jpg", # of different file formats -# 'recog_error_msg': [ None ], # . - #dmtxread recognition - opt = { 'tmp_file': "02.jpg", # some issues with recogition - 'recog_class': utils.RunExternal, # . - 'recog_cmd': "%s -v -D %s02.jpg"%(paths["dmtxread"],self.temp), # of different file formats - 'recog_error_msg': [ "error" ], # . - - #opt = { 'tmp_file': "02.bmp", # and drawing/marking the - # 'recog_cmd': (self.temp+"02.bmp", [ None ], utils.ocr.RunLibdmtx), } # processed region(s)... - #opt = { 'tmp_file': "02.png", # (but this should work for 'tif') - # 'recog_cmd': (self.temp+"02.png", [ None ], utils.ocr.RunLibdmtx), } # - 'resolution': 150, } - elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) - self.on_placement_value_changed() # scan selected range - self.on_orientation_changed() # orientation mode - opt = { 'tmp_file': "02.png", - 'recog_class': utils.RunExternal, - 'recog_cmd': self.cmd_pdf417dec % (self.temp+"02",), - 'recog_error_msg': [ "wine: cannot find", "pdf417decode.exe imagefile|string.txt|-i", "Decoding failed." ], - 'resolution': 300, } + #os.chdir(home_path) # (still needed?) + self.refresh() + if self.__stop: return - #os.chdir(home_path) # (still needed?) - self.refresh() - if self.__stop: return + # Scaning and retrieving data OR reading from image file + # (tesseract has a direct python interface: http://code.google.com/p/pytesser/) + # (1/?) + if source_mode: # SANE scanning interface + self.progress(1./max_steps, "Scanning data...") + self.inp_file = self.temp+"01.tif" + #self.run_sane = utils.ocr.RunExternal(self.cmd_scan % ( self.scan_koords + (inp_file,) ), [ "no SANE devices found" ]) + self.run_sane.post_init(self.scan_koords, self.inp_file) # utils.ocr.RunSANE().post_init(...) 2nd part of __init__(...) + self.run_sane.resolution = opt["resolution"] + if self.run_sane(): + print self.run_sane.stderr + self.progress(0., self.run_sane.stderr) + return None + #del self.run_sane + else: # direct file input + self.progress(1./max_steps, "Reading image...") + #self.inp_file = self.filechooserbutton.get_filename() + #if not os.path.exists(self.inp_file): + # self.progress(0., "File not found!") + # return None + self.refresh() + if self.__stop: return - # Scaning and retrieving data OR reading from image file - # (tesseract has a direct python interface: http://code.google.com/p/pytesser/) - # (1/?) - if source_mode: # SANE scanning interface - self.progress(1./max_steps, "Scanning data...") - self.inp_file = self.temp+"01.tif" - #self.run_sane = utils.ocr.RunExternal(self.cmd_scan % ( self.scan_koords + (inp_file,) ), [ "no SANE devices found" ]) - self.run_sane.post_init(self.scan_koords, self.inp_file) # utils.ocr.RunSANE().post_init(...) 2nd part of __init__(...) - self.run_sane.resolution = opt["resolution"] - if self.run_sane(): - print self.run_sane.stderr - self.progress(0., self.run_sane.stderr) - return None - #del self.run_sane - else: # direct file input - self.progress(1./max_steps, "Reading image...") - #self.inp_file = self.filechooserbutton.get_filename() - #if not os.path.exists(self.inp_file): - # self.progress(0., "File not found!") - # return None - self.refresh() - if self.__stop: return + # Adjust and rotate the retrieved data + # (2/?) + self.progress(2./max_steps, "Adjusting image/picture data...") + mode = self.mode + try: + self.inp_file + except: + print "No input file. Please select input file or SANE Interface." + self.progress(0., "No input file. Please select input file or SANE Interface.") + return None + self.run_convert = utils.RunExternal(self.cmd_convert % (self.inp_file, mode, self.temp+opt['tmp_file']), error_msg=[ "convert: unable to open image" ]) +# self.run_convert = utils.RunMagickWand(inp_file, mode*90, self.temp+opt['tmp_file']) + # improve quality by using imagemagicks filter and conversion capabilities... + if self.run_convert(): + self.progress(0., self.run_convert.stderr[:-1]) + return None + #if (op_mode == self.MDE['invoices']): # 0: invoices + self.setimage( self.temp+opt['tmp_file'] ) + if source_mode: # SANE scanning interface + os.remove(self.inp_file) # clean-up + del self.run_convert + self.refresh() + if self.__stop: return - # Adjust and rotate the retrieved data - # (2/?) - self.progress(2./max_steps, "Adjusting image/picture data...") - mode = self.mode - try: - self.inp_file - except: - print "No input file. Please select input file or SANE Interface." - self.progress(0., "No input file. Please select input file or SANE Interface.") - return None - self.run_convert = utils.RunExternal(self.cmd_convert % (self.inp_file, mode, self.temp+opt['tmp_file']), error_msg=[ "convert: unable to open image" ]) -# self.run_convert = utils.RunMagickWand(inp_file, mode*90, self.temp+opt['tmp_file']) - # improve quality by using imagemagicks filter and conversion capabilities... - if self.run_convert(): - self.progress(0., self.run_convert.stderr[:-1]) - return None - #if (op_mode == self.MDE['invoices']): # 0: invoices - self.setimage( self.temp+opt['tmp_file'] ) - if source_mode: # SANE scanning interface - os.remove(self.inp_file) # clean-up - del self.run_convert - self.refresh() - if self.__stop: return + # Data character recognition / Barcode search and recognition + # (3/?) + self.progress(3./max_steps, "Recognition...") + self.run_recognition = opt['recog_class'](opt['recog_cmd'], error_msg=opt['recog_error_msg']) + if self.run_recognition(): + # create debug info output + os.rename(self.temp+opt['tmp_file'], self.debug[0]+opt['tmp_file'][-4:]) + #print "debug info output in '%s'" % self.debug[0] - # Data character recognition / Barcode search and recognition - # (3/?) - self.progress(3./max_steps, "Recognition...") - self.run_recognition = opt['recog_class'](opt['recog_cmd'], error_msg=opt['recog_error_msg']) - if self.run_recognition(): - # create debug info output - os.rename(self.temp+opt['tmp_file'], self.debug[0]+opt['tmp_file'][-4:]) - #print "debug info output in '%s'" % self.debug[0] + print self.run_recognition.stderr[:-1] + " Look at debug info!" + self.progress(0., self.run_recognition.stderr[:-1] + " Look at debug info!") + return None - print self.run_recognition.stderr[:-1] + " Look at debug info!" - self.progress(0., self.run_recognition.stderr[:-1] + " Look at debug info!") - return None + if (op_mode == self.MDE['invoices']): # 0: invoices + # Simple workaround: The program simply continuous if no text is found at all + # and therefore no txt-file is generated. + if not os.path.exists(self.temp+"03.txt"): + origdata = "$" + data = "$" + else: + df = file(self.temp+"03.txt", "r") + data = df.read(-1) + df.close() + origdata = data + os.remove(self.temp+"03.txt") # clean-up + + elif (op_mode == self.MDE['barcode']): # 1: barcode + # (cheap'n'ugly but working...) + raw_data = self.regex_gocr.search(self.run_recognition.stdout).groups() + raw_data = raw_data[0].strip() + raw_data = raw_data.replace("=", ":") + raw_data = raw_data.replace('" ', '", "') + raw_data = raw_data.replace(':"', '":"') + raw_data = '{ "' + raw_data + ' }' + data = eval( raw_data ) + origdata = str(data) + elif (op_mode == self.MDE['DataMatrix']): # 2: DataMatrix (libdmtx) + data = self.run_recognition.stdout + #pydmtx recognition +# if self.run_recognition.count == 1: +# data = self.run_recognition.message[0] +# else: +# data = str(self.run_recognition.message) +# origdata = str(self.run_recognition.stats) + elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) + data = self.run_recognition.stdout.split("\r\n")[1] + origdata = data + self.refresh() + if self.__stop: return - if (op_mode == self.MDE['invoices']): # 0: invoices - # Simple workaround: The program simply continuous if no text is found at all - # and therefore no txt-file is generated. - if not os.path.exists(self.temp+"03.txt"): - origdata = "$" - data = "$" - else: - df = file(self.temp+"03.txt", "r") - data = df.read(-1) - df.close() - origdata = data - os.remove(self.temp+"03.txt") # clean-up - - elif (op_mode == self.MDE['barcode']): # 1: barcode - # (cheap'n'ugly but working...) - raw_data = self.regex_gocr.search(self.run_recognition.stdout).groups() - raw_data = raw_data[0].strip() - raw_data = raw_data.replace("=", ":") - raw_data = raw_data.replace('" ', '", "') - raw_data = raw_data.replace(':"', '":"') - raw_data = '{ "' + raw_data + ' }' - data = eval( raw_data ) - origdata = str(data) - elif (op_mode == self.MDE['DataMatrix']): # 2: DataMatrix (libdmtx) - data = self.run_recognition.stdout - #pydmtx recognition -# if self.run_recognition.count == 1: -# data = self.run_recognition.message[0] -# else: -# data = str(self.run_recognition.message) -# origdata = str(self.run_recognition.stats) - elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) - data = self.run_recognition.stdout.split("\r\n")[1] - origdata = data - self.refresh() - if self.__stop: return + # Data character correction + # (4/?) + if (op_mode == self.MDE['invoices']): # 0: invoices + self.progress(4./max_steps, "Character correction...") + print "*** " * 10 + data = utils.ocr.char_correction(data) + self.refresh() + if self.__stop: return - # Data character correction - # (4/?) - if (op_mode == self.MDE['invoices']): # 0: invoices - self.progress(4./max_steps, "Character correction...") - print "*** " * 10 - data = utils.ocr.char_correction(data) - self.refresh() - if self.__stop: return + # Data validity check + # (5/?) + self.progress(5./max_steps, "Check on validity...") + if (op_mode == self.MDE['invoices']): # 0: invoices + check = (not "?" in data) or (not "!" in data) # any unrecognized char in code? + check = check and ( len(data) in opt['valid_code_len'] ) # correct code len? + if check: + tmp = data[:-1].split(">") + amount = tmp[0] + tmp = tmp[1].split("+ ") + reference = tmp[0] + account = tmp[1] + # initialize modulo10 checksum + m10 = modulo10(amount, account, reference) + # check amount, account number and reference number + print "Amount: " + str(m10.amount) +" "+ str(m10.checksum_b) + print "Account number: " +str(m10.account) +" "+ str(m10.checksum_k) + print "Reference number: "+ str(m10.reference) +" "+ str(m10.checksum_r) + + checksum = m10.checksum + +# if len(data) == 42: +# # extract details +# (tmp, betrag, tmp, referenz, tmp, konto, tmp) = struct.unpack("2s11ss16s2s9ss",data) +# print "Betrag: "+str(int(betrag[:-1])/100.) +# print "Konto: "+konto[:2]+"-"+konto[3:-2]+"-"+konto[-2:] +# print "Referenznr: "+referenz +# if check: +# # modulo10 checksum for betrag +# checknr = modulo10().run(betrag[:-1]) +# print "Checknr: ",checknr +# checknr = ( checknr == int(betrag[-1]) ) + elif (op_mode == self.MDE['barcode']): # 1: barcode + check = not (data['type'] == "unknown") + if check: + check = check and ( int(data['crc']) == 0 ) # CRC error check? + check = check and (float(data['error']) < 0.15) # recognizion errors? + print 'type:' +" "+ data['type'] + print 'chars:' +" "+ data['chars'] + print 'crc:' +" "+ data['crc'] + print 'error:' +" "+ data['error'] + data = data['code'] + else: + data = "type: " + data['type'] + #check = check and ( len(data) in opt['valid_code_len'] ) # correct code len? + elif (op_mode == self.MDE['DataMatrix']): # 2: DataMatrix (libdmtx) + check = not (self.run_recognition.error == "error") + #pydmtx recognition +# check = not self.run_recognition.error +# if check: +# print self.run_recognition.decode +# print self.run_recognition.count +# #print self.run_recognition.message +# print self.run_recognition.stats + + elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) + check = not self.run_recognition.error + print data +" "+ str(len(data)) +" "+ str(check) + del self.run_recognition + self.refresh() + if self.__stop: return - # Data validity check - # (5/?) - self.progress(5./max_steps, "Check on validity...") - if (op_mode == self.MDE['invoices']): # 0: invoices - check = (not "?" in data) or (not "!" in data) # any unrecognized char in code? - check = check and ( len(data) in opt['valid_code_len'] ) # correct code len? - if check: - tmp = data[:-1].split(">") - amount = tmp[0] - tmp = tmp[1].split("+ ") - reference = tmp[0] - account = tmp[1] - # initialize modulo10 checksum - m10 = modulo10(amount, account, reference) - # check amount, account number and reference number - print "Amount: " + str(m10.amount) +" "+ str(m10.checksum_b) - print "Account number: " +str(m10.account) +" "+ str(m10.checksum_k) - print "Reference number: "+ str(m10.reference) +" "+ str(m10.checksum_r) - - checksum = m10.checksum - -# if len(data) == 42: -# # extract details -# (tmp, betrag, tmp, referenz, tmp, konto, tmp) = struct.unpack("2s11ss16s2s9ss",data) -# print "Betrag: "+str(int(betrag[:-1])/100.) -# print "Konto: "+konto[:2]+"-"+konto[3:-2]+"-"+konto[-2:] -# print "Referenznr: "+referenz -# if check: -# # modulo10 checksum for betrag -# checknr = modulo10().run(betrag[:-1]) -# print "Checknr: ",checknr -# checknr = ( checknr == int(betrag[-1]) ) - elif (op_mode == self.MDE['barcode']): # 1: barcode - check = not (data['type'] == "unknown") - if check: - check = check and ( int(data['crc']) == 0 ) # CRC error check? - check = check and (float(data['error']) < 0.15) # recognizion errors? - print 'type:' +" "+ data['type'] - print 'chars:' +" "+ data['chars'] - print 'crc:' +" "+ data['crc'] - print 'error:' +" "+ data['error'] - data = data['code'] - else: - data = "type: " + data['type'] - #check = check and ( len(data) in opt['valid_code_len'] ) # correct code len? - elif (op_mode == self.MDE['DataMatrix']): # 2: DataMatrix (libdmtx) - check = not (self.run_recognition.error == "error") - #pydmtx recognition -# check = not self.run_recognition.error -# if check: -# print self.run_recognition.decode -# print self.run_recognition.count -# #print self.run_recognition.message -# print self.run_recognition.stats - - elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) - check = not self.run_recognition.error - print data +" "+ str(len(data)) +" "+ str(check) - del self.run_recognition - self.refresh() - if self.__stop: return + # Data final output + # (6/?) + self.progress(6./max_steps, "Final data output...") + if check: + os.remove(self.temp+opt['tmp_file']) # clean-up - # Data final output - # (6/?) - self.progress(6./max_steps, "Final data output...") - if check: - os.remove(self.temp+opt['tmp_file']) # clean-up + self.output.set_text(data) - self.output.set_text(data) + # get the clipboard + clipboard = gtk.clipboard_get() + # set the clipboard text data + clipboard.set_text(data) + # make our data available to other applications + clipboard.store() + #print "data sent to (gtk/gnome) clipboard" + if checksum: + self.progress(1., "Code recognized and sent to clipboard. Finished.") + else: + self.progress(1., "Code recognized and sent to clipboard, BUT checksum failed! CHECK code again! Finished.") + else: + # create debug info output + log = file(self.debug[1], "w") + for i in range(len(origdata)): + log.write(str( (origdata[i], ord(origdata[i])) )) + log.write("\n") + for i in range(len(data)): + log.write(str( (data[i], ord(data[i])) )) + log.close() + #print "debug info output in '%s'" % self.debug[1] + os.rename(self.temp+opt['tmp_file'], self.debug[0]+opt['tmp_file'][-4:]) + #print "debug info output in '%s'" % self.debug[0] - # get the clipboard - clipboard = gtk.clipboard_get() - # set the clipboard text data - clipboard.set_text(data) - # make our data available to other applications - clipboard.store() - #print "data sent to (gtk/gnome) clipboard" - if checksum: - self.progress(1., "Code recognized and sent to clipboard. Finished.") - else: - self.progress(1., "Code recognized and sent to clipboard, BUT checksum failed! CHECK code again! Finished.") - else: - # create debug info output - log = file(self.debug[1], "w") - for i in range(len(origdata)): - log.write(str( (origdata[i], ord(origdata[i])) )) - log.write("\n") - for i in range(len(data)): - log.write(str( (data[i], ord(data[i])) )) - log.close() - #print "debug info output in '%s'" % self.debug[1] - os.rename(self.temp+opt['tmp_file'], self.debug[0]+opt['tmp_file'][-4:]) - #print "debug info output in '%s'" % self.debug[0] + self.progress(1., "Code could not be recognized correct. Look at debug info!") + self.refresh() + if self.__stop: return - self.progress(1., "Code could not be recognized correct. Look at debug info!") - self.refresh() - if self.__stop: return + # Done + # (7/7) + return check - # Done - # (7/7) - return check + ## Refresh window during running processes. + def refresh(self): + self.main_window.queue_draw() + time.sleep(0.1) # give also some time to the user... :) + while gtk.events_pending(): + gtk.main_iteration() - ## Refresh window during running processes. - def refresh(self): - self.main_window.queue_draw() - time.sleep(0.1) # give also some time to the user... :) - while gtk.events_pending(): - gtk.main_iteration() + ## Resize and set PIL image to gtk/gnome window. + # resize an image using the PIL image library + # tested with Python24 vegaseat 11oct2005 + # open an image file (.bmp,.jpg,.png,.gif) you have in the working folder + # @see http://www.daniweb.com/code/snippet216637.html + # @see http://www.pythonware.com/products/pil/index.htm + def setimage(self, imageFile): + print imageFile[-3:] + if imageFile[-3:] in ["bmp","jpg","png","gif"]: + #already in right format + # original file name + self.imageFile = imageFile + # load file + im1 = Image.open(self.imageFile) + else: + #convert Image + self.run_convert = utils.RunExternal(self.cmd_convert % (imageFile, 0, self.temp+"04.jpg"), error_msg=[ "convert: unable to open image" ]) + if self.run_convert(): + self.progress(0., self.run_convert.stderr[:-1]) + return None + # original filename + self.imageFile = self.temp+"04.jpg" + # load file + im1 = Image.open(self.imageFile) + + # adjust width and height to your needs and keep ratio + (im_width, im_height) = im1.size #get image size + #get needed size + width = self.main_image.allocation.width + height = self.main_image.allocation.height + ratio = min(float(width)/im_width,float(height)/im_height) #calculate resizing ratio + self.new_width = int(im_width*ratio) + self.new_height = int(im_height*ratio) + + # use one of these filter options to resize the image + + #im = im1.resize((new_width, new_height), Image.NEAREST) # use nearest neighbour + im = im1.resize((self.new_width, self.new_height), Image.BILINEAR) # linear interpolation in a 2x2 environment + #im = im1.resize((new_width, new_height), Image.BICUBIC) # cubic spline interpolation in a 4x4 environment + #im = im1.resize((new_width, new_height), Image.ANTIALIAS) # best down-sizing filter + #ext = ".jpg" + + # set image preview + self.image_file_small = self.temp+"05.jpg" + im.save( self.image_file_small ) + self.main_image.set_from_file( self.image_file_small ) - ## Resize and set PIL image to gtk/gnome window. - # resize an image using the PIL image library - # tested with Python24 vegaseat 11oct2005 - # open an image file (.bmp,.jpg,.png,.gif) you have in the working folder - # @see http://www.daniweb.com/code/snippet216637.html - # @see http://www.pythonware.com/products/pil/index.htm - def setimage(self, imageFile): - print imageFile[-3:] - if imageFile[-3:] in ["bmp","jpg","png","gif"]: - #already in right format - # original file name - self.imageFile = imageFile - # load file - im1 = Image.open(self.imageFile) - else: - #convert Image - self.run_convert = utils.RunExternal(self.cmd_convert % (imageFile, 0, self.temp+"04.jpg"), error_msg=[ "convert: unable to open image" ]) - if self.run_convert(): - self.progress(0., self.run_convert.stderr[:-1]) - return None - # original filename - self.imageFile = self.temp+"04.jpg" - # load file - im1 = Image.open(self.imageFile) - - # adjust width and height to your needs and keep ratio - (im_width, im_height) = im1.size #get image size - #get needed size - width = self.main_image.allocation.width - height = self.main_image.allocation.height - ratio = min(float(width)/im_width,float(height)/im_height) #calculate resizing ratio - self.new_width = int(im_width*ratio) - self.new_height = int(im_height*ratio) - - # use one of these filter options to resize the image - - #im = im1.resize((new_width, new_height), Image.NEAREST) # use nearest neighbour - im = im1.resize((self.new_width, self.new_height), Image.BILINEAR) # linear interpolation in a 2x2 environment - #im = im1.resize((new_width, new_heigh... [truncated message content] |
From: <la...@us...> - 2011-07-27 13:51:41
|
Revision: 57 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=57&view=rev Author: laserb Date: 2011-07-27 13:51:33 +0000 (Wed, 27 Jul 2011) Log Message: ----------- + Display infos about devices in corresponding tab + Display log in tab instead of terminal + Added program icon, needs to be improved, feel free to change it if you have a better idea Modified Paths: -------------- trunk/PyCodeOCR.py trunk/utils/__init__.py trunk/utils/ocr.py Added Paths: ----------- trunk/PyCodeOCR.png trunk/PyCodeOCR.svg trunk/utils/logging.py Added: trunk/PyCodeOCR.png =================================================================== (Binary files differ) Property changes on: trunk/PyCodeOCR.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-07-27 07:36:33 UTC (rev 56) +++ trunk/PyCodeOCR.py 2011-07-27 13:51:33 UTC (rev 57) @@ -122,15 +122,6 @@ "A4": (( 0, 0, 296, 215 ), 0), } # scan whole range (A4: http://www.cl.cam.ac.uk/~mgk25/iso-paper.html) #"A4": (( 0, 0, 290, 210 ), 0), } # (more secure; with small border) -## redirect print to textbuffer instead of shell -class logging: - def __init__(self, textbuffer): - self.textbuffer = textbuffer - - def write(self, text): - enditer = self.textbuffer.get_end_iter() - self.textbuffer.insert(enditer,"%s" % text ) - ## MainWindow # The GUI was created/designed using GLADE # @@ -181,6 +172,7 @@ # get objects from glade/GTKBuilder ## main window self.main_window = self.builder.get_object('main_window') + self.main_window.set_icon_from_file(raw_path+".png") ## notebok self.notebook = self.builder.get_object('notebook') ## image window @@ -201,7 +193,7 @@ self.output = self.builder.get_object('output') self.log_text = self.builder.get_object('log_text') self.textbuffer = self.log_text.get_buffer() - self.entry3 = self.builder.get_object('device_info_text') + self.device_info_text = self.builder.get_object('device_info_text') ## progressbar self.progressbar = self.builder.get_object('progressbar') ## Orientation label @@ -269,9 +261,9 @@ # redirect print - self.logging = logging(self.textbuffer) -# sys.stdout = self.logging -# sys.stderr = self.logging + self.logging = utils.logging(self.textbuffer) + sys.stdout = self.logging + sys.stderr = self.logging # initialize treeviews in Blacklist Manager @@ -294,8 +286,10 @@ self.device_chooser_event = threading.Event() ## initialize sane - self.run_sane = utils.ocr.RunSANE(self.notebook, self.progress, self.device_chooser_button, BlacklistMgr,self.device_chooser_event) + self.run_sane = utils.ocr.RunSANE(self.notebook, self.progress, self.device_chooser_button, BlacklistMgr,self.device_chooser_event,self.device_info_text) self.run_sane.start() + # redirect print again to old textbuffer + sys.stdout = self.logging gtk.main() Added: trunk/PyCodeOCR.svg =================================================================== --- trunk/PyCodeOCR.svg (rev 0) +++ trunk/PyCodeOCR.svg 2011-07-27 13:51:33 UTC (rev 57) @@ -0,0 +1,739 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="96" + height="96" + id="svg2408" + inkscape:version="0.48.2 r9819" + sodipodi:docname="pyCodeOCR.svg"> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1676" + inkscape:window-height="993" + id="namedview60" + showgrid="false" + inkscape:zoom="2.4583333" + inkscape:cx="-19.728814" + inkscape:cy="48" + inkscape:window-x="0" + inkscape:window-y="26" + inkscape:window-maximized="0" + inkscape:current-layer="svg2408" /> + <defs + id="defs2410"> + <inkscape:path-effect + effect="envelope" + id="path-effect5517" + is_visible="true" + yy="true" + xx="true" + bendpath1="m -104.1387,-70.660316 92.329171,0" + bendpath2="m -11.809529,-70.660316 0,49.999931" + bendpath3="m -104.1387,-20.660385 92.329171,0" + bendpath4="m -104.1387,-70.660316 0,49.999931" /> + <linearGradient + id="linearGradient5503"> + <stop + style="stop-color:#000000;stop-opacity:0.77631581;" + offset="0" + id="stop5505" /> + <stop + id="stop5515" + offset="0.71120352" + style="stop-color:#000000;stop-opacity:0.9868421;" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop5507" /> + </linearGradient> + <inkscape:path-effect + effect="envelope" + id="path-effect5493" + is_visible="true" + yy="true" + xx="true" + bendpath1="m -102.95333,-67.077292 c 48.568167,-40.285028 53.09126,32.208086 91.045264,42.239695" + bendpath2="m -11.908066,-24.837597 0,4.254275" + bendpath3="m -103.44693,-56.118303 c 29.104665,-13.697544 33.638272,46.9089172 91.538864,35.534981" + bendpath4="m -104.9277,-73.111534 0.98718,7.606632" + bendpath1-nodetypes="cc" + bendpath3-nodetypes="cc" + bendpath4-nodetypes="cc" /> + <inkscape:path-effect + effect="envelope" + id="path-effect5491" + is_visible="true" + yy="true" + xx="false" + bendpath1="m -106.37629,-68.427295 c 33.66968,1.169568 1.67227,76.0227568 89.632807,8.045656" + bendpath2="m -11.807562,-68.427295 0,48.744647" + bendpath3="m -106.37629,-19.682648 94.568728,0" + bendpath4="m -106.37629,-68.427295 0,48.744647" + bendpath1-nodetypes="cc" /> + <inkscape:path-effect + effect="bend_path" + id="path-effect5473" + is_visible="true" + bendpath="m -105.42129,-42.824599 c 44.735743,-67.438381 45.978505,32.051229 93.513224,20.11414" + prop_scale="1" + scale_y_rel="false" + vertical="false" + bendpath-nodetypes="cc" /> + <linearGradient + inkscape:collect="always" + id="linearGradient5350"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop5352" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop5354" /> + </linearGradient> + <linearGradient + id="linearGradient3731"> + <stop + id="stop3733" + style="stop-color:#dcdcdc;stop-opacity:1" + offset="0" /> + <stop + id="stop3757" + style="stop-color:#ebebeb;stop-opacity:1" + offset="0.30654153" /> + <stop + id="stop3737" + style="stop-color:#ffffff;stop-opacity:1" + offset="0.70706075" /> + <stop + id="stop3759" + style="stop-color:#fafafa;stop-opacity:1" + offset="0.84501493" /> + <stop + id="stop3735" + style="stop-color:#f0f0f0;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient2881"> + <stop + id="stop2883" + style="stop-color:#e4a033;stop-opacity:0.55263156;" + offset="0" /> + <stop + id="stop2885" + style="stop-color:#f08230;stop-opacity:1;" + offset="1" /> + </linearGradient> + <linearGradient + x1="45.447727" + y1="92.539597" + x2="45.447727" + y2="7.0165396" + id="ButtonShadow" + gradientUnits="userSpaceOnUse" + gradientTransform="scale(1.0058652,0.994169)"> + <stop + id="stop3750" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3752" + style="stop-color:#000000;stop-opacity:0.58823532" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3737"> + <stop + id="stop3739" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3741" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <filter + color-interpolation-filters="sRGB" + id="filter3174"> + <feGaussianBlur + id="feGaussianBlur3176" + stdDeviation="1.71" /> + </filter> + <linearGradient + x1="36.357143" + y1="6" + x2="36.357143" + y2="63.893143" + id="linearGradient3188" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" /> + <filter + x="-0.192" + y="-0.192" + width="1.3839999" + height="1.3839999" + color-interpolation-filters="sRGB" + id="filter3794"> + <feGaussianBlur + id="feGaussianBlur3796" + stdDeviation="5.28" /> + </filter> + <linearGradient + x1="48" + y1="20.220806" + x2="48" + y2="138.66119" + id="linearGradient3613" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="48" + cy="90.171875" + r="42" + fx="48" + fy="90.171875" + id="radialGradient3619" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.1573129,0,0,0.99590774,-7.5510206,0.19713193)" /> + <clipPath + id="clipPath3613"> + <rect + width="84" + height="84" + rx="6" + ry="6" + x="6" + y="6" + id="rect3615" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </clipPath> + <linearGradient + x1="48" + y1="90" + x2="48" + y2="5.9877172" + id="linearGradient3617" + xlink:href="#linearGradient2881" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="45.447727" + y1="92.539597" + x2="45.447727" + y2="7.0165396" + id="ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0058652,0,0,0.994169,100,0)"> + <stop + id="stop3750-8" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3752-5" + style="stop-color:#000000;stop-opacity:0.58823532" + offset="1" /> + </linearGradient> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3780" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3772" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3725" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3721" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,-97)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient2918" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="6.6201301" + y1="16.384687" + x2="6.6201301" + y2="1.0923122" + id="linearGradient3053" + xlink:href="#linearGradient3731" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-4.5057883,0,0,3.8842887,81.128906,14.057144)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2881" + id="linearGradient5255" + x1="6" + y1="48" + x2="90" + y2="48" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2881" + id="linearGradient5269" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" + x1="6" + y1="48" + x2="90" + y2="48" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2881" + id="linearGradient5271" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" + x1="6" + y1="48" + x2="90" + y2="48" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2881" + id="linearGradient5273" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" + x1="6" + y1="48" + x2="90" + y2="48" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5350" + id="linearGradient5356" + x1="6" + y1="48" + x2="90" + y2="48" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5350" + id="linearGradient5374" + gradientUnits="userSpaceOnUse" + x1="6" + y1="48" + x2="90" + y2="48" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5350" + id="linearGradient5376" + gradientUnits="userSpaceOnUse" + x1="6" + y1="48" + x2="90" + y2="48" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5350" + id="linearGradient5378" + gradientUnits="userSpaceOnUse" + x1="6" + y1="48" + x2="90" + y2="48" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5503" + id="linearGradient5513" + x1="-11.340742" + y1="-44.44244" + x2="-105.09332" + y2="-43.771969" + gradientUnits="userSpaceOnUse" /> + </defs> + <metadata + id="metadata2413"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer2" + style="display:none"> + <rect + width="86" + height="85" + rx="6" + ry="6" + x="5" + y="7" + id="rect3745" + style="opacity:0.9;fill:url(#ButtonShadow);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3174)" /> + </g> + <g + id="layer7" + style="display:inline" + transform="translate(0.4067798,-1.6271182)"> + <path + d="m 12,-95.03125 c -5.5110903,0 -10.03125,4.52016 -10.03125,10.03125 l 0,71 c 0,5.5110902 4.5201598,10.03125 10.03125,10.03125 l 72,0 c 5.51109,0 10.03125,-4.5201597 10.03125,-10.03125 l 0,-71 c 0,-5.51109 -4.52016,-10.03125 -10.03125,-10.03125 l -72,0 z" + transform="scale(1,-1)" + id="path3786" + style="opacity:0.07999998;fill:url(#linearGradient2918);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" + inkscape:connector-curvature="0" /> + <path + d="m 12,-94.03125 c -4.971633,0 -9.03125,4.059617 -9.03125,9.03125 l 0,71 c 0,4.9716329 4.0596171,9.03125 9.03125,9.03125 l 72,0 c 4.971633,0 9.03125,-4.059617 9.03125,-9.03125 l 0,-71 c 0,-4.971633 -4.059617,-9.03125 -9.03125,-9.03125 l -72,0 z" + transform="scale(1,-1)" + id="path3778" + style="opacity:0.1;fill:url(#linearGradient3780);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" + inkscape:connector-curvature="0" /> + <path + d="m 12,-93 c -4.4091333,0 -8,3.590867 -8,8 l 0,71 c 0,4.4091333 3.5908667,8 8,8 l 72,0 c 4.409133,0 8,-3.5908667 8,-8 l 0,-71 c 0,-4.409133 -3.590867,-8 -8,-8 l -72,0 z" + transform="scale(1,-1)" + id="path3770" + style="opacity:0.2;fill:url(#linearGradient3772);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" + inkscape:connector-curvature="0" /> + <rect + width="86" + height="85" + rx="7" + ry="7" + x="5" + y="-92" + transform="scale(1,-1)" + id="rect3723" + style="opacity:0.3;fill:url(#linearGradient3725);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" /> + <rect + width="84" + height="84" + rx="6" + ry="6" + x="6" + y="-91" + transform="scale(1,-1)" + id="rect3716" + style="opacity:0.45;fill:url(#linearGradient3721);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" /> + </g> + <rect + style="fill:#f2f2f2;fill-opacity:0.98058256;fill-rule:nonzero;stroke:none" + id="rect5384" + width="83.389839" + height="83.796608" + x="6.9152541" + y="5.6949153" + rx="6.6329193" + ry="4.1945705" /> + <g + id="layer1" + style="fill:url(#linearGradient5255);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" + transform="matrix(0.00204918,-0.66276636,0.9999979,0.00135813,0.71530508,92.720005)"> + <rect + width="84" + height="84" + rx="6" + ry="6" + x="6" + y="6" + id="rect2419" + style="fill:url(#linearGradient5269);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 12,6 C 8.676,6 6,8.676 6,12 l 0,2 0,68 0,2 c 0,0.334721 0.04135,0.6507 0.09375,0.96875 0.0487,0.295596 0.09704,0.596915 0.1875,0.875 0.00988,0.03038 0.020892,0.0636 0.03125,0.09375 0.098865,0.287771 0.2348802,0.547452 0.375,0.8125 0.1445918,0.273507 0.3156161,0.535615 0.5,0.78125 0.1843839,0.245635 0.3737765,0.473472 0.59375,0.6875 0.439947,0.428056 0.94291,0.814526 1.5,1.09375 0.278545,0.139612 0.5734731,0.246947 0.875,0.34375 -0.2562018,-0.100222 -0.4867109,-0.236272 -0.71875,-0.375 -0.00741,-0.0044 -0.023866,0.0045 -0.03125,0 -0.031933,-0.0193 -0.062293,-0.04251 -0.09375,-0.0625 -0.120395,-0.0767 -0.2310226,-0.163513 -0.34375,-0.25 -0.1061728,-0.0808 -0.2132809,-0.161112 -0.3125,-0.25 C 8.4783201,88.557317 8.3087904,88.373362 8.15625,88.1875 8.0486711,88.057245 7.9378561,87.922215 7.84375,87.78125 7.818661,87.74287 7.805304,87.69538 7.78125,87.65625 7.716487,87.553218 7.6510225,87.451733 7.59375,87.34375 7.4927417,87.149044 7.3880752,86.928049 7.3125,86.71875 7.30454,86.69694 7.288911,86.6782 7.28125,86.65625 7.2494249,86.5643 7.2454455,86.469419 7.21875,86.375 7.1884177,86.268382 7.1483606,86.171969 7.125,86.0625 7.0521214,85.720988 7,85.364295 7,85 L 7,83 7,15 7,13 C 7,10.218152 9.2181517,8 12,8 l 2,0 68,0 2,0 c 2.781848,0 5,2.218152 5,5 l 0,2 0,68 0,2 c 0,0.364295 -0.05212,0.720988 -0.125,1.0625 -0.04415,0.206893 -0.08838,0.397658 -0.15625,0.59375 -0.0077,0.02195 -0.0233,0.04069 -0.03125,0.0625 -0.06274,0.173739 -0.138383,0.367449 -0.21875,0.53125 -0.04158,0.0828 -0.07904,0.169954 -0.125,0.25 -0.0546,0.09721 -0.126774,0.18835 -0.1875,0.28125 -0.09411,0.140965 -0.204921,0.275995 -0.3125,0.40625 -0.143174,0.17445 -0.303141,0.346998 -0.46875,0.5 -0.01117,0.0102 -0.01998,0.02115 -0.03125,0.03125 -0.138386,0.125556 -0.285091,0.234436 -0.4375,0.34375 -0.102571,0.07315 -0.204318,0.153364 -0.3125,0.21875 -0.0074,0.0045 -0.02384,-0.0044 -0.03125,0 -0.232039,0.138728 -0.462548,0.274778 -0.71875,0.375 0.301527,-0.0968 0.596455,-0.204138 0.875,-0.34375 0.55709,-0.279224 1.060053,-0.665694 1.5,-1.09375 0.219973,-0.214028 0.409366,-0.441865 0.59375,-0.6875 0.184384,-0.245635 0.355408,-0.507743 0.5,-0.78125 0.14012,-0.265048 0.276135,-0.524729 0.375,-0.8125 0.01041,-0.03078 0.02133,-0.06274 0.03125,-0.09375 0.09046,-0.278085 0.1388,-0.579404 0.1875,-0.875 C 89.95865,84.6507 90,84.334721 90,84 l 0,-2 0,-68 0,-2 C 90,8.676 87.324,6 84,6 L 12,6 z" + inkscape:connector-curvature="0" + id="rect3728" + style="opacity:0.4;fill:url(#linearGradient5271);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 12,90 C 8.676,90 6,87.324 6,84 L 6,82 6,14 6,12 c 0,-0.334721 0.04135,-0.6507 0.09375,-0.96875 0.0487,-0.295596 0.09704,-0.596915 0.1875,-0.875 C 6.29113,10.12587 6.302142,10.09265 6.3125,10.0625 6.411365,9.774729 6.5473802,9.515048 6.6875,9.25 6.8320918,8.976493 7.0031161,8.714385 7.1875,8.46875 7.3718839,8.223115 7.5612765,7.995278 7.78125,7.78125 8.221197,7.353194 8.72416,6.966724 9.28125,6.6875 9.559795,6.547888 9.8547231,6.440553 10.15625,6.34375 9.9000482,6.443972 9.6695391,6.580022 9.4375,6.71875 c -0.00741,0.0044 -0.023866,-0.0045 -0.03125,0 -0.031933,0.0193 -0.062293,0.04251 -0.09375,0.0625 -0.120395,0.0767 -0.2310226,0.163513 -0.34375,0.25 -0.1061728,0.0808 -0.2132809,0.161112 -0.3125,0.25 C 8.4783201,7.442683 8.3087904,7.626638 8.15625,7.8125 8.0486711,7.942755 7.9378561,8.077785 7.84375,8.21875 7.818661,8.25713 7.805304,8.30462 7.78125,8.34375 7.716487,8.446782 7.6510225,8.548267 7.59375,8.65625 7.4927417,8.850956 7.3880752,9.071951 7.3125,9.28125 7.30454,9.30306 7.288911,9.3218 7.28125,9.34375 7.2494249,9.4357 7.2454455,9.530581 7.21875,9.625 7.1884177,9.731618 7.1483606,9.828031 7.125,9.9375 7.0521214,10.279012 7,10.635705 7,11 l 0,2 0,68 0,2 c 0,2.781848 2.2181517,5 5,5 l 2,0 68,0 2,0 c 2.781848,0 5,-2.218152 5,-5 l 0,-2 0,-68 0,-2 C 89,10.635705 88.94788,10.279012 88.875,9.9375 88.83085,9.730607 88.78662,9.539842 88.71875,9.34375 88.71105,9.3218 88.69545,9.30306 88.6875,9.28125 88.62476,9.107511 88.549117,8.913801 88.46875,8.75 88.42717,8.6672 88.38971,8.580046 88.34375,8.5 88.28915,8.40279 88.216976,8.31165 88.15625,8.21875 88.06214,8.077785 87.951329,7.942755 87.84375,7.8125 87.700576,7.63805 87.540609,7.465502 87.375,7.3125 87.36383,7.3023 87.35502,7.29135 87.34375,7.28125 87.205364,7.155694 87.058659,7.046814 86.90625,6.9375 86.803679,6.86435 86.701932,6.784136 86.59375,6.71875 c -0.0074,-0.0045 -0.02384,0.0044 -0.03125,0 -0.232039,-0.138728 -0.462548,-0.274778 -0.71875,-0.375 0.301527,0.0968 0.596455,0.204138 0.875,0.34375 0.55709,0.279224 1.060053,0.665694 1.5,1.09375 0.219973,0.214028 0.409366,0.441865 0.59375,0.6875 0.184384,0.245635 0.355408,0.507743 0.5,0.78125 0.14012,0.265048 0.276135,0.524729 0.375,0.8125 0.01041,0.03078 0.02133,0.06274 0.03125,0.09375 0.09046,0.278085 0.1388,0.579404 0.1875,0.875 C 89.95865,11.3493 90,11.665279 90,12 l 0,2 0,68 0,2 c 0,3.324 -2.676,6 -6,6 l -72,0 z" + inkscape:connector-curvature="0" + id="path3615" + style="opacity:0.2;fill:url(#linearGradient5273);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + style="fill:#666666;stroke:#666666;stroke-width:1.10000001999999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.10000000000000009, 1.10000000000000009;stroke-dashoffset:0;fill-opacity:0.97734630000000000" + d="m 47.59322,32.542373 0,36.610169" + id="path5521" + inkscape:connector-curvature="0" /> + <g + id="layer5" + style="display:none"> + <rect + width="66" + height="66" + rx="12" + ry="12" + x="15" + y="15" + clip-path="url(#clipPath3613)" + id="rect3171" + style="opacity:0.1;fill:url(#linearGradient3613);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3794)" /> + </g> + <rect + style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect5283" + width="69.559624" + height="19.525425" + x="20.745771" + y="69.152542" + rx="6.7946978" + ry="4.2352943" /> + <g + transform="matrix(0.00204918,-0.66276636,0.9999979,0.00135813,-0.09825424,93.533564)" + style="fill:#f9f9f9;fill-opacity:0;fill-rule:nonzero;stroke:url(#linearGradient5356);stroke-opacity:1;display:inline" + id="g5342"> + <rect + style="fill:#f9f9f9;fill-opacity:0;fill-rule:nonzero;stroke:url(#linearGradient5374);stroke-opacity:1" + id="rect5344" + y="6" + x="6" + ry="6" + rx="6" + height="84" + width="84" /> + <path + style="opacity:0.4;fill:#f9f9f9;fill-opacity:0;fill-rule:nonzero;stroke:url(#linearGradient5376);stroke-opacity:1" + id="path5346" + inkscape:connector-curvature="0" + d="M 12,6 C 8.676,6 6,8.676 6,12 l 0,2 0,68 0,2 c 0,0.334721 0.04135,0.6507 0.09375,0.96875 0.0487,0.295596 0.09704,0.596915 0.1875,0.875 0.00988,0.03038 0.020892,0.0636 0.03125,0.09375 0.098865,0.287771 0.2348802,0.547452 0.375,0.8125 0.1445918,0.273507 0.3156161,0.535615 0.5,0.78125 0.1843839,0.245635 0.3737765,0.473472 0.59375,0.6875 0.439947,0.428056 0.94291,0.814526 1.5,1.09375 0.278545,0.139612 0.5734731,0.246947 0.875,0.34375 -0.2562018,-0.100222 -0.4867109,-0.236272 -0.71875,-0.375 -0.00741,-0.0044 -0.023866,0.0045 -0.03125,0 -0.031933,-0.0193 -0.062293,-0.04251 -0.09375,-0.0625 -0.120395,-0.0767 -0.2310226,-0.163513 -0.34375,-0.25 -0.1061728,-0.0808 -0.2132809,-0.161112 -0.3125,-0.25 C 8.4783201,88.557317 8.3087904,88.373362 8.15625,88.1875 8.0486711,88.057245 7.9378561,87.922215 7.84375,87.78125 7.818661,87.74287 7.805304,87.69538 7.78125,87.65625 7.716487,87.553218 7.6510225,87.451733 7.59375,87.34375 7.4927417,87.149044 7.3880752,86.928049 7.3125,86.71875 7.30454,86.69694 7.288911,86.6782 7.28125,86.65625 7.2494249,86.5643 7.2454455,86.469419 7.21875,86.375 7.1884177,86.268382 7.1483606,86.171969 7.125,86.0625 7.0521214,85.720988 7,85.364295 7,85 L 7,83 7,15 7,13 C 7,10.218152 9.2181517,8 12,8 l 2,0 68,0 2,0 c 2.781848,0 5,2.218152 5,5 l 0,2 0,68 0,2 c 0,0.364295 -0.05212,0.720988 -0.125,1.0625 -0.04415,0.206893 -0.08838,0.397658 -0.15625,0.59375 -0.0077,0.02195 -0.0233,0.04069 -0.03125,0.0625 -0.06274,0.173739 -0.138383,0.367449 -0.21875,0.53125 -0.04158,0.0828 -0.07904,0.169954 -0.125,0.25 -0.0546,0.09721 -0.126774,0.18835 -0.1875,0.28125 -0.09411,0.140965 -0.204921,0.275995 -0.3125,0.40625 -0.143174,0.17445 -0.303141,0.346998 -0.46875,0.5 -0.01117,0.0102 -0.01998,0.02115 -0.03125,0.03125 -0.138386,0.125556 -0.285091,0.234436 -0.4375,0.34375 -0.102571,0.07315 -0.204318,0.153364 -0.3125,0.21875 -0.0074,0.0045 -0.02384,-0.0044 -0.03125,0 -0.232039,0.138728 -0.462548,0.274778 -0.71875,0.375 0.301527,-0.0968 0.596455,-0.204138 0.875,-0.34375 0.55709,-0.279224 1.060053,-0.665694 1.5,-1.09375 0.219973,-0.214028 0.409366,-0.441865 0.59375,-0.6875 0.184384,-0.245635 0.355408,-0.507743 0.5,-0.78125 0.14012,-0.265048 0.276135,-0.524729 0.375,-0.8125 0.01041,-0.03078 0.02133,-0.06274 0.03125,-0.09375 0.09046,-0.278085 0.1388,-0.579404 0.1875,-0.875 C 89.95865,84.6507 90,84.334721 90,84 l 0,-2 0,-68 0,-2 C 90,8.676 87.324,6 84,6 L 12,6 z" /> + <path + style="opacity:0.2;fill:#f9f9f9;fill-opacity:0;fill-rule:nonzero;stroke:url(#linearGradient5378);stroke-opacity:1" + id="path5348" + inkscape:connector-curvature="0" + d="M 12,90 C 8.676,90 6,87.324 6,84 L 6,82 6,14 6,12 c 0,-0.334721 0.04135,-0.6507 0.09375,-0.96875 0.0487,-0.295596 0.09704,-0.596915 0.1875,-0.875 C 6.29113,10.12587 6.302142,10.09265 6.3125,10.0625 6.411365,9.774729 6.5473802,9.515048 6.6875,9.25 6.8320918,8.976493 7.0031161,8.714385 7.1875,8.46875 7.3718839,8.223115 7.5612765,7.995278 7.78125,7.78125 8.221197,7.353194 8.72416,6.966724 9.28125,6.6875 9.559795,6.547888 9.8547231,6.440553 10.15625,6.34375 9.9000482,6.443972 9.6695391,6.580022 9.4375,6.71875 c -0.00741,0.0044 -0.023866,-0.0045 -0.03125,0 -0.031933,0.0193 -0.062293,0.04251 -0.09375,0.0625 -0.120395,0.0767 -0.2310226,0.163513 -0.34375,0.25 -0.1061728,0.0808 -0.2132809,0.161112 -0.3125,0.25 C 8.4783201,7.442683 8.3087904,7.626638 8.15625,7.8125 8.0486711,7.942755 7.9378561,8.077785 7.84375,8.21875 7.818661,8.25713 7.805304,8.30462 7.78125,8.34375 7.716487,8.446782 7.6510225,8.548267 7.59375,8.65625 7.4927417,8.850956 7.3880752,9.071951 7.3125,9.28125 7.30454,9.30306 7.288911,9.3218 7.28125,9.34375 7.2494249,9.4357 7.2454455,9.530581 7.21875,9.625 7.1884177,9.731618 7.1483606,9.828031 7.125,9.9375 7.0521214,10.279012 7,10.635705 7,11 l 0,2 0,68 0,2 c 0,2.781848 2.2181517,5 5,5 l 2,0 68,0 2,0 c 2.781848,0 5,-2.218152 5,-5 l 0,-2 0,-68 0,-2 C 89,10.635705 88.94788,10.279012 88.875,9.9375 88.83085,9.730607 88.78662,9.539842 88.71875,9.34375 88.71105,9.3218 88.69545,9.30306 88.6875,9.28125 88.62476,9.107511 88.549117,8.913801 88.46875,8.75 88.42717,8.6672 88.38971,8.580046 88.34375,8.5 88.28915,8.40279 88.216976,8.31165 88.15625,8.21875 88.06214,8.077785 87.951329,7.942755 87.84375,7.8125 87.700576,7.63805 87.540609,7.465502 87.375,7.3125 87.36383,7.3023 87.35502,7.29135 87.34375,7.28125 87.205364,7.155694 87.058659,7.046814 86.90625,6.9375 86.803679,6.86435 86.701932,6.784136 86.59375,6.71875 c -0.0074,-0.0045 -0.02384,0.0044 -0.03125,0 -0.232039,-0.138728 -0.462548,-0.274778 -0.71875,-0.375 0.301527,0.0968 0.596455,0.204138 0.875,0.34375 0.55709,0.279224 1.060053,0.665694 1.5,1.09375 0.219973,0.214028 0.409366,0.441865 0.59375,0.6875 0.184384,0.245635 0.355408,0.507743 0.5,0.78125 0.14012,0.265048 0.276135,0.524729 0.375,0.8125 0.01041,0.03078 0.02133,0.06274 0.03125,0.09375 0.09046,0.278085 0.1388,0.579404 0.1875,0.875 C 89.95865,11.3493 90,11.665279 90,12 l 0,2 0,68 0,2 c 0,3.324 -2.676,6 -6,6 l -72,0 z" /> + </g> + <text + xml:space="preserve" + style="font-size:5.48460484px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" + x="29.985468" + y="64.419136" + id="text5362" + sodipodi:linespacing="125%" + transform="scale(0.82412104,1.213414)"><tspan + sodipodi:role="line" + id="tspan5364" + x="29.985468" + y="64.419136">0101692>48949+120943></tspan></text> + <rect + style="fill:#ffffff;fill-opacity:0;fill-rule:nonzero;stroke:none" + id="rect5382" + width="50.440678" + height="45.559322" + x="8.9491529" + y="-70.372879" + rx="6.7946978" + ry="4.2352943" /> + <path + style="fill:#666666;stroke:#666666;stroke-width:0.85770785999999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.85770784000000000, 0.85770784000000000;stroke-dashoffset:0" + d="m 49.686232,45.966102 40.212073,0" + id="path5523" + inkscape:connector-curvature="0" /> + <g + transform="matrix(0.82412104,0,0,1.213414,97.627119,102.91525)" + style="font-size:5.48460484000000026px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient5513);fill-opacity:1;stroke:none;font-family:Sans" + id="text5405" + inkscape:path-effect="#path-effect5493"> + <path + d="m -102.3486,-70.065413 c -0.45372,0.01972 -0.81136,0.0063 -1.05378,0.04878 -0.24241,0.04251 -0.36738,0.152936 -0.38209,0.426998 -0.0147,0.274062 0.0799,0.716251 0.24088,1.303402 0.16097,0.587151 0.3859,1.317012 0.62334,2.032969 0.23743,0.715958 0.48674,1.410212 0.71372,1.867864 0.22698,0.457651 0.43377,0.665863 0.59007,0.509197 0.15629,-0.156666 0.25921,-0.684588 0.2753,-1.435203 0.0161,-0.750616 -0.0704,-1.698643 -0.15162,-2.551591 -0.0744,-0.544877 -0.0982,-1.107003 -0.16086,-1.505832 -0.0313,-0.199415 -0.0785,-0.36383 -0.18077,-0.480625 -0.10222,-0.116795 -0.2608,-0.18176 -0.51419,-0.215963 z m 0.25246,-0.200276 c 0.3643,-0.03372 0.61181,-0.0097 0.78331,0.135798 0.17149,0.145511 0.26769,0.401743 0.33684,0.729627 0.0692,0.327884 0.11415,0.721262 0.16434,1.184263 0.0502,0.463001 0.10628,1.002771 0.14454,1.656831 0.0383,0.654059 0.0541,1.432502 0.002,2.261356 -0.0521,0.828854 -0.17491,1.70611 -0.37233,2.374369 -0.19741,0.668259 -0.46462,1.109757 -0.78227,1.036931 -0.31764,-0.07283 -0.68325,-0.681403 -1.12517,-1.833316 -0.34724,-1.416806 -0.70833,-3.195186 -0.99211,-4.541296 -0.14189,-0.673056 -0.26104,-1.246707 -0.33804,-1.690553 -0.077,-0.443846 -0.11125,-0.758514 -0.0914,-0.962121 0.0396,-0.407213 0.30894,-0.369275 0.73086,-0.321988 0.21095,0.02364 0.45627,0.04678 0.71776,0.04231 0.26148,-0.0045 0.53846,-0.03768 0.82175,-0.07221 z" + id="path5410" + inkscape:connector-curvature="0" + inkscape:original-d="m -86.239658,-24.372847 c -2.477575,0.958443 0.730416,5.393411 0.840902,1.646989 -0.01991,-0.587284 -0.02836,-1.6044 -0.840902,-1.646989 z m 0,-0.428484 c 2.375792,0.132605 1.593431,5.411682 -0.830524,3.850002 -0.855804,-0.995242 -0.913988,-3.76136 0.830524,-3.850002 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -98.871161,-62.850536 c 0.403376,0.444676 0.663939,0.530381 0.818552,0.365481 0.154614,-0.1649 0.201563,-0.568953 0.182143,-1.040166 -0.01942,-0.471213 -0.10453,-1.004791 -0.197583,-1.497569 -0.09305,-0.492779 -0.191891,-0.948048 -0.248156,-1.336456 -0.0855,-0.308796 -0.112433,-0.682137 -0.09422,-1.060931 0.01822,-0.378795 0.08342,-0.775204 0.130195,-1.145616 0.04677,-0.370413 0.07076,-0.712358 -0.0215,-0.883565 -0.09226,-0.171208 -0.305187,-0.145669 -0.696043,0.06445 -0.33417,-0.09431 -0.437153,-0.223187 -0.389569,-0.370476 0.04758,-0.147288 0.246395,-0.321725 0.509577,-0.521299 0.263182,-0.199573 0.589928,-0.428753 0.889798,-0.590629 0.299869,-0.161876 0.57289,-0.244511 0.732565,-0.102952 -0.120107,0.865797 -0.246593,1.605792 -0.331876,2.253928 -0.08528,0.648136 -0.127819,1.206733 -0.107544,1.774224 0.04055,1.134982 0.366274,2.334348 0.678328,4.515853 0.326807,-0.21838 0.605034,-0.12005 0.816602,0.108297 0.211568,0.228347 0.355358,0.603719 0.40271,0.998989 0.04735,0.39527 -0.0035,0.813807 -0.168165,1.032345 -0.164676,0.218538 -0.439853,0.219247 -0.836616,-0.209939 -0.330307,-0.416656 -0.860114,-0.04721 -1.298736,-0.06243 -0.219311,-0.0076 -0.413889,-0.123743 -0.550036,-0.486872 -0.136146,-0.363128 -0.214278,-0.987948 -0.220396,-1.804661 -1e-5,-2e-6 -2.1e-5,-5e-6 -3.2e-5,-7e-6 z" + id="path5412" + inkscape:connector-curvature="0" + inkscape:original-d="m -83.810685,-21.185991 c 1.117055,0.363473 0.902637,-0.604528 0.88375,-1.376997 -0.148257,-0.585453 0.437231,-2.066419 -0.613687,-1.5502 -1.071243,-0.127671 0.522204,-0.847199 1.109057,-0.615837 0.094,1.10042 0.01332,2.375527 0.04024,3.543034 1.11822,-0.3247 1.113098,0.759261 0.0075,0.455265 -0.453194,-0.151724 -1.701327,0.387829 -1.426835,-0.455265 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -93.22695,-70.249588 c -0.477876,0.584656 -0.859601,1.262734 -1.133538,1.890921 -0.273937,0.628187 -0.436678,1.213239 -0.479122,1.761003 -0.04244,0.547764 0.03672,1.066137 0.204051,1.59707 0.167334,0.530933 0.420223,1.080728 0.693644,1.616983 0.273422,0.536254 0.56498,1.056463 0.82211,1.416395 0.25713,0.359932 0.481878,0.544117 0.635761,0.435983 0.153882,-0.108134 0.231938,-0.51152 0.211615,-1.113372 -0.01016,-0.300927 -0.0443,-0.64632 -0.08892,-1.031382 -0.04462,-0.385062 -0.09967,-0.804917 -0.131854,-1.321954 -0.03238,-0.32739 -0.04851,-0.725425 -0.05141,-1.195332 -0.0029,-0.469907 0.0074,-1.018744 -0.0029,-1.595708 -0.01024,-0.576963 -0.04324,-1.181182 -0.143532,-1.650744 -0.100289,-0.469563 -0.268389,-0.789172 -0.535941,-0.809863 z m 0.222831,-2.198889 c 0.39294,-0.03255 0.680356,0.463129 0.869667,1.254862 0.189311,0.791733 0.277682,1.844639 0.317921,2.826347 0.04024,0.981708 0.03909,1.881744 0.06015,2.634793 0.02106,0.753049 0.06777,1.377006 0.123407,2.000819 0.05564,0.623813 0.113629,1.266426 0.103965,1.943973 -0.0097,0.677547 -0.0919,1.385758 -0.267771,1.904888 -0.175875,0.51913 -0.438947,0.824133 -0.77428,0.697419 -0.335332,-0.126714 -0.741943,-0.698278 -1.253158,-1.601243 -0.187938,-0.48693 -0.380271,-1.012714 -0.567609,-1.523618 0,0 0,-10e-7 0,-10e-7 -0.25112,-0.684374 -0.492649,-1.337488 -0.681708,-1.926879 -0.18906,-0.58939 -0.322973,-1.119207 -0.371044,-1.63943 -0.04807,-0.520223 -0.0099,-1.036622 0.107851,-1.603898 0.117702,-0.567277 0.312795,-1.19003 0.554602,-1.847755 0.233663,-0.635435 0.50903,-1.30384 0.807972,-1.880616 0.298942,-0.576776 0.622414,-1.056517 0.970033,-1.239661 z" + id="path5414" + inkscape:connector-curvature="0" + inkscape:original-d="m -79.255356,-24.372847 c -2.477576,0.958443 0.730417,5.393412 0.840901,1.646989 -0.01991,-0.587284 -0.02836,-1.6044 -0.840901,-1.646989 z m 0,-0.428484 c 2.375791,0.132606 1.59343,5.411682 -0.830525,3.850002 -0.855804,-0.995243 -0.913988,-3.761361 0.830525,-3.850002 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -89.645193,-60.315936 c 0.422306,0.475937 0.680346,0.620072 0.825789,0.485356 0.145443,-0.134716 0.175324,-0.528727 0.135348,-0.992703 -0.03997,-0.463976 -0.149331,-0.989274 -0.260168,-1.487853 -0.110836,-0.498578 -0.219756,-0.97888 -0.273563,-1.444612 -0.08463,-0.365161 -0.100744,-0.851184 -0.05571,-1.470247 0.04503,-0.619063 0.152688,-1.397628 0.238311,-2.214331 0.08562,-0.816703 0.142406,-1.661002 0.05913,-2.081047 -0.04164,-0.210023 -0.117946,-0.309321 -0.238819,-0.258896 -0.120873,0.05043 -0.286524,0.252383 -0.502019,0.589031 -0.345531,-0.159895 -0.444327,-0.501635 -0.384779,-0.962512 0.05955,-0.460878 0.278071,-1.053063 0.564975,-1.667365 0.286905,-0.614302 0.642342,-1.2523 0.970378,-1.640275 0.328035,-0.387975 0.628907,-0.500542 0.795545,-0.06828 -0.165213,2.319152 -0.366762,4.147491 -0.519549,5.573438 -0.152788,1.425947 -0.254474,2.454808 -0.265449,3.303337 -0.01098,0.848528 0.06917,1.522434 0.213388,2.282603 0.144218,0.760169 0.350816,1.611412 0.535948,2.778938 0.08352,-0.04667 0.164221,-0.06945 0.24169,-0.07321 0.49741,-0.02373 0.862967,0.724711 0.943922,1.527785 0.04048,0.401537 0.0093,0.812775 -0.100701,1.050761 -0.109973,0.237985 -0.295801,0.288381 -0.567486,-0.01369 -0.08225,-0.09141 -0.172588,-0.214012 -0.272113,-0.36833 -0.316302,-0.555301 -0.819618,-0.299817 -1.245887,-0.443533 -0.213135,-0.07186 -0.405529,-0.249032 -0.55039,-0.640246 -0.14486,-0.391213 -0.244041,-1.00545 -0.287755,-1.76411 -1.1e-5,-4e-6 -2.2e-5,-8e-6 -3.3e-5,-1.2e-5 z" + id="path5416" + inkscape:connector-curvature="0" + inkscape:original-d="m -76.826384,-21.185991 c 1.117055,0.363473 0.902637,-0.604528 0.88375,-1.376997 -0.148257,-0.585453 0.437231,-2.066419 -0.613687,-1.5502 -1.071243,-0.127671 0.522204,-0.847199 1.109057,-0.615837 0.094,1.10042 0.01332,2.375527 0.04024,3.543034 1.11822,-0.3247 1.113098,0.759261 0.0075,0.455265 -0.453194,-0.151724 -1.701327,0.387829 -1.426835,-0.455265 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -84.370572,-63.481346 c -0.3502,0.06696 -0.603377,0.275139 -0.761582,0.549043 -0.158204,0.273905 -0.220501,0.613492 -0.202097,0.997506 0.0184,0.384013 0.117237,0.816848 0.262141,1.29586 0.144903,0.479013 0.334257,1.008602 0.529784,1.533309 0.195528,0.524706 0.396513,1.042922 0.581214,1.419915 0.184701,0.376993 0.355063,0.602626 0.496273,0.552903 0.14121,-0.04972 0.253512,-0.382698 0.304483,-0.956642 0.05097,-0.573943 0.03003,-1.359595 -0.04212,-2.260821 -0.06111,-0.695215 -0.209317,-1.411623 -0.40053,-2.016839 -0.191213,-0.605217 -0.439401,-1.08661 -0.767568,-1.114234 z m 2.795805,-10.48319 c -0.139526,1.308249 -0.278217,2.122576 -0.422598,2.693604 -0.144381,0.571027 -0.294898,0.891262 -0.454832,1.091638 -0.319867,0.40075 -0.679369,0.323512 -1.060761,0.419616 -0.190695,0.04805 -0.386319,0.137173 -0.580919,0.327719 -0.194599,0.190546 -0.388407,0.484265 -0.570897,0.905563 -0.182491,0.421299 -0.354418,0.970804 -0.493704,1.616388 -0.139287,0.645584 -0.247078,1.382102 -0.274398,2.14811 -0.03599,0.176742 0.830834,-0.145184 1.5815,0.333513 0.375334,0.239348 0.711185,0.703832 0.933629,1.424239 0.111223,0.360203 0.196347,0.777178 0.260419,1.253244 0.06407,0.476066 0.109112,1.001861 0.13578,1.677838 0.03937,0.825297 0.05727,1.62347 0.02095,2.374662 -0.03632,0.751191 -0.122674,1.438326 -0.240578,1.952151 -0.117904,0.513826 -0.26507,0.849645 -0.42224,0.96559 -0.15717,0.115944 -0.324303,0.01362 -0.498077,-0.263356 -0.347549,-0.553947 -0.732372,-1.788175 -1.161369,-3.015694 -0.214499,-0.613759 -0.438022,-1.226936 -0.652588,-1.799916 -0.214565,-0.572981 -0.419567,-1.105861 -0.587006,-1.609069 0,0 -1e-6,0 -1e-6,-10e-7 -0.21793,-0.654753 -0.370135,-1.258252 -0.399763,-1.932407 -0.02963,-0.674155 0.06421,-1.424627 0.305548,-2.414509 0.156547,-0.642632 0.374218,-1.386936 0.653483,-2.268547 0.572386,-2.504664 1.403613,-5.281584 2.153062,-6.622017 0.374725,-0.670217 0.733375,-0.979861 1.040265,-0.852562 0.306891,0.127299 0.560504,0.691855 0.735093,1.594225 10e-7,-7e-6 2e-6,-1.4e-5 3e-6,-2.2e-5 z" + id="path5418" + inkscape:connector-curvature="0" + inkscape:original-d="m -72.204104,-22.945457 c -2.118425,0.390015 0.538594,3.28804 0.790019,0.931955 0.03935,-0.452898 -0.289167,-0.968876 -0.790019,-0.931955 z m 1.07389,-1.695193 c 0.1729,0.96584 -2.112937,-0.233647 -1.927847,1.406304 -0.03364,0.09804 2.503244,-0.519848 2.187616,1.220846 -0.485936,3.030078 -4.183398,0.14924 -2.507975,-1.917468 0.380529,-0.86151 1.445501,-1.055397 2.248206,-0.70968 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -81.070614,-53.839827 c -0.01256,-0.854791 -0.0043,-1.350925 0.04041,-1.67844 0.04474,-0.327515 0.123718,-0.47881 0.228313,-0.542171 0.209192,-0.126722 0.517748,0.107311 0.820977,0.229467 0.303228,0.122157 0.604555,0.108811 0.804057,-0.416707 0.09975,-0.262759 0.172864,-0.647198 0.204252,-1.146455 0.03139,-0.499256 0.01801,-1.103301 -0.03104,-1.829976 0.01766,-0.180752 -0.732444,-0.08739 -1.479744,-0.640594 -0.37365,-0.276602 -0.756259,-0.699264 -1.013414,-1.383752 -0.128577,-0.342244 -0.224748,-0.747715 -0.249476,-1.291719 -0.02473,-0.544003 0.02082,-1.212845 0.209954,-2.269867 0.158802,-0.92138 0.368287,-1.918451 0.599128,-2.934141 0.230841,-1.01569 0.482876,-2.046357 0.735103,-3.005032 0.504455,-1.917351 1.005531,-3.506927 1.415435,-4.293305 0.409905,-0.786379 0.729775,-0.76876 0.931497,-0.05349 0.201722,0.715269 0.284894,2.100542 0.285609,3.700447 7.15e-4,1.599904 -0.07658,3.388315 -0.161258,4.989485 -0.08468,1.60117 -0.171758,3.009211 -0.234353,4.177791 -0.0626,1.168581 -0.101323,2.112767 -0.16899,3.039082 -0.06767,0.926316 -0.169675,1.857136 -0.389148,2.953677 -0.09007,0.972368 -0.255034,1.917091 -0.462844,2.677415 -0.207809,0.760324 -0.454489,1.324061 -0.700106,1.578793 -0.245617,0.254732 -0.489327,0.199395 -0.719561,-0.139504 -0.230234,-0.338899 -0.448618,-0.95642 -0.6648,-1.721018 0,5e-6 -1e-6,1e-5 -1e-6,1.4e-5 z m 0.990488,-6.806946 c 0.662678,-0.06792 0.962734,-0.783982 1.169536,-2.045477 0.103401,-0.630747 0.183585,-1.411406 0.249638,-2.307123 0.06605,-0.895718 0.117494,-1.910545 0.133887,-2.882439 0.01639,-0.971894 -0.0045,-1.893459 -0.09055,-2.49551 -0.08603,-0.602052 -0.239045,-0.867009 -0.461802,-0.613951 -0.222756,0.253058 -0.517073,1.035651 -0.835873,2.198927 -0.318799,1.163275 -0.664925,2.679754 -0.90265,4.149254 -0.178643,1.136941 -0.160038,2.075812 -0.0055,2.767225 0.154538,0.691413 0.428122,1.168612 0.743309,1.229094 z" + id="path5420" + inkscape:connector-curvature="0" + inkscape:original-d="m -69.919744,-20.813745 c -0.17305,-0.966374 2.111714,0.234823 1.927678,-1.405131 0.03784,-0.109784 -2.504841,0.519138 -2.184769,-1.222019 0.486754,-3.031102 4.179317,-0.145419 2.505295,1.919143 -0.378938,0.863284 -1.446471,1.052241 -2.248204,0.708005 z m 1.076568,-1.695195 c 2.117049,-0.391631 -0.54078,-3.285579 -0.790019,-0.931954 -0.04045,0.45476 0.287407,0.969232 0.790019,0.931954 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -76.633813,-53.083877 c 0.138379,0.43341 0.345139,0.584495 0.578247,0.631313 0.233108,0.04682 0.491163,-0.0013 0.72107,0.06256 0.229907,0.06385 0.433452,0.228586 0.544281,0.741059 0.05541,0.256237 0.08747,0.600403 0.0815,1.094246 -0.006,0.493843 -0.04909,1.134247 -0.157944,2.042394 -0.339314,0.40393 -0.677487,0.299891 -1.01513,-0.01593 -0.337644,-0.315823 -0.679491,-0.825365 -1.024092,-1.199604 -0.178754,-0.194171 -0.357689,-0.353588 -0.534212,-0.437535 -0.02539,-0.0121 -0.05073,-0.02263 -0.07601,-0.03147 0.07426,-1.200777 0.164587,-2.228593 0.272482,-3.115849 0.16988,-1.396832 0.384482,-2.442747 0.643644,-3.321779 0.25163,-0.852894 0.545845,-1.552511 0.864873,-2.30334 0.319029,-0.750829 0.663986,-1.559452 0.988051,-2.586486 0.324066,-1.027033 0.62898,-2.278604 0.816558,-3.77327 0.187579,-1.494667 0.258274,-3.236525 0.04329,-5.024995 -0.56744,1.182979 -0.949069,1.750284 -1.224635,2.021999 0,0 0,0 0,0 -0.240342,0.237069 -0.396797,0.236282 -0.487822,0.07833 -0.09102,-0.157951 -0.115702,-0.476582 -0.08152,-0.91432 0.04966,-0.635745 0.225338,-1.532571 0.502467,-2.534128 0,-10e-7 0,-10e-7 0,-10e-7 0.18644,-0.673832 0.418609,-1.393573 0.681201,-2.06767 0.262593,-0.674096 0.555654,-1.301606 0.855028,-1.752376 0,0 0,0 0,0 0.33034,-0.49736 0.667958,-0.774506 0.971028,-0.651709 0.403096,0.715067 0.56994,1.8938 0.576571,3.263415 0.0066,1.369615 -0.143492,2.920477 -0.360982,4.409005 -0.21749,1.488529 -0.500623,2.911413 -0.786413,4.151678 -0.285791,1.240265 -0.574346,2.300138 -0.840688,3.19571 -0.532684,1.791143 -0.971251,2.952093 -1.379845,4.185657 -0.204297,0.616782 -0.403829,1.25031 -0.601008,1.905485 -0.19718,0.655174 -0.39217,1.330696 -0.569994,1.947585 -2e-6,1e-5 -4e-6,2e-5 -5e-6,3e-5 z" + id="path5422" + inkscape:connector-curvature="0" + inkscape:original-d="m -65.977686,-21.185991 c 0.557154,0.197364 1.938183,-0.429146 1.888011,0.375545 -0.674697,0.18642 -1.695964,0.02627 -2.503632,0.07972 -0.193801,-1.183245 3.434684,-2.751786 1.132481,-3.61534 -1.427069,0.763271 -1.507313,-0.49268 -0.01071,-0.45527 2.843361,0.346404 0.541999,2.725021 -0.506147,3.61534 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -72.205415,-61.672395 c 0.127686,-0.747454 0.273156,-1.371647 0.407584,-1.819861 0.134428,-0.448215 0.257979,-0.719452 0.362157,-0.819555 0.208356,-0.200205 0.336868,0.290785 0.446722,0.991179 0.109855,0.700394 0.210751,1.579061 0.339881,2.267415 0.129131,0.688354 0.280547,1.206954 0.447843,1.321024 0.05063,0.601695 0.209755,1.016149 0.39384,1.39244 0.184084,0.376291 0.394872,0.709372 0.570509,1.092739 0.175638,0.383367 0.315779,0.815755 0.373139,1.370041 0.05736,0.554287 0.03553,1.211809 -0.113116,2.141566 -1.521037,1.042854 -2.963989,2.339476 -4.551548,4.78023 0.08784,-0.951925 0.160551,-1.641404 0.238144,-2.183409 0.07759,-0.542006 0.159253,-0.934002 0.250284,-1.238001 0.18206,-0.607998 0.402516,-0.87062 0.645041,-1.03557 0.485048,-0.329902 1.049566,-0.266748 1.452159,-0.947697 1.573669,-0.237195 1.164983,-1.658376 0.151049,-3.46831 -0.502191,-1.189073 -0.9805,-2.430814 -1.413688,-3.844231 0,0 0,0 0,0 z" + id="path5424" + inkscape:connector-curvature="0" + inkscape:original-d="m -62.956868,-23.43018 c -0.143214,-0.992665 1.20031,0.135448 1.765194,0.15286 0.515053,0.378573 1.810764,0.209878 1.66804,1.049575 -1.144411,0.415095 -2.288823,0.830189 -3.433234,1.245284 -0.143593,-0.889833 1.203497,-0.726403 1.769881,-1.114592 1.281043,-0.255658 0.802535,-0.512832 -0.190708,-0.770451 -0.526391,-0.187559 -1.052782,-0.375117 -1.579173,-0.562676 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -63.015168,-64.18037 c -0.744663,1.909958 -1.350571,3.432562 -1.857765,4.698968 -1.362623,3.402557 -2.014835,4.958845 -2.700959,7.209358 0.393888,0.458919 0.777087,0.870228 1.119751,0.756978 0.234908,-0.07761 0.449192,-0.399214 0.635539,-1.063489 0.09317,-0.332137 0.179075,-0.747691 0.266805,-1.27935 0.08773,-0.53166 0.175618,-1.174071 0.299613,-2.035578 0.417943,-1.930998 1.063201,-4.349616 2.237016,-8.286887 0,0 0,0 0,0 z m 1.591403,-5.903979 c 0.347811,-0.472458 0.555952,-0.610532 0.63857,-0.448168 0.08262,0.162363 0.04096,0.621509 -0.08594,1.275399 -0.253808,1.30778 -0.837176,3.359399 -1.412589,5.303503 -0.575413,1.944104 -1.136566,3.766554 -1.548589,5.208473 -0.412024,1.441918 -0.686897,2.541529 -0.825945,3.377328 -0.433749,1.162146 -0.560976,1.965221 -0.591544,2.684667 -0.03057,0.719446 0.0464,1.324365 0.121537,1.861159 0.07514,0.536793 0.150787,1.000187 0.129196,1.443196 -0.02159,0.443009 -0.139639,0.861567 -0.459827,1.371026 -0.100458,-0.176031 -0.283324,0.395205 -0.532789,1.423833 -0.124732,0.514315 -0.26795,1.149726 -0.426169,1.857383 -0.15822,0.707658 -0.331983,1.48931 -0.504274,2.240596 -0.34458,1.502573 -0.682863,2.880335 -0.747273,2.805833 -0.0322,-0.03725 0.0058,-0.443863 0.113252,-1.25787 0.107488,-0.814008 0.284421,-2.037201 0.476958,-3.494971 0.196728,-0.950207 0.322116,-1.653826 0.404338,-2.218985 0.08222,-0.565159 0.120596,-0.989407 0.130091,-1.328656 0.01899,-0.678498 -0.07629,-1.023726 -0.223333,-1.234851 -0.205308,-0.294852 -0.515344,-0.308085 -0.809943,-0.358894 -0.2946,-0.05081 -0.572596,-0.145666 -0.725339,-0.592394 0.06952,-1.163021 0.180412,-2.054633 0.344596,-2.838268 0.164183,-0.783636 0.380893,-1.457589 0.64753,-2.149382 0.533276,-1.383587 1.263323,-2.82918 2.133125,-5.263377 0.574725,-1.436133 1.2679,-3.187226 2.127433,-5.411264 0,0 0,-10e-7 0,-10e-7 0,0 0,0 0,0 1e-6,0 1e-6,-1e-6 1e-6,-1e-6 0.486099,-1.257743 1.025429,-2.666726 1.626927,-4.255314 0,0 0,0 0,0 z" + id="path5426" + inkscape:connector-curvature="0" + inkscape:original-d="m -56.869706,-24.257691 c -0.455265,0.711463 -0.91053,1.422926 -1.365795,2.134389 0.874751,0.08567 1.693957,0.115792 1.365795,-1.001453 0,-0.377645 0,-0.755291 0,-1.132936 z m -0.141936,-0.471334 c 1.102551,-0.333358 0.553252,0.985135 0.68022,1.627361 -0.556185,1.003667 1.116492,1.002682 0.320057,1.428271 -0.420389,-0.05568 -0.450813,1.807609 -0.858341,0.567122 0.253182,-1.026403 -1.152446,-0.393996 -1.752542,-0.567122 -0.263263,-0.736834 0.672268,-1.411579 0.977992,-2.09194 0.210872,-0.32123 0.421743,-0.642461 0.632614,-0.963692 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -62.125743,-51.093097 c -0.776361,0.112277 -1.201408,0.995102 -1.426368,2.341592 -0.11248,0.673245 -0.17992,1.473712 -0.222313,2.336708 -0.04239,0.862996 -0.06052,1.790221 -0.04792,2.619375 0.0126,0.829155 0.05783,1.553001 0.160963,1.950726 0.103131,0.397726 0.267885,0.455658 0.493564,0.05936 0.225679,-0.396294 0.512855,-1.250557 0.795421,-2.416081 0.282567,-1.165523 0.546666,-2.600417 0.745271,-4.137485 0.0676,-0.83054 0.02927,-1.453706 -0.06624,-1.915079 -0.09552,-0.461372 -0.251024,-0.752199 -0.432374,-0.839121 z m -0.408344,-1.48443 c -0.212178,-0.988953 -0.263065,-1.977415 -0.151629,-3.041156 0.111435,-1.063742 0.387542,-2.21046 0.798702,-3.444217 0.41116,-1.233756 0.958144,-2.55716 1.555888,-3.819457 0.597744,-1.262297 1.244055,-2.456667 1.807956,-3.307114 0.563901,-0.850446 1.040018,-1.342141 1.309223,-1.241207 0.269206,0.100934 0.325901,0.808245 0.14992,2.086881 -0.17598,1.278637 -0.583636,3.123986 -1.101529,5.142274 -0.258947,1.009143 -0.543102,2.055604 -0.83166,3.080632 -0.288559,1.025028 -0.580627,2.025713 -0.863908,2.975581 -0.639167,0.638988 -0.957693,1.376703 -1.112522,2.19847 -0.154828,0.821768 -0.145262,1.723946 -0.145568,2.764408 -3.06e-4,1.040462 -0.008,2.208924 -0.239158,3.739063 -0.231149,1.530139 -0.681669,3.403715 -1.65843,6.243865 -0.522022,1.514404 -0.992324,2.642561 -1.337616,3.16871 -0.345292,0.52615 -0.566815,0.45599 -0.677979,-0.09448 -0.111165,-0.550468 -0.116075,-1.566383 -0.0696,-2.772442 0.04647,-1.206059 0.141351,-2.59175 0.24403,-3.920848 0.102679,-1.329097 0.212811,-2.599682 0.3293,-3.708342 0.11649,-1.10866 0.241006,-2.060094 0.400697,-2.858971 0.159691,-0.798877 0.356534,-1.451528 0.61678,-1.982635 0.260245,-0.531107 0.584591,-0.943493 0.977107,-1.209016 0,0 0,0 0,0 z m 0.93267,-4.912214 c -0.201532,0.893519 -0.320502,1.558894 -0.396054,2.097326 -0.07555,0.538433 -0.106741,0.947088 -0.112516,1.271402 -0.01155,0.648627 0.076,0.964284 0.206565,1.073707 0.261137,0.218846 0.696049,-0.38262 1.198733,-1.539095 0.251342,-0.578238 0.523991,-1.30832 0.795378,-2.14769 0.271387,-0.83937 0.542907,-1.792387 0.749442,-2.708587 0.206535,-0.916199 0.345731,-1.789829 0.314533,-2.366002 -0.0312,-0.576172 -0.239563,-0.837113 -0.695851,-0.604508 -0.260267,0.234178 -0.663942,1.029706 -1.052168,1.968152 -0.388227,0.938445 -0.7555,2.004677 -1.008062,2.955295 z" + id="path5428" + inkscape:connector-curvature="0" + inkscape:original-d="m -53.706951,-22.629449 c -2.395714,0.516849 1.141994,2.824229 0.774621,0.451249 -0.113653,-0.310332 -0.462549,-0.467557 -0.774621,-0.451249 z m -0.540962,-0.230311 c -2.544898,-1.267859 2.220598,-3.288762 1.769506,-0.588495 -1.427664,0.652009 1.071909,1.314691 -0.21357,2.48454 -1.378682,1.248216 -3.677,-1.078649 -1.555936,-1.896045 z m -0.198174,-0.854291 c 0.560353,1.978126 2.622565,-0.988679 0.427145,-0.615274 -0.267629,0.06854 -0.445505,0.345482 -0.427145,0.615274 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -61.974664,-36.292864 c 0.320094,-1.635037 0.534672,-2.541018 0.725563,-3.122847 0.19089,-0.58183 0.353524,-0.822665 0.512768,-0.913461 0.318488,-0.181593 0.618864,0.252314 0.98369,0.23502 0,0 0,0 0,0 0.290483,-0.01369 0.630021,-0.345675 1.000896,-1.291031 0.370875,-0.945356 0.759522,-2.472282 1.040541,-4.332332 0.05364,-0.199018 -0.406539,-0.158059 -0.888636,-0.505859 -0.390719,-0.28158 -0.793401,-0.841149 -0.96543,-1.904835 -0.08602,-0.531842 -0.117921,-1.176668 -0.04278,-1.991717 0.03757,-0.407524 0.102447,-0.858617 0.210539,-1.383977 0.108092,-0.525359 0.258809,-1.123288 0.482549,-1.864033 0.454128,-1.532535 1.023915,-3.140741 1.612526,-4.647866 0.588612,-1.507125 1.187605,-2.886548 1.689317,-3.89374 0.501713,-1.007192 0.904076,-1.635883 1.164326,-1.809258 0.260249,-0.173374 0.379816,0.104556 0.383171,0.734193 0.0058,1.090164 -0.329114,3.212563 -0.696523,5.398422 -0.183705,1.092929 -0.375117,2.201125 -0.551323,3.247383 -0.176206,1.046258 -0.337074,2.030133 -0.480837,2.932624 -0.287527,1.80498 -0.496391,3.252592 -0.814092,4.772791 -0.317702,1.520198 -0.766756,3.184977 -1.542276,5.440706 -0.469337,1.721787 -1.028961,3.451732 -1.561484,4.823426 -0.532524,1.371693 -1.031684,2.36286 -1.409074,2.735846 -0.303503,0.299961 -0.529227,0.204375 -0.668853,-0.266012 -0.139626,-0.470387 -0.193972,-1.312512 -0.184577,-2.393467 -10e-7,8e-6 -3e-6,1.6e-5 -5e-6,2.4e-5 z m 3.566747,-11.494783 c 0.03004,-9.93e-4 0.05968,-0.0039 0.08893,-0.0086 0.412128,-0.06633 0.741399,-0.485045 1.012867,-1.11628 0.271467,-0.631235 0.488795,-1.484421 0.705581,-2.537888 0.216787,-1.053468 0.441665,-2.332178 0.650665,-3.630722 0.208999,-1.298545 0.397569,-2.606007 0.415963,-3.381895 0.01034,-0.437435 -0.03595,-0.699044 -0.159243,-0.703111 -0.123297,-0.0041 -0.324887,0.25277 -0.595342,0.775122 -0.270454,0.522351 -0.609619,1.309383 -0.968193,2.264731 -0.358573,0.955348 -0.732951,2.06753 -1.059879,3.224011 -0.350142,1.256892 -0.510106,2.42565 -0.516239,3.356389 -0.0061,0.930738 0.130048,1.640986 0.424894,1.758241 z" + id="path5430" + inkscape:connector-curvature="0" + inkscape:original-d="m -51.355642,-20.813745 c -0.17305,-0.966374 2.111714,0.234823 1.927678,-1.405131 0.03784,-0.109784 -2.504841,0.519138 -2.184769,-1.222019 0.486754,-3.031102 4.179317,-0.145419 2.505295,1.919143 -0.378938,0.863284 -1.44647,1.052241 -2.248204,0.708005 z m 1.076568,-1.695195 c 2.117049,-0.391631 -0.540779,-3.285578 -0.790019,-0.931954 -0.04045,0.45476 0.287408,0.969232 0.790019,0.931954 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -51.768778,-54.068 c -1.072093,2.579272 -1.799291,4.261061 -2.39959,5.669661 -0.600299,1.4086 -1.073364,2.544709 -1.625757,4.081768 -0.04915,0.136739 -0.09891,0.276678 -0.149449,0.42031 0.01984,0.02534 0.03968,0.05053 0.05951,0.07548 0.43661,0.549501 0.8752,0.963895 1.282662,0.531763 0.203731,-0.216065 0.396637,-0.633218 0.565806,-1.28029 0.08458,-0.323536 0.163067,-0.703522 0.23896,-1.155063 0.07589,-0.451541 0.148371,-0.972356 0.234439,-1.613738 0.360146,-1.680614 0.849176,-3.61764 1.793421,-6.729892 0,0 0,0 0,0 z m 1.306799,-4.727028 c 0.284662,-0.30607 0.451672,-0.35775 0.516322,-0.18513 0.06465,0.172621 0.02803,0.566748 -0.07556,1.103151 -0.207189,1.072805 -0.671028,2.686195 -1.119856,4.20728 -0.448829,1.521085 -0.879992,2.941631 -1.199293,4.092374 -0.319301,1.150743 -0.538158,2.064261 -0.650292,2.792068 -0.3833,0.979693 -0.52032,1.750178 -0.564624,2.456251 -0.0443,0.706074 0.01218,1.324185 0.0704,1.872754 0.05823,0.548568 0.119443,1.024578 0.07878,1.488589 -0.04067,0.464011 -0.182046,0.91115 -0.548851,1.489053 -0.100257,-0.17517 -0.323347,0.451799 -0.640249,1.589483 -0.158451,0.568843 -0.342096,1.272351 -0.543207,2.05665 -0.201111,0.784299 -0.420117,1.651118 -0.634176,2.484947 -0.428117,1.66766 -0.835634,3.199893 -0.909425,3.140299 -0.0369,-0.0298 0.01138,-0.464501 0.151046,-1.350201 0.13967,-0.885701 0.371565,-2.225377 0.643942,-3.830754 0.245632,-1.012994 0.412774,-1.770902 0.530372,-2.381558 0.117597,-0.610656 0.185109,-1.071893 0.219112,-1.441718 0.06801,-0.739651 0.0039,-1.121777 -0.122292,-1.355453 -0.252446,-0.467353 -0.764521,-0.293921 -1.158556,-0.408076 0,0 0,0 0,0 -0.200999,-0.05824 -0.369861,-0.197719 -0.458592,-0.535921 0.208596,-1.610194 0.452579,-2.755319 0.741008,-3.714425 0.288429,-0.959107 0.62042,-1.729051 0.988819,-2.527158 0,0 0,0 0,0 0.466559,-1.010876 0.988008,-2.05931 1.556548,-3.568755 0.763015,-1.776228 1.742614,-4.099313 3.128627,-7.47375 0,0 0,0 0,0 z" + id="path5432" + inkscape:connector-curvature="0" + inkscape:original-d="m -46.393254,-24.257691 c -0.455265,0.711463 -0.91053,1.422926 -1.365795,2.134389 0.874751,0.08567 1.693957,0.115792 1.365795,-1.001453 0,-0.377645 0,-0.755291 0,-1.132936 z m -0.141936,-0.471334 c 1.102551,-0.333358 0.553252,0.985135 0.68022,1.627361 -0.556185,1.003667 1.116492,1.002682 0.320057,1.428271 -0.420389,-0.05568 -0.450813,1.807609 -0.858341,0.567122 0.253182,-1.026403 -1.152446,-0.393996 -1.752542,-0.567122 -0.263263,-0.736834 0.672268,-1.411579 0.977992,-2.09194 0.210872,-0.32123 0.421743,-0.642461 0.632614,-0.963692 z" + style="stroke:none;fill-opacity:1.0;fill:url(#linearGradient5513)" /> + <path + d="m -54.27263,-30.620632 c 0.289572,-1.495111 0.499656,-2.394543 0.685864,-3.004014 0.186209,-0.609471 0.346276,-0.918575 0.501024,-1.080457 0.309497,-0.323764 0.596677,-0.05273 0.925339,0.01786 0.164332,0.0353 0.338735,0.02141 0.527172,-0.125993 0.188436,-0.147402 0.391513,-0.431061 0.603283,-0.892893 0.211771,-0.461832 0.432454,-1.10285 0.638887,-1.889439 0.206432,-0.786589 0.396251,-1.710148 0.54174,-2.707898 0.06773,-0.248655 -0.761374,-0.08468 -1.370089,-0.89007 -0.304357,-0.402696 -0.552295,-1.058386 -0.625695,-2.018408 -0.0367,-0.48001 -0.0314,-1.02955 0.04244,-1.67828 0.07384,-0.64873 0.212002,-1.384564 0.494229,-2.384584 0.240876,-0.874306 0.520445,-1.749922 0.822917,-2.607157 0.302472,-0.857234 0.626295,-1.691195 0.941896,-2.43752 0.631203,-1.49265 1.214075,-2.594167 1.592477,-2.985026 0.378403,-0.39086 0.554928,-0.07808 0.574831,0.743581 0.0199,0.821661 -0.105182,2.123537 -0.253475,3.509866 -0.148293,1.386329 -0.313041,2.838789 -0.442208,4.13041 -0.129168,1.291621 -0.224281,2.4227 -0.340867,3.470267 -0.116587,1.047568 -0.260265,2.02613 -0.534785,3.198203 -0.27452,1.172073 -0.684413,2.557386 -1.302029,4.337756 -0.422801,1.544225 -0.920923,3.117023 -1.410986,4.442017 -0.490062,1.324994 -0.969316,2.388779 -1.368461,2.979838 -0.399145,0.591059 -0.717179,0.705611 -0.926005,0.324033 -0.208825,-0.381579 -0.308929,-1.... [truncated message content] |
From: Dr. T. <dr....@su...> - 2011-07-27 08:41:50
|
Hallo Ich hoffe die Aenderung: + changed glade format to GTKBuilder instead of libglade, as libglade is depriciated ( no longer supported as of glade 3.10 ) war nicht ZU aufwändig - musste das selbe in einem anderen Projekt machen - hätte Dir das zusenden sollen als Beispiel... Danke dafür! Noch eine andere Sache wäre http://drliddle.com/index.php?option=com_content&view=article&id=14:quicktuttraits&catid=3:tutorials&Itemid=6 schau's Dir mal an; könnte eine gute alternative sein für einfache Konfigurations-Dialoge (wie z.B. Geräte Auswahl am Anfang). Grüsse Am 27.07.2011 09:36, schrieb la...@us...: > Revision: 56 > http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=56&view=rev > Author: laserb > Date: 2011-07-27 07:36:33 +0000 (Wed, 27 Jul 2011) > > Log Message: > ----------- > branch merged with trunk > > Removed Paths: > ------------- > branches/laserb/ > > > This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. > > ------------------------------------------------------------------------------ > Got Input? Slashdot Needs You. > Take our quick survey online. Come on, we don't ask for help often. > Plus, you'll get a chance to win $100 to spend on ThinkGeek. > http://p.sf.net/sfu/slashdot-survey > _______________________________________________ > Pycodeocr-main mailing list > Pyc...@li... > https://lists.sourceforge.net/lists/listinfo/pycodeocr-main |
From: <la...@us...> - 2011-07-27 07:36:39
|
Revision: 56 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=56&view=rev Author: laserb Date: 2011-07-27 07:36:33 +0000 (Wed, 27 Jul 2011) Log Message: ----------- branch merged with trunk Removed Paths: ------------- branches/laserb/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <la...@us...> - 2011-07-27 07:33:38
|
Revision: 55 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=55&view=rev Author: laserb Date: 2011-07-27 07:33:30 +0000 (Wed, 27 Jul 2011) Log Message: ----------- Merge with branche from laserb: + outsource RunExternal, RunLibdmtx and RunMagickWand from ocr.py + add blacklist_manager + clean up scanner initialization code, no longer jumping back and forth in code, retry connecting to scanner possible + renamed some gtk elements to have a meaningful name + make main window resizable + added tabstyle, todo: show information in different tabs + changed glade format to GTKBuilder instead of libglade, as libglade is depriciated ( no longer supported as of glade 3.10 ) Modified Paths: -------------- trunk/PyCodeOCR.glade trunk/PyCodeOCR.py trunk/README trunk/utils/__init__.py trunk/utils/ocr.py Added Paths: ----------- trunk/utils/RunExternal.py trunk/utils/RunLibdmtx.py trunk/utils/RunMagickWand.py trunk/utils/blacklist_manager.py Modified: trunk/PyCodeOCR.glade =================================================================== --- trunk/PyCodeOCR.glade 2011-04-28 10:21:55 UTC (rev 54) +++ trunk/PyCodeOCR.glade 2011-07-27 07:33:30 UTC (rev 55) @@ -1,417 +1,865 @@ -<?xml version="1.0"?> -<glade-interface> - <!-- interface-requires gtk+ 2.16 --> - <!-- interface-naming-policy toplevel-contextual --> - <widget class="GtkWindow" id="window1"> - <property name="width_request">798</property> - <property name="height_request">246</property> - <property name="visible">True</property> - <property name="title" translatable="yes">PyCodeOCR</property> - <property name="resizable">False</property> - <signal name="destroy" handler="on_window1_destroy"/> +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="2.24"/> + <object class="GtkAdjustment" id="adjustment1"> + <property name="upper">300</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkAdjustment" id="adjustment2"> + <property name="upper">300</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkAdjustment" id="adjustment3"> + <property name="upper">300</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkAdjustment" id="adjustment4"> + <property name="upper">300</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkWindow" id="img_popup"> + <property name="can_focus">False</property> + <property name="type">popup</property> + <property name="window_position">mouse</property> + <property name="destroy_with_parent">True</property> + <signal name="leave-notify-event" handler="on_main_image_eventbox_button_press_event" swapped="no"/> <child> - <widget class="GtkFixed" id="fixed1"> + <object class="GtkVBox" id="vbox1"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkProgressBar" id="progressbar1"> - <property name="width_request">504</property> - <property name="height_request">20</property> + <object class="GtkEventBox" id="popup_image_eventbox"> <property name="visible">True</property> - <property name="pulse_step">0.10000000149</property> - </widget> + <property name="can_focus">False</property> + <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK</property> + <property name="visible_window">False</property> + <child> + <object class="GtkImage" id="popup_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> + </object> <packing> - <property name="x">16</property> - <property name="y">208</property> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> </packing> </child> + </object> + </child> + </object> + <object class="GtkWindow" id="main_window"> + <property name="width_request">786</property> + <property name="height_request">242</property> + <property name="can_focus">False</property> + <signal name="destroy" handler="on_main_window_destroy" swapped="no"/> + <signal name="motion-notify-event" handler="on_pointer_motion" swapped="no"/> + <child> + <object class="GtkNotebook" id="notebook"> + <property name="width_request">786</property> + <property name="height_request">242</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tab_pos">left</property> <child> - <widget class="GtkEntry" id="entry1"> - <property name="width_request">504</property> - <property name="height_request">27</property> + <object class="GtkHBox" id="hbox1"> + <property name="width_request">1284</property> + <property name="height_request">443</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">False</property> - <property name="invisible_char">●</property> - </widget> - <packing> - <property name="x">16</property> - <property name="y">168</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label5"> - <property name="width_request">90</property> - <property name="height_request">21</property> - <property name="visible">True</property> - <property name="label" translatable="yes">Orientation:</property> - </widget> - <packing> - <property name="x">569</property> - <property name="y">160</property> - </packing> - </child> - <child> - <widget class="GtkComboBox" id="combobox1"> - <property name="width_request">90</property> - <property name="height_request">29</property> - <property name="visible">True</property> - <property name="items" translatable="yes">0 deg -90 deg -180 deg -270 deg</property> - <signal name="changed" handler="on_combobox1_changed"/> - </widget> - <packing> - <property name="x">691</property> - <property name="y">155</property> - </packing> - </child> - <child> - <widget class="GtkFrame" id="frame1"> - <property name="width_request">224</property> - <property name="height_request">91</property> - <property name="visible">True</property> - <property name="label_xalign">0</property> + <property name="can_focus">False</property> <child> - <widget class="GtkAlignment" id="alignment1"> + <object class="GtkVBox" id="vbox4"> <property name="visible">True</property> - <property name="left_padding">12</property> + <property name="can_focus">False</property> <child> - <widget class="GtkFixed" id="fixed2"> + <object class="GtkHBox" id="hbox2"> + <property name="height_request">32</property> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="label2"> - <property name="width_request">72</property> - <property name="height_request">17</property> + <object class="GtkHBox" id="hbox6"> + <property name="height_request">30</property> <property name="visible">True</property> - <property name="label" translatable="yes">Position:</property> - </widget> + <property name="can_focus">False</property> + <property name="spacing">11</property> + <child> + <object class="GtkRadioButton" id="file_input_button"> + <property name="width_request">21</property> + <property name="height_request">21</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="group">sane_input_button</property> + <signal name="toggled" handler="on_mode_changed" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFileChooserButton" id="filechooserbutton"> + <property name="width_request">168</property> + <property name="height_request">29</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="do_overwrite_confirmation">True</property> + <signal name="file-set" handler="on_filechooserbutton_file_set" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">1</property> + </packing> + </child> + </object> <packing> - <property name="y">8</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="pack_type">end</property> + <property name="position">0</property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinbutton1"> - <property name="width_request">56</property> - <property name="height_request">27</property> + <object class="GtkComboBox" id="mode_combobox"> + <property name="width_request">200</property> + <property name="height_request">29</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="adjustment">1 0 200 1 10 0</property> - <property name="climb_rate">1</property> - <property name="numeric">True</property> - <signal name="value_changed" handler="on_spinbutton_value_changed"/> - </widget> + <property name="can_focus">False</property> + <property name="model">mode_list</property> + <property name="active">0</property> + <property name="has_entry">True</property> + <property name="entry_text_column">0</property> + <signal name="changed" handler="on_mode_changed" swapped="no"/> + <child internal-child="entry"> + <object class="GtkEntry" id="combobox-entry2"> + <property name="can_focus">False</property> + <property name="editable">False</property> + <property name="shadow_type">none</property> + <property name="caps_lock_warning">False</property> + </object> + </child> + </object> <packing> - <property name="x">80</property> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="scanned_code_label"> + <property name="width_request">102</property> + <property name="height_request">17</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Scanned code:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkEventBox" id="main_image_eventbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <signal name="button-press-event" handler="on_main_image_eventbox_button_press_event" swapped="no"/> <child> - <widget class="GtkSpinButton" id="spinbutton2"> - <property name="width_request">56</property> - <property name="height_request">27</property> + <object class="GtkImage" id="main_image"> <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">4</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="output"> + <property name="width_request">504</property> + <property name="height_request">27</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="invisible_char">•</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="progressbar"> + <property name="width_request">504</property> + <property name="height_request">20</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="pulse_step">0.10000000149</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkHBox" id="hbox3"> + <property name="height_request">30</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkRadioButton" id="sane_input_button"> + <property name="label" translatable="yes">Standard SANE Interface</property> + <property name="width_request">224</property> + <property name="height_request">21</property> + <property name="visible">True</property> <property name="can_focus">True</property> - <property name="adjustment">1 0 200 1 10 0</property> - <property name="climb_rate">1</property> - <property name="numeric">True</property> - <signal name="value_changed" handler="on_spinbutton_value_changed"/> - </widget> + <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_mode_changed" swapped="no"/> + </object> <packing> - <property name="x">144</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">0</property> </packing> </child> <child> - <widget class="GtkSpinButton" id="spinbutton3"> - <property name="width_request">56</property> - <property name="height_request">27</property> - <property name="visible">True</property> + <object class="GtkButton" id="retry_button"> + <property name="label" translatable="yes">Retry</property> + <property name="width_request">60</property> + <property name="height_request">29</property> <property name="can_focus">True</property> - <property name="adjustment">1 0 200 1 10 0</property> - <property name="climb_rate">1</property> - <property name="numeric">True</property> - <signal name="value_changed" handler="on_spinbutton_value_changed"/> - </widget> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_retry_button_clicked" swapped="no"/> + </object> <packing> - <property name="x">80</property> - <property name="y">40</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">1</property> </packing> </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="placement_frame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label_xalign">0</property> <child> - <widget class="GtkSpinButton" id="spinbutton4"> - <property name="width_request">56</property> - <property name="height_request">27</property> + <object class="GtkAlignment" id="alignment1"> <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="left_padding">12</property> + <child> + <object class="GtkFixed" id="fixed2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="position_label"> + <property name="width_request">72</property> + <property name="height_request">17</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Position:</property> + </object> + <packing> + <property name="y">8</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="position_x"> + <property name="width_request">56</property> + <property name="height_request">27</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="adjustment">adjustment1</property> + <property name="climb_rate">1</property> + <property name="numeric">True</property> + <signal name="value-changed" handler="on_placement_value_changed" swapped="no"/> + </object> + <packing> + <property name="x">80</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="position_y"> + <property name="width_request">56</property> + <property name="height_request">27</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="adjustment">adjustment2</property> + <property name="climb_rate">1</property> + <property name="numeric">True</property> + <signal name="value-changed" handler="on_placement_value_changed" swapped="no"/> + </object> + <packing> + <property name="x">144</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="size_x"> + <property name="width_request">56</property> + <property name="height_request">27</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="adjustment">adjustment3</property> + <property name="climb_rate">1</property> + <property name="numeric">True</property> + <signal name="value-changed" handler="on_placement_value_changed" swapped="no"/> + </object> + <packing> + <property name="x">80</property> + <property name="y">40</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="size_y"> + <property name="width_request">56</property> + <property name="height_request">27</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="adjustment">adjustment4</property> + <property name="climb_rate">1</property> + <property name="numeric">True</property> + <signal name="value-changed" handler="on_placement_value_changed" swapped="no"/> + </object> + <packing> + <property name="x">144</property> + <property name="y">40</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="size_label"> + <property name="width_request">72</property> + <property name="height_request">17</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Size:</property> + </object> + <packing> + <property name="y">48</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="placement_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Placement</property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox4"> + <property name="width_request">1</property> + <property name="height_request">30</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="orientation_label"> + <property name="width_request">92</property> + <property name="height_request">21</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Orientation:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="orientation"> + <property name="width_request">90</property> + <property name="height_request">29</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="model">orientation_list</property> + <property name="has_entry">True</property> + <property name="entry_text_column">0</property> + <signal name="changed" handler="on_orientation_changed" swapped="no"/> + <child internal-child="entry"> + <object class="GtkEntry" id="combobox-entry4"> + <property name="can_focus">False</property> + <property name="editable">False</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox5"> + <property name="height_request">31</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkToggleButton" id="scan_button"> + <property name="label" translatable="yes">scan</property> + <property name="width_request">90</property> + <property name="height_request">29</property> + <property name="visible">True</property> <property name="can_focus">True</property> - <property name="adjustment">1 0 200 1 10 0</property> - <property name="climb_rate">1</property> - <property name="numeric">True</property> - <signal name="value_changed" handler="on_spinbutton_value_changed"/> - </widget> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <signal name="toggled" handler="on_scan_button_clicked" swapped="no"/> + </object> <packing> - <property name="x">144</property> - <property name="y">40</property> + <property name="expand">True</property> + <property name="fill">False</property> + <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label3"> - <property name="width_request">72</property> - <property name="height_request">17</property> + <object class="GtkButton" id="exit_button"> + <property name="label" translatable="yes">exit</property> + <property name="width_request">90</property> + <property name="height_request">19</property> <property name="visible">True</property> - <property name="label" translatable="yes">Size:</property> - </widget> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="on_exit_button_clicked" swapped="no"/> + </object> <packing> - <property name="y">48</property> + <property name="expand">True</property> + <property name="fill">False</property> + <property name="position">1</property> </packing> </child> - </widget> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">4</property> + </packing> </child> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="label" translatable="yes">Placement</property> - <property name="use_markup">True</property> - </widget> + </object> <packing> - <property name="type">label_item</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> </packing> </child> - </widget> - <packing> - <property name="x">558</property> - <property name="y">56</property> - </packing> + </object> </child> - <child> - <widget class="GtkLabel" id="label4"> - <property name="width_request">102</property> - <property name="height_request">17</property> + <child type="tab"> + <object class="GtkLabel" id="scan_label"> <property name="visible">True</property> - <property name="label" translatable="yes">Scanned code:</property> - </widget> + <property name="can_focus">False</property> + <property name="label" translatable="yes">SCAN</property> + </object> <packing> - <property name="x">16</property> - <property name="y">55</property> + <property name="tab_fill">False</property> </packing> </child> <child> - <widget class="GtkButton" id="button2"> - <property name="label" translatable="yes">exit</property> - <property name="width_request">90</property> - <property name="height_request">29</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <signal name="clicked" handler="on_button2_clicked"/> - </widget> - <packing> - <property name="x">692</property> - <property name="y">200</property> - </packing> + <placeholder/> </child> <child> - <widget class="GtkToggleButton" id="togglebutton1"> - <property name="label" translatable="yes">scan</property> - <property name="width_request">90</property> - <property name="height_request">29</property> + <object class="GtkVBox" id="vbox3"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_togglebutton1_toggled"/> - </widget> + <property name="can_focus">False</property> + <property name="resize_mode">immediate</property> + <child> + <object class="GtkScrolledWindow" id="device_info_scrolled"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="window_placement_set">True</property> + <child> + <object class="GtkTextView" id="device_info_text"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="wrap_mode">word</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> <packing> - <property name="x">568</property> - <property name="y">200</property> + <property name="position">1</property> </packing> </child> - <child> - <widget class="GtkComboBox" id="combobox2"> - <property name="width_request">256</property> - <property name="height_request">31</property> + <child type="tab"> + <object class="GtkLabel" id="device_info_label"> <property name="visible">True</property> - <property name="items" translatable="yes">E-Banking invoice OCR -Barcode optical recogn. (beta) -DataMatrix optical recogn. (beta) -PDF417 bc. optical recogn. (beta) -</property> - <signal name="changed" handler="on_combobox2_changed"/> - </widget> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Device Info</property> + </object> <packing> - <property name="x">16</property> - <property name="y">16</property> + <property name="position">1</property> + <property name="tab_fill">False</property> </packing> </child> <child> - <widget class="GtkRadioButton" id="radiobutton2"> - <property name="label" translatable="yes">Standard SANE Interface</property> - <property name="width_request">224</property> - <property name="height_request">21</property> + <object class="GtkHBox" id="hbox10"> + <property name="width_request">100</property> + <property name="height_request">80</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_combobox2_changed"/> - </widget> + <property name="can_focus">False</property> + <child> + <object class="GtkVBox" id="vbox9"> + <property name="width_request">100</property> + <property name="height_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkScrolledWindow" id="device_list_scrolled"> + <property name="width_request">740</property> + <property name="height_request">140</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <object class="GtkTreeView" id="device_treeview"> + <property name="width_request">740</property> + <property name="height_request">140</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="enable_grid_lines">horizontal</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection1"/> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="device_chooser_button"> + <property name="label" translatable="yes">OK</property> + <property name="width_request">90</property> + <property name="height_request">29</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_device_chooser_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox8"> + <property name="width_request">75</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="blacklist_add_button"> + <property name="label" translatable="yes">--></property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="blacklist_add" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="blacklist_remove_button"> + <property name="label" translatable="yes"><--</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <property name="image_position">right</property> + <signal name="clicked" handler="blacklist_remove" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox7"> + <property name="width_request">100</property> + <property name="height_request">80</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkScrolledWindow" id="blacklist_scrolled"> + <property name="width_request">740</property> + <property name="height_request">140</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <object class="GtkTreeView" id="blacklist_treeview"> + <property name="width_request">740</property> + <property name="height_request">140</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="enable_grid_lines">horizontal</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection2"/> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> <packing> - <property name="x">534</property> - <property name="y">24</property> + <property name="position">3</property> </packing> </child> - <child> - <widget class="GtkRadioButton" id="radiobutton1"> - <property name="width_request">21</property> - <property name="height_request">21</property> + <child type="tab"> + <object class="GtkLabel" id="blacklist_label"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> - <property name="group">radiobutton2</property> - <signal name="toggled" handler="on_combobox2_changed"/> - </widget> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Blacklist</property> + </object> <packing> - <property name="x">318</property> - <property name="y">24</property> + <property name="position">2</property> + <property name="tab_fill">False</property> </packing> </child> <child> - <widget class="GtkFileChooserButton" id="filechooserbutton1"> - <property name="width_request">168</property> - <property name="height_request">31</property> + <object class="GtkVBox" id="vbox6"> <property name="visible">True</property> - <property name="do_overwrite_confirmation">True</property> - <signal name="file_set" handler="on_filechooserbutton1_file_set"/> - </widget> - <packing> - <property name="x">342</property> - <property name="y">16</property> - </packing> - </child> - <child> - <widget class="GtkButton" id="button1"> - <property name="label" translatable="yes">Restart</property> - <property name="width_request">60</property> - <property name="height_request">29</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="on_button1_clicked"/> - </widget> - <packing> - <property name="x">721</property> - <property name="y">20</property> - </packing> - </child> - <child> - <widget class="GtkEventBox" id="eventbox2"> - <property name="width_request">505</property> - <property name="height_request">84</property> - <property name="visible">True</property> - <signal name="button_press_event" handler="on_eventbox2_button_press_event"/> + <property name="can_focus">False</property> + <property name="resize_mode">immediate</property> <child> - <widget class="GtkImage" id="image1"> - <property name="width_request">505</property> - <property name="height_request">84</property> + <object class="GtkScrolledWindow" id="log_scrolled"> <property name="visible">True</property> - </widget> + <property name="can_focus">True</property> + <property name="window_placement_set">True</property> + <child> + <object class="GtkTextView" id="log_text"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="wrap_mode">word</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> </child> - </widget> + </object> <packing> - <property name="x">16</property> - <property name="y">75</property> + <property name="position">3</property> </packing> </child> - </widget> - </child> - </widget> - <widget class="GtkWindow" id="window2"> - <property name="width_request">470</property> - <property name="height_request">190</property> - <property name="title" translatable="yes">Device selection</property> - <property name="resizable">False</property> - <property name="modal">True</property> - <property name="window_position">center</property> - <property name="destroy_with_parent">True</property> - <property name="type_hint">dialog</property> - <property name="urgency_hint">True</property> - <property name="deletable">False</property> - <property name="transient_for">window1</property> - <child> - <widget class="GtkFixed" id="fixed1"> - <property name="visible">True</property> - <child> - <widget class="GtkTreeView" id="treeview1"> - <property name="width_request">440</property> - <property name="height_request">84</property> + <child type="tab"> + <object class="GtkLabel" id="log_label"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="enable_grid_lines">horizontal</property> - <signal name="row_activated" handler="on_treeview1_row_activated"/> - </widget> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Log</property> + </object> <packing> - <property name="x">15</property> - <property name="y">52</property> + <property name="position">3</property> + <property name="tab_fill">False</property> </packing> </child> - <child> - <widget class="GtkButton" id="button3"> - <property name="label" translatable="yes">OK</property> - <property name="width_request">90</property> - <property name="height_request">29</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> - <signal name="clicked" handler="on_button3_clicked"/> - </widget> - <packing> - <property name="x">365</property> - <property name="y">149</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label1"> - <property name="width_request">416</property> - <property name="height_request">30</property> - <property name="visible">True</property> - <property name="label" translatable="yes">Select device to use.</property> - </widget> - <packing> - <property name="x">23</property> - <property name="y">12</property> - </packing> - </child> - </widget> + </object> </child> - </widget> - <widget class="GtkWindow" id="window3"> - <property name="type">popup</property> - <property name="window_position">mouse</property> - <property name="destroy_with_parent">True</property> - <child> - <widget class="GtkFixed" id="fixed1"> - <property name="visible">True</property> - <child> - <widget class="GtkEventBox" id="eventbox... [truncated message content] |
From: <drt...@us...> - 2011-04-28 10:22:01
|
Revision: 54 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=54&view=rev Author: drtrigon Date: 2011-04-28 10:21:55 +0000 (Thu, 28 Apr 2011) Log Message: ----------- minor docu string change Modified Paths: -------------- trunk/PyCodeOCR.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-04-28 07:41:54 UTC (rev 53) +++ trunk/PyCodeOCR.py 2011-04-28 10:21:55 UTC (rev 54) @@ -25,10 +25,10 @@ # # @section Dependencies # -# Python modules needed are: pygtk2, sane, PIL. -# External programs needed are: tesseract-ocr, convert (ImageMagick). -# And external optional programs: gocr, libdmtx (dmtxread), -# pdf417decode.exe with WINE. +# @li Python modules needed are: pygtk2, sane, PIL. +# @li External programs needed are: tesseract-ocr, convert (ImageMagick). +# @li And external optional programs: gocr, libdmtx (dmtxread), +# pdf417decode.exe with WINE. # # @section unittest Unit Test # This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-28 07:42:00
|
Revision: 53 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=53&view=rev Author: drtrigon Date: 2011-04-28 07:41:54 +0000 (Thu, 28 Apr 2011) Log Message: ----------- README and CHANGES into doxygen docu, more deps auto install (for tesseract and convert) Modified Paths: -------------- trunk/CHANGES trunk/Doxyfile trunk/PyCodeOCR.py trunk/README trunk/utils/ocr.py trunk/utils/requirements.py Modified: trunk/CHANGES =================================================================== --- trunk/CHANGES 2011-04-27 21:22:33 UTC (rev 52) +++ trunk/CHANGES 2011-04-28 07:41:54 UTC (rev 53) @@ -60,4 +60,3 @@ # - Some docu written for orientation and use, look at README. # # - Modified: trunk/Doxyfile =================================================================== --- trunk/Doxyfile 2011-04-27 21:22:33 UTC (rev 52) +++ trunk/Doxyfile 2011-04-28 07:41:54 UTC (rev 53) @@ -656,7 +656,7 @@ # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = . # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-04-27 21:22:33 UTC (rev 52) +++ trunk/PyCodeOCR.py 2011-04-28 07:41:54 UTC (rev 53) @@ -34,6 +34,14 @@ # # (not implemented yet). # +# @section readme Readme +# +# @include "./README" +# +# @section changes Changes +# +# @include "./CHANGES" +# # python standard modules import os, re, sys, time @@ -451,6 +459,9 @@ # helpers # ## Main scanning and number recognition procedure. + # + # @todo Put this function (may be as class with functions for each step) into utils::ocr + # def scancode(self): # Initialization of scanning process # (0/7) Modified: trunk/README =================================================================== --- trunk/README 2011-04-27 21:22:33 UTC (rev 52) +++ trunk/README 2011-04-28 07:41:54 UTC (rev 53) @@ -145,5 +145,3 @@ # # If there is is any question or suggestion please contact me at sf.net, thanks! # - - Modified: trunk/utils/ocr.py =================================================================== --- trunk/utils/ocr.py 2011-04-27 21:22:33 UTC (rev 52) +++ trunk/utils/ocr.py 2011-04-28 07:41:54 UTC (rev 53) @@ -2,7 +2,7 @@ ## # @file utils/ocr.py # @namespace utils::ocr -# @authors drtrigon +# @authors laserb, drtrigon # @version 1.1 # @brief Character recogition (OCR) functions and classes. # Modified: trunk/utils/requirements.py =================================================================== --- trunk/utils/requirements.py 2011-04-27 21:22:33 UTC (rev 52) +++ trunk/utils/requirements.py 2011-04-28 07:41:54 UTC (rev 53) @@ -7,6 +7,8 @@ # # $Id$ # +# @todo Check if further dependencies/packages are needed...? +# # @section Description # # module that allows online inspection of environment to test presence of @@ -172,8 +174,6 @@ # # @since (added for PyCodeOCR) # -# @todo Check if further dependencies/packages are needed...? -# def check_pygtk(): # checks for the presence of pygtk, which is more important than the rest. try: @@ -192,8 +192,6 @@ # # @since (added for PyCodeOCR) # -# @todo Check if further dependencies/packages are needed...? -# def check_sane(): try: require_python_module('sane') @@ -203,6 +201,27 @@ if not r: raise +## Checks if external programs (tesseract and convert) are installed. +# +# @since (added for PyCodeOCR) +# +def check_binaries(): + try: + require_executable('tesseract') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-fedora': ['tesseract']}) + # other deps? + if not r: + raise + + try: + require_executable('convert') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-fedora': ['imagemagick']}) + # other deps? + if not r: + raise + ## Checks if optional libraries are installed. # # @since (added for PyCodeOCR) @@ -235,6 +254,8 @@ check_pygtk() print " * NEEDED 'sane' (scanner)" check_sane() + print " * NEEDED 'tesseract' and 'convert' (binaries)" + check_binaries() # optional print " * OPTIONAL 'gocr', 'dmtxread'" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-27 21:22:39
|
Revision: 52 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=52&view=rev Author: drtrigon Date: 2011-04-27 21:22:33 +0000 (Wed, 27 Apr 2011) Log Message: ----------- updates for 'char_correction' Modified Paths: -------------- trunk/utils/ocr.py Modified: trunk/utils/ocr.py =================================================================== --- trunk/utils/ocr.py 2011-04-27 20:26:18 UTC (rev 51) +++ trunk/utils/ocr.py 2011-04-27 21:22:33 UTC (rev 52) @@ -35,7 +35,7 @@ # Three ("\?>", "3"), # Four - ("l\.", "4"), ("A", "4"), ("l»", "4"), ("h", "4"), ("i»", "4"), ("l\xe2\x80\xa2", "4"), ("&", "4"), + ("l\.", "4"), ("A", "4"), ("l»", "4"), ("h", "4"), ("i»", "4"), ("l\xe2\x80\xa2", "4"), ("&", "4"), ("l\+", "4"), # Five ("S", "5"), # Six @@ -54,6 +54,7 @@ ("l", "1"), (chr(39)+"!", "1"), (chr(39)+"\|", "1"), + ("'\|", "1"), ("\|", "1"), ("'\]", "1"), ("'\}", "1"), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-27 20:26:27
|
Revision: 51 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=51&view=rev Author: drtrigon Date: 2011-04-27 20:26:18 +0000 (Wed, 27 Apr 2011) Log Message: ----------- more OCR code moved to utils, now main code below 1000 lines ;) Modified Paths: -------------- trunk/PyCodeOCR.py trunk/utils/__init__.py trunk/utils/checksum.py trunk/utils/ocr.py Property Changed: ---------------- trunk/utils/__init__.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-04-27 19:43:41 UTC (rev 50) +++ trunk/PyCodeOCR.py 2011-04-27 20:26:18 UTC (rev 51) @@ -9,9 +9,6 @@ # # $Id$ # -# @todo This module/script has become large (more than 1000 lines) -# and should be splitted into seperate files. -# # For further information please consult the @ref mainpage also. # # @mainpage PyCodeOCR @@ -39,7 +36,7 @@ # # python standard modules -import os, re, sys, subprocess, time, gobject, string, struct +import os, re, sys, time # PyCodeOCR python standard utils (modules) import utils @@ -63,7 +60,6 @@ # PIL image library and it's SANE bindings import Image, ImageDraw #from PIL import Image -import sane # f12: 'python-imaging-sane' #(fedora 12 has no libWand, so it's not working at the moment...) # ImageMagick's MagickWand API @@ -102,6 +98,7 @@ # global variables and constants ## path from which this program is currently executed local_path = os.path.realpath(os.path.dirname(sys.argv[0])) +utils.ocr.local_path = local_path # (ugly patch) ## path of program without extension local_path/PyCodeOCR raw_path = os.path.join(local_path, os.path.splitext(sys.argv[0])[0]) ## users home path /home/user @@ -256,7 +253,7 @@ # lock window self.window1.set_sensitive(False) # init sane - self.run_sane = RunSANE(self.progress, self.window2, self.treeview1) + self.run_sane = utils.ocr.RunSANE(self.progress, self.window2, self.treeview1) # try to set sensitivity, fails if no scanner is initialized yet try: @@ -465,7 +462,7 @@ self.on_spinbutton_value_changed() # scan selected range self.on_combobox1_changed() # orientation mode opt = { 'tmp_file': "02.tif", - 'recog_class': RunExternal, + 'recog_class': utils.ocr.RunExternal, 'recog_cmd': self.cmd_tesser % (self.temp+"02", self.temp+"03"), 'recog_error_msg': [ "Unable" ], 'valid_code_len': self.valid_code_len, @@ -475,7 +472,7 @@ self.scan_koords = std_scan_koords["A4"][0] #self.mode = std_scan_koords["A4"][1] opt = { 'tmp_file': "02.pnm", - 'recog_class': RunExternal, + 'recog_class': utils.ocr.RunExternal, 'recog_cmd': self.cmd_gocr % (self.temp+"02",), 'recog_error_msg': [ "\nERROR pnm.c" ], 'valid_code_len': [ 13, 10, 9 ], @@ -486,25 +483,25 @@ self.mode = std_scan_koords["A4"][1] #pydmtx recognition # opt = { 'tmp_file': "02.jpg", # some issues with recogition -# 'recog_class': RunLibdmtx, # . +# 'recog_class': utils.ocr.RunLibdmtx, # . # 'recog_cmd': self.temp+"02.jpg", # of different file formats # 'recog_error_msg': [ None ], # . #dmtxread recognition opt = { 'tmp_file': "02.jpg", # some issues with recogition - 'recog_class': RunExternal, # . + 'recog_class': utils.ocr.RunExternal, # . 'recog_cmd': "%s -v -D %s02.jpg"%(paths["dmtxread"],self.temp), # of different file formats 'recog_error_msg': [ "error" ], # . #opt = { 'tmp_file': "02.bmp", # and drawing/marking the - # 'recog_cmd': (self.temp+"02.bmp", [ None ], RunLibdmtx), } # processed region(s)... + # 'recog_cmd': (self.temp+"02.bmp", [ None ], utils.ocr.RunLibdmtx), } # processed region(s)... #opt = { 'tmp_file': "02.png", # (but this should work for 'tif') - # 'recog_cmd': (self.temp+"02.png", [ None ], RunLibdmtx), } # + # 'recog_cmd': (self.temp+"02.png", [ None ], utils.ocr.RunLibdmtx), } # 'resolution': 150, } elif (op_mode == self.MDE['PDF417']): # 3: PDF417 barcode (pdf417decode/wine) self.on_spinbutton_value_changed() # scan selected range self.on_combobox1_changed() # orientation mode opt = { 'tmp_file': "02.png", - 'recog_class': RunExternal, + 'recog_class': utils.ocr.RunExternal, 'recog_cmd': self.cmd_pdf417dec % (self.temp+"02",), 'recog_error_msg': [ "wine: cannot find", "pdf417decode.exe imagefile|string.txt|-i", "Decoding failed." ], 'resolution': 300, } @@ -519,8 +516,8 @@ if source_mode: # SANE scanning interface self.progress(1./max_steps, "Scanning data...") self.inp_file = self.temp+"01.tif" - #self.run_sane = RunExternal(self.cmd_scan % ( self.scan_koords + (inp_file,) ), [ "no SANE devices found" ]) - self.run_sane.post_init(self.scan_koords, self.inp_file) # RunSANE().post_init(...) 2nd part of __init__(...) + #self.run_sane = utils.ocr.RunExternal(self.cmd_scan % ( self.scan_koords + (inp_file,) ), [ "no SANE devices found" ]) + self.run_sane.post_init(self.scan_koords, self.inp_file) # utils.ocr.RunSANE().post_init(...) 2nd part of __init__(...) self.run_sane.resolution = opt["resolution"] if self.run_sane(): self.progress(0., self.run_sane.stderr) @@ -545,8 +542,8 @@ print "No input file. Please select input file or SANE Interface." #self.progress(0., "No input file. Please select input file or SANE Interface.") return None - self.run_convert = RunExternal(self.cmd_convert % (self.inp_file, mode, self.temp+opt['tmp_file']), error_msg=[ "convert: unable to open image" ]) -# self.run_convert = RunMagickWand(inp_file, mode*90, self.temp+opt['tmp_file']) + self.run_convert = utils.ocr.RunExternal(self.cmd_convert % (self.inp_file, mode, self.temp+opt['tmp_file']), error_msg=[ "convert: unable to open image" ]) +# self.run_convert = utils.ocr.RunMagickWand(inp_file, mode*90, self.temp+opt['tmp_file']) # improve quality by using imagemagicks filter and conversion capabilities... if self.run_convert(): self.progress(0., self.run_convert.stderr[:-1]) @@ -742,7 +739,7 @@ im1 = Image.open(self.imageFile) else: #convert Image - self.run_convert = RunExternal(self.cmd_convert % (imageFile, 0, self.temp+"04.jpg"), error_msg=[ "convert: unable to open image" ]) + self.run_convert = utils.ocr.RunExternal(self.cmd_convert % (imageFile, 0, self.temp+"04.jpg"), error_msg=[ "convert: unable to open image" ]) if self.run_convert(): self.progress(0., self.run_convert.stderr[:-1]) return None @@ -777,285 +774,6 @@ self.progressbar1.set_text(text) self.refresh() -## Run external shell command/application. -class RunExternal: - - error_msg = [ "/bin/sh: " ] - - ## initialize - def __init__(self, cmd, error_msg): - self.cmd = cmd - self.error_msg += error_msg - - ## call - def __call__(self): - (self.error, self.stdout, self.stderr) = self._run() - return self.error - - ## Execute external shell command. - def _run(self, piped=True): - if piped: - run = subprocess.Popen( self.cmd, - stdin =subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True ) - (stdoutdata, stderrdata) = run.communicate() - return ((max(map(stderrdata.find, self.error_msg)) != -1), stdoutdata, stderrdata) - else: - os.system( self.cmd ) - return (False, "", "") - -#class RunLibdmtx: -# """ Use libdmtx python wrapper/bindings (pydmtx). """ - -# def __init__(self, cmd, error_msg): -# #self.cmd = cmd -# #self.error_msg += error_msg -# self.filename = cmd - -# def __call__(self): -# (self.error, self.stdout, self.stderr) = self._run() -# return self.error - -# # thanks to: http://www.pastequestion.com/blog/python/how-to-use-python-imaging-library.html -# def _run(self): -# """ Read a Data Matrix barcode. """ -# dm_read = DataMatrix() -# #print self.filename -# img = Image.open(self.filename) -# try: -# self.decode = dm_read.decode(img.size[0], img.size[1], buffer(img.tostring())) -# self.count = dm_read.count() -# self.message = [ dm_read.message(i+1) for i in range(self.count) ] -# self.stats = [ dm_read.stats(i+1) for i in range(self.count) ] -# except: -# return (True, "error", sys.exc_info()[1]) - -# print "Detected %i DataMatrix barcodes" % self.count -# for i in range(self.count): -# print "Code # %i:" % (i+1) -# print self.message[i] -# stats = self.stats[i] -# print stats - -# # mark the recognized region and save back to file -# points = list(stats[1]) -# points.append(points[0]) -# draw = ImageDraw.Draw(img) -# old = points[0] -# for i, xy in enumerate(points[1:]): -# #draw.line(old+xy, fill=(0, 255, 0), width=2) -# #draw.line(old+xy, fill=(0, 255, 0)) -# draw.line(old+xy, fill="rgb(0, 255, 0)") -# old = xy -# img.save(self.filename) - -# #return (False, self.message, "") -# #print self.stats, (self.count == 0) -# return ((self.count == 0), self.message, "") - -#class RunMagickWand: -# """ Use Python bindings to ImageMagick's MagickWand API. """ -# # "convert %s.tif -crop 1600x250+800+960 -depth 8 %s.tif" -# # "convert %s.tif -crop 1700x250+750+960 -depth 8 %s.tif" -# # "convert %s.tif -crop 3400x500+1500+1900 -depth 8 %s.tif" -# # "convert %s.tif -depth 8 %s.tif" -# # "convert %s.tif -depth 8 -rotate %d %s.tif" -# # "convert %s.tif -depth 8 -rotate %d %s" -# #cmd_convert = "convert %s -depth 8 -rotate %d %s" -# -# def __init__(self, inp_filename, rotate, out_filename): -# self.inp_filename = inp_filename -# self.out_filename = out_filename -# self.angle = rotate -# self.depth = 8 -# -# def __call__(self): -# (self.error, self.stdout, self.stderr) = self._run() -# return self.error -# -# # thanks to: http://www.assembla.com/wiki/show/pythonmagickwand -# def _run(self): -# """ This rotates, changes depth, format and writes a new file. """ -# try: -# i = Image(self.inp_filename) -# i.rotate(self.angle) -# i.depth(self.depth) -# i.format = self.out_filename[-3:].upper() -# i.save(self.out_filename) -# except: -# return (True, "error", sys.exc_info()[1]) -# -# return (False, "ok", "") - -## sSANE/PIL interface python wrapper/bindings. -class RunSANE: - # "scanimage --format=tif --resolution 300 --mode Gray > %s.tif" - # "scanimage --format=tif --resolution 600 --mode Gray -t 82 -y 20 -l 60 -x 155.9 > %s.tif" - #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s.tif" - - resolution = 600 - - ## Init of sane interface -> device. - def __init__(self, progress, window2, treeview): - print "init sane python interface ...", - sys.stdout.flush() - - # Get the path set up properly - #sys.path.append('.') - - # create treeview things - list_store = gtk.ListStore(gobject.TYPE_STRING) - treeview.set_model(list_store) - col = gtk.TreeViewColumn("Devices", gtk.CellRendererText(),text=0) - treeview.append_column(col) - - # get blacklist - self.read_blacklist() - - # init SANE - self.n=4. - progress(0.,"init sane python interface ...") - try: - self.version = sane.init() - progress(1./self.n,"init sane python interface ... search devices") - # get sane devices - self.devices1 = sane.get_devices() - # init filtered list - self.devices = [] - - print "\n" - # add found devices to treeview - for i in range(len(self.devices1)): - # filter devices: remove blacklisted devices - if not self.devices1[i][1]+" "+self.devices1[i][2] in self.blacklist: - self.devices.append(self.devices1[i]) - print str(i)+": "+self.devices1[i][1]+" "+self.devices1[i][2] - list_store.append([self.devices1[i][1]+" "+self.devices1[i][2]]) - else: - print str(i)+": "+self.devices1[i][1]+" "+self.devices1[i][2]+" BLOCKED" - # self.devices is now filtered - - # check how many devices we found - if len(self.devices) == 0: - progress(0./self.n,"No device found.") - self.found_scanner = False - elif len(list_store) > 1: - # more than one device, choose one. - progress(2./self.n,"More than one device found.") - if sys.argv[1:]: - # choose one by command line - devnr = raw_input("Choose device: ") - progress(2./self.n,"More than one device found. Choose device number %i" % devnr) - # continue to init scanner - self.init_scanner(progress, window2, treeview, devnr) - else: - # simply continue and select device in GUI ( look in init_sane ) - progress(2./self.n,"More than one device found.") - - else: - # only one device found - progress(2./self.n,"Device: %s" % self.devices[0][1]+" "+self.devices[0][2]) - # continue to init scanner - self.init_scanner(progress, window2, treeview, 0) - - except: - # No device found at all - self.found_scanner = False - print "No sane device found. Restart to try it again." - - ## iInit of sane interface -> scanner - def init_scanner(self, progress, window2, treeview, devnr): - print "Use device number: "+str(devnr) - try: - # finish init device - self.dev = self.devices[devnr][0] # choose first device - print self.dev - progress(3./self.n,"Device initialized. Open scanner...") - - # open scanner device - self.scanner = sane.open(self.dev) - self.params = self.scanner.get_parameters() - self.opts = self.scanner.get_options() - - self.found_scanner = True - - progress(4./self.n,"Ready: %s" % self.devices[devnr][1]+" "+self.devices[devnr][2]) - print "done." - - except: - # init scanner failed. maybe device has no scanner - self.found_scanner = False - print "Loading sane device failed. Restart to try it again." - - - ## Not init of sane and scanner, but of scan operation. - def post_init(self, coords, out_filename): - self.coords = coords - self.out_filename = out_filename - self.info() - - ## call - def __call__(self): - (self.error, self.stdout, self.stderr) = self._run() - return self.error - - ## Scan and save the PIL image object to file. - # @see http://mail.python.org/pipermail/image-sig/1997-June/000307.html - # @see http://sane-pygtk.sourceforge.net/) - def _run(self): - try: - # Set scan parameters (also with higher resolution!) - (t, l, y, x) = self.coords - self.scanner.tl_y = float(t) - self.scanner.tl_x = float(l) - self.scanner.br_y = (float(y) + self.scanner.tl_y) - self.scanner.br_x = (float(x) + self.scanner.tl_x) - self.scanner.resolution = self.resolution - self.scanner.mode = "Gray" - - # Initiate the scan - self.scanner.start() - - # Get an Image object containing the scanned image - im = self.scanner.snap() - - # Write the image out as a TIFF file (or whatever) - im.save(self.out_filename) - - #self.scanner.close() - except: - return (True, "error", sys.exc_info()[1]) - - return (False, "ok", "") - - ## Show some info about the scanner and SANE. - def info(self): - print 'SANE version:', self.version - print 'Available devices=', self.devices - print 'Selected device=', self.dev #, "\n" - - print 'SaneDev object=', self.scanner - print 'Device parameters:', self.params - #print 'Device options:', "\n",self.opts - - ## get blacklisted devices - def read_blacklist(self): - bl = open('%s/blacklist' % local_path, 'r' ) - temp = bl.readlines() - bl.close - self.blacklist = [] - for line in temp: - self.blacklist.append(line.strip()) - - ## write blacklisted devices - # @todo add UI way to blacklist device - def write_blacklist(self, blacklist): - bl = open('%s/blacklist' % local_path, 'w' ) - bl.write(blacklist) - bl.close() - if __name__ == '__main__': ## run main application main = MainWindowGTK() Modified: trunk/utils/__init__.py =================================================================== --- trunk/utils/__init__.py 2011-04-27 19:43:41 UTC (rev 50) +++ trunk/utils/__init__.py 2011-04-27 20:26:18 UTC (rev 51) @@ -6,7 +6,7 @@ # @version 1.1 # @brief This is the utils package with important functions. # -# $Id: checksum.py -1 $ +# $Id$ # # @section Description # Property changes on: trunk/utils/__init__.py ___________________________________________________________________ Added: svn:keywords + Id Modified: trunk/utils/checksum.py =================================================================== --- trunk/utils/checksum.py 2011-04-27 19:43:41 UTC (rev 50) +++ trunk/utils/checksum.py 2011-04-27 20:26:18 UTC (rev 51) @@ -33,7 +33,7 @@ try: self.amount = str(int(amount[2:-1])/100.) except ValueError: - self.amount = amount + " (error)" + self.amount = amount + " [ERROR!]" def _run(self, nr): self.uebertrag = 0 Modified: trunk/utils/ocr.py =================================================================== --- trunk/utils/ocr.py 2011-04-27 19:43:41 UTC (rev 50) +++ trunk/utils/ocr.py 2011-04-27 20:26:18 UTC (rev 51) @@ -4,7 +4,7 @@ # @namespace utils::ocr # @authors drtrigon # @version 1.1 -# @brief Character recogition (OCR) functions. +# @brief Character recogition (OCR) functions and classes. # # $Id$ # @@ -14,8 +14,12 @@ # # python standard modules -import re +import os, re, sys, subprocess, gobject +# PIL image library and it's SANE bindings +import sane # f12: 'python-imaging-sane' + + ## Character correction after recogition (on basis that there should be numbers and few special chars). # # @test Add unittest to check correct operation of this important module/function. @@ -74,3 +78,284 @@ if not (data == olddata): print 'subst: "%s" => "%s"' % (item[0], item[1]) return data + + +## Run external shell command/application. +class RunExternal: + + error_msg = [ "/bin/sh: " ] + + ## initialize + def __init__(self, cmd, error_msg): + self.cmd = cmd + self.error_msg += error_msg + + ## call + def __call__(self): + (self.error, self.stdout, self.stderr) = self._run() + return self.error + + ## Execute external shell command. + def _run(self, piped=True): + if piped: + run = subprocess.Popen( self.cmd, + stdin =subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True ) + (stdoutdata, stderrdata) = run.communicate() + return ((max(map(stderrdata.find, self.error_msg)) != -1), stdoutdata, stderrdata) + else: + os.system( self.cmd ) + return (False, "", "") + +#class RunLibdmtx: +# """ Use libdmtx python wrapper/bindings (pydmtx). """ + +# def __init__(self, cmd, error_msg): +# #self.cmd = cmd +# #self.error_msg += error_msg +# self.filename = cmd + +# def __call__(self): +# (self.error, self.stdout, self.stderr) = self._run() +# return self.error + +# # thanks to: http://www.pastequestion.com/blog/python/how-to-use-python-imaging-library.html +# def _run(self): +# """ Read a Data Matrix barcode. """ +# dm_read = DataMatrix() +# #print self.filename +# img = Image.open(self.filename) +# try: +# self.decode = dm_read.decode(img.size[0], img.size[1], buffer(img.tostring())) +# self.count = dm_read.count() +# self.message = [ dm_read.message(i+1) for i in range(self.count) ] +# self.stats = [ dm_read.stats(i+1) for i in range(self.count) ] +# except: +# return (True, "error", sys.exc_info()[1]) + +# print "Detected %i DataMatrix barcodes" % self.count +# for i in range(self.count): +# print "Code # %i:" % (i+1) +# print self.message[i] +# stats = self.stats[i] +# print stats + +# # mark the recognized region and save back to file +# points = list(stats[1]) +# points.append(points[0]) +# draw = ImageDraw.Draw(img) +# old = points[0] +# for i, xy in enumerate(points[1:]): +# #draw.line(old+xy, fill=(0, 255, 0), width=2) +# #draw.line(old+xy, fill=(0, 255, 0)) +# draw.line(old+xy, fill="rgb(0, 255, 0)") +# old = xy +# img.save(self.filename) + +# #return (False, self.message, "") +# #print self.stats, (self.count == 0) +# return ((self.count == 0), self.message, "") + +#class RunMagickWand: +# """ Use Python bindings to ImageMagick's MagickWand API. """ +# # "convert %s.tif -crop 1600x250+800+960 -depth 8 %s.tif" +# # "convert %s.tif -crop 1700x250+750+960 -depth 8 %s.tif" +# # "convert %s.tif -crop 3400x500+1500+1900 -depth 8 %s.tif" +# # "convert %s.tif -depth 8 %s.tif" +# # "convert %s.tif -depth 8 -rotate %d %s.tif" +# # "convert %s.tif -depth 8 -rotate %d %s" +# #cmd_convert = "convert %s -depth 8 -rotate %d %s" +# +# def __init__(self, inp_filename, rotate, out_filename): +# self.inp_filename = inp_filename +# self.out_filename = out_filename +# self.angle = rotate +# self.depth = 8 +# +# def __call__(self): +# (self.error, self.stdout, self.stderr) = self._run() +# return self.error +# +# # thanks to: http://www.assembla.com/wiki/show/pythonmagickwand +# def _run(self): +# """ This rotates, changes depth, format and writes a new file. """ +# try: +# i = Image(self.inp_filename) +# i.rotate(self.angle) +# i.depth(self.depth) +# i.format = self.out_filename[-3:].upper() +# i.save(self.out_filename) +# except: +# return (True, "error", sys.exc_info()[1]) +# +# return (False, "ok", "") + +## SANE/PIL interface python wrapper/bindings. +class RunSANE: + # "scanimage --format=tif --resolution 300 --mode Gray > %s.tif" + # "scanimage --format=tif --resolution 600 --mode Gray -t 82 -y 20 -l 60 -x 155.9 > %s.tif" + #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s.tif" + + resolution = 600 + + ## Init of sane interface -> device. + def __init__(self, progress, window2, treeview): + print "init sane python interface ...", + sys.stdout.flush() + + # Get the path set up properly + #sys.path.append('.') + + # create treeview things + import gtk # (ugly patch) + list_store = gtk.ListStore(gobject.TYPE_STRING) + treeview.set_model(list_store) + col = gtk.TreeViewColumn("Devices", gtk.CellRendererText(),text=0) + treeview.append_column(col) + + # get blacklist + self.read_blacklist() + + # init SANE + self.n=4. + progress(0.,"init sane python interface ...") + try: + self.version = sane.init() + progress(1./self.n,"init sane python interface ... search devices") + # get sane devices + self.devices1 = sane.get_devices() + # init filtered list + self.devices = [] + + print "\n" + # add found devices to treeview + for i in range(len(self.devices1)): + # filter devices: remove blacklisted devices + if not self.devices1[i][1]+" "+self.devices1[i][2] in self.blacklist: + self.devices.append(self.devices1[i]) + print str(i)+": "+self.devices1[i][1]+" "+self.devices1[i][2] + list_store.append([self.devices1[i][1]+" "+self.devices1[i][2]]) + else: + print str(i)+": "+self.devices1[i][1]+" "+self.devices1[i][2]+" BLOCKED" + # self.devices is now filtered + + # check how many devices we found + if len(self.devices) == 0: + progress(0./self.n,"No device found.") + self.found_scanner = False + elif len(list_store) > 1: + # more than one device, choose one. + progress(2./self.n,"More than one device found.") + if sys.argv[1:]: + # choose one by command line + devnr = raw_input("Choose device: ") + progress(2./self.n,"More than one device found. Choose device number %i" % devnr) + # continue to init scanner + self.init_scanner(progress, window2, treeview, devnr) + else: + # simply continue and select device in GUI ( look in init_sane ) + progress(2./self.n,"More than one device found.") + + else: + # only one device found + progress(2./self.n,"Device: %s" % self.devices[0][1]+" "+self.devices[0][2]) + # continue to init scanner + self.init_scanner(progress, window2, treeview, 0) + + except: + # No device found at all + self.found_scanner = False + print "No sane device found. Restart to try it again." + + ## iInit of sane interface -> scanner + def init_scanner(self, progress, window2, treeview, devnr): + print "Use device number: "+str(devnr) + try: + # finish init device + self.dev = self.devices[devnr][0] # choose first device + print self.dev + progress(3./self.n,"Device initialized. Open scanner...") + + # open scanner device + self.scanner = sane.open(self.dev) + self.params = self.scanner.get_parameters() + self.opts = self.scanner.get_options() + + self.found_scanner = True + + progress(4./self.n,"Ready: %s" % self.devices[devnr][1]+" "+self.devices[devnr][2]) + print "done." + + except: + # init scanner failed. maybe device has no scanner + self.found_scanner = False + print "Loading sane device failed. Restart to try it again." + + + ## Not init of sane and scanner, but of scan operation. + def post_init(self, coords, out_filename): + self.coords = coords + self.out_filename = out_filename + self.info() + + ## call + def __call__(self): + (self.error, self.stdout, self.stderr) = self._run() + return self.error + + ## Scan and save the PIL image object to file. + # @see http://mail.python.org/pipermail/image-sig/1997-June/000307.html + # @see http://sane-pygtk.sourceforge.net/) + def _run(self): + try: + # Set scan parameters (also with higher resolution!) + (t, l, y, x) = self.coords + self.scanner.tl_y = float(t) + self.scanner.tl_x = float(l) + self.scanner.br_y = (float(y) + self.scanner.tl_y) + self.scanner.br_x = (float(x) + self.scanner.tl_x) + self.scanner.resolution = self.resolution + self.scanner.mode = "Gray" + + # Initiate the scan + self.scanner.start() + + # Get an Image object containing the scanned image + im = self.scanner.snap() + + # Write the image out as a TIFF file (or whatever) + im.save(self.out_filename) + + #self.scanner.close() + except: + return (True, "error", sys.exc_info()[1]) + + return (False, "ok", "") + + ## Show some info about the scanner and SANE. + def info(self): + print 'SANE version:', self.version + print 'Available devices=', self.devices + print 'Selected device=', self.dev #, "\n" + + print 'SaneDev object=', self.scanner + print 'Device parameters:', self.params + #print 'Device options:', "\n",self.opts + + ## get blacklisted devices + def read_blacklist(self): + bl = open('%s/blacklist' % local_path, 'r' ) + temp = bl.readlines() + bl.close + self.blacklist = [] + for line in temp: + self.blacklist.append(line.strip()) + + ## write blacklisted devices + # @todo add UI way to blacklist device + def write_blacklist(self, blacklist): + bl = open('%s/blacklist' % local_path, 'w' ) + bl.write(blacklist) + bl.close() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-27 19:43:48
|
Revision: 50 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=50&view=rev Author: drtrigon Date: 2011-04-27 19:43:41 +0000 (Wed, 27 Apr 2011) Log Message: ----------- group the various modules into one single package 'utils' Modified Paths: -------------- trunk/PyCodeOCR.py Added Paths: ----------- trunk/utils/ trunk/utils/__init__.py trunk/utils/checksum.py trunk/utils/installbundle.py trunk/utils/ocr.py trunk/utils/requirements.py Removed Paths: ------------- trunk/checksum.py trunk/installbundle.py trunk/requirements.py Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-04-27 19:01:54 UTC (rev 49) +++ trunk/PyCodeOCR.py 2011-04-27 19:43:41 UTC (rev 50) @@ -41,12 +41,14 @@ # python standard modules import os, re, sys, subprocess, time, gobject, string, struct +# PyCodeOCR python standard utils (modules) +import utils + # check and install requirements #print "To check and install requirements run: 'python %s --install-deps'" % sys.argv[0] -import requirements if "--install-deps" in sys.argv: - requirements.check_all_pycodeocr_requirements() + utils.requirements.check_all_pycodeocr_requirements() sys.exit() @@ -56,7 +58,7 @@ import gtk, gtk.glade import gobject -from checksum import modulo10 +from utils.checksum import modulo10 # PIL image library and it's SANE bindings import Image, ImageDraw @@ -76,9 +78,9 @@ print "To check and install requirements run: 'python %s --install-deps'" % sys.argv[0] pakages = [] # gocr -paths = { "gocr": requirements.which("gocr"), - "dmtxread": requirements.which("dmtxread"), - "pdf417decode.exe": requirements.which("pdf417decode.exe"), } +paths = { "gocr": utils.requirements.which("gocr"), + "dmtxread": utils.requirements.which("dmtxread"), + "pdf417decode.exe": utils.requirements.which("pdf417decode.exe"), } if os.path.exists(paths["gocr"]): pakages.append( "gocr" ) print "gocr found." @@ -612,7 +614,7 @@ if (op_mode == self.MDE['invoices']): # 0: invoices self.progress(4./max_steps, "Character correction...") print "*** " * 10 - data = self.char_correction(data) + data = utils.ocr.char_correction(data) self.refresh() if self.__stop: return @@ -775,68 +777,6 @@ self.progressbar1.set_text(text) self.refresh() - ## Character correction after recogition (on basis that there should be numbers and few special chars). - # - # @test Add unittest to check correct operation of this important module/function. - # - # @todo May be this important function should be placed into a separate module, - # similar to @ref checksum. - # - def char_correction(self, data): - data = re.sub("\n", "", data) - print data - corrections = [ - # Zero - ("O", "0"), ("D", "0"), ("U", "0"), ("Q", "0"), ("\(\)", "0"), ("G", "0"), ("o", "0"), - # Two - ("Z", "2"), - # Three - ("\?>", "3"), - # Four - ("l\.", "4"), ("A", "4"), ("l»", "4"), ("h", "4"), ("i»", "4"), ("l\xe2\x80\xa2", "4"), ("&", "4"), - # Five - ("S", "5"), - # Six - ("c>", "6"), - # Seven - #("\?", "7"), - # One (critical, therefore done as last; has also Overlapps e.g. with Four) - (chr(226)+chr(128)+chr(153)+"I", "1"), - (chr(226)+chr(128)+chr(153)+"\|", "1"), - (chr(226)+chr(128)+chr(152)+"\|", "1"), - (chr(226)+chr(128)+chr(152)+"I", "1"), - (chr(39)+"I", "1"), - ("I", "1"), - (chr(153)+"l", "1"), - (chr(39)+"l", "1"), - ("l", "1"), - (chr(39)+"!", "1"), - (chr(39)+"\|", "1"), - ("\|", "1"), - ("'\]", "1"), - ("'\}", "1"), - (r'\\', "1"), - # non-numbers - (" ", ""), - ("\xe2", ""), - ("\x80", ""), - ("\xbb", ""), - ("\x99", ""), - ("\x98", ""), - ("\x5f", ""), - ("\x60", ""), - ("'", ""), - #('\xbb', 187)('\x99', 153)('\x98', 152) - ("\+", "+ "), - ("\x92", "1"), # post correction - ] - for item in corrections: - olddata = data - data = re.sub(item[0], item[1], data) - if not (data == olddata): print 'subst: "%s" => "%s"' % (item[0], item[1]) - - return data - ## Run external shell command/application. class RunExternal: Deleted: trunk/checksum.py =================================================================== --- trunk/checksum.py 2011-04-27 19:01:54 UTC (rev 49) +++ trunk/checksum.py 2011-04-27 19:43:41 UTC (rev 50) @@ -1,47 +0,0 @@ -## -# @file checksum.py -# @package checksum -# @authors laserb, drtrigon -# @version 1.1 -# @brief Modulo 10 checksum for e-banking codes. -# -# @test Add unittest to check correct operation of this important module. -# -# $Id$ -# -# @section Description -# -# Modulo 10 checksum for e-banking codes -# - -class modulo10: - # thanks to http://www.hosang.ch/modulo10.aspx - # much more details http://www.sic.ch/de/dl_tkicch_dta.pdf ( page 51 ) - # @see http://www.bundesbank.de/download/zahlungsverkehr/zv_pz201012.pdf - # @see http://www.bundesbank.de/zahlungsverkehr/zahlungsverkehr_pruefziffernberechnung.php - def __init__(self, amount, account, reference): - self.tabelle = [0,9,4,6,8,2,7,1,3,5] - - self.account = account - self.reference = reference - - self.checksum_b = self._checksum(amount) - self.checksum_k = self._checksum(account) - self.checksum_r = self._checksum(reference) - self.checksum = self.checksum_b and self.checksum_k and self.checksum_r - - try: - self.amount = str(int(amount[2:-1])/100.) - except ValueError: - self.amount = amount + " (error)" - - def _run(self, nr): - self.uebertrag = 0 - # iterate over each character - for i in range(len(nr)): - self.uebertrag = self.tabelle[(self.uebertrag + int(nr[i]) )%10] - - return (10-self.uebertrag)%10 - - def _checksum(self, value): - return (int(value[-1]) == self._run(value[:-1]) ) Deleted: trunk/installbundle.py =================================================================== --- trunk/installbundle.py 2011-04-27 19:01:54 UTC (rev 49) +++ trunk/installbundle.py 2011-04-27 19:43:41 UTC (rev 50) @@ -1,196 +0,0 @@ -## -# @file installbundle.py -# @package installbundle -# @authors University of Utah (VisTrails), drtrigon -# @version 1.1 -# @brief Module with utilities to try and install a bundle if possible. -# -# $Id$ -# -# @section Description -# -# Module with utilities to try and install a bundle if possible. -# -############################################################################ -## -## Copyright (C) 2006-2010 University of Utah. All rights reserved. -## -## This file is part of VisTrails. -## -## This file may be used under the terms of the GNU General Public -## License version 2.0 as published by the Free Software Foundation -## and appearing in the file LICENSE.GPL included in the packaging of -## this file. Please review the following to ensure GNU General Public -## Licensing requirements will be met: -## http://www.opensource.org/licenses/gpl-license.php -## -## If you are unsure which license is appropriate for your use (for -## instance, you are interested in developing a commercial derivative -## of VisTrails), please contact us at vis...@sc.... -## -## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -## -## Changed 2011 by drtrigon. Source from 'core.bundles.installbundle' -## http://downloads.sourceforge.net/project/vistrails/vistrails/nightly/vistrails-src-nightly.tar.gz -## -## This file was modified to be used as part of PyCodeOCR. -## -############################################################################ -# - -"""Module with utilities to try and install a bundle if possible.""" - -import os - -############################################################################## - -def linux_ubuntu_install(package_name): - qt = has_qt() - hide_splash_if_necessary() - - if qt: - cmd = core.system.vistrails_root_directory() - cmd += '/core/bundles/linux_ubuntu_install.py' - else: - cmd = 'apt-get install -y' - - if type(package_name) == str: - cmd += ' ' + package_name - elif type(package_name) == list: - for package in package_name: - if type(package) != str: - raise TypeError("Expected string or list of strings") - cmd += ' ' + package - - if qt: - sucmd = guess_graphical_sudo() + " '" + cmd + "'" - else: - debug.warning("PyCodeOCR wants to install package(s) '%s'" % - package_name) - sucmd = "sudo " + cmd - - result = os.system(sucmd) - - return (result == 0) # 0 indicates success - -def linux_fedora_install(package_name): - qt = has_qt() - hide_splash_if_necessary() - if qt: - cmd = core.system.vistrails_root_directory() - cmd += '/core/bundles/linux_fedora_install.py' - else: - cmd = 'yum -y install' - - if type(package_name) == str: - cmd += ' ' + package_name - elif type(package_name) == list: - for package in package_name: - if type(package) != str: - raise TypeError("Expected string or list of strings") - cmd += ' ' + package - - if qt: - sucmd = guess_graphical_sudo() + " " + cmd - else: - debug.warning(("PyCodeOCR wants to install package(s) '%s' through " - "_sudo_. Make sure you are a sudoer.") % package_name) - sucmd = "sudo " + cmd - - debug.warning("EXECUTING: sucmd") - result = os.system(sucmd) - debug.warning("RETURN VALUE: %s" % result) - return (result == 0) - -def show_question(which_files): - qt = has_qt() - if qt: - import gui.utils - if type(which_files) == str: - which_files = [which_files] - v = gui.utils.show_question("Required packages missing", - "One or more required packages are missing: " + - " ".join(which_files) + - ". PyCodeOCR can " + - "automaticallly install them. " + - "If you click OK, PyCodeOCR will need "+ - "administrator privileges, and you " + - "might be asked for the administrator password.", - buttons=[gui.utils.OK_BUTTON, - gui.utils.CANCEL_BUTTON], - default=gui.utils.OK_BUTTON) - return v == gui.utils.OK_BUTTON - else: - print "Required package missing" - print ("A required package is missing, but PyCodeOCR can " + - "automatically install it. " + - "If you say Yes, PyCodeOCR will need "+ - "administrator privileges, and you" + - "might be asked for the administrator password.") - print "Give PyCodeOCR permission to try to install package? (y/N)" - v = raw_input().upper() - return v == 'Y' or v == 'YES' - - -def install(dependency_dictionary): - """Tries to import a python module. If unsuccessful, tries to install -the appropriate bundle and then reimport. py_import tries to be smart -about which system it runs on.""" - - # Ugly fix to avoid circular import - distro = guess_system() - if not dependency_dictionary.has_key(distro): - return False - else: - files = dependency_dictionary[distro] - if show_question(files): - callable_ = getattr(installbundle, - distro.replace('-', '_') + '_install') - return callable_(files) - else: - return False - -############################################################################## - -## Guesses the operation system. -# -# Replaces original VisTrails 'core.bundles.utils.guess_system'. -# -# @since (added for PyCodeOCR) -# -def guess_system(): - import platform - #print os.name, platform.platform() - return ("%s-%s" % (platform.system(), platform.dist()[0])).lower() - -## Dummy function, returns False. -# -# Replaces original VisTrails 'has_qt'. -# -# @since (added for PyCodeOCR) -# -def has_qt(): - return False - -import installbundle - -## Dummy function, just passes. -# -# Replaces original VisTrails 'hide_splash_if_necessary'. -# -# @since (added for PyCodeOCR) -# -def hide_splash_if_necessary(): - pass - -## Debug warning output handler. -# -# Replaces original VisTrails 'core.debug.warning'. -# -# @since (added for PyCodeOCR) -# -class dbg(): - def warning(self, *args): - print "".join(args) -debug = dbg() Deleted: trunk/requirements.py =================================================================== --- trunk/requirements.py 2011-04-27 19:01:54 UTC (rev 49) +++ trunk/requirements.py 2011-04-27 19:43:41 UTC (rev 50) @@ -1,241 +0,0 @@ -## -# @file requirements.py -# @package requirements -# @authors University of Utah (VisTrails), drtrigon -# @version 1.1 -# @brief Online test presence of runtime components. -# -# $Id$ -# -# @section Description -# -# module that allows online inspection of environment to test presence of -# runtime components such as binaries, libraries, other python modules, etc. -# -############################################################################ -## -## Copyright (C) 2006-2010 University of Utah. All rights reserved. -## -## This file is part of VisTrails. -## -## This file may be used under the terms of the GNU General Public -## License version 2.0 as published by the Free Software Foundation -## and appearing in the file LICENSE.GPL included in the packaging of -## this file. Please review the following to ensure GNU General Public -## Licensing requirements will be met: -## http://www.opensource.org/licenses/gpl-license.php -## -## If you are unsure which license is appropriate for your use (for -## instance, you are interested in developing a commercial derivative -## of VisTrails), please contact us at vis...@sc.... -## -## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -## -## Changed 2011 by drtrigon. Source from 'core.requirements' -## http://downloads.sourceforge.net/project/vistrails/vistrails/nightly/vistrails-src-nightly.tar.gz -## -## This file was modified to be used as part of PyCodeOCR. -## -############################################################################ -# - -"""module that allows online inspection of environment to test presence of -runtime components such as binaries, libraries, other python modules, etc.""" - -import sys - -############################################################################## - -def python_module_exists(module_name): - """python_module_exists(module_name): Boolean. -Returns if python module of given name can be safely imported.""" - - try: - sys.modules[module_name] - return True - except KeyError: - pass - try: - __import__(module_name) - return True - except ImportError: - return False - - -def executable_file_exists(filename): - """executable_file_exists(filename): Boolean. -Returns if certain file is in current path and is executable.""" - result = executable_is_in_path(filename) - if result == "": - result = executable_is_in_pythonpath(filename) - return result != "" - -# FIXME: Add documentation. - -def require_python_module(module_name): - if not python_module_exists(module_name): - raise MissingRequirement(module_name) - -def require_executable(filename): - if not executable_file_exists(filename): - raise MissingRequirement(filename) - -def check_pyqt4(): - # checks for the presence of pyqt4, which is more important than the rest, - # since using pyqt requires a qapplication. - try: - require_python_module('PyQt4.QtGui') - require_python_module('PyQt4.QtOpenGL') - except MissingRequirement: - r = core.bundles.installbundle.install({'linux-ubuntu': ['python-qt4', - 'python-qt4-gl', - 'python-qt4-sql']}) - if not r: - raise - - -def check_all_vistrails_requirements(): - pass - - # check scipy -# try: -# require_python_module('scipy') -# except MissingRequirement: -# r = core.bundles.installbundle.install({'linux-ubuntu': 'python-scipy'}) -# if not r: -# raise - - -############################################################################## - -class MissingRequirement(Exception): - """Raise this exception in packages when necessary items are missing.""" - def __init__(self, req): - self.requirement = req - def __str__(self): - return "Missing Requirement: %s" % self.requirement - -############################################################################## - -import installbundle -import os - - -## Shows the full path of (shell) commands. -# -# According to shell command 'which', look also at: -# @see http://unixhelp.ed.ac.uk/CGI/man-cgi?which -# @see http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python -# -# @since (added for PyCodeOCR) -# -def which(program, search_path=None): - is_exe = lambda fpath: os.path.exists(fpath) and os.access(fpath, os.X_OK) - #is_exe = lambda fpath: os.path.exists(fpath) - - fpath, fname = os.path.split(program) - if fpath: - if is_exe(program): - return program - else: - if not search_path: - search_path = os.environ["PATH"].split(os.pathsep) - search_path += [ '.' ] # add local path - for path in search_path: - exe_file = os.path.join(path, program) - if is_exe(exe_file): - return exe_file - return "" - -## Checks if executable is in system PATH. -# -# Replaces original VisTrails 'core.system.executable_is_in_path'. -# -# @since (added for PyCodeOCR) -# -def executable_is_in_path(filename): - #print os.system(filename) - return which(filename) - -## Checks if executable is in system PYTHONPATH. -# -# Replaces original VisTrails 'core.system.executable_is_in_pythonpath'. -# -# @since (added for PyCodeOCR) -# -def executable_is_in_pythonpath(filename): - return which(filename, search_path=os.environ.get("PYTHONPATH", None)) - - -## Checks if pygtk libraries are installed. -# -# @since (added for PyCodeOCR) -# -# @todo Check if further dependencies/packages are needed...? -# -def check_pygtk(): - # checks for the presence of pygtk, which is more important than the rest. - try: - require_python_module('pygtk') - #pygtk.require('2.0') - require_python_module('gtk') - require_python_module('gtk.glade') - require_python_module('gobject') - except MissingRequirement: - r = core.bundles.installbundle.install({'linux-fedora': ['pygtk2']}) - # other deps? - if not r: - raise - -## Checks if sane libraries are installed. -# -# @since (added for PyCodeOCR) -# -# @todo Check if further dependencies/packages are needed...? -# -def check_sane(): - try: - require_python_module('sane') - except MissingRequirement: - r = core.bundles.installbundle.install({'linux-fedora': ['python-imaging-sane']}) - # other deps? - if not r: - raise - -## Checks if optional libraries are installed. -# -# @since (added for PyCodeOCR) -# -def check_optionals(): - try: - require_executable("gocr") - except MissingRequirement: - r = installbundle.install({'linux-fedora': ['gocr'], - 'linux-ubuntu': ['gocr']}) - - try: - #require_python_module('pydmtx') - require_executable("dmtxread") - except MissingRequirement: - #r = installbundle.install({'linux-fedora': ['python-libdmtx']}) - r = installbundle.install({'linux-fedora': ['libdmtx-utils'], - 'linux-ubuntu': ['libdmtx-utils']}) - - -## Checks if all libraries whether needed or optional are installed. -# -# @since (added for PyCodeOCR) -# -def check_all_pycodeocr_requirements(): - print "Checking all PyCodeOCR requirements:" - - # needed - print " * NEEDED 'pygtk2'" - check_pygtk() - print " * NEEDED 'sane' (scanner)" - check_sane() - - # optional - print " * OPTIONAL 'gocr', 'dmtxread'" - check_optionals() Added: trunk/utils/__init__.py =================================================================== --- trunk/utils/__init__.py (rev 0) +++ trunk/utils/__init__.py 2011-04-27 19:43:41 UTC (rev 50) @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +## +# @file __init__.py +# @namespace utils +# @authors drtrigon +# @version 1.1 +# @brief This is the utils package with important functions. +# +# $Id: checksum.py -1 $ +# +# @section Description +# +# This is the utils package with important functions. +# + +import utils.checksum +import utils.requirements +import utils.ocr Property changes on: trunk/utils/__init__.py ___________________________________________________________________ Added: svn:eol-style + native Copied: trunk/utils/checksum.py (from rev 49, trunk/checksum.py) =================================================================== --- trunk/utils/checksum.py (rev 0) +++ trunk/utils/checksum.py 2011-04-27 19:43:41 UTC (rev 50) @@ -0,0 +1,47 @@ +## +# @file utils/checksum.py +# @namespace utils::checksum +# @authors laserb, drtrigon +# @version 1.1 +# @brief Modulo 10 checksum for e-banking codes. +# +# @test Add unittest to check correct operation of this important module. +# +# $Id$ +# +# @section Description +# +# Modulo 10 checksum for e-banking codes +# + +class modulo10: + # thanks to http://www.hosang.ch/modulo10.aspx + # much more details http://www.sic.ch/de/dl_tkicch_dta.pdf ( page 51 ) + # @see http://www.bundesbank.de/download/zahlungsverkehr/zv_pz201012.pdf + # @see http://www.bundesbank.de/zahlungsverkehr/zahlungsverkehr_pruefziffernberechnung.php + def __init__(self, amount, account, reference): + self.tabelle = [0,9,4,6,8,2,7,1,3,5] + + self.account = account + self.reference = reference + + self.checksum_b = self._checksum(amount) + self.checksum_k = self._checksum(account) + self.checksum_r = self._checksum(reference) + self.checksum = self.checksum_b and self.checksum_k and self.checksum_r + + try: + self.amount = str(int(amount[2:-1])/100.) + except ValueError: + self.amount = amount + " (error)" + + def _run(self, nr): + self.uebertrag = 0 + # iterate over each character + for i in range(len(nr)): + self.uebertrag = self.tabelle[(self.uebertrag + int(nr[i]) )%10] + + return (10-self.uebertrag)%10 + + def _checksum(self, value): + return (int(value[-1]) == self._run(value[:-1]) ) Copied: trunk/utils/installbundle.py (from rev 46, trunk/installbundle.py) =================================================================== --- trunk/utils/installbundle.py (rev 0) +++ trunk/utils/installbundle.py 2011-04-27 19:43:41 UTC (rev 50) @@ -0,0 +1,196 @@ +## +# @file utils/installbundle.py +# @namespace utils::installbundle +# @authors University of Utah (VisTrails), drtrigon +# @version 1.1 +# @brief Module with utilities to try and install a bundle if possible. +# +# $Id$ +# +# @section Description +# +# Module with utilities to try and install a bundle if possible. +# +############################################################################ +## +## Copyright (C) 2006-2010 University of Utah. All rights reserved. +## +## This file is part of VisTrails. +## +## This file may be used under the terms of the GNU General Public +## License version 2.0 as published by the Free Software Foundation +## and appearing in the file LICENSE.GPL included in the packaging of +## this file. Please review the following to ensure GNU General Public +## Licensing requirements will be met: +## http://www.opensource.org/licenses/gpl-license.php +## +## If you are unsure which license is appropriate for your use (for +## instance, you are interested in developing a commercial derivative +## of VisTrails), please contact us at vis...@sc.... +## +## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +## +## Changed 2011 by drtrigon. Source from 'core.bundles.installbundle' +## http://downloads.sourceforge.net/project/vistrails/vistrails/nightly/vistrails-src-nightly.tar.gz +## +## This file was modified to be used as part of PyCodeOCR. +## +############################################################################ +# + +"""Module with utilities to try and install a bundle if possible.""" + +import os + +############################################################################## + +def linux_ubuntu_install(package_name): + qt = has_qt() + hide_splash_if_necessary() + + if qt: + cmd = core.system.vistrails_root_directory() + cmd += '/core/bundles/linux_ubuntu_install.py' + else: + cmd = 'apt-get install -y' + + if type(package_name) == str: + cmd += ' ' + package_name + elif type(package_name) == list: + for package in package_name: + if type(package) != str: + raise TypeError("Expected string or list of strings") + cmd += ' ' + package + + if qt: + sucmd = guess_graphical_sudo() + " '" + cmd + "'" + else: + debug.warning("PyCodeOCR wants to install package(s) '%s'" % + package_name) + sucmd = "sudo " + cmd + + result = os.system(sucmd) + + return (result == 0) # 0 indicates success + +def linux_fedora_install(package_name): + qt = has_qt() + hide_splash_if_necessary() + if qt: + cmd = core.system.vistrails_root_directory() + cmd += '/core/bundles/linux_fedora_install.py' + else: + cmd = 'yum -y install' + + if type(package_name) == str: + cmd += ' ' + package_name + elif type(package_name) == list: + for package in package_name: + if type(package) != str: + raise TypeError("Expected string or list of strings") + cmd += ' ' + package + + if qt: + sucmd = guess_graphical_sudo() + " " + cmd + else: + debug.warning(("PyCodeOCR wants to install package(s) '%s' through " + "_sudo_. Make sure you are a sudoer.") % package_name) + sucmd = "sudo " + cmd + + debug.warning("EXECUTING: sucmd") + result = os.system(sucmd) + debug.warning("RETURN VALUE: %s" % result) + return (result == 0) + +def show_question(which_files): + qt = has_qt() + if qt: + import gui.utils + if type(which_files) == str: + which_files = [which_files] + v = gui.utils.show_question("Required packages missing", + "One or more required packages are missing: " + + " ".join(which_files) + + ". PyCodeOCR can " + + "automaticallly install them. " + + "If you click OK, PyCodeOCR will need "+ + "administrator privileges, and you " + + "might be asked for the administrator password.", + buttons=[gui.utils.OK_BUTTON, + gui.utils.CANCEL_BUTTON], + default=gui.utils.OK_BUTTON) + return v == gui.utils.OK_BUTTON + else: + print "Required package missing" + print ("A required package is missing, but PyCodeOCR can " + + "automatically install it. " + + "If you say Yes, PyCodeOCR will need "+ + "administrator privileges, and you" + + "might be asked for the administrator password.") + print "Give PyCodeOCR permission to try to install package? (y/N)" + v = raw_input().upper() + return v == 'Y' or v == 'YES' + + +def install(dependency_dictionary): + """Tries to import a python module. If unsuccessful, tries to install +the appropriate bundle and then reimport. py_import tries to be smart +about which system it runs on.""" + + # Ugly fix to avoid circular import + distro = guess_system() + if not dependency_dictionary.has_key(distro): + return False + else: + files = dependency_dictionary[distro] + if show_question(files): + callable_ = getattr(installbundle, + distro.replace('-', '_') + '_install') + return callable_(files) + else: + return False + +############################################################################## + +## Guesses the operation system. +# +# Replaces original VisTrails 'core.bundles.utils.guess_system'. +# +# @since (added for PyCodeOCR) +# +def guess_system(): + import platform + #print os.name, platform.platform() + return ("%s-%s" % (platform.system(), platform.dist()[0])).lower() + +## Dummy function, returns False. +# +# Replaces original VisTrails 'has_qt'. +# +# @since (added for PyCodeOCR) +# +def has_qt(): + return False + +import installbundle + +## Dummy function, just passes. +# +# Replaces original VisTrails 'hide_splash_if_necessary'. +# +# @since (added for PyCodeOCR) +# +def hide_splash_if_necessary(): + pass + +## Debug warning output handler. +# +# Replaces original VisTrails 'core.debug.warning'. +# +# @since (added for PyCodeOCR) +# +class dbg(): + def warning(self, *args): + print "".join(args) +debug = dbg() Added: trunk/utils/ocr.py =================================================================== --- trunk/utils/ocr.py (rev 0) +++ trunk/utils/ocr.py 2011-04-27 19:43:41 UTC (rev 50) @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +## +# @file utils/ocr.py +# @namespace utils::ocr +# @authors drtrigon +# @version 1.1 +# @brief Character recogition (OCR) functions. +# +# $Id$ +# +# @section Description +# +# Character recogition (OCR) functions. +# + +# python standard modules +import re + +## Character correction after recogition (on basis that there should be numbers and few special chars). +# +# @test Add unittest to check correct operation of this important module/function. +# +def char_correction(data): + data = re.sub("\n", "", data) + print data + corrections = [ + # Zero + ("O", "0"), ("D", "0"), ("U", "0"), ("Q", "0"), ("\(\)", "0"), ("G", "0"), ("o", "0"), + # Two + ("Z", "2"), + # Three + ("\?>", "3"), + # Four + ("l\.", "4"), ("A", "4"), ("l»", "4"), ("h", "4"), ("i»", "4"), ("l\xe2\x80\xa2", "4"), ("&", "4"), + # Five + ("S", "5"), + # Six + ("c>", "6"), + # Seven + #("\?", "7"), + # One (critical, therefore done as last; has also Overlapps e.g. with Four) + (chr(226)+chr(128)+chr(153)+"I", "1"), + (chr(226)+chr(128)+chr(153)+"\|", "1"), + (chr(226)+chr(128)+chr(152)+"\|", "1"), + (chr(226)+chr(128)+chr(152)+"I", "1"), + (chr(39)+"I", "1"), + ("I", "1"), + (chr(153)+"l", "1"), + (chr(39)+"l", "1"), + ("l", "1"), + (chr(39)+"!", "1"), + (chr(39)+"\|", "1"), + ("\|", "1"), + ("'\]", "1"), + ("'\}", "1"), + (r'\\', "1"), + # non-numbers + (" ", ""), + ("\xe2", ""), + ("\x80", ""), + ("\xbb", ""), + ("\x99", ""), + ("\x98", ""), + ("\x5f", ""), + ("\x60", ""), + ("'", ""), + #('\xbb', 187)('\x99', 153)('\x98', 152) + ("\+", "+ "), + ("\x92", "1"), # post correction + ] + for item in corrections: + olddata = data + data = re.sub(item[0], item[1], data) + if not (data == olddata): print 'subst: "%s" => "%s"' % (item[0], item[1]) + + return data Property changes on: trunk/utils/ocr.py ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + native Copied: trunk/utils/requirements.py (from rev 49, trunk/requirements.py) =================================================================== --- trunk/utils/requirements.py (rev 0) +++ trunk/utils/requirements.py 2011-04-27 19:43:41 UTC (rev 50) @@ -0,0 +1,241 @@ +## +# @file utils/requirements.py +# @namespace utils::requirements +# @authors University of Utah (VisTrails), drtrigon +# @version 1.1 +# @brief Online test presence of runtime components. +# +# $Id$ +# +# @section Description +# +# module that allows online inspection of environment to test presence of +# runtime components such as binaries, libraries, other python modules, etc. +# +############################################################################ +## +## Copyright (C) 2006-2010 University of Utah. All rights reserved. +## +## This file is part of VisTrails. +## +## This file may be used under the terms of the GNU General Public +## License version 2.0 as published by the Free Software Foundation +## and appearing in the file LICENSE.GPL included in the packaging of +## this file. Please review the following to ensure GNU General Public +## Licensing requirements will be met: +## http://www.opensource.org/licenses/gpl-license.php +## +## If you are unsure which license is appropriate for your use (for +## instance, you are interested in developing a commercial derivative +## of VisTrails), please contact us at vis...@sc.... +## +## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +## +## Changed 2011 by drtrigon. Source from 'core.requirements' +## http://downloads.sourceforge.net/project/vistrails/vistrails/nightly/vistrails-src-nightly.tar.gz +## +## This file was modified to be used as part of PyCodeOCR. +## +############################################################################ +# + +"""module that allows online inspection of environment to test presence of +runtime components such as binaries, libraries, other python modules, etc.""" + +import sys + +############################################################################## + +def python_module_exists(module_name): + """python_module_exists(module_name): Boolean. +Returns if python module of given name can be safely imported.""" + + try: + sys.modules[module_name] + return True + except KeyError: + pass + try: + __import__(module_name) + return True + except ImportError: + return False + + +def executable_file_exists(filename): + """executable_file_exists(filename): Boolean. +Returns if certain file is in current path and is executable.""" + result = executable_is_in_path(filename) + if result == "": + result = executable_is_in_pythonpath(filename) + return result != "" + +# FIXME: Add documentation. + +def require_python_module(module_name): + if not python_module_exists(module_name): + raise MissingRequirement(module_name) + +def require_executable(filename): + if not executable_file_exists(filename): + raise MissingRequirement(filename) + +def check_pyqt4(): + # checks for the presence of pyqt4, which is more important than the rest, + # since using pyqt requires a qapplication. + try: + require_python_module('PyQt4.QtGui') + require_python_module('PyQt4.QtOpenGL') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-ubuntu': ['python-qt4', + 'python-qt4-gl', + 'python-qt4-sql']}) + if not r: + raise + + +def check_all_vistrails_requirements(): + pass + + # check scipy +# try: +# require_python_module('scipy') +# except MissingRequirement: +# r = core.bundles.installbundle.install({'linux-ubuntu': 'python-scipy'}) +# if not r: +# raise + + +############################################################################## + +class MissingRequirement(Exception): + """Raise this exception in packages when necessary items are missing.""" + def __init__(self, req): + self.requirement = req + def __str__(self): + return "Missing Requirement: %s" % self.requirement + +############################################################################## + +import installbundle +import os + + +## Shows the full path of (shell) commands. +# +# According to shell command 'which', look also at: +# @see http://unixhelp.ed.ac.uk/CGI/man-cgi?which +# @see http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python +# +# @since (added for PyCodeOCR) +# +def which(program, search_path=None): + is_exe = lambda fpath: os.path.exists(fpath) and os.access(fpath, os.X_OK) + #is_exe = lambda fpath: os.path.exists(fpath) + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + if not search_path: + search_path = os.environ["PATH"].split(os.pathsep) + search_path += [ '.' ] # add local path + for path in search_path: + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return "" + +## Checks if executable is in system PATH. +# +# Replaces original VisTrails 'core.system.executable_is_in_path'. +# +# @since (added for PyCodeOCR) +# +def executable_is_in_path(filename): + #print os.system(filename) + return which(filename) + +## Checks if executable is in system PYTHONPATH. +# +# Replaces original VisTrails 'core.system.executable_is_in_pythonpath'. +# +# @since (added for PyCodeOCR) +# +def executable_is_in_pythonpath(filename): + return which(filename, search_path=os.environ.get("PYTHONPATH", None)) + + +## Checks if pygtk libraries are installed. +# +# @since (added for PyCodeOCR) +# +# @todo Check if further dependencies/packages are needed...? +# +def check_pygtk(): + # checks for the presence of pygtk, which is more important than the rest. + try: + require_python_module('pygtk') + #pygtk.require('2.0') + require_python_module('gtk') + require_python_module('gtk.glade') + require_python_module('gobject') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-fedora': ['pygtk2']}) + # other deps? + if not r: + raise + +## Checks if sane libraries are installed. +# +# @since (added for PyCodeOCR) +# +# @todo Check if further dependencies/packages are needed...? +# +def check_sane(): + try: + require_python_module('sane') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-fedora': ['python-imaging-sane']}) + # other deps? + if not r: + raise + +## Checks if optional libraries are installed. +# +# @since (added for PyCodeOCR) +# +def check_optionals(): + try: + require_executable("gocr") + except MissingRequirement: + r = installbundle.install({'linux-fedora': ['gocr'], + 'linux-ubuntu': ['gocr']}) + + try: + #require_python_module('pydmtx') + require_executable("dmtxread") + except MissingRequirement: + #r = installbundle.install({'linux-fedora': ['python-libdmtx']}) + r = installbundle.install({'linux-fedora': ['libdmtx-utils'], + 'linux-ubuntu': ['libdmtx-utils']}) + + +## Checks if all libraries whether needed or optional are installed. +# +# @since (added for PyCodeOCR) +# +def check_all_pycodeocr_requirements(): + print "Checking all PyCodeOCR requirements:" + + # needed + print " * NEEDED 'pygtk2'" + check_pygtk() + print " * NEEDED 'sane' (scanner)" + check_sane() + + # optional + print " * OPTIONAL 'gocr', 'dmtxread'" + check_optionals() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-27 19:02:00
|
Revision: 49 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=49&view=rev Author: drtrigon Date: 2011-04-27 19:01:54 +0000 (Wed, 27 Apr 2011) Log Message: ----------- some followup to r47, main-window improved, checksum class and char_correction updated Modified Paths: -------------- trunk/CHANGES trunk/PyCodeOCR.glade trunk/PyCodeOCR.py trunk/checksum.py trunk/requirements.py Modified: trunk/CHANGES =================================================================== --- trunk/CHANGES 2011-04-27 15:51:57 UTC (rev 48) +++ trunk/CHANGES 2011-04-27 19:01:54 UTC (rev 49) @@ -25,6 +25,7 @@ # CHANGES: # # * (Version 1.1): +# - [ r18 - HEAD ] # - Added support for barcodes with gocr (somehow preliminary). Can find and # recognize the code automatic, therefore the whole page is scanned. [expermental # or beta] Modified: trunk/PyCodeOCR.glade =================================================================== --- trunk/PyCodeOCR.glade 2011-04-27 15:51:57 UTC (rev 48) +++ trunk/PyCodeOCR.glade 2011-04-27 19:01:54 UTC (rev 49) @@ -340,7 +340,6 @@ <property name="urgency_hint">True</property> <property name="deletable">False</property> <property name="transient_for">window1</property> - <signal name="destroy" handler="on_window2_destroy"/> <child> <widget class="GtkFixed" id="fixed1"> <property name="visible">True</property> Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-04-27 15:51:57 UTC (rev 48) +++ trunk/PyCodeOCR.py 2011-04-27 19:01:54 UTC (rev 49) @@ -9,6 +9,9 @@ # # $Id$ # +# @todo This module/script has become large (more than 1000 lines) +# and should be splitted into seperate files. +# # For further information please consult the @ref mainpage also. # # @mainpage PyCodeOCR @@ -278,11 +281,12 @@ self.on_eventbox2_button_press_event() def on_pointer_motion(self, source=None, event=None): - (x,y,state) = self.window1.window.get_pointer() - (wxim, wyim ) = self.image1.get_size_request() - if x > 16+(wxim-self.new_width)/2 and x < 16+(wxim+self.new_width)/2 and y > 75+(wyim-self.new_height)/2 and y < 75+(wyim+self.new_height)/2: - if not self.window3.get_visible(): - self.on_eventbox2_button_press_event() + pass +# (x,y,state) = self.window1.window.get_pointer() +# (wxim, wyim ) = self.image1.get_size_request() +# if x > 16+(wxim-self.new_width)/2 and x < 16+(wxim+self.new_width)/2 and y > 75+(wyim-self.new_height)/2 and y < 75+(wyim+self.new_height)/2: +# if not self.window3.get_visible(): +# self.on_eventbox2_button_press_event() def on_eventbox2_button_press_event(self, source=None, event=None): if self.window3.get_visible(): @@ -422,16 +426,6 @@ pass # exit gtk.main_quit() - - ## press x-button on device select window - def on_window2_destroy(self, source=None): - # when windows is closed by pressing the x-button - # choose first device - devnr = 0 - # init scanner - self.run_sane.init_scanner(self.progress, self.window2, self.treeview1, devnr) - # set sensitivity - self.init_sensitivity() ## file selected def on_filechooserbutton1_file_set(self, source=None): @@ -450,8 +444,10 @@ def toggle_placement_sensitive(self, value): if self.radiobutton2.get_active(): self.frame1.set_sensitive(value) + self.filechooserbutton1.set_sensitive(False) else: self.frame1.set_sensitive(False) + self.filechooserbutton1.set_sensitive(True) # helpers # @@ -494,7 +490,7 @@ #dmtxread recognition opt = { 'tmp_file': "02.jpg", # some issues with recogition 'recog_class': RunExternal, # . - 'recog_cmd': "%s %s02.jpg"%(paths["dmtxread"],self.temp), # of different file formats + 'recog_cmd': "%s -v -D %s02.jpg"%(paths["dmtxread"],self.temp), # of different file formats 'recog_error_msg': [ "error" ], # . #opt = { 'tmp_file': "02.bmp", # and drawing/marking the @@ -633,16 +629,13 @@ reference = tmp[0] account = tmp[1] # initialize modulo10 checksum - m10 = modulo10() + m10 = modulo10(amount, account, reference) # check amount, account number and reference number - checksum_b = (int(amount[-1]) == m10.run(amount[:-1]) ) - checksum_k = (int(account[-1]) == m10.run(account[:-1]) ) - checksum_r = (int(reference[-1]) == m10.run(reference[:-1]) ) - print "Amount: "+str(int(amount[2:-1])/100.),checksum_b - print "Account number: "+account,checksum_k - print "Reference number: "+reference,checksum_r + print "Amount:", m10.amount, m10.checksum_b + print "Account number:", m10.account, m10.checksum_k + print "Reference number:", m10.reference, m10.checksum_r - checksum = checksum_b and checksum_k and checksum_r + checksum = m10.checksum # if len(data) == 42: # # extract details @@ -688,11 +681,10 @@ # Data final output # (6/?) self.progress(6./max_steps, "Final data output...") + self.entry1.set_text(data) if check: os.remove(self.temp+opt['tmp_file']) # clean-up - self.entry1.set_text(data) - # get the clipboard clipboard = gtk.clipboard_get() # set the clipboard text data @@ -795,7 +787,7 @@ print data corrections = [ # Zero - ("O", "0"), ("D", "0"), ("U", "0"), ("Q", "0"), ("\(\)", "0"), ("G", "0"), + ("O", "0"), ("D", "0"), ("U", "0"), ("Q", "0"), ("\(\)", "0"), ("G", "0"), ("o", "0"), # Two ("Z", "2"), # Three @@ -833,6 +825,7 @@ ("\x98", ""), ("\x5f", ""), ("\x60", ""), + ("'", ""), #('\xbb', 187)('\x99', 153)('\x98', 152) ("\+", "+ "), ("\x92", "1"), # post correction Modified: trunk/checksum.py =================================================================== --- trunk/checksum.py 2011-04-27 15:51:57 UTC (rev 48) +++ trunk/checksum.py 2011-04-27 19:01:54 UTC (rev 49) @@ -19,13 +19,29 @@ # much more details http://www.sic.ch/de/dl_tkicch_dta.pdf ( page 51 ) # @see http://www.bundesbank.de/download/zahlungsverkehr/zv_pz201012.pdf # @see http://www.bundesbank.de/zahlungsverkehr/zahlungsverkehr_pruefziffernberechnung.php - def __init__(self): + def __init__(self, amount, account, reference): self.tabelle = [0,9,4,6,8,2,7,1,3,5] + + self.account = account + self.reference = reference - def run(self,nr): + self.checksum_b = self._checksum(amount) + self.checksum_k = self._checksum(account) + self.checksum_r = self._checksum(reference) + self.checksum = self.checksum_b and self.checksum_k and self.checksum_r + + try: + self.amount = str(int(amount[2:-1])/100.) + except ValueError: + self.amount = amount + " (error)" + + def _run(self, nr): self.uebertrag = 0 # iterate over each character for i in range(len(nr)): self.uebertrag = self.tabelle[(self.uebertrag + int(nr[i]) )%10] return (10-self.uebertrag)%10 + + def _checksum(self, value): + return (int(value[-1]) == self._run(value[:-1]) ) Modified: trunk/requirements.py =================================================================== --- trunk/requirements.py 2011-04-27 15:51:57 UTC (rev 48) +++ trunk/requirements.py 2011-04-27 19:01:54 UTC (rev 49) @@ -218,6 +218,7 @@ #require_python_module('pydmtx') require_executable("dmtxread") except MissingRequirement: + #r = installbundle.install({'linux-fedora': ['python-libdmtx']}) r = installbundle.install({'linux-fedora': ['libdmtx-utils'], 'linux-ubuntu': ['libdmtx-utils']}) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-27 14:58:51
|
Revision: 47 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=47&view=rev Author: drtrigon Date: 2011-04-27 14:58:45 +0000 (Wed, 27 Apr 2011) Log Message: ----------- followup to r24 and r43: default action/button does work now Modified Paths: -------------- trunk/PyCodeOCR.glade trunk/PyCodeOCR.py Added Paths: ----------- README Added: README =================================================================== --- README (rev 0) +++ README 2011-04-27 14:58:45 UTC (rev 47) @@ -0,0 +1,17 @@ +The 'trunk' is the main line of development in a SVN repository. + +A 'branch' is a side-line of development created to make larger, experimental or +disrupting work without annoying users of the trunk version. Also, branches can +be used to create development lines for multiple versions of the same product, +like having a place to backport bugfixes into a stable release. + +Finally, 'tags' are markers to highlight notable revisions in the history of the +repository, usually things like "this was released as 1.0". + +See the HTML version of "Version Control with Subversion", especially Chapter 4: +Branching and Merging or buy it in paper (e.g. from amazon) for an in-depth +discussion of the technical details. +http://svnbook.red-bean.com/ +http://svnbook.red-bean.com/en/1.5/svn.branchmerge.html + +http://stackoverflow.com/questions/698313/what-is-trunk-branch-and-tag-in-subversion Modified: trunk/PyCodeOCR.glade =================================================================== --- trunk/PyCodeOCR.glade 2011-04-27 14:31:11 UTC (rev 46) +++ trunk/PyCodeOCR.glade 2011-04-27 14:58:45 UTC (rev 47) @@ -351,6 +351,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="enable_grid_lines">horizontal</property> + <signal name="row_activated" handler="on_treeview1_row_activated"/> </widget> <packing> <property name="x">15</property> Modified: trunk/PyCodeOCR.py =================================================================== --- trunk/PyCodeOCR.py 2011-04-27 14:31:11 UTC (rev 46) +++ trunk/PyCodeOCR.py 2011-04-27 14:58:45 UTC (rev 47) @@ -14,6 +14,8 @@ # @mainpage PyCodeOCR # @anchor mainpage # +# http://pycodeocr.sourceforge.net/ +# # @section Description # # Turn your scanner into a free document @@ -316,6 +318,10 @@ self.run_sane.init_scanner(self.progress, self.window2, self.treeview1, devnr) # set sensitivity self.init_sensitivity() + + # http://www.pygtk.org/pygtk2tutorial/sec-TreeViewSignals.html + def on_treeview1_row_activated(self, *args, **kwargs): + self.on_button3_clicked() ## set sensitivity of buttons the first time def init_sensitivity(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <drt...@us...> - 2011-04-27 12:25:27
|
Revision: 44 http://pycodeocr.svn.sourceforge.net/pycodeocr/?rev=44&view=rev Author: drtrigon Date: 2011-04-27 12:25:14 +0000 (Wed, 27 Apr 2011) Log Message: ----------- Thanks to the guys from VisTrails at the University of Utah we have code now for automatic dependency check and installation of needed repos. This works for fedora and ubuntu at the moment. Modified Paths: -------------- PyCodeOCR.py Added Paths: ----------- installbundle.py requirements.py Property Changed: ---------------- PyCodeOCR.py checksum.py Modified: PyCodeOCR.py =================================================================== --- PyCodeOCR.py 2011-04-26 21:19:41 UTC (rev 43) +++ PyCodeOCR.py 2011-04-27 12:25:14 UTC (rev 44) @@ -10,6 +10,14 @@ import os, re, sys, subprocess, time, gobject, string, struct +# check and install requirements +#print "To check and install requirements run: 'python %s --install-deps'" % sys.argv[0] +import requirements +if "--install-deps" in sys.argv: + requirements.check_all_pycodeocr_requirements() + sys.exit() + + # GTK, PyGTK, GLADE (GNOME) modules import pygtk pygtk.require('2.0') @@ -33,19 +41,26 @@ os.system('python %s' % sys.argv[0]) # sys.exit() # ## list of available pakages +print "To check and install requirements run: 'python %s --install-deps'" % sys.argv[0] pakages = [] # gocr -if os.path.exists("gocr"): +paths = { "gocr": requirements.which("gocr"), + "dmtxread": requirements.which("dmtxread"), + "pdf417decode.exe": requirements.which("pdf417decode.exe"), } +if os.path.exists(paths["gocr"]): pakages.append( "gocr" ) print "gocr found." # libdmtx bindings -try: - #from pydmtx import DataMatrix +#try: +# from pydmtx import DataMatrix +# pakages.append( "libdmtx" ) +# print "libdmtx and pydmtx found." +#except: pass +if os.path.exists(paths["dmtxread"]): pakages.append( "libdmtx" ) print "libdmtx and pydmtx found." -except: pass # pdf417decode -if os.path.exists("pdf417decode.exe"): +if os.path.exists(paths["pdf417decode.exe"]): pakages.append( "pdf417decode" ) print "pdf417decode.exe found." @@ -76,7 +91,7 @@ # initialization # (variables) max_retry = 3 # max. scan attempts - valid_code_len = [ 53, 42, 32 ] # valid code lenghts + valid_code_len = [ 53, 42, 32 ] # valid code lenghts scan_koords = std_scan_koords["0 deg"][0] # default scan pos. mode = std_scan_koords["0 deg"][1] # default scan orient. res_color = { True: gtk.gdk.color_parse("#00FF00"), @@ -87,11 +102,11 @@ os.path.join(home_path, "PyCodeOCR_debug.txt"), ) regex_gocr = re.compile('<barcode(.*?)/>') - #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s" # SANE scan command - cmd_convert = "convert %s -depth 8 -rotate %d %s" # ImageMagick command - cmd_tesser = "tesseract %s.tif %s" # TesserAct command - cmd_gocr = os.path.join(local_path, "gocr") + " -i %s.pnm" # GOCR command (local) - cmd_pdf417dec = "wine " + os.path.join(local_path, "pdf417decode.exe") + " %s.png" # pdf417decode/wine command (local) + #cmd_scan = "scanimage --format=tif --resolution 600 --mode Gray -t %d -l %d -y %d -x %d > %s" # SANE scan command + cmd_convert = "convert %s -depth 8 -rotate %d %s" # ImageMagick command + cmd_tesser = "tesseract %s.tif %s" # TesserAct command + cmd_gocr = paths["gocr"] + " -i %s.pnm" # GOCR command (local) + cmd_pdf417dec = "wine " + paths["pdf417decode.exe"] + " %s.png" # pdf417decode/wine command (local) __stop = False @@ -440,13 +455,13 @@ self.mode = std_scan_koords["A4"][1] #pydmtx recognition # opt = { 'tmp_file': "02.jpg", # some issues with recogition -# 'recog_class': RunLibdmtx, # . -# 'recog_cmd': self.temp+"02.jpg", # of different file formats +# 'recog_class': RunLibdmtx, # . +# 'recog_cmd': self.temp+"02.jpg", # of different file formats # 'recog_error_msg': [ None ], # . #dmtxread recognition - opt = { 'tmp_file': "02.jpg", # some issues with recogition - 'recog_class': RunExternal, # . - 'recog_cmd': "dmtxread "+self.temp+"02.jpg", # of different file formats + opt = { 'tmp_file': "02.jpg", # some issues with recogition + 'recog_class': RunExternal, # . + 'recog_cmd': "%s %s02.jpg"%(paths["dmtxread"],self.temp), # of different file formats 'recog_error_msg': [ "error" ], # . #opt = { 'tmp_file': "02.bmp", # and drawing/marking the Property changes on: PyCodeOCR.py ___________________________________________________________________ Added: svn:keywords + Id Property changes on: checksum.py ___________________________________________________________________ Added: svn:keywords + Id Added: installbundle.py =================================================================== --- installbundle.py (rev 0) +++ installbundle.py 2011-04-27 12:25:14 UTC (rev 44) @@ -0,0 +1,158 @@ +############################################################################ +## +## Copyright (C) 2006-2010 University of Utah. All rights reserved. +## +## This file is part of VisTrails. +## +## This file may be used under the terms of the GNU General Public +## License version 2.0 as published by the Free Software Foundation +## and appearing in the file LICENSE.GPL included in the packaging of +## this file. Please review the following to ensure GNU General Public +## Licensing requirements will be met: +## http://www.opensource.org/licenses/gpl-license.php +## +## If you are unsure which license is appropriate for your use (for +## instance, you are interested in developing a commercial derivative +## of VisTrails), please contact us at vis...@sc.... +## +## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +## +## Changed 2011 by drtrigon. Source from 'core.bundles.installbundle' +## http://downloads.sourceforge.net/project/vistrails/vistrails/nightly/vistrails-src-nightly.tar.gz +## +## This file was modified to be used as part of PyCodeOCR. +## +############################################################################ + +"""Module with utilities to try and install a bundle if possible.""" + +import os + +############################################################################## + +def linux_ubuntu_install(package_name): + qt = has_qt() + hide_splash_if_necessary() + + if qt: + cmd = core.system.vistrails_root_directory() + cmd += '/core/bundles/linux_ubuntu_install.py' + else: + cmd = 'apt-get install -y' + + if type(package_name) == str: + cmd += ' ' + package_name + elif type(package_name) == list: + for package in package_name: + if type(package) != str: + raise TypeError("Expected string or list of strings") + cmd += ' ' + package + + if qt: + sucmd = guess_graphical_sudo() + " '" + cmd + "'" + else: + debug.warning("PyCodeOCR wants to install package(s) '%s'" % + package_name) + sucmd = "sudo " + cmd + + result = os.system(sucmd) + + return (result == 0) # 0 indicates success + +def linux_fedora_install(package_name): + qt = has_qt() + hide_splash_if_necessary() + if qt: + cmd = core.system.vistrails_root_directory() + cmd += '/core/bundles/linux_fedora_install.py' + else: + cmd = 'yum -y install' + + if type(package_name) == str: + cmd += ' ' + package_name + elif type(package_name) == list: + for package in package_name: + if type(package) != str: + raise TypeError("Expected string or list of strings") + cmd += ' ' + package + + if qt: + sucmd = guess_graphical_sudo() + " " + cmd + else: + debug.warning(("PyCodeOCR wants to install package(s) '%s' through " + "_sudo_. Make sure you are a sudoer.") % package_name) + sucmd = "sudo " + cmd + + debug.warning("EXECUTING: sucmd") + result = os.system(sucmd) + debug.warning("RETURN VALUE: %s" % result) + return (result == 0) + +def show_question(which_files): + qt = has_qt() + if qt: + import gui.utils + if type(which_files) == str: + which_files = [which_files] + v = gui.utils.show_question("Required packages missing", + "One or more required packages are missing: " + + " ".join(which_files) + + ". PyCodeOCR can " + + "automaticallly install them. " + + "If you click OK, PyCodeOCR will need "+ + "administrator privileges, and you " + + "might be asked for the administrator password.", + buttons=[gui.utils.OK_BUTTON, + gui.utils.CANCEL_BUTTON], + default=gui.utils.OK_BUTTON) + return v == gui.utils.OK_BUTTON + else: + print "Required package missing" + print ("A required package is missing, but PyCodeOCR can " + + "automatically install it. " + + "If you say Yes, PyCodeOCR will need "+ + "administrator privileges, and you" + + "might be asked for the administrator password.") + print "Give PyCodeOCR permission to try to install package? (y/N)" + v = raw_input().upper() + return v == 'Y' or v == 'YES' + + +def install(dependency_dictionary): + """Tries to import a python module. If unsuccessful, tries to install +the appropriate bundle and then reimport. py_import tries to be smart +about which system it runs on.""" + + # Ugly fix to avoid circular import + distro = guess_system() + if not dependency_dictionary.has_key(distro): + return False + else: + files = dependency_dictionary[distro] + if show_question(files): + callable_ = getattr(installbundle, + distro.replace('-', '_') + '_install') + return callable_(files) + else: + return False + +############################################################################## + +def guess_system(): + import platform + #print os.name, platform.platform() + return ("%s-%s" % (platform.system(), platform.dist()[0])).lower() + +def has_qt(): + return False + +import installbundle + +def hide_splash_if_necessary(): + pass + +class dbg(): + def warning(self, *args): + print "".join(args) +debug = dbg() Property changes on: installbundle.py ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + native Added: requirements.py =================================================================== --- requirements.py (rev 0) +++ requirements.py 2011-04-27 12:25:14 UTC (rev 44) @@ -0,0 +1,186 @@ +############################################################################ +## +## Copyright (C) 2006-2010 University of Utah. All rights reserved. +## +## This file is part of VisTrails. +## +## This file may be used under the terms of the GNU General Public +## License version 2.0 as published by the Free Software Foundation +## and appearing in the file LICENSE.GPL included in the packaging of +## this file. Please review the following to ensure GNU General Public +## Licensing requirements will be met: +## http://www.opensource.org/licenses/gpl-license.php +## +## If you are unsure which license is appropriate for your use (for +## instance, you are interested in developing a commercial derivative +## of VisTrails), please contact us at vis...@sc.... +## +## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +## +## Changed 2011 by drtrigon. Source from 'core.requirements' +## http://downloads.sourceforge.net/project/vistrails/vistrails/nightly/vistrails-src-nightly.tar.gz +## +## This file was modified to be used as part of PyCodeOCR. +## +############################################################################ + +"""module that allows online inspection of environment to test presence of +runtime components such as binaries, libraries, other python modules, etc.""" + +import sys + +############################################################################## + +def python_module_exists(module_name): + """python_module_exists(module_name): Boolean. +Returns if python module of given name can be safely imported.""" + + try: + sys.modules[module_name] + return True + except KeyError: + pass + try: + __import__(module_name) + return True + except ImportError: + return False + + +def executable_file_exists(filename): + """executable_file_exists(filename): Boolean. +Returns if certain file is in current path and is executable.""" + result = executable_is_in_path(filename) + if result == "": + result = executable_is_in_pythonpath(filename) + return result != "" + +# FIXME: Add documentation. + +def require_python_module(module_name): + if not python_module_exists(module_name): + raise MissingRequirement(module_name) + +def require_executable(filename): + if not executable_file_exists(filename): + raise MissingRequirement(filename) + +def check_pyqt4(): + # checks for the presence of pyqt4, which is more important than the rest, + # since using pyqt requires a qapplication. + try: + require_python_module('PyQt4.QtGui') + require_python_module('PyQt4.QtOpenGL') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-ubuntu': ['python-qt4', + 'python-qt4-gl', + 'python-qt4-sql']}) + if not r: + raise + + +def check_all_vistrails_requirements(): + pass + + # check scipy +# try: +# require_python_module('scipy') +# except MissingRequirement: +# r = core.bundles.installbundle.install({'linux-ubuntu': 'python-scipy'}) +# if not r: +# raise + + +############################################################################## + +class MissingRequirement(Exception): + """Raise this exception in packages when necessary items are missing.""" + def __init__(self, req): + self.requirement = req + def __str__(self): + return "Missing Requirement: %s" % self.requirement + +############################################################################## + +import installbundle +import os + + +# http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python +def which(program, search_path=None): + is_exe = lambda fpath: os.path.exists(fpath) and os.access(fpath, os.X_OK) + #is_exe = lambda fpath: os.path.exists(fpath) + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + if not search_path: + search_path = os.environ["PATH"].split(os.pathsep) + search_path += [ '.' ] # add local path + for path in search_path: + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return "" + +def executable_is_in_path(filename): + #print os.system(filename) + return which(filename) + +def executable_is_in_pythonpath(filename): + return which(filename, search_path=os.environ.get("PYTHONPATH", None)) + + +def check_pygtk(): + # checks for the presence of pygtk, which is more important than the rest. + try: + require_python_module('pygtk') + #pygtk.require('2.0') + require_python_module('gtk') + require_python_module('gtk.glade') + require_python_module('gobject') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-fedora': ['pygtk2']}) + # other deps? + if not r: + raise + +def check_sane(): + try: + require_python_module('sane') + except MissingRequirement: + r = core.bundles.installbundle.install({'linux-fedora': ['python-imaging-sane']}) + # other deps? + if not r: + raise + +def check_optionals(): + try: + require_executable("gocr") + except MissingRequirement: + r = installbundle.install({'linux-fedora': ['gocr'], + 'linux-ubuntu': ['gocr']}) + + try: + #require_python_module('pydmtx') + require_executable("dmtxread") + except MissingRequirement: + r = installbundle.install({'linux-fedora': ['libdmtx-utils'], + 'linux-ubuntu': ['libdmtx-utils']}) + + +def check_all_pycodeocr_requirements(): + print "Checking all PyCodeOCR requirements:" + + # needed + print " * NEEDED 'pygtk2'" + check_pygtk() + print " * NEEDED 'sane' (scanner)" + check_sane() + + # optional + print " * OPTIONAL 'gocr', 'dmtxread'" + check_optionals() Property changes on: requirements.py ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |