Pointer to Image

C

Chris Jankowski

Hi all,
I am still new to using Python, so bare with me. I am trying to call
a DLL from my program to use some of it's functions. The only
parameter is supposed to be a pointer to an image. I have tried
several variations on passing this parameter to the DLL and I am not
having much luck. This is going to call other functions later for
OCR, but I want to get a simple one working first.

Here is my code: (Very basic)

from ctypes import *
import Image

myOcr = windll.LoadLibrary('ocrdll.dll') # my DLL

mySize = myOcr.GetImgBitmapSize ## load the function

im = Image.open('C:\\chris.tif') ## load the Image
print id(im) ## for testing print address of im

##myFile = c_char_p(id(im)) # I have tried several variations of this

x = mySize(myFile) ## Actual call to the DLL Function
## documentation only one parameter passed
pointer to Image
## Must be DIB Image(Device Independent Bitmap)
## (could this be the problem?)
Thanks for the help.

Chris J.
 
L

Larry Bates

Chris said:
Hi all,
I am still new to using Python, so bare with me. I am trying to call
a DLL from my program to use some of it's functions. The only
parameter is supposed to be a pointer to an image. I have tried
several variations on passing this parameter to the DLL and I am not
having much luck. This is going to call other functions later for
OCR, but I want to get a simple one working first.

Here is my code: (Very basic)

from ctypes import *
import Image

myOcr = windll.LoadLibrary('ocrdll.dll') # my DLL

mySize = myOcr.GetImgBitmapSize ## load the function

im = Image.open('C:\\chris.tif') ## load the Image
print id(im) ## for testing print address of im

##myFile = c_char_p(id(im)) # I have tried several variations of this

x = mySize(myFile) ## Actual call to the DLL Function
## documentation only one parameter passed
pointer to Image
## Must be DIB Image(Device Independent Bitmap)
## (could this be the problem?)
Thanks for the help.

Chris J.

Can you supply any docs on the ocrdll.dll API (e.g example C
code or function/parameter documentation)? I've interfaced
with ExperVision's OCR RTK Toolkit via calls to their .DLL
but it looks like you are using something different.

-Larry
 
T

Thomas Heller

Hi all,
I am still new to using Python, so bare with me. I am trying to call
a DLL from my program to use some of it's functions. The only
parameter is supposed to be a pointer to an image. I have tried
several variations on passing this parameter to the DLL and I am not
having much luck. This is going to call other functions later for
OCR, but I want to get a simple one working first.

Here is my code: (Very basic)

from ctypes import *
import Image

myOcr = windll.LoadLibrary('ocrdll.dll') # my DLL

mySize = myOcr.GetImgBitmapSize ## load the function

im = Image.open('C:\\chris.tif') ## load the Image
print id(im) ## for testing print address of im

##myFile = c_char_p(id(im)) # I have tried several variations of this

x = mySize(myFile) ## Actual call to the DLL Function
## documentation only one parameter passed
pointer to Image
## Must be DIB Image(Device Independent Bitmap)
## (could this be the problem?)
Thanks for the help.

I assume the Image function you import in the code above is from PIL?
In this case, it cannot work. You cannot take the address (id) of an
arbitrary Python object, and assume that it points to C compatible data.
Maybe you should use a function from the dll to load the image data, or
you can read the file's bytes into python string, and pass that.

Thomas
 
C

Chris Jankowski

Larry Bates said:
Can you supply any docs on the ocrdll.dll API (e.g example C
code or function/parameter documentation)? I've interfaced
with ExperVision's OCR RTK Toolkit via calls to their .DLL
but it looks like you are using something different.

-Larry

Here is the website with the documentation.

http://www.simpleocr.com/Help.asp

There are two .DLL files needed
ocrdll.dll
Dllwain.dll

please let me know if there is anything else.
 
C

Chris Jankowski

Larry Bates said:
Can you supply any docs on the ocrdll.dll API (e.g example C
code or function/parameter documentation)? I've interfaced
with ExperVision's OCR RTK Toolkit via calls to their .DLL
but it looks like you are using something different.

