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): def convert_images(self, images):
from calibre.ebooks.pdf.image_writer import convert 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): def get_cover_data(self):
oeb = self.oeb oeb = self.oeb

View File

@ -5,22 +5,20 @@
from __future__ import absolute_import, division, print_function, unicode_literals from __future__ import absolute_import, division, print_function, unicode_literals
import os import os
from io import BytesIO
from PyQt5.Qt import ( from PyQt5.Qt import QApplication, QTimer, QUrl
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, 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 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
@ -103,20 +101,14 @@ class Renderer(QWebEnginePage):
def add_cover(pdf_doc, cover_data, page_layout, opts): def add_cover(pdf_doc, cover_data, page_layout, opts):
buf = QBuffer() buf = BytesIO()
buf.open(QBuffer.ReadWrite) page_size = page_layout.fullRectPoints().size()
cover_layout = QPageLayout(page_layout) img = Image(cover_data)
cover_layout.setMargins(QMarginsF(0, 0, 0, 0)) writer = PDFStream(buf, (page_size.width(), page_size.height()), compress=True)
img = image_from_data(cover_data) writer.apply_fill(color=(1, 1, 1))
writer = QPdfWriter(buf) draw_image_page(writer, img, preserve_aspect_ratio=opts.preserve_cover_aspect_ratio)
writer.setPageLayout(cover_layout) writer.end()
painter = QPainter() cover_pdf = buf.getvalue()
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() podofo = get_podofo()
cover_pdf_doc = podofo.PDFDoc() cover_pdf_doc = podofo.PDFDoc()
cover_pdf_doc.load(cover_pdf) 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 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.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.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 calibre.utils.podofo import get_podofo, set_metadata_implementation
from polyglot.builtins import as_unicode
class PDFMetadata(object): # {{{ 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): 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) page_size = tuple(writer.page_size)
scaling = list(writer.page_size) scaling = list(writer.page_size)
translation = [0, 0] translation = [0, 0]
img_ar = img.width() / img.height() img_ar = img.width / img.height
page_ar = page_size[0]/page_size[1] page_ar = page_size[0]/page_size[1]
if preserve_aspect_ratio and page_ar != img_ar: if preserve_aspect_ratio and page_ar != img_ar:
if 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) 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() buf = BytesIO()
page_layout = get_page_layout(opts, for_comic=True) page_layout = get_page_layout(opts, for_comic=True)
page_size = page_layout.fullRectPoints().size() page_size = page_layout.fullRectPoints().size()
@ -122,7 +147,7 @@ def convert(images, output_path, opts, metadata):
writer.apply_fill(color=(1, 1, 1)) writer.apply_fill(color=(1, 1, 1))
pdf_metadata = PDFMetadata(metadata) pdf_metadata = PDFMetadata(metadata)
for i, path in enumerate(images): for i, path in enumerate(images):
img = image_from_path(path) img = Image(as_unicode(path, filesystem_encoding))
draw_image_page(writer, img) draw_image_page(writer, img)
writer.end_page() writer.end_page()
writer.end() writer.end()

View File

@ -416,6 +416,9 @@ class PDFStream(object):
self.objects.commit(r, self.stream) self.objects.commit(r, self.stream)
return r 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): def add_image(self, img, cache_key):
ref = self.get_image(cache_key) ref = self.get_image(cache_key)
if ref is not None: if ref is not None: