mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
EPUB metadata: When setting metadata in an EPUB file, if it has a well defined image based cover, update it
This commit is contained in:
parent
1b3a799d0d
commit
d7d9fa4141
@ -5,7 +5,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
'''Read meta information from epub files'''
|
||||
|
||||
import os, re
|
||||
import os, re, posixpath
|
||||
from cStringIO import StringIO
|
||||
from contextlib import closing
|
||||
|
||||
@ -126,7 +126,6 @@ class OCFDirReader(OCFReader):
|
||||
return open(os.path.join(self.root, path), *args, **kwargs)
|
||||
|
||||
def get_cover(opf, opf_path, stream, reader=None):
|
||||
import posixpath
|
||||
from calibre.ebooks import render_html_svg_workaround
|
||||
from calibre.utils.logging import default_log
|
||||
raster_cover = opf.raster_cover
|
||||
@ -185,7 +184,37 @@ def get_quick_metadata(stream):
|
||||
def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
|
||||
stream.seek(0)
|
||||
reader = OCFZipReader(stream, root=os.getcwdu())
|
||||
raster_cover = reader.opf.raster_cover
|
||||
mi = MetaInformation(mi)
|
||||
new_cdata = None
|
||||
replacements = {}
|
||||
try:
|
||||
new_cdata = mi.cover_data[1]
|
||||
if not new_cdata:
|
||||
raise Exception('no cover')
|
||||
except:
|
||||
try:
|
||||
new_cdata = open(mi.cover, 'rb').read()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
if new_cdata and raster_cover:
|
||||
try:
|
||||
cpath = posixpath.join(posixpath.dirname(reader.opf_path),
|
||||
raster_cover)
|
||||
cover_replacable = not reader.encryption_meta.is_encrypted(cpath) and \
|
||||
os.path.splitext(cpath)[1].lower() in ('.png', '.jpg', '.jpeg')
|
||||
if cover_replacable:
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.utils.magick_draw import save_cover_data_to
|
||||
new_cover = PersistentTemporaryFile(suffix=os.path.splitext(cpath)[1])
|
||||
new_cover.close()
|
||||
save_cover_data_to(new_cdata, new_cover.name)
|
||||
replacements[cpath] = open(new_cover.name, 'rb')
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
for x in ('guide', 'toc', 'manifest', 'spine'):
|
||||
setattr(mi, x, None)
|
||||
reader.opf.smart_update(mi)
|
||||
@ -200,5 +229,6 @@ def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
|
||||
reader.opf.timestamp = mi.timestamp
|
||||
|
||||
newopf = StringIO(reader.opf.render())
|
||||
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf)
|
||||
safe_replace(stream, reader.container[OPF.MIMETYPE], newopf,
|
||||
extra_replacements=replacements)
|
||||
|
||||
|
@ -183,7 +183,8 @@ class ContentServer(object):
|
||||
fmt = TemporaryFile()
|
||||
fmt.write(raw)
|
||||
fmt.seek(0)
|
||||
set_metadata(fmt, self.db.get_metadata(id, index_is_id=True),
|
||||
set_metadata(fmt, self.db.get_metadata(id, index_is_id=True,
|
||||
get_cover=True),
|
||||
'epub')
|
||||
fmt.seek(0)
|
||||
mt = guess_type('dummy.'+format.lower())[0]
|
||||
|
@ -1362,7 +1362,7 @@ class ZipFile:
|
||||
self.fp.close()
|
||||
self.fp = None
|
||||
|
||||
def safe_replace(zipstream, name, datastream):
|
||||
def safe_replace(zipstream, name, datastream, extra_replacements={}):
|
||||
'''
|
||||
Replace a file in a zip file in a safe manner. This proceeds by extracting
|
||||
and re-creating the zipfile. This is necessary because :method:`ZipFile.replace`
|
||||
@ -1371,13 +1371,19 @@ def safe_replace(zipstream, name, datastream):
|
||||
:param zipstream: Stream from a zip file
|
||||
:param name: The name of the file to replace
|
||||
:param datastream: The data to replace the file with.
|
||||
:param extra_replacements: Extra replacements. Mapping of name to file-like
|
||||
objects
|
||||
|
||||
'''
|
||||
z = ZipFile(zipstream, 'r')
|
||||
replacements = {name:datastream}
|
||||
replacements.update(extra_replacements)
|
||||
names = frozenset(replacements.keys())
|
||||
with SpooledTemporaryFile(max_size=100*1024*1024) as temp:
|
||||
ztemp = ZipFile(temp, 'w')
|
||||
for obj in z.infolist():
|
||||
if obj.filename == name:
|
||||
ztemp.writestr(obj, datastream.read())
|
||||
if obj.filename in names:
|
||||
ztemp.writestr(obj, replacements[obj.filename].read())
|
||||
else:
|
||||
ztemp.writestr(obj, z.read_raw(obj), raw_bytes=True)
|
||||
ztemp.close()
|
||||
|
Loading…
x
Reference in New Issue
Block a user