471,319 Members | 1,947 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,319 software developers and data experts.

using Mac OS X CoreGraphics via ctypes

I'm trying to implement a routine that converts a PDF document to
image files using ctypes and the Apple CoreGraphics library as per the
'Splitting a PDF File' example on Apple's web site [0]. Unfortunately
I cannot use the CoreGraphics module used in that example because I'm
using Python 2.5 (AFAIK that module is only available in the system
default Python 2.3.5). There are three questions in the code snippet
below. Each problem area has been commented out in the example so it
runs through to the end. The code is obviously not complete, but it's
enough do demonstrate my problems so far.

BTW, this is the only way I have found to convert a PDF (generated by
ReportLab) to an image that can be fed into a PyQt (v3) QPrinter
object. If anyone knows another way to gain access to the system print
services on Mac OS X using Python please do tell. Oh yes, I'd rather
not include PyObjC because I'm already packaging PyQt, and that would
make the resulting app a lot bigger.

# BEGIN CODE
from ctypes import cdll, c_void_p
from ctypes.util import find_library

cglib = cdll.LoadLibrary(find_library('ApplicationServices '))

# the next line causes a segfault - what's the right way to do this?
#GCS_RGB = cglib.kCGColorSpaceGenericRGB()
#cs = cglib.CGColorSpaceCreateWithName(GCS_RGB)

# the next line causes the following error:
#CGPDFDocumentRef = cglib.CGPDFDocumentRef
# AttributeError: dlsym(0x1018c0, CGPDFDocumentRef): symbol not found

CGPDFDocumentCreateWithProvider =
cglib.CGPDFDocumentCreateWithProvider
CGPDFDocumentCreateWithProvider.restype = c_void_p #CGPDFDocumentRef

provider = cglib.CGDataProviderCreateWithFilename("sample.pdf ")
pdf = CGPDFDocumentCreateWithProvider(provider)

#for page in xrange(1, pdf.getNumberOfPages() + 1):
# print page
# pdf.getNumberOfPages caues the following error:
# AttributeError: 'int' object has no attribute 'getNumberOfPages'
# I presume the 'pdf' object is a pointer. How do I get a real
# CGPDFDocuemnt instance that has a getNumberOfPages method?

cglib.CGPDFDocumentRelease(pdf)
# END CODE

[0] Splitting a PDF File <http://developer.apple.com/graphicsimaging/
pythonandquartz.html>

Thanks in advance for any hints you can provide.

~ Daniel

Jun 15 '07 #1
5 5659
Daniel schrieb:
I'm trying to implement a routine that converts a PDF document to
image files using ctypes and the Apple CoreGraphics library as per the
'Splitting a PDF File' example on Apple's web site [0]. Unfortunately
I cannot use the CoreGraphics module used in that example because I'm
using Python 2.5 (AFAIK that module is only available in the system
default Python 2.3.5). There are three questions in the code snippet
below. Each problem area has been commented out in the example so it
runs through to the end. The code is obviously not complete, but it's
enough do demonstrate my problems so far.

BTW, this is the only way I have found to convert a PDF (generated by
ReportLab) to an image that can be fed into a PyQt (v3) QPrinter
object. If anyone knows another way to gain access to the system print
services on Mac OS X using Python please do tell. Oh yes, I'd rather
not include PyObjC because I'm already packaging PyQt, and that would
make the resulting app a lot bigger.
# BEGIN CODE
from ctypes import cdll, c_void_p
from ctypes.util import find_library

cglib = cdll.LoadLibrary(find_library('ApplicationServices '))

# the next line causes a segfault - what's the right way to do this?
#GCS_RGB = cglib.kCGColorSpaceGenericRGB()
Usually, things in the OSX lib that start with k* are a constant - not a
function. As is this.
Diez
Jun 15 '07 #2
# the next line causes a segfault - what's the right way to do this?
#GCS_RGB = cglib.kCGColorSpaceGenericRGB()

Usually, things in the OSX lib that start with k* are a constant - not a
function. As is this.

Diez
That's what I thought too. But when I try passing it directly as if it
were a constant:

GCS_RGB = cglib.kCGColorSpaceGenericRGB
cs = cglib.CGColorSpaceCreateWithName(GCS_RGB)

I get a segfault too. ctypes said kCGColorSpaceGenericRGB was a
function pointer, so I thought maybe I needed to call it to get the
value (not very good reasoning, I know).

~ Daniel

Jun 15 '07 #3
Daniel wrote:
# the next line causes a segfault - what's the right way to do this?
#GCS_RGB = cglib.kCGColorSpaceGenericRGB()

Usually, things in the OSX lib that start with k* are a constant - not a
function. As is this.

Diez

That's what I thought too. But when I try passing it directly as if it
were a constant:

