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.
|