-Larry

I think I may have it. cdll instead of windll
 
C

Chris Jankowski

Thomas Heller said:
I assume the Image function you import in the code above is from PIL?
In this case, it cannot work. You cannot take the address (id) of an
arbitrary Python object, and assume that it points to C compatible data.
Maybe you should use a function from the dll to load the image data, or
you can read the file's bytes into python string, and pass that.

Thomas

Here is what I have now.

from ctypes import *
def myOutputHandler(infotype, param):
outputFile.write("outhandler")
if infotype == "OT_TEXT":
print param
## return param
## elif infotype == "OT_ENDL":
## return "\n"
## elif infotype == "OT_ENDZ":
## return "\n\n"
return
#***************************************************************
#* main process *
#* myList - requests *
#* inList - data file *
#***************************************************************
if __name__ == '__main__':
outputFile=open('c:\\newOCR.txt', 'w')
myOcr = cdll.LoadLibrary('C:\\SimpleOCR\\ocrdll.dll')
loadImg = myOcr.LoadMultipleImg
x = loadImg("c:\\chris.tif")
print x
setLanguage = myOcr.SetLanguage
setLanguage('ENGLISH',".")

setOutputMode = myOcr.SetOutputMode
setOutputMode("OM_TEXT")

setOutputHandler = myOcr.OCRSetOutputHandler
z = id(myOutputHandler)
errorx = setOutputHandler(z)

getImage = myOcr.GetImage
img = getImage(x,0)

getNBImages = myOcr.GetNbImages
numImg = getNBImages(x)

processOCR = myOcr.OCR
myTest = processOCR(img) ## it will run without this line.

freeMultipleImage = myOcr.FreeMultipleImg
freeMultipleImage(x)

outputFile.close()

This will not run it abends when I try to call the .OCR function. I
am thinking that it cannot call the procedure to write the file. Any
ideas?
 
T

Thomas Heller

Here is what I have now.

from ctypes import *
def myOutputHandler(infotype, param):
outputFile.write("outhandler")
if infotype == "OT_TEXT":
print param
## return param
## elif infotype == "OT_ENDL":
## return "\n"
## elif infotype == "OT_ENDZ":
## return "\n\n"
return
#***************************************************************
#* main process *
#* myList - requests *
#* inList - data file *
#***************************************************************
if __name__ == '__main__':
outputFile=open('c:\\newOCR.txt', 'w')
myOcr = cdll.LoadLibrary('C:\\SimpleOCR\\ocrdll.dll')
loadImg = myOcr.LoadMultipleImg
x = loadImg("c:\\chris.tif")
print x
setLanguage = myOcr.SetLanguage
setLanguage('ENGLISH',".")

setOutputMode = myOcr.SetOutputMode
setOutputMode("OM_TEXT")

setOutputHandler = myOcr.OCRSetOutputHandler
z = id(myOutputHandler)
errorx = setOutputHandler(z)

getImage = myOcr.GetImage
img = getImage(x,0)

getNBImages = myOcr.GetNbImages
numImg = getNBImages(x)

processOCR = myOcr.OCR
myTest = processOCR(img) ## it will run without this line.

freeMultipleImage = myOcr.FreeMultipleImg
freeMultipleImage(x)

outputFile.close()

This will not run it abends when I try to call the .OCR function. I
am thinking that it cannot call the procedure to write the file. Any
ideas?

At least one problem that I see is that you are passing
id(myOutputHandler) to setOutputHandler call. Assuming that
setOutputHandler expects a C callback function, this will not work.

Ok - send me (in private email) a pointer to where I can download the
ocrdll.dll including C header files, plus your 'chris.tif' image, and I
will take a look at it.

Thomas
 
J

Jeff Shannon

Chris said:
# [...]
setLanguage = myOcr.SetLanguage
setLanguage('ENGLISH',".")

setOutputMode = myOcr.SetOutputMode
setOutputMode("OM_TEXT")

setOutputHandler = myOcr.OCRSetOutputHandler
z = id(myOutputHandler)
errorx = setOutputHandler(z)
# [...]

As a minor stylistic note, I find your constant use of temporary local
names of module functions to be distracting and even slightly
confusing. When you actually *call* a function, it's not immediately
apparent whether that's a helper function that you've written yourself
or whether it's a function in your OCR module -- I have to backtrack to
see where the function came from, and I'm never quite sure whether I
will find it somewhere in the current code block (because you've bound
the imported function to a local name) or whether I should look
elsewhere in the current module (because it's a function you've defined
yourself).

I'd find the above code snippet *much* easier to read without the
temporaries:

myOcr.SetLanguage('ENGLISH', ".")
myOcr.SetOutputMode("OM_TEXT")
errorx = myOcr.OCRSetOutputHandler( id(myOutputHandler) )

To my eyes, this makes it much more clear where everything is found, and
because it's so much shorter it's much easier to take in at a glance.

(I also share Thomas Heller's suspicion that passing the id() of
myOutputHandler() is *not* what you want to do here. The ID is merely
an integer that Python uses internally to track an object; it is
typically not useful for code that wants to *use* an object to know what
its ID is. You don't need to know your co-workers' social security
numbers in order to work with them effectively, right? Similarly, a
Python object's ID is only needed in very special circumstances where
the exact identity of an object is in question, and it's *not* needed
for normal usage of an object such as being able to call a function object.)

Jeff Shannon
Technician/Programmer
Credit International
 
C

Chris Jankowski

Jeff Shannon said:
Chris said:
# [...]
setLanguage = myOcr.SetLanguage
setLanguage('ENGLISH',".")

setOutputMode = myOcr.SetOutputMode
setOutputMode("OM_TEXT")

setOutputHandler = myOcr.OCRSetOutputHandler
z = id(myOutputHandler)
errorx = setOutputHandler(z)
# [...]

As a minor stylistic note, I find your constant use of temporary local
names of module functions to be distracting and even slightly
confusing. When you actually *call* a function, it's not immediately
apparent whether that's a helper function that you've written yourself
or whether it's a function in your OCR module -- I have to backtrack to
see where the function came from, and I'm never quite sure whether I
will find it somewhere in the current code block (because you've bound
the imported function to a local name) or whether I should look
elsewhere in the current module (because it's a function you've defined
yourself).

I'd find the above code snippet *much* easier to read without the
temporaries:

myOcr.SetLanguage('ENGLISH', ".")
myOcr.SetOutputMode("OM_TEXT")
errorx = myOcr.OCRSetOutputHandler( id(myOutputHandler) )

To my eyes, this makes it much more clear where everything is found, and
because it's so much shorter it's much easier to take in at a glance.

(I also share Thomas Heller's suspicion that passing the id() of
myOutputHandler() is *not* what you want to do here. The ID is merely
an integer that Python uses internally to track an object; it is
typically not useful for code that wants to *use* an object to know what
its ID is. You don't need to know your co-workers' social security
numbers in order to work with them effectively, right? Similarly, a
Python object's ID is only needed in very special circumstances where
the exact identity of an object is in question, and it's *not* needed
for normal usage of an object such as being able to call a function object.)

Jeff Shannon
Technician/Programmer
Credit International

Hey Jeff,
Thanks for the pointers. I am still new to Python and sometimes do
things the hard way, because I don't know any better. (yet) I just
copied this from the cytpes documentation and plugged in my variable
names.

The part that is confusing to me, still has not been answered.

This DLL file has several functions. One is a handler that needs to be
set to a Python function. How do I pass it an address to make this
happen?

def myOutputHandler(infotype, param):
print("outhandler")
if infotype == "OT_TEXT":
print param
##[...]

myOcr.OCRSetOutputHandler(address of myOutputHandler?) ###
??????????????

Thanks,

Chris J.
 
T

Thomas Heller

The part that is confusing to me, still has not been answered.

This DLL file has several functions. One is a handler that needs to be
set to a Python function. How do I pass it an address to make this
happen?

It's not that complicated. First, you have to declare the callback
function's prototype - you find it in the include file for the dll, and
you have to convert it into ctypes notation. In this sample, the
callback receives an integer as parameter, and returns an integer as
result:

# typedef int (* OCRProgressHandler)(int percent);
OCRProgressHandler = CFUNCTYPE(c_int, c_int)

Then, you define a Python function which will handle the events:

def py_handler(percent):
# do something with 'percent', which will be an integer
return 42

Next, you create the C callback function itself:

callback = OCRProgressHandler(py_handler)

And finally, you can install the callback:

ocrdll.SetProgressHandler(callback) # or something like that

Chris sent me a link where to download the dll (actually a whole OCR
application, the dll is part of it): wocar25.zip
<http://ccambien.free.fr/wocar25.zip>, plus a header file (which seems
not to be included in the application, but may be available elsewhere).

I made a script which passes one of the example tif's to the OCR
functions, and it seems to work quite well.
Since the script is not too large, I'll append it at the end of this
post. I tried to insert comments to explain what's going in, I hope it
helps to get started.

Thomas

PS: The first paragraph of the OCR output is this - nice, although it
doesn't recognize fi ligatures (is that the correct terminus?):

Artificial Neural Networks
Neural network technology is at the centre of attention in many parts of both the world
scienti<?-5?>c community and the world industrial community. This intensive activity is partly a
response to the need of industry to tind solutions for a huge variety of hard information-
handling problems.

<script>
from ctypes import *

######## some definitions from the include file, converted to ctypes ########

# callback function prototypes

## typedef int (* OCRProgressHandler)(int percent);
OCRProgressHandler = CFUNCTYPE(c_int, c_int)

## typedef void (* OCROutputHandler)(int infotype,int param);
OCROutputHandler = CFUNCTYPE(None, c_int, c_int)

## typedef void (* OCRErrorHandler)(const char *module,
## const char* fmt, va_list);
OCRErrorHandler = CFUNCTYPE(None, POINTER(c_char),
POINTER(c_char), POINTER(c_char))

## typedef void (* OCRWarningHandler)(const char *module,
## int level,const char* fmt, va_list);
OCRWarningHandler = CFUNCTYPE(None, POINTER(c_char),
c_int, POINTER(c_char), POINTER(c_char))

# Allowed languages
NONE = 0
ENGLISH = 1
FRENCH = 2
DUTCH = 3

# OCR Events
OT_TEXT = 0
OT_PROP = 1
OT_ITAL = 2
OT_BOLD = 3
OT_UNDS = 4
OT_SIZE = 5
OT_HILT = 6
OT_ENDL = 7
OT_ENDZ = 8
OT_BITM = 9

# Output modes
OM_TEXT = 0
OM_RICHTEXT = 1
OM_WINDOW = 2

######## load the ocr dll.
# ocrdll.dll needs another private dll - so we add the directory to $PATH

import os, sys
os.environ["PATH"] = "c:\wocar"
ocrdll = CDLL(r"c:\wocar\ocrdll.dll")

# load an image

##img = ocrdll.LoadImg(r"c:\chris_ocr.tif")
img = ocrdll.LoadImg(r"c:\wocar\samples\english.tif")

# define a Python event handler
def callback(event, param):
if event == OT_TEXT:
try:
sys.stdout.write(chr(param))
except ValueError:
sys.stdout.write("<?%d?>" % param)
elif event in (OT_ENDL, OT_ENDZ):
sys.stdout.write("\n")

# create a C callback function from it, and install it as Output Handler
callback = OCROutputHandler(callback)
ocrdll.OCRSetOutputHandler(callback)

# scan the image
ocrdll.OCR(img)

# cleanup totally omitted...
<script/>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,209
Messages
2,571,088
Members
47,687
Latest member
IngridXxj

Latest Threads

Top