2 Stimmen

Anwenden eines Quartz-Filters beim Speichern von PDF unter Mac OS X 10.6.3

Mit Hilfe der Mac OS X API versuche ich, eine PDF-Datei mit einem Quartz-Filter zu speichern, so wie es über den "Speichern unter"-Dialog in der Vorschau-Anwendung möglich ist. Bisher habe ich den folgenden Code geschrieben (mit Python und pyObjC, aber das ist für mich nicht wichtig):

-- filter-pdf.py: begin

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)

-- filter-pdf.py: end

Leider wird der Filter "Blauton" nicht angewendet, das Ausgabe-PDF sieht genauso aus wie das Eingabe-PDF.

Frage: Was habe ich verpasst? Wie wendet man einen Filter an?

Nun, die Dokumentation verspricht nicht, dass diese Art der Erstellung und Verwendung von "fdict" dazu führen sollte, dass der Filter angewendet wird. Aber ich habe gerade neu geschrieben (soweit ich kann) Beispielcode /Developer/Examples/Quartz/Python/filter-pdf.py, die mit älteren Versionen von Mac verteilt wurde (inzwischen, dieser Code funktioniert auch nicht):

----- filter-pdf-old.py: begin

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: end

\=======================================================================

Der Arbeitscode basiert auf der Antwort:

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)

5voto

Petr Mifek Punkte 66

Wenn Sie eine bereits existierende Datei öffnen und ändern möchten, verwenden Sie das PDFDocument des PDFKit ( Referenz ) und verwenden Sie PDFDocuments writeToFile_withOptions_ mit der Option dict einschließlich der Option "QuartzFilter" des benötigten Filters.

OTOH, wenn Sie Ihre eigene Zeichnung benötigen und einen CGContext zur Hand haben, können Sie etwas in dieser Richtung verwenden:

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...).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X