Code to add cover to textual PDF output

This commit is contained in:
Kovid Goyal 2019-07-08 18:20:35 +05:30
parent 6c78ae2105
commit 8029b3cc83
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 56 additions and 4 deletions

View File

@ -238,4 +238,7 @@ class PDFOutput(OutputFormatPlugin):
oeb_output = plugin_for_output_format('oeb') oeb_output = plugin_for_output_format('oeb')
oeb_output.convert(oeb_book, oeb_dir, self.input_plugin, self.opts, self.log) oeb_output.convert(oeb_book, oeb_dir, self.input_plugin, self.opts, self.log)
opfpath = glob.glob(os.path.join(oeb_dir, '*.opf'))[0] opfpath = glob.glob(os.path.join(oeb_dir, '*.opf'))[0]
convert(opfpath, self.opts, metadata=self.metadata, output_path=self.output_path, log=self.log) convert(
opfpath, self.opts, metadata=self.metadata, output_path=self.output_path,
log=self.log, cover_data=self.cover_data
)

View File

@ -6,17 +6,21 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import os import os
from PyQt5.Qt import QApplication, QTimer, QUrl from PyQt5.Qt import (
QApplication, QBuffer, QMarginsF, QPageLayout, QPainter, QPdfWriter, QTimer,
QUrl
)
from PyQt5.QtWebEngineWidgets import QWebEnginePage from PyQt5.QtWebEngineWidgets import QWebEnginePage
from calibre.constants import iswindows from calibre.constants import iswindows
from calibre.ebooks.oeb.polish.container import Container as ContainerBase from calibre.ebooks.oeb.polish.container import Container as ContainerBase
from calibre.ebooks.oeb.polish.split import merge_html from calibre.ebooks.oeb.polish.split import merge_html
from calibre.ebooks.pdf.image_writer import ( from calibre.ebooks.pdf.image_writer import (
PDFMetadata, get_page_layout, update_metadata PDFMetadata, draw_image_page, get_page_layout, update_metadata
) )
from calibre.gui2 import setup_unix_signals from calibre.gui2 import setup_unix_signals
from calibre.gui2.webengine import secure_webengine from calibre.gui2.webengine import secure_webengine
from calibre.utils.img import image_from_data
from calibre.utils.logging import default_log from calibre.utils.logging import default_log
from calibre.utils.podofo import get_podofo from calibre.utils.podofo import get_podofo
from polyglot.builtins import range from polyglot.builtins import range
@ -98,7 +102,28 @@ class Renderer(QWebEnginePage):
return self.pdf_data return self.pdf_data
def convert(opf_path, opts, metadata=None, output_path=None, log=default_log): def add_cover(pdf_doc, cover_data, page_layout, opts):
buf = QBuffer()
buf.open(QBuffer.ReadWrite)
cover_layout = QPageLayout(page_layout)
cover_layout.setMargins(QMarginsF(0, 0, 0, 0))
img = image_from_data(cover_data)
writer = QPdfWriter(buf)
writer.setPageLayout(cover_layout)
painter = QPainter()
painter.begin(writer)
try:
draw_image_page(painter, img, preserve_aspect_ratio=opts.preserve_cover_aspect_ratio)
finally:
painter.end()
cover_pdf = buf.data().data()
podofo = get_podofo()
cover_pdf_doc = podofo.PDFDoc()
cover_pdf_doc.load(cover_pdf)
pdf_doc.insert_existing_page(cover_pdf_doc)
def convert(opf_path, opts, metadata=None, output_path=None, log=default_log, cover_data=None):
container = Container(opf_path, log) container = Container(opf_path, log)
spine_names = [name for name, is_linear in container.spine_names] spine_names = [name for name, is_linear in container.spine_names]
master = spine_names[0] master = spine_names[0]
@ -115,6 +140,9 @@ def convert(opf_path, opts, metadata=None, output_path=None, log=default_log):
pdf_doc = podofo.PDFDoc() pdf_doc = podofo.PDFDoc()
pdf_doc.load(pdf_data) pdf_doc.load(pdf_data)
if cover_data:
add_cover(pdf_doc, cover_data, page_layout, opts)
if metadata is not None: if metadata is not None:
update_metadata(pdf_doc, PDFMetadata(metadata)) update_metadata(pdf_doc, PDFMetadata(metadata))

View File

@ -219,6 +219,24 @@ PDFDoc_append(PDFDoc *self, PyObject *args) {
Py_RETURN_NONE; Py_RETURN_NONE;
} // }}} } // }}}
// insert_existing_page() {{{
static PyObject *
PDFDoc_insert_existing_page(PDFDoc *self, PyObject *args) {
PDFDoc *src_doc;
int src_page = 0, at = 0;
if (!PyArg_ParseTuple(args, "O!|ii", &PDFDocType, &src_doc, &src_page, &at)) return NULL;
try {
self->doc->InsertExistingPageAt(*src_doc->doc, src_page, at);
} catch (const PdfError & err) {
podofo_set_exception(err);
return NULL;
}
Py_RETURN_NONE;
} // }}}
// set_box() {{{ // set_box() {{{
static PyObject * static PyObject *
PDFDoc_set_box(PDFDoc *self, PyObject *args) { PDFDoc_set_box(PDFDoc *self, PyObject *args) {
@ -629,6 +647,9 @@ static PyMethodDef PDFDoc_methods[] = {
{"append", (PyCFunction)PDFDoc_append, METH_VARARGS, {"append", (PyCFunction)PDFDoc_append, METH_VARARGS,
"append(doc) -> Append doc (which must be a PDFDoc) to this document." "append(doc) -> Append doc (which must be a PDFDoc) to this document."
}, },
{"insert_existing_page", (PyCFunction)PDFDoc_insert_existing_page, METH_VARARGS,
"insert_existing_page(src_doc, src_page, at) -> Insert the page src_page from src_doc at index: at."
},
{"set_box", (PyCFunction)PDFDoc_set_box, METH_VARARGS, {"set_box", (PyCFunction)PDFDoc_set_box, METH_VARARGS,
"set_box(page_num, box, left, bottom, width, height) -> Set the PDF bounding box for the page numbered nu, box must be one of: MediaBox, CropBox, TrimBox, BleedBox, ArtBox. The numbers are interpreted as pts." "set_box(page_num, box, left, bottom, width, height) -> Set the PDF bounding box for the page numbered nu, box must be one of: MediaBox, CropBox, TrimBox, BleedBox, ArtBox. The numbers are interpreted as pts."
}, },