Beginning of PDF conversion

This commit is contained in:
John Schember 2009-02-11 20:19:11 -05:00
parent 358ec20ceb
commit 9ff64bd715
4 changed files with 226 additions and 0 deletions

View File

@ -0,0 +1,69 @@
'''
Convert any ebook format to PDF.
'''
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net ' \
'and Marshall T. Vandegrift <llasram@gmail.com>' \
'and John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import sys, os, glob, logging
from calibre.ebooks.epub.from_any import any2epub, formats, USAGE
from calibre.ebooks.epub import config as common_config
from calibre.ptempfile import TemporaryDirectory
from calibre.ebooks.pdf.writer import oeb2pdf, config as pdf_config
def config(defaults=None):
c = common_config(defaults=defaults, name='pdf')
c.remove_opt('profile')
pdfc = pdf_config(defaults=defaults)
c.update(pdfc)
return c
def option_parser(usage=USAGE):
usage = usage % ('PDF', formats())
parser = config().option_parser(usage=usage)
return parser
def any2pdf(opts, path, notification=None):
ext = os.path.splitext(path)[1]
if not ext:
raise ValueError('Unknown file type: '+path)
ext = ext.lower()[1:]
if opts.output is None:
opts.output = os.path.splitext(os.path.basename(path))[0]+'.pdf'
opts.output = os.path.abspath(opts.output)
orig_output = opts.output
with TemporaryDirectory('_any2pdf') as tdir:
oebdir = os.path.join(tdir, 'oeb')
os.mkdir(oebdir)
opts.output = os.path.join(tdir, 'dummy.epub')
opts.profile = 'None'
opts.dont_split_on_page_breaks = True
orig_bfs = opts.base_font_size2
opts.base_font_size2 = 0
any2epub(opts, path, create_epub=False, oeb_cover=True, extract_to=oebdir)
opts.base_font_size2 = orig_bfs
opf = glob.glob(os.path.join(oebdir, '*.opf'))[0]
opts.output = orig_output
logging.getLogger('html2epub').info(_('Creating PDF file from EPUB...'))
oeb2pdf(opts, opf)
def main(args=sys.argv):
parser = option_parser()
opts, args = parser.parse_args(args)
if len(args) < 2:
parser.print_help()
print 'No input file specified.'
return 1
any2pdf(opts, args[1])
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,153 @@
'''
Write content to PDF.
'''
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
import os, logging, shutil, sys
from calibre.ebooks.oeb.base import Logger, OEBBook
from calibre.ebooks.oeb.profile import Context
from calibre.ebooks.epub.iterator import SpineItem
from calibre.ebooks.metadata.opf2 import OPF
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.customize.ui import run_plugins_on_postprocess
from calibre.utils.config import Config, StringConfig
from PyQt4 import QtCore
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, QApplication, QPrinter, \
QMetaObject
from PyQt4.Qt import *
from PyQt4.QtWebKit import QWebView
from pyPdf import PdfFileWriter, PdfFileReader
class PDFWriter(QObject):
def __init__(self):
if QApplication.instance() is None:
QApplication([])
QObject.__init__(self)
self.loop = QEventLoop()
self.view = QWebView()
self.connect(self.view, SIGNAL('loadFinished(bool)'), self._render_html)
self.render_queue = []
self.combine_queue = []
self.tmp_path = PersistentTemporaryDirectory('_any2pdf_parts')
def dump(self, oeb, oebpath, path):
self._reset()
opf = OPF(oebpath, os.path.dirname(oebpath))
self.render_queue = [SpineItem(i.path) for i in opf.spine]
self.path = path
QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection)
self.loop.exec_()
@QtCore.pyqtSignature('_render_book()')
def _render_book(self):
if len(self.render_queue) == 0:
self._write()
else:
self._render_next()
def _render_next(self):
item = str(self.render_queue.pop(0))
self.combine_queue.append(os.path.join(self.tmp_path, '%s.pdf' % os.path.basename(item)))
self.view.load(QUrl(item))
def _render_html(self, ok):
if ok:
printer = QPrinter(QPrinter.HighResolution)
printer.setPageMargins(1, 1, 1, 1, QPrinter.Inch)
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName(os.path.join(self.tmp_path, '%s.pdf' % os.path.basename(str(self.view.url().toLocalFile()))))
self.view.print_(printer)
self._render_book()
def _reset(self):
self.render_queue = []
self.combine_queue = []
self.path = ''
if os.path.exists(self.tmp_path):
shutil.rmtree(self.tmp_path, True)
self.tmp_path = PersistentTemporaryDirectory('_any2pdf_parts')
def _write(self):
print self.path
try:
outPDF = PdfFileWriter()
for item in self.combine_queue:
inputPDF = PdfFileReader(file(item, 'rb'))
for page in inputPDF.pages:
outPDF.addPage(page)
outputStream = file(self.path, 'wb')
outPDF.write(outputStream)
outputStream.close()
finally:
self._reset()
self.loop.exit(0)
def config(defaults=None):
desc = _('Options to control the conversion to PDF')
if defaults is None:
c = Config('pdf', desc)
else:
c = StringConfig(defaults, desc)
pdf = c.add_group('PDF', _('PDF options.'))
return c
def option_parser():
c = config()
parser = c.option_parser(usage='%prog '+_('[options]')+' file.opf')
parser.add_option(
'-o', '--output', default=None,
help=_('Output file. Default is derived from input filename.'))
parser.add_option(
'-v', '--verbose', default=0, action='count',
help=_('Useful for debugging.'))
return parser
def oeb2pdf(opts, inpath):
logger = Logger(logging.getLogger('oeb2pdf'))
logger.setup_cli_handler(opts.verbose)
outpath = opts.output
if outpath is None:
outpath = os.path.basename(inpath)
outpath = os.path.splitext(outpath)[0] + '.pdf'
# source = opts.source_profile
# if source not in Context.PROFILES:
# logger.error(_('Unknown source profile %r') % source)
# return 1
# dest = opts.dest_profile
# if dest not in Context.PROFILES:
# logger.error(_('Unknown destination profile %r') % dest)
# return 1
oeb = OEBBook(inpath, logger=logger, encoding=opts.encoding)
writer = PDFWriter()
writer.dump(oeb, inpath, outpath)
run_plugins_on_postprocess(outpath, 'pdf')
logger.info(_('Output written to ') + outpath)
def main(argv=sys.argv):
parser = option_parser()
opts, args = parser.parse_args(argv[1:])
if len(args) != 1:
parser.print_help()
return 1
inpath = args[0]
retval = oeb2pdf(opts, inpath)
return retval
if __name__ == '__main__':
sys.exit(main())

View File

@ -51,6 +51,7 @@ entry_points = {
'any2epub = calibre.ebooks.epub.from_any:main',
'any2lit = calibre.ebooks.lit.from_any:main',
'any2mobi = calibre.ebooks.mobi.from_any:main',
'any2pdf = calibre.ebooks.pdf.from_any:main',
'lrf2lrs = calibre.ebooks.lrf.lrfparser:main',
'lrs2lrf = calibre.ebooks.lrf.lrs.convert_from:main',
'pdfreflow = calibre.ebooks.lrf.pdf.reflow:main',

View File

@ -71,6 +71,9 @@ PARALLEL_FUNCS = {
'any2mobi' :
('calibre.ebooks.mobi.from_any', 'any2mobi', {}, None),
'any2pdf' :
('calibre.ebooks.pdf.from_any', 'any2pdf', {}, None),
'feeds2mobi' :
('calibre.ebooks.mobi.from_feeds', 'main', {}, 'notification'),