1
0
mirror of https://github.com/gryf/ebook-converter.git synced 2026-04-01 18:03:35 +02:00

Enable mobi write support.

This commit is contained in:
2020-04-13 15:25:19 +02:00
parent 32b86ab224
commit a4533957f7
15 changed files with 77 additions and 90 deletions

View File

@@ -66,6 +66,7 @@ Currently, following formats are supported:
- lrf (for Sony readers) - lrf (for Sony readers)
- epub - epub
- mobi
Installation Installation

View File

@@ -11,13 +11,13 @@ import copy
import re import re
import numbers import numbers
from lxml import etree from lxml import etree
from calibre.ebooks.oeb.base import namespace, barename from ebook_converter.ebooks.oeb.base import namespace, barename
from calibre.ebooks.oeb.base import XHTML, XHTML_NS, urlnormalize from ebook_converter.ebooks.oeb.base import XHTML, XHTML_NS, urlnormalize
from calibre.ebooks.oeb.stylizer import Stylizer from ebook_converter.ebooks.oeb.stylizer import Stylizer
from calibre.ebooks.oeb.transforms.flatcss import KeyMapper from ebook_converter.ebooks.oeb.transforms.flatcss import KeyMapper
from calibre.ebooks.mobi.utils import convert_color_for_font_tag from ebook_converter.ebooks.mobi.utils import convert_color_for_font_tag
from calibre.utils.imghdr import identify from ebook_converter.utils.imghdr import identify
from polyglot.builtins import unicode_type, string_or_bytes from ebook_converter.polyglot.builtins import unicode_type, string_or_bytes
MBP_NS = 'http://mobipocket.com/ns/mbp' MBP_NS = 'http://mobipocket.com/ns/mbp'

View File

@@ -175,9 +175,9 @@ def rescale_image(data, maxsizeb=IMAGE_MAX_SIZE, dimen=None):
else: else:
width = height = dimen width = height = dimen
data = scale_image(data, width=width, height=height, compression_quality=90)[-1] data = scale_image(data, width=width, height=height, compression_quality=90)[-1]
else: # else:
# Replace transparent pixels with white pixels and convert to JPEG # Replace transparent pixels with white pixels and convert to JPEG
data = save_cover_data_to(data) #data = save_cover_data_to(data)
if len(data) <= maxsizeb: if len(data) <= maxsizeb:
return data return data
orig_data = data # save it in case compression fails orig_data = data # save it in case compression fails

View File

@@ -11,9 +11,9 @@ from struct import pack
import io import io
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
from calibre.ebooks.mobi.utils import (encint, encode_number_as_hex, from ebook_converter.ebooks.mobi.utils import (encint, encode_number_as_hex,
encode_tbs, align_block, RECORD_SIZE, CNCX as CNCX_) encode_tbs, align_block, RECORD_SIZE, CNCX as CNCX_)
from polyglot.builtins import filter, iteritems, itervalues, map, range from ebook_converter.polyglot.builtins import filter, iteritems, itervalues, map, range
class CNCX(CNCX_): # {{{ class CNCX(CNCX_): # {{{

View File

