Pass JPEG images unmodified when creating PDF image pages

This commit is contained in:
Kovid Goyal 2019-07-09 16:05:30 +05:30
parent 4815c6167e
commit 22ba6c3ab7
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 47 additions and 27 deletions

View File

@ -178,7 +178,7 @@ class PDFOutput(OutputFormatPlugin):
def convert_images(self, images):
from calibre.ebooks.pdf.image_writer import convert
convert(images, self.output_path, self.opts, self.metadata)
convert(images, self.output_path, self.opts, self.metadata, self.report_progress)
def get_cover_data(self):
oeb = self.oeb

View File

@ -5,22 +5,20 @@
from __future__ import absolute_import, division, print_function, unicode_literals
import os
from io import BytesIO
from PyQt5.Qt import (
QApplication, QBuffer, QMarginsF, QPageLayout, QPainter, QPdfWriter, QTimer,
QUrl
)
from PyQt5.Qt import QApplication, QTimer, QUrl
from PyQt5.QtWebEngineWidgets import QWebEnginePage
from calibre.constants import iswindows
from calibre.ebooks.oeb.polish.container import Container as ContainerBase
from calibre.ebooks.oeb.polish.split import merge_html
from calibre.ebooks.pdf.image_writer import (
PDFMetadata, draw_image_page, get_page_layout, update_metadata
Image, PDFMetadata, draw_image_page, get_page_layout, update_metadata
)
from calibre.ebooks.pdf.render.serialize import PDFStream
from calibre.gui2 import setup_unix_signals
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.podofo import get_podofo
from polyglot.builtins import range
@ -103,20 +101,14 @@ class Renderer(QWebEnginePage):
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()
buf = BytesIO()
page_size = page_layout.fullRectPoints().size()
img = Image(cover_data)
writer = PDFStream(buf, (page_size.width(), page_size.height()), compress=True)
writer.apply_fill(color=(1, 1, 1))
draw_image_page(writer, img, preserve_aspect_ratio=opts.preserve_cover_aspect_ratio)
writer.end()
cover_pdf = buf.getvalue()
podofo = get_podofo()
cover_pdf_doc = podofo.PDFDoc()
cover_pdf_doc.load(cover_pdf)

View File

@ -8,11 +8,14 @@ from io import BytesIO
from PyQt5.Qt import QMarginsF, QPageLayout, QPageSize, QSize
from calibre.ebooks.pdf.render.common import cicero, cm, didot, inch, mm, pica
from calibre.constants import filesystem_encoding
from calibre.ebooks.metadata.xmp import metadata_to_xmp_packet
from calibre.ebooks.pdf.render.common import cicero, cm, didot, inch, mm, pica
from calibre.ebooks.pdf.render.serialize import PDFStream
from calibre.utils.img import image_from_path
from calibre.utils.img import image_and_format_from_data
from calibre.utils.imghdr import identify
from calibre.utils.podofo import get_podofo, set_metadata_implementation
from polyglot.builtins import as_unicode
class PDFMetadata(object): # {{{
@ -89,12 +92,34 @@ def get_page_layout(opts, for_comic=False):
# }}}
class Image(object): # {{{
def __init__(self, path_or_bytes):
if not isinstance(path_or_bytes, bytes):
with open(path_or_bytes, 'rb') as f:
path_or_bytes = f.read()
self.img_data = path_or_bytes
fmt, width, height = identify(path_or_bytes)
if width > 0 and height > 0 and fmt == 'jpeg':
self.fmt = fmt
self.width, self.height = width, height
self.cache_key = None
else:
self.img, self.fmt = image_and_format_from_data(path_or_bytes)
self.width, self.height = self.img.width(), self.img.height()
self.cache_key = self.img.cacheKey()
# }}}
def draw_image_page(writer, img, preserve_aspect_ratio=True):
ref = writer.add_image(img, img.cacheKey())
if img.fmt == 'jpeg':
ref = writer.add_jpeg_image(img.img_data, img.width, img.height, img.cache_key)
else:
ref = writer.add_image(img.img, img.cache_key)
page_size = tuple(writer.page_size)
scaling = list(writer.page_size)
translation = [0, 0]
img_ar = img.width() / img.height()
img_ar = img.width / img.height
page_ar = page_size[0]/page_size[1]
if preserve_aspect_ratio and page_ar != img_ar:
if page_ar > img_ar:
@ -114,7 +139,7 @@ def update_metadata(pdf_doc, pdf_metadata):
pdf_metadata.mi.book_producer, pdf_metadata.mi.tags, xmp_packet)
def convert(images, output_path, opts, metadata):
def convert(images, output_path, opts, metadata, report_progress):
buf = BytesIO()
page_layout = get_page_layout(opts, for_comic=True)
page_size = page_layout.fullRectPoints().size()
@ -122,7 +147,7 @@ def convert(images, output_path, opts, metadata):
writer.apply_fill(color=(1, 1, 1))
pdf_metadata = PDFMetadata(metadata)
for i, path in enumerate(images):
img = image_from_path(path)
img = Image(as_unicode(path, filesystem_encoding))
draw_image_page(writer, img)
writer.end_page()
writer.end()

View File

@ -416,6 +416,9 @@ class PDFStream(object):
self.objects.commit(r, self.stream)
return r
def add_jpeg_image(self, img_data, w, h, cache_key=None):
return self.write_image(img_data, w, h, 32, dct=True)
def add_image(self, img, cache_key):
ref = self.get_image(cache_key)
if ref is not None: