From 4a661f91382e30476ef315caa8eaa06601617cda Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 10 Mar 2020 13:50:28 +0530 Subject: [PATCH] MOBI Input: Upshift non-animated GIF to PNG as it is a more widely supported format --- src/calibre/ebooks/mobi/reader/mobi6.py | 10 ++++++++-- src/calibre/utils/img.py | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/mobi/reader/mobi6.py b/src/calibre/ebooks/mobi/reader/mobi6.py index 85988dbb04..ebd54e326e 100644 --- a/src/calibre/ebooks/mobi/reader/mobi6.py +++ b/src/calibre/ebooks/mobi/reader/mobi6.py @@ -21,7 +21,7 @@ from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata.opf2 import OPFCreator, OPF from calibre.ebooks.metadata.toc import TOC from calibre.ebooks.mobi.reader.headers import BookHeader -from calibre.utils.img import save_cover_data_to +from calibre.utils.img import save_cover_data_to, gif_data_to_png_data, AnimatedGIF from calibre.utils.imghdr import what from polyglot.builtins import iteritems, unicode_type, range, map @@ -897,9 +897,15 @@ class MobiReader(object): continue if imgfmt == 'jpeg': imgfmt = 'jpg' + if imgfmt == 'gif': + try: + data = gif_data_to_png_data(data) + imgfmt = 'png' + except AnimatedGIF: + pass path = os.path.join(output_dir, '%05d.%s' % (image_index, imgfmt)) image_name_map[image_index] = os.path.basename(path) - if imgfmt in ('gif', 'png'): + if imgfmt == 'png': with open(path, 'wb') as f: f.write(data) else: diff --git a/src/calibre/utils/img.py b/src/calibre/utils/img.py index 71d1966138..e6f14e3a62 100644 --- a/src/calibre/utils/img.py +++ b/src/calibre/utils/img.py @@ -67,7 +67,7 @@ def load_jxr_data(data): # }}} -# png to gif {{{ +# png <-> gif {{{ def png_data_to_gif_data(data): @@ -91,6 +91,20 @@ def png_data_to_gif_data(data): img.save(buf, 'gif') return buf.getvalue() + +class AnimatedGIF(ValueError): + pass + + +def gif_data_to_png_data(data, discard_animation=False): + from PIL import Image + img = Image.open(BytesIO(data)) + if img.is_animated and not discard_animation: + raise AnimatedGIF() + buf = BytesIO() + img.save(buf, 'png') + return buf.getvalue() + # }}} # Loading images {{{