MOBI Output: Improve conversion of PNG images with transparency to GIF

This commit is contained in:
Kovid Goyal 2020-03-10 10:00:35 +05:30
parent 0c67299374
commit 0e6e5afe8d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 29 additions and 12 deletions

View File

@ -10,7 +10,7 @@ import struct, string, zlib, os
from collections import OrderedDict from collections import OrderedDict
from io import BytesIO from io import BytesIO
from calibre.utils.img import save_cover_data_to, scale_image, image_to_data, image_from_data, resize_image from calibre.utils.img import save_cover_data_to, scale_image, image_to_data, image_from_data, resize_image, png_data_to_gif_data
from calibre.utils.imghdr import what from calibre.utils.imghdr import what
from calibre.ebooks import normalize from calibre.ebooks import normalize
from polyglot.builtins import unicode_type, range, as_bytes, map from polyglot.builtins import unicode_type, range, as_bytes, map
@ -417,13 +417,8 @@ def to_base(num, base=32, min_num_digits=None):
def mobify_image(data): def mobify_image(data):
'Convert PNG images to GIF as the idiotic Kindle cannot display some PNG' 'Convert PNG images to GIF as the idiotic Kindle cannot display some PNG'
fmt = what(None, data) fmt = what(None, data)
if fmt == 'png': if fmt == 'png':
from PIL import Image data = png_data_to_gif_data(data)
im = Image.open(BytesIO(data))
buf = BytesIO()
im.save(buf, 'gif')
data = buf.getvalue()
return data return data
# Font records {{{ # Font records {{{

View File

@ -67,6 +67,32 @@ def load_jxr_data(data):
# }}} # }}}
# png to gif {{{
def png_data_to_gif_data(data):
from PIL import Image
img = Image.open(BytesIO(data))
buf = BytesIO()
if img.mode in ('p', 'P'):
transparency = img.info.get('transparency')
if transparency is not None:
img.save(buf, 'gif', transparency=transparency)
else:
img.save(buf, 'gif')
elif img.mode in ('rgba', 'RGBA'):
alpha = img.split()[3]
mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
img.paste(255, mask)
img.save(buf, 'gif', transparency=255)
else:
img = img.convert('P', palette=Image.ADAPTIVE)
img.save(buf, 'gif')
return buf.getvalue()
# }}}
# Loading images {{{ # Loading images {{{
@ -140,11 +166,7 @@ def image_to_data(img, compression_quality=95, fmt='JPEG', png_compression_level
w.setQuality(90) w.setQuality(90)
if not w.write(img): if not w.write(img):
raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString())
from PIL import Image return png_data_to_gif_data(ba.data())
im = Image.open(BytesIO(ba.data()))
buf = BytesIO()
im.save(buf, 'gif')
return buf.getvalue()
is_jpeg = fmt in ('JPG', 'JPEG') is_jpeg = fmt in ('JPG', 'JPEG')
w = QImageWriter(buf, fmt.encode('ascii')) w = QImageWriter(buf, fmt.encode('ascii'))
if is_jpeg: if is_jpeg: