I am trying to save an image to jpeg after processing with leptonica. I am using python with ctypes and my code is:
import ctypes
leptlib = "liblept.so"
leptonica = ctypes.cdll.LoadLibrary(leptlib)
filename = "IMAG0724.jpg"
img = leptonica.pixRead(filename)
leptonica.pixConvertTo8.argtypes = [ctypes.c_void_p,
ctypes.c_int32]
pix_image = leptonica.pixConvertTo8(img, False)
leptonica.pixOtsuAdaptiveThreshold.argtypes = [ctypes.c_void_p,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_float]
otsu = leptonica.pixOtsuAdaptiveThreshold(pix_image,20,20,0,0,0.1)
leptonica.pixWriteJpeg.argtypes = [ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_int32,
ctypes.c_int32]
leptonica.pixWriteJpeg("otsu-lept", otsu, 75, 0)
This code produces the error:
Error in pixWriteJpeg: pix not defined
I believe this is because I need to do something after applying the otsu but before writing the new image. What am I missing?
EDIT-
I have now ammended the following per leptonica docs http://tpgit.github.io/Leptonica/binarize_8c.html:
leptonica.pixOtsuAdaptiveThreshold.argtypes = [ctypes.c_void_p,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_float,
ctypes.c_void_p]
leptonica.pixOtsuAdaptiveThreshold(pix_image,20,20,0,0,0.1, img)
leptonica.pixWriteJpeg("otsu-lept", img, 75, 0)
A new error now occurs:
Maximum supported image dimension is 65500 pixels Error in pixWriteStreamJpeg: internal jpeg error Error in pixWriteJpeg: pix not written to stream
My image resolution is 1552 x 2592 and leptonica.pixWriteJpeg works when the otsu function line is commented out so it seems that the problem is still with the image being returned by the otsu function.
**** EDIT 2 ****
When I check the output img using leptonica it is telling me the width is some large number which seems to vary each time I run the function (eg 149996048) and the height remains correct at the same value as input image. It looks like the otsu function changing the image width to this large value for some reason.
EDIT 3
jsbueno below provided me with the solution to this problem which I will share here. The issue is because I was passing the image directly to the function when it is actually necessary to pass a pointer of a pointer to the function which then works. Final working code is below:
import ctypes
leptlib = "liblept.so"
leptonica = ctypes.cdll.LoadLibrary(leptlib)
filename = "IMAG0724.jpg"
img = leptonica.pixRead(filename)
leptonica.pixConvertTo8.argtypes = [ctypes.c_void_p,
ctypes.c_int32
]
pix_image = leptonica.pixConvertTo8(img, False)
w = leptonica.pixGetWidth(img)
h = leptonica.pixGetHeight(img)
pixa_out = leptonica.pixCreate(w,h,8)
pixa = ctypes.c_void_p(pixa_out)
leptonica.pixOtsuAdaptiveThreshold.argtypes = [ctypes.c_void_p,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_int32,
ctypes.c_float,
ctypes.c_void_p,
ctypes.c_void_p
]
otsu = leptonica.pixOtsuAdaptiveThreshold(pix_image,
20,
20,
0,
0,
0.1,
None,
ctypes.addressof(pixa)
)
leptonica.pixWritePng("otsu-lept", pixa, 8)