mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Create mobi-meta command line tool and make cover extraction from MOBI files more efficient
This commit is contained in:
parent
a33aa9140a
commit
79e1e261af
29
src/calibre/ebooks/metadata/mobi.py
Normal file
29
src/calibre/ebooks/metadata/mobi.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2009, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
from calibre.ebooks.mobi.reader import get_metadata
|
||||||
|
|
||||||
|
def main(args=sys.argv):
|
||||||
|
if len(args) != 2:
|
||||||
|
print >>sys.stderr, 'Usage: %s file.mobi' % args[0]
|
||||||
|
return 1
|
||||||
|
fname = args[1]
|
||||||
|
mi = get_metadata(open(fname, 'rb'))
|
||||||
|
print unicode(mi)
|
||||||
|
if mi.cover_data[1]:
|
||||||
|
cover = os.path.abspath(
|
||||||
|
'.'.join((os.path.splitext(os.path.basename(fname))[0],
|
||||||
|
mi.cover_data[0].lower())))
|
||||||
|
open(cover, 'wb').write(mi.cover_data[1])
|
||||||
|
print _('Cover saved to'), cover
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
@ -311,7 +311,7 @@ class MobiReader(object):
|
|||||||
opf.cover = 'images/%05d.jpg'%(self.book_header.exth.cover_offset+1)
|
opf.cover = 'images/%05d.jpg'%(self.book_header.exth.cover_offset+1)
|
||||||
manifest = [(htmlfile, 'text/x-oeb1-document')]
|
manifest = [(htmlfile, 'text/x-oeb1-document')]
|
||||||
bp = os.path.dirname(htmlfile)
|
bp = os.path.dirname(htmlfile)
|
||||||
for i in self.image_names:
|
for i in getattr(self, 'image_names', []):
|
||||||
manifest.append((os.path.join(bp, 'images/', i), 'image/jpg'))
|
manifest.append((os.path.join(bp, 'images/', i), 'image/jpg'))
|
||||||
|
|
||||||
opf.create_manifest(manifest)
|
opf.create_manifest(manifest)
|
||||||
@ -451,7 +451,7 @@ class MobiReader(object):
|
|||||||
image_index += 1
|
image_index += 1
|
||||||
try:
|
try:
|
||||||
im = PILImage.open(buf)
|
im = PILImage.open(buf)
|
||||||
except IOError, e:
|
except IOError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
path = os.path.join(output_dir, '%05d.jpg'%image_index)
|
path = os.path.join(output_dir, '%05d.jpg'%image_index)
|
||||||
@ -476,32 +476,24 @@ def get_metadata(stream):
|
|||||||
if mr.book_header.exth is None:
|
if mr.book_header.exth is None:
|
||||||
mi = MetaInformation(mr.name, [_('Unknown')])
|
mi = MetaInformation(mr.name, [_('Unknown')])
|
||||||
else:
|
else:
|
||||||
tdir = tempfile.mkdtemp('_mobi_meta', __appname__+'_')
|
|
||||||
atexit.register(shutil.rmtree, tdir)
|
|
||||||
#print tdir
|
|
||||||
mr.extract_images([], tdir)
|
|
||||||
mi = mr.create_opf('dummy.html')
|
mi = mr.create_opf('dummy.html')
|
||||||
if mi.cover:
|
try:
|
||||||
cover = os.path.join(tdir, mi.cover)
|
if hasattr(mr.book_header.exth, 'cover_offset'):
|
||||||
if not os.access(cover, os.R_OK):
|
cover_index = mr.book_header.first_image_index + mr.book_header.exth.cover_offset
|
||||||
fname = os.path.basename(cover)
|
data = mr.sections[cover_index][0]
|
||||||
match = re.match(r'(\d+)(.+)', fname)
|
|
||||||
if match:
|
|
||||||
num, ext = int(match.group(1), 10), match.group(2)
|
|
||||||
while num > 0:
|
|
||||||
num -= 1
|
|
||||||
candidate = os.path.join(os.path.dirname(cover), '%05d%s'%(num, ext))
|
|
||||||
if os.access(candidate, os.R_OK):
|
|
||||||
cover = candidate
|
|
||||||
break
|
|
||||||
if os.access(cover, os.R_OK):
|
|
||||||
mi.cover_data = ('JPEG', open(os.path.join(tdir, cover), 'rb').read())
|
|
||||||
else:
|
else:
|
||||||
path = os.path.join(tdir, 'images', '00001.jpg')
|
data = mr.sections[mr.book_header.first_image_index][0]
|
||||||
if os.access(path, os.R_OK):
|
buf = cStringIO.StringIO(data)
|
||||||
mi.cover_data = ('JPEG', open(path, 'rb').read())
|
im = PILImage.open(buf)
|
||||||
|
obuf = cStringIO.StringIO()
|
||||||
|
im.convert('RGBA').save(obuf, format='JPEG')
|
||||||
|
mi.cover_data = ('jpg', obuf.getvalue())
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
return mi
|
return mi
|
||||||
|
|
||||||
|
|
||||||
def option_parser():
|
def option_parser():
|
||||||
from calibre.utils.config import OptionParser
|
from calibre.utils.config import OptionParser
|
||||||
parser = OptionParser(usage=_('%prog [options] myebook.mobi'))
|
parser = OptionParser(usage=_('%prog [options] myebook.mobi'))
|
||||||
|
@ -26,6 +26,7 @@ entry_points = {
|
|||||||
'opf-meta = calibre.ebooks.metadata.opf2:main',
|
'opf-meta = calibre.ebooks.metadata.opf2:main',
|
||||||
'odt-meta = calibre.ebooks.metadata.odt:main',
|
'odt-meta = calibre.ebooks.metadata.odt:main',
|
||||||
'epub-meta = calibre.ebooks.metadata.epub:main',
|
'epub-meta = calibre.ebooks.metadata.epub:main',
|
||||||
|
'mobi-meta = calibre.ebooks.metadata.mobi:main',
|
||||||
'txt2lrf = calibre.ebooks.lrf.txt.convert_from:main',
|
'txt2lrf = calibre.ebooks.lrf.txt.convert_from:main',
|
||||||
'html2lrf = calibre.ebooks.lrf.html.convert_from:main',
|
'html2lrf = calibre.ebooks.lrf.html.convert_from:main',
|
||||||
'html2oeb = calibre.ebooks.html:main',
|
'html2oeb = calibre.ebooks.html:main',
|
||||||
@ -423,7 +424,7 @@ def install_man_pages(fatal_errors):
|
|||||||
if prog in ('prs500', 'pdf-meta', 'epub-meta', 'lit-meta',
|
if prog in ('prs500', 'pdf-meta', 'epub-meta', 'lit-meta',
|
||||||
'markdown-calibre', 'calibre-debug', 'fb2-meta',
|
'markdown-calibre', 'calibre-debug', 'fb2-meta',
|
||||||
'calibre-fontconfig', 'calibre-parallel', 'odt-meta',
|
'calibre-fontconfig', 'calibre-parallel', 'odt-meta',
|
||||||
'rb-meta', 'imp-meta'):
|
'rb-meta', 'imp-meta', 'mobi-meta'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
help2man = ('help2man', prog, '--name', 'part of %s'%__appname__,
|
help2man = ('help2man', prog, '--name', 'part of %s'%__appname__,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user