By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,758 Members | 1,225 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,758 IT Pros & Developers. It's quick & easy.

using Mac OS X CoreGraphics via ctypes

P: n/a
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
Share this Question
Share on Google+
5 Replies


P: n/a
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

P: n/a
# 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

P: n/a
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

P: n/a
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

P: n/a
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.