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:
@@ -66,6 +66,7 @@ Currently, following formats are supported:
|
|||||||
|
|
||||||
- lrf (for Sony readers)
|
- lrf (for Sony readers)
|
||||||
- epub
|
- epub
|
||||||
|
- mobi
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_): # {{{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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:')):
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
|
||||||
'''
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user