2010-04-28 12 views
2

En utilisant l'API Mac OS X, j'essaie d'enregistrer un fichier PDF avec un filtre Quartz appliqué, comme c'est possible dans la boîte de dialogue "Enregistrer sous" dans l'application Aperçu. Jusqu'à présent, j'ai écrit le code suivant (en utilisant Python et PyObjC, mais il est pas important pour moi):Appliquer un filtre Quartz tout en enregistrant le PDF sous Mac OS X 10.6.3

- filter-pdf.py: commencer

from Foundation import * 
from Quartz import * 
import objc 

page_rect = CGRectMake (0, 0, 612, 792) 
fdict = NSDictionary.dictionaryWithContentsOfFile_("/System/Library/Filters/Blue 
\ Tone.qfilter") 
in_pdf = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename ("test 
.pdf")) 
url = CFURLCreateWithFileSystemPath(None, "test_out.pdf", kCFURLPOSIXPathStyle, 
False) 
c = CGPDFContextCreateWithURL(url, page_rect, fdict) 

np = CGPDFDocumentGetNumberOfPages(in_pdf) 
for ip in range (1, np+1): 
     page = CGPDFDocumentGetPage(in_pdf, ip) 
     r = CGPDFPageGetBoxRect(page, kCGPDFMediaBox) 
     CGContextBeginPage(c, r) 
     CGContextDrawPDFPage(c, page) 
     CGContextEndPage(c) 

- filtre pdf .py: end

Malheureusement, le filtre "Blue Tone" n'est pas appliqué, le PDF de sortie ressemble exactement au PDF d'entrée.

Question: qu'est ce que j'ai manqué? Comment appliquer un filtre? Bien, la documentation ne promet pas que cette façon de créer et d'utiliser "fdict" devrait provoquer l'application du filtre. Mais je viens de réécrire (autant que je peux) l'exemple de code /Developer/Examples/Quartz/Python/filter-pdf.py, qui était distribué avec les anciennes versions de Mac (en attendant, ce code ne fonctionne pas aussi):

filter-pdf-old.py -----: commencer

from CoreGraphics import * 
import sys, os, math, getopt, string 

def usage(): 
    print ''' 
usage: python filter-pdf.py FILTER INPUT-PDF OUTPUT-PDF 

Apply a ColorSync Filter to a PDF document. 
''' 

def main(): 

    page_rect = CGRectMake (0, 0, 612, 792) 

    try: 
    opts,args = getopt.getopt (sys.argv[1:], '', []) 
    except getopt.GetoptError: 
    usage() 
    sys.exit (1) 

    if len (args) != 3: 
    usage() 
    sys.exit (1) 

    filter = CGContextFilterCreateDictionary (args[0]) 
    if not filter: 
    print 'Unable to create context filter' 
    sys.exit (1) 
    pdf = CGPDFDocumentCreateWithProvider (CGDataProviderCreateWithFilename (args[1])) 
    if not pdf: 
    print 'Unable to open input file' 
    sys.exit (1) 

    c = CGPDFContextCreateWithFilename (args[2], page_rect, filter) 
    if not c: 
    print 'Unable to create output context' 
    sys.exit (1) 

    for p in range (1, pdf.getNumberOfPages() + 1): 
    #r = pdf.getMediaBox (p) 
    r = pdf.getPage(p).getBoxRect(p) 
    c.beginPage (r) 
    c.drawPDFDocument (r, pdf, p) 
    c.endPage() 

    c.finish() 

if __name__ == '__main__': 
    main() 

----- filter-pdf-old.py: fin

========= ============================================= =============

Le code de travail basé sur la réponse:

from Foundation import * 
from Quartz import * 

pdf_url = NSURL.fileURLWithPath_("test.pdf") 
pdf_doc = PDFDocument.alloc().initWithURL_(pdf_url) 

furl = NSURL.fileURLWithPath_("/System/Library/Filters/Blue Tone.qfilter") 
fobj = QuartzFilter.quartzFilterWithURL_(furl) 
fdict = { 'QuartzFilter': fobj } 
pdf_doc.writeToFile_withOptions_("test_out.pdf", fdict) 

Répondre

4

deux approches - si vous avez besoin d'ouvrir et de modifier un fichier déjà existant, utilisez PDFDocument (reference) du PDFKit et l'utilisation de writeToFile_withOptions_ PDFDocument avec option dict y compris l'option « QuartzFilter » du filtre nécessaire.

OTOH si vous avez besoin de votre propre dessin et un CGContext à portée de main, vous pouvez utiliser quelque chose le long de ces lignes:

from Quartz import * 
data = NSMutableData.dataWithCapacity_(1024**2) 
dataConsumer = CGDataConsumerCreateWithCFData(data) 
context = CGPDFContextCreate(dataConsumer, None, None) 
f = QuartzFilter.quartzFilterWithURL_(NSURL.fileURLWithPath_("YourFltr.qfilter")) 
f.applyToContext_(context) 
# do your drawing 
CGPDFContextClose(context) 
# the PDF is in the data variable. Do whatever you need to do with the data (save to file...). 
+0

Merci beaucoup, les deux approches fonctionnent. Un exemple de code est en cours d'édition des questions. En attendant, je me demande d'où vous connaissez la clé "QuartzFilter", je ne l'ai pas trouvée dans la documentation. – olpa

+0

Cheers. La clé QuartzFilter est mentionnée uniquement dans les fichiers d'en-tête. Autant que je sache, aucune mention de cela sur le web docs jusqu'à présent (s'il vous plaît signaler le problème à Apple en cliquant sur les boutons en bas de cette page;)). Voir par exemple PDFDocument.h quelque part dans /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Quartz.framework (l'emplacement exact dépend de votre SDK et de l'installation). –