diff --git a/src/calibre/ebooks/conversion/plugins/pdf_output.py b/src/calibre/ebooks/conversion/plugins/pdf_output.py index 88c5208d4f..c2d0e83448 100644 --- a/src/calibre/ebooks/conversion/plugins/pdf_output.py +++ b/src/calibre/ebooks/conversion/plugins/pdf_output.py @@ -28,8 +28,8 @@ class PDFMetadata(object): # {{{ def __init__(self, mi=None): from calibre import force_unicode from calibre.ebooks.metadata import authors_to_string - self.title = _(u'Unknown') - self.author = _(u'Unknown') + self.title = _('Unknown') + self.author = _('Unknown') self.tags = '' self.mi = mi @@ -189,7 +189,7 @@ class PDFOutput(OutputFormatPlugin): def convert_images(self, images): from calibre.ebooks.pdf.image_writer import convert - convert(images, self.output_path, self.opts) + convert(images, self.output_path, self.opts, PDFMetadata(self.metadata)) def get_cover_data(self): oeb = self.oeb diff --git a/src/calibre/ebooks/pdf/image_writer.py b/src/calibre/ebooks/pdf/image_writer.py index 1751bd17e7..636e673974 100644 --- a/src/calibre/ebooks/pdf/image_writer.py +++ b/src/calibre/ebooks/pdf/image_writer.py @@ -4,13 +4,13 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from PyQt5.Qt import ( - QMarginsF, QPageLayout, QPageSize, QPainter, QPdfWriter, QSize -) +from PyQt5.Qt import QMarginsF, QPageLayout, QPageSize, QPainter, QPdfWriter, QSize from calibre import fit_image from calibre.ebooks.docx.writer.container import cicero, cm, didot, inch, mm, pica +from calibre.ebooks.metadata.xmp import metadata_to_xmp_packet from calibre.utils.img import image_from_path +from calibre.utils.podofo import get_podofo, set_metadata_implementation # Page layout {{{ @@ -81,8 +81,10 @@ def draw_image_page(painter, img, preserve_aspect_ratio=True): painter.drawImage(page_rect, img) -def convert(images, output_path, opts): +def convert(images, output_path, opts, pdf_metadata): writer = QPdfWriter(output_path) + writer.setCreator(pdf_metadata.author) + writer.setTitle(pdf_metadata.title) writer.setPageLayout(get_page_layout(opts, for_comic=True)) painter = QPainter() painter.begin(writer) @@ -94,3 +96,16 @@ def convert(images, output_path, opts): draw_image_page(painter, img) finally: painter.end() + if pdf_metadata.mi: + podofo = get_podofo() + pdf_doc = podofo.PDFDoc() + with open(output_path, 'r+b') as f: + raw = f.read() + pdf_doc.load(raw) + xmp_packet = metadata_to_xmp_packet(pdf_metadata.mi) + set_metadata_implementation( + pdf_doc, pdf_metadata.title, pdf_metadata.mi.authors, + pdf_metadata.mi.book_producer, pdf_metadata.tags, xmp_packet) + raw = pdf_doc.write() + f.seek(0), f.truncate() + f.write(raw) diff --git a/src/calibre/utils/podofo/__init__.py b/src/calibre/utils/podofo/__init__.py index c2d322f06a..33d53180c9 100644 --- a/src/calibre/utils/podofo/__init__.py +++ b/src/calibre/utils/podofo/__init__.py @@ -69,6 +69,9 @@ def set_metadata_implementation(pdf_doc, title, authors, bkp, tags, xmp_packet): if bkp and bkp != pdf_doc.creator: pdf_doc.creator = bkp touched = True + if bkp and bkp != pdf_doc.producer: + pdf_doc.producer = bkp + touched = True try: tags = prep(', '.join([x.strip() for x in tags if x.strip()])) @@ -172,7 +175,9 @@ def test_podofo(): from io import BytesIO from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.xmp import metadata_to_xmp_packet + # {{{ raw = b"%PDF-1.1\n%\xe2\xe3\xcf\xd3\n1 0 obj<>\nendobj\n2 0 obj<>\nendobj\n3 0 obj<>>>>>>>\nendobj\n4 0 obj<>\nstream\n BT\n /F1 18 Tf\n 0 0 Td\n (Hello World) Tj\n ET\nendstream\nendobj\n5 0 obj<>\nendobj\n6 0 obj<>\nstream\nx\x9c\xed\x98\xcd\xb2\x930\x14\xc7\xf7}\n&.\x1d\x1ahoGa\x80\x8e\xb6\xe3x\x17ua\xaf\xe3\xd2\t\xc9i\x1b\x0b\x81&a\xc0\xfbj.|$_\xc1\xd0r\xe9\xb7V\x9d\xbb\x83\x15\x9c\x9c\xff\xff\x97\x8fs\xb2 \x18W9\xa1k\xd0V\x0cK.B\xf4\xf3\xfb\x0fdq\x16\xa2\xcf\xa3\x993\xcb'\xb0\xe2\xef\x1f%\xcc\x1f?<\xd0\xc75\xf5\x18\x1aG\xbd\xa0\xf2\xab4OA\x13\xabJ\x13\xa1\xfc*D\x84e1\xf8\xe6\xbd\x0ec\x14\xf5,+\x90l\xe1\x7f\x9c\xbek\x92\xccW\x88VZ\xe7>\xc6eY\xf6\xcba?\x93K\xecz\x9e\x87\x9d\x01\x1e\x0cl\x93a\xaboB\x93\xca\x16\xea\xc5\xd6\xa3q\x99\x82\xa2\x92\xe7\x9ag\xa2qc\xb45\xcb\x0b\x99l\xad\x18\xc5\x90@\nB+\xec\xf6]\x8c\xacZK\xe2\xac\xd0!j\xec\x8c!\xa3>\xdb\xfb=\x85\x1b\xd2\x9bD\xef#M,\xe15\xd4O\x88X\x86\xa8\xb2\x19,H\x91h\x14\x05x7z`\x81O<\x02|\x99VOBs\x9d\xc0\x7f\xe0\x05\x94\xfa\xd6)\x1c\xb1jx^\xc4\tW+\x90'\x13xK\x96\xf8Hy\x96X\xabU\x11\x7f\x05\xaa\xff\xa4=I\xab\x95T\x02\xd1\xd9)u\x0e\x9b\x0b\xcb\x8e>\x89\xb5\xc8Jqm\x91\x07\xaa-\xee\xc8{\x972=\xdd\xfa+\xe5d\xea\xb9\xad'\xa1\xfa\xdbj\xee\xd3,\xc5\x15\xc9M-9\xa6\x96\xdaD\xce6Wr\xd3\x1c\xdf3S~|\xc1A\xe2MA\x92F{\xb1\x0eM\xba?3\xdd\xc2\x88&S\xa2!\x1a8\xee\x9d\xedx\xb6\xeb=\xb8C\xff\xce\xf1\x87\xaf\xfb\xde\xe0\xd5\xc8\xf3^:#\x7f\xe8\x04\xf8L\xf2\x0fK\xcd%W\xe9\xbey\xea/\xa5\x89`D\xb2m\x17\t\x92\x822\xb7\x02(\x1c\x13\xc5)\x1e\x9c-\x01\xff\x1e\xc0\x16\xd5\xe5\r\xaaG\xcc\x8e\x0c\xff\xca\x8e\x92\x84\xc7\x12&\x93\xd6\xb3\x89\xd8\x10g\xd9\xfai\xe7\xedv\xde6-\x94\xceR\x9bfI\x91\n\x85\x8e}nu9\x91\xcd\xefo\xc6+\x90\x1c\x94\xcd\x05\x83\xea\xca\xd17\x16\xbb\xb6\xfc\xa22\xa9\x9bn\xbe0p\xfd\x88wAs\xc3\x9a+\x19\xb7w\xf2a#=\xdf\xd3A:H\x07\xe9 \x1d\xa4\x83t\x90\x0e\xd2A:H\x07yNH/h\x7f\xd6\x80`!*\xd18\xfa\x05\x94\x80P\xb0\nendstream\nendobj\nxref\n0 7\n0000000000 65535 f \n0000000015 00000 n \n0000000074 00000 n \n0000000148 00000 n \n0000000280 00000 n \n0000000382 00000 n \n0000000522 00000 n \ntrailer\n<<4D028D512DEBEFD964756764AD8FF726>]/Info 5 0 R/Root 1 0 R/Size 7>>\nstartxref\n1199\n%%EOF\n" # noqa + # }}} mi = Metadata('title1', ['author1']) xmp_packet = metadata_to_xmp_packet(mi) podofo = get_podofo()