@@ -9,16 +9,16 @@ __docformat__ = 'restructuredtext en'
import io, random, time import io, random, time
from struct import pack from struct import pack
from calibre.ebooks import normalize from ebook_converter.ebooks import normalize
from calibre.ebooks.mobi.writer2.serializer import Serializer from ebook_converter.ebooks.mobi.writer2.serializer import Serializer
from calibre.ebooks.compression.palmdoc import compress_doc from ebook_converter.ebooks.compression.palmdoc import compress_doc
from calibre.ebooks.mobi.langcodes import iana2mobi from ebook_converter.ebooks.mobi.langcodes import iana2mobi
from calibre.utils.filenames import ascii_filename from ebook_converter.utils.filenames import ascii_filename
from calibre.ebooks.mobi.writer2 import (PALMDOC, UNCOMPRESSED) from ebook_converter.ebooks.mobi.writer2 import (PALMDOC, UNCOMPRESSED)
from calibre.ebooks.mobi.utils import (encint, encode_trailing_data, from ebook_converter.ebooks.mobi.utils import (encint, encode_trailing_data,
align_block, detect_periodical, RECORD_SIZE, create_text_record) align_block, detect_periodical, RECORD_SIZE, create_text_record)
from calibre.ebooks.mobi.writer2.indexer import Indexer from ebook_converter.ebooks.mobi.writer2.indexer import Indexer
from polyglot.builtins import iteritems, unicode_type, range from ebook_converter.polyglot.builtins import iteritems, unicode_type, range
# Disabled as I dont care about uncrossable breaks # Disabled as I dont care about uncrossable breaks
WRITE_UNCROSSABLE_BREAKS = False WRITE_UNCROSSABLE_BREAKS = False
@@ -201,7 +201,7 @@ class MobiWriter(object):
# header as well # header as well
bt = 0x103 if self.indexer.is_flat_periodical else 0x101 bt = 0x103 if self.indexer.is_flat_periodical else 0x101
from calibre.ebooks.mobi.writer8.exth import build_exth from ebook_converter.ebooks.mobi.writer8.exth import build_exth
exth = build_exth(metadata, exth = build_exth(metadata,
prefer_author_sort=self.opts.prefer_author_sort, prefer_author_sort=self.opts.prefer_author_sort,
is_periodical=self.is_periodical, is_periodical=self.is_periodical,
@@ -374,9 +374,9 @@ class MobiWriter(object):
# }}} # }}}
def generate_joint_record0(self): # {{{ def generate_joint_record0(self): # {{{
from calibre.ebooks.mobi.writer8.mobi import (MOBIHeader, from ebook_converter.ebooks.mobi.writer8.mobi import (MOBIHeader,
HEADER_FIELDS) HEADER_FIELDS)
from calibre.ebooks.mobi.writer8.exth import build_exth from ebook_converter.ebooks.mobi.writer8.exth import build_exth
# Insert resource records # Insert resource records
first_image_record = None first_image_record = None

View File

@@ -46,8 +46,14 @@ class Resources(object):
try: try:
return func(data) return func(data)
except Exception: except Exception:
if 'png' != what(None, data): ext = what(None, data)
if ext not in ('png', 'gif'):
raise raise
if ext == 'gif':
with PersistentTemporaryFile(suffix='.gif') as pt:
pt.write(data)
return mobify_image(data)
with PersistentTemporaryFile(suffix='.png') as pt: with PersistentTemporaryFile(suffix='.png') as pt:
pt.write(data) pt.write(data)
try: try:

View File

@@ -12,13 +12,13 @@ import unicodedata
from collections import defaultdict from collections import defaultdict
from io import BytesIO from io import BytesIO
from calibre.ebooks.mobi.mobiml import MBP_NS from ebook_converter.ebooks.mobi.mobiml import MBP_NS
from calibre.ebooks.mobi.utils import is_guide_ref_start from ebook_converter.ebooks.mobi.utils import is_guide_ref_start
from calibre.ebooks.oeb.base import ( from ebook_converter.ebooks.oeb.base import (
OEB_DOCS, XHTML, XHTML_NS, XML_NS, namespace, prefixname, urlnormalize OEB_DOCS, XHTML, XHTML_NS, XML_NS, namespace, prefixname, urlnormalize
) )
from polyglot.builtins import unicode_type, string_or_bytes from ebook_converter.polyglot.builtins import unicode_type, string_or_bytes
from polyglot.urllib import urldefrag from ebook_converter.polyglot.urllib import urldefrag
class Buf(BytesIO): class Buf(BytesIO):

View File

@@ -1,10 +0,0 @@
#!/usr/bin/env python2
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import absolute_import, division, print_function, unicode_literals
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from calibre.ebooks.oeb.base import XPath from ebook_converter.ebooks.oeb.base import XPath
class CSSCleanup(object): class CSSCleanup(object):

View File

@@ -10,11 +10,11 @@ import re
from struct import pack from struct import pack
from io import BytesIO from io import BytesIO
from calibre.constants import iswindows, isosx from ebook_converter.constants import iswindows, isosx
from calibre.ebooks.mobi.utils import (utf8_text, to_base) from ebook_converter.ebooks.mobi.utils import (utf8_text, to_base)
from calibre.utils.localization import lang_as_iso639_1 from ebook_converter.utils.localization import lang_as_iso639_1
from calibre.ebooks.metadata import authors_to_sort_string from ebook_converter.ebooks.metadata import authors_to_sort_string
from polyglot.builtins import iteritems, unicode_type from ebook_converter.polyglot.builtins import iteritems, unicode_type
EXTH_CODES = { EXTH_CODES = {
'creator': 100, 'creator': 100,
@@ -99,7 +99,7 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False,
# Write UUID as ASIN # Write UUID as ASIN
uuid = None uuid = None
from calibre.ebooks.oeb.base import OPF from ebook_converter.ebooks.oeb.base import OPF
for x in metadata['identifier']: for x in metadata['identifier']:
if (x.get(OPF('scheme'), None).lower() == 'uuid' or if (x.get(OPF('scheme'), None).lower() == 'uuid' or
unicode_type(x).startswith('urn:uuid:')): unicode_type(x).startswith('urn:uuid:')):

View File

@@ -6,10 +6,10 @@ HTML-TOC-adding transform.
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>' __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
from calibre.ebooks.oeb.base import XML, XHTML, XHTML_NS from ebook_converter.ebooks.oeb.base import XML, XHTML, XHTML_NS
from calibre.ebooks.oeb.base import XHTML_MIME, CSS_MIME from ebook_converter.ebooks.oeb.base import XHTML_MIME, CSS_MIME
from calibre.ebooks.oeb.base import element, XPath from ebook_converter.ebooks.oeb.base import element, XPath
from polyglot.builtins import unicode_type from ebook_converter.polyglot.builtins import unicode_type
__all__ = ['HTMLTOCAdder'] __all__ = ['HTMLTOCAdder']
@@ -69,7 +69,7 @@ class HTMLTOCAdder(object):
if 'toc' in oeb.guide: if 'toc' in oeb.guide:
# Ensure toc pointed to in <guide> is in spine # Ensure toc pointed to in <guide> is in spine
from calibre.ebooks.oeb.base import urlnormalize from ebook_converter.ebooks.oeb.base import urlnormalize
href = urlnormalize(oeb.guide['toc'].href) href = urlnormalize(oeb.guide['toc'].href)
if href in oeb.manifest.hrefs: if href in oeb.manifest.hrefs:
item = oeb.manifest.hrefs[href] item = oeb.manifest.hrefs[href]

View File

@@ -7,11 +7,11 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>' __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
from lxml import etree from lxml import etree
from calibre.ebooks.oeb.base import XHTML, XHTML_NS from ebook_converter.ebooks.oeb.base import XHTML, XHTML_NS
from calibre.ebooks.oeb.base import CSS_MIME from ebook_converter.ebooks.oeb.base import CSS_MIME
from calibre.ebooks.oeb.base import namespace from ebook_converter.ebooks.oeb.base import namespace
from calibre.ebooks.oeb.stylizer import Stylizer from ebook_converter.ebooks.oeb.stylizer import Stylizer
from polyglot.builtins import string_or_bytes from ebook_converter.polyglot.builtins import string_or_bytes
CASE_MANGLER_CSS = """ CASE_MANGLER_CSS = """
.calibre_lowercase { .calibre_lowercase {

View File

@@ -8,17 +8,17 @@ __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
import os, re import os, re
from PyQt5.Qt import ( # from PyQt5.Qt import (
Qt, QByteArray, QBuffer, QIODevice, QColor, QImage, QPainter, QSvgRenderer) # Qt, QByteArray, QBuffer, QIODevice, QColor, QImage, QPainter, QSvgRenderer)
from calibre.ebooks.oeb.base import XHTML, XLINK from ebook_converter.ebooks.oeb.base import XHTML, XLINK
from calibre.ebooks.oeb.base import SVG_MIME, PNG_MIME from ebook_converter.ebooks.oeb.base import SVG_MIME, PNG_MIME
from calibre.ebooks.oeb.base import xml2str, xpath from ebook_converter.ebooks.oeb.base import xml2str, xpath
from calibre.ebooks.oeb.base import urlnormalize from ebook_converter.ebooks.oeb.base import urlnormalize
from calibre.ebooks.oeb.stylizer import Stylizer from ebook_converter.ebooks.oeb.stylizer import Stylizer
from calibre.ptempfile import PersistentTemporaryFile from ebook_converter.ptempfile import PersistentTemporaryFile
from calibre.utils.imghdr import what from ebook_converter.utils.imghdr import what
from polyglot.builtins import unicode_type from ebook_converter.polyglot.builtins import unicode_type
from polyglot.urllib import urldefrag from ebook_converter.polyglot.urllib import urldefrag
IMAGE_TAGS = {XHTML('img'), XHTML('object')} IMAGE_TAGS = {XHTML('img'), XHTML('object')}
KEEP_ATTRS = {'class', 'style', 'width', 'height', 'align'} KEEP_ATTRS = {'class', 'style', 'width', 'height', 'align'}
@@ -32,8 +32,8 @@ class SVGRasterizer(object):
def __init__(self, base_css=''): def __init__(self, base_css=''):
self.base_css = base_css self.base_css = base_css
from calibre.gui2 import must_use_qt # from ebook_converter.gui2 import must_use_qt
must_use_qt() # must_use_qt()
@classmethod @classmethod
def config(cls, cfg): def config(cls, cfg):

View File

@@ -1,10 +0,0 @@
#!/usr/bin/env python2
from __future__ import absolute_import, division, print_function, unicode_literals
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
'''
Used for pdf output for comic2pdf
'''

View File

@@ -11,15 +11,15 @@ import shutil
import subprocess import subprocess
import sys import sys
from calibre import CurrentDir, xml_replace_entities, prints from ebook_converter import CurrentDir, xml_replace_entities, prints
from calibre.constants import ( from ebook_converter.constants import (
filesystem_encoding, isbsd, islinux, isosx, ispy3, iswindows filesystem_encoding, isbsd, islinux, isosx, ispy3, iswindows
) )
from calibre.ebooks import ConversionError, DRMError from ebook_converter.ebooks import ConversionError, DRMError
from calibre.ebooks.chardet import xml_to_unicode from ebook_converter.ebooks.chardet import xml_to_unicode
from calibre.ptempfile import PersistentTemporaryFile from ebook_converter.ptempfile import PersistentTemporaryFile
from calibre.utils.cleantext import clean_xml_chars from ebook_converter.utils.cleantext import clean_xml_chars
from calibre.utils.ipc import eintr_retry_call from ebook_converter.utils.ipc import eintr_retry_call
PDFTOHTML = 'pdftohtml' PDFTOHTML = 'pdftohtml'
@@ -98,7 +98,7 @@ def pdftohtml(output_dir, pdf_path, no_images, as_xml=False):
with lopen(index, 'r+b') as i: with lopen(index, 'r+b') as i:
raw = i.read().decode('utf-8', 'replace') raw = i.read().decode('utf-8', 'replace')
raw = flip_images(raw) raw = flip_images(raw)
raw = raw.replace('<head', '<!-- created by calibre\'s pdftohtml -->\n <head', 1) raw = raw.replace('<head', '<!-- created by ebook_converter\'s pdftohtml -->\n <head', 1)
i.seek(0) i.seek(0)
i.truncate() i.truncate()
# versions of pdftohtml >= 0.20 output self closing <br> tags, this # versions of pdftohtml >= 0.20 output self closing <br> tags, this
@@ -129,11 +129,11 @@ def pdftohtml(output_dir, pdf_path, no_images, as_xml=False):
def parse_outline(raw, output_dir): def parse_outline(raw, output_dir):
from lxml import etree from lxml import etree
from calibre.utils.xml_parse import safe_xml_fromstring from ebook_converter.utils.xml_parse import safe_xml_fromstring
raw = clean_xml_chars(xml_to_unicode(raw, strip_encoding_pats=True, assume_utf8=True)[0]) raw = clean_xml_chars(xml_to_unicode(raw, strip_encoding_pats=True, assume_utf8=True)[0])
outline = safe_xml_fromstring(raw).xpath('(//outline)[1]') outline = safe_xml_fromstring(raw).xpath('(//outline)[1]')
if outline: if outline:
from calibre.ebooks.oeb.polish.toc import TOC, create_ncx from ebook_converter.ebooks.oeb.polish.toc import TOC, create_ncx
outline = outline[0] outline = outline[0]
toc = TOC() toc = TOC()
count = [0] count = [0]
@@ -156,7 +156,7 @@ def parse_outline(raw, output_dir):
def flip_image(img, flip): def flip_image(img, flip):
from calibre.utils.img import flip_image, image_and_format_from_data, image_to_data from ebook_converter.utils.img import flip_image, image_and_format_from_data, image_to_data
with lopen(img, 'r+b') as f: with lopen(img, 'r+b') as f:
img, fmt = image_and_format_from_data(f.read()) img, fmt = image_and_format_from_data(f.read())
img = flip_image(img, horizontal='x' in flip, vertical='y' in flip) img = flip_image(img, horizontal='x' in flip, vertical='y' in flip)