GCS_RGB = cglib.kCGColorSpaceGenericRGB
cs = cglib.CGColorSpaceCreateWithName(GCS_RGB)

I get a segfault too. ctypes said kCGColorSpaceGenericRGB was a
function pointer, so I thought maybe I needed to call it to get the
value (not very good reasoning, I know).
I'm not sure what that constant exported is - but how about looking the
constant up in the ref docs and pass it as value? Usually these thingies
are some 4-byte-string, or a normal zero-terminated one.

Diez
Jun 18 '07 #4
On Jun 18, 6:07 am, "Diez B. Roggisch" <d...@nospam.web.dewrote:
Daniel wrote:
# the next line causes a segfault - what's the right way to do this?
#GCS_RGB = cglib.kCGColorSpaceGenericRGB()
Usually, things in the OSX lib that start with k* are a constant - not a
function. As is this.
Diez
That's what I thought too. But when I try passing it directly as if it
were a constant:
GCS_RGB = cglib.kCGColorSpaceGenericRGB
cs = cglib.CGColorSpaceCreateWithName(GCS_RGB)
I get a segfault too. ctypes said kCGColorSpaceGenericRGB was a
function pointer, so I thought maybe I needed to call it to get the
value (not very good reasoning, I know).

I'm not sure what that constant exported is - but how about looking the
constant up in the ref docs and pass it as value? Usually these thingies
are some 4-byte-string, or a normal zero-terminated one.
Thanks Diez. I'll try that if I decide to keep going with ctypes. I
got a bit further but had some problems with memory management (i.e.
retaining and releasing object references). It seemed like Python/
ctypes was accessing referenced objects after I had released them,
which caused segfaults. I may resort to writing an extension in C that
will handle the entire print process for me rather than fiddling
around with something that gets me half way there. For anyone
interested, here is the code I ended up with:
from ctypes import cdll, cast, c_void_p
from ctypes.util import find_library
cglib = cdll.LoadLibrary(find_library("ApplicationServices "))

CFStringRef = c_void_p

CGColorSpaceCreateWithName = cglib.CGColorSpaceCreateWithName
CGColorSpaceCreateWithName.restype = c_void_p
CGColorSpaceCreateWithName.argtypes = [CFStringRef]

CGPDFDocumentCreateWithProvider =
cglib.CGPDFDocumentCreateWithProvider
CGPDFDocumentCreateWithProvider.restype = c_void_p

provider = cglib.CGDataProviderCreateWithFilename("sample.pdf ")
if provider:
BMP_INFO = cglib.kCGBitmapByteOrderDefault
CS_RGB = cast(cglib.kCGColorSpaceGenericRGB, CFStringRef)

#cs = CGColorSpaceCreateWithName(CS_RGB) # segfault
pdf = CGPDFDocumentCreateWithProvider(provider)
npages = cglib.CGPDFDocumentGetNumberOfPages(pdf)

for pnum in xrange(1, npages + 1):
print "processing page", pnum
page = cglib.CGPDFDocumentGetPage(pdf, pnum)
rect = cglib.CGPDFPageGetBoxRect(page, 0) # kCGPDFMediaBox = 0
page_w = cglib.CGRectGetWidth(rect)
page_h = cglib.CGRectGetHeight(rect)

# incorrect constructor for bitmap
#bitmap = cglib.CGBitmapContextCreate(None, page_w, page_h,
cs, BMP_INFO)
#cglib.CGContextDrawPDFDocument(bitmap, rect, pdf, pnum)

#cglib.CGPDFDocumentRelease(pdf) # segfault
#cglib.CGColorSpaceRelease(cs)
cglib.CGDataProviderRelease(provider)

~ Daniel

Jun 18 '07 #5
Daniel wrote:
Thanks Diez. I'll try that if I decide to keep going with ctypes. I
got a bit further but had some problems with memory management (i.e.
retaining and releasing object references). It seemed like Python/
ctypes was accessing referenced objects after I had released them,
which caused segfaults.
I would be unlikely that this is the case. Much more likely is that you've
got some memory allocated by Python which is being passed on to a C library
and is subsequently freed by Python before the C library is finished with
it. Happens all the time. Just make sure you keep a reference in Python
land to any objects you've handed over to C for the lifetime that the C
library is likely to use it.

Having said that, it doesn't look like that's what's happening with your
CGPDFDocumentRelease call, though perhaps you needed to clean up the page
or rect that you obtained in the loop?

"k" constants defined as strings are 32-bit numbers derived from 4 character
strings. You'll need to convert those strings to the correct number. Once
you've done that I believe your CGColorSpaceCreateWithName call will work.
Richard

Jun 18 '07 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by sjdevnull | last post: by
10 posts views Thread by David C. Ullrich | last post: by
6 posts views Thread by Jack | last post: by
1 post views Thread by moreati | last post: by
3 posts views Thread by Andrew Lentvorski | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.