Remove Pillow as dependency
This commit is contained in:
parent
d957b2d20f
commit
352b4a0b73
44
cps/comic.py
44
cps/comic.py
@ -18,21 +18,21 @@
|
||||
|
||||
from __future__ import division, print_function, unicode_literals
|
||||
import os
|
||||
import io
|
||||
|
||||
from . import logger, isoLanguages
|
||||
from .constants import BookMeta
|
||||
|
||||
try:
|
||||
from PIL import Image as PILImage
|
||||
use_PIL = True
|
||||
except ImportError as e:
|
||||
use_PIL = False
|
||||
|
||||
|
||||
log = logger.create()
|
||||
|
||||
|
||||
try:
|
||||
from wand.image import Image
|
||||
use_IM = True
|
||||
except (ImportError, RuntimeError) as e:
|
||||
use_IM = False
|
||||
|
||||
|
||||
try:
|
||||
from comicapi.comicarchive import ComicArchive, MetaDataStyle
|
||||
use_comic_meta = True
|
||||
@ -52,20 +52,26 @@ except (ImportError, LookupError) as e:
|
||||
use_rarfile = False
|
||||
use_comic_meta = False
|
||||
|
||||
COVER_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp', '.bmp']
|
||||
|
||||
|
||||
def _cover_processing(tmp_file_name, img, extension):
|
||||
if use_PIL:
|
||||
tmp_cover_name = os.path.join(os.path.dirname(tmp_file_name), 'cover.jpg')
|
||||
if use_IM:
|
||||
# convert to jpg because calibre only supports jpg
|
||||
if extension in ('.png', '.webp'):
|
||||
imgc = PILImage.open(io.BytesIO(img))
|
||||
im = imgc.convert('RGB')
|
||||
tmp_bytesio = io.BytesIO()
|
||||
im.save(tmp_bytesio, format='JPEG')
|
||||
img = tmp_bytesio.getvalue()
|
||||
cover_ext = COVER_EXTENSIONS
|
||||
cover_ext.remove('.jpeg')
|
||||
cover_ext.remove('.jpg')
|
||||
if extension in cover_ext:
|
||||
with Image(filename=tmp_file_name) as imgc:
|
||||
imgc.format = 'jpeg'
|
||||
imgc.transform_colorspace('rgb')
|
||||
imgc.save(tmp_cover_name)
|
||||
return tmp_cover_name
|
||||
|
||||
if not img:
|
||||
return None
|
||||
|
||||
tmp_cover_name = os.path.join(os.path.dirname(tmp_file_name), 'cover.jpg')
|
||||
with open(tmp_cover_name, 'wb') as f:
|
||||
f.write(img)
|
||||
return tmp_cover_name
|
||||
@ -80,7 +86,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExecutable):
|
||||
ext = os.path.splitext(name)
|
||||
if len(ext) > 1:
|
||||
extension = ext[1].lower()
|
||||
if extension in ('.jpg', '.jpeg', '.png', '.webp'):
|
||||
if extension in COVER_EXTENSIONS:
|
||||
cover_data = archive.getPage(index)
|
||||
break
|
||||
else:
|
||||
@ -90,7 +96,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExecutable):
|
||||
ext = os.path.splitext(name)
|
||||
if len(ext) > 1:
|
||||
extension = ext[1].lower()
|
||||
if extension in ('.jpg', '.jpeg', '.png', '.webp'):
|
||||
if extension in COVER_EXTENSIONS:
|
||||
cover_data = cf.read(name)
|
||||
break
|
||||
elif original_file_extension.upper() == '.CBT':
|
||||
@ -99,7 +105,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExecutable):
|
||||
ext = os.path.splitext(name)
|
||||
if len(ext) > 1:
|
||||
extension = ext[1].lower()
|
||||
if extension in ('.jpg', '.jpeg', '.png', '.webp'):
|
||||
if extension in COVER_EXTENSIONS:
|
||||
cover_data = cf.extractfile(name).read()
|
||||
break
|
||||
elif original_file_extension.upper() == '.CBR' and use_rarfile:
|
||||
@ -110,7 +116,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExecutable):
|
||||
ext = os.path.splitext(name)
|
||||
if len(ext) > 1:
|
||||
extension = ext[1].lower()
|
||||
if extension in ('.jpg', '.jpeg', '.png', '.webp'):
|
||||
if extension in COVER_EXTENSIONS:
|
||||
cover_data = cf.read(name)
|
||||
break
|
||||
except Exception as e:
|
||||
|
@ -50,13 +50,6 @@ try:
|
||||
except ImportError:
|
||||
use_unidecode = False
|
||||
|
||||
try:
|
||||
from PIL import Image as PILImage
|
||||
from PIL import UnidentifiedImageError
|
||||
use_PIL = True
|
||||
except ImportError:
|
||||
use_PIL = False
|
||||
|
||||
from . import calibre_db
|
||||
from .tasks.convert import TaskConvert
|
||||
from . import logger, config, get_locale, db, ub
|
||||
@ -66,9 +59,15 @@ from .subproc_wrapper import process_wait
|
||||
from .services.worker import WorkerThread, STAT_WAITING, STAT_FAIL, STAT_STARTED, STAT_FINISH_SUCCESS
|
||||
from .tasks.mail import TaskEmail
|
||||
|
||||
|
||||
log = logger.create()
|
||||
|
||||
try:
|
||||
from wand.image import Image
|
||||
use_IM = True
|
||||
except (ImportError, RuntimeError) as e:
|
||||
log.debug('Cannot import Image, generating covers from non jpg files will not work: %s', e)
|
||||
use_IM = False
|
||||
|
||||
|
||||
# Convert existing book entry to new format
|
||||
def convert_book_format(book_id, calibrepath, old_book_format, new_book_format, user_id, kindle_mail=None):
|
||||
@ -109,21 +108,21 @@ def convert_book_format(book_id, calibrepath, old_book_format, new_book_format,
|
||||
def send_test_mail(kindle_mail, user_name):
|
||||
WorkerThread.add(user_name, TaskEmail(_(u'Calibre-Web test e-mail'), None, None,
|
||||
config.get_mail_settings(), kindle_mail, _(u"Test e-mail"),
|
||||
_(u'This e-mail has been sent via Calibre-Web.')))
|
||||
_(u'This e-mail has been sent via Calibre-Web.')))
|
||||
return
|
||||
|
||||
|
||||
# Send registration email or password reset email, depending on parameter resend (False means welcome email)
|
||||
def send_registration_mail(e_mail, user_name, default_password, resend=False):
|
||||
text = "Hello %s!\r\n" % user_name
|
||||
txt = "Hello %s!\r\n" % user_name
|
||||
if not resend:
|
||||
text += "Your new account at Calibre-Web has been created. Thanks for joining us!\r\n"
|
||||
text += "Please log in to your account using the following informations:\r\n"
|
||||
text += "User name: %s\r\n" % user_name
|
||||
text += "Password: %s\r\n" % default_password
|
||||
text += "Don't forget to change your password after first login.\r\n"
|
||||
text += "Sincerely\r\n\r\n"
|
||||
text += "Your Calibre-Web team"
|
||||
txt += "Your new account at Calibre-Web has been created. Thanks for joining us!\r\n"
|
||||
txt += "Please log in to your account using the following informations:\r\n"
|
||||
txt += "User name: %s\r\n" % user_name
|
||||
txt += "Password: %s\r\n" % default_password
|
||||
txt += "Don't forget to change your password after first login.\r\n"
|
||||
txt += "Sincerely\r\n\r\n"
|
||||
txt += "Your Calibre-Web team"
|
||||
WorkerThread.add(None, TaskEmail(
|
||||
subject=_(u'Get Started with Calibre-Web'),
|
||||
filepath=None,
|
||||
@ -131,7 +130,7 @@ def send_registration_mail(e_mail, user_name, default_password, resend=False):
|
||||
settings=config.get_mail_settings(),
|
||||
recipient=e_mail,
|
||||
taskMessage=_(u"Registration e-mail for user: %(name)s", name=user_name),
|
||||
text=text
|
||||
text=txt
|
||||
))
|
||||
|
||||
return
|
||||
@ -177,7 +176,7 @@ def check_send_to_kindle(entry):
|
||||
'convert': 0,
|
||||
'text': _('Send %(format)s to Kindle', format='Pdf')})
|
||||
if config.config_converterpath:
|
||||
if 'EPUB' in formats and not 'MOBI' in formats:
|
||||
if 'EPUB' in formats and 'MOBI' not in formats:
|
||||
bookformats.append({'format': 'Mobi',
|
||||
'convert':1,
|
||||
'text': _('Convert %(orig)s to %(format)s and send to Kindle',
|
||||
@ -586,16 +585,15 @@ def save_cover_from_url(url, book_path):
|
||||
requests.exceptions.Timeout) as ex:
|
||||
log.info(u'Cover Download Error %s', ex)
|
||||
return False, _("Error Downloading Cover")
|
||||
except UnidentifiedImageError as ex:
|
||||
log.info(u'File Format Error %s', ex)
|
||||
return False, _("Cover Format Error")
|
||||
# except UnidentifiedImageError as ex:
|
||||
# log.info(u'File Format Error %s', ex)
|
||||
# return False, _("Cover Format Error")
|
||||
|
||||
|
||||
def save_cover_from_filestorage(filepath, saved_filename, img):
|
||||
if hasattr(img, '_content'):
|
||||
f = open(os.path.join(filepath, saved_filename), "wb")
|
||||
f.write(img._content)
|
||||
f.close()
|
||||
if hasattr(img,"metadata"):
|
||||
img.save(filename=os.path.join(filepath, saved_filename))
|
||||
img.close()
|
||||
else:
|
||||
# check if file path exists, otherwise create it, copy file to calibre path and delete temp file
|
||||
if not os.path.exists(filepath):
|
||||
@ -616,20 +614,19 @@ def save_cover_from_filestorage(filepath, saved_filename, img):
|
||||
def save_cover(img, book_path):
|
||||
content_type = img.headers.get('content-type')
|
||||
|
||||
if use_PIL:
|
||||
if content_type not in ('image/jpeg', 'image/png', 'image/webp'):
|
||||
log.error("Only jpg/jpeg/png/webp files are supported as coverfile")
|
||||
return False, _("Only jpg/jpeg/png/webp files are supported as coverfile")
|
||||
if use_IM:
|
||||
if content_type not in ('image/jpeg', 'image/png', 'image/webp', 'image/bmp'):
|
||||
log.error("Only jpg/jpeg/png/webp/bmp files are supported as coverfile")
|
||||
return False, _("Only jpg/jpeg/png/webp/bmp files are supported as coverfile")
|
||||
# convert to jpg because calibre only supports jpg
|
||||
if content_type in ('image/png', 'image/webp'):
|
||||
if content_type != 'image/jpg':
|
||||
if hasattr(img, 'stream'):
|
||||
imgc = PILImage.open(img.stream)
|
||||
imgc = Image(blob=img.stream)
|
||||
else:
|
||||
imgc = PILImage.open(io.BytesIO(img.content))
|
||||
im = imgc.convert('RGB')
|
||||
tmp_bytesio = io.BytesIO()
|
||||
im.save(tmp_bytesio, format='JPEG')
|
||||
img._content = tmp_bytesio.getvalue()
|
||||
imgc = Image(blob=io.BytesIO(img.content))
|
||||
imgc.format = 'jpeg'
|
||||
imgc.transform_colorspace("rgb")
|
||||
img = imgc
|
||||
else:
|
||||
if content_type not in 'image/jpeg':
|
||||
log.error("Only jpg/jpeg files are supported as coverfile")
|
||||
|
@ -66,14 +66,6 @@ except ImportError as e:
|
||||
log.debug('Cannot import fb2, extracting fb2 metadata will not work: %s', e)
|
||||
use_fb2_meta = False
|
||||
|
||||
try:
|
||||
from PIL import Image as PILImage
|
||||
from PIL import __version__ as PILversion
|
||||
use_PIL = True
|
||||
except ImportError as e:
|
||||
log.debug('Cannot import Pillow, using png and webp images as cover will not work: %s', e)
|
||||
use_PIL = False
|
||||
|
||||
|
||||
def process(tmp_file_path, original_file_name, original_file_extension, rarExecutable):
|
||||
meta = None
|
||||
@ -179,10 +171,6 @@ def get_versions():
|
||||
XVersion = 'v'+'.'.join(map(str, lxmlversion))
|
||||
else:
|
||||
XVersion = u'not installed'
|
||||
if use_PIL:
|
||||
PILVersion = 'v' + PILversion
|
||||
else:
|
||||
PILVersion = u'not installed'
|
||||
if comic.use_comic_meta:
|
||||
ComicVersion = comic.comic_version or u'installed'
|
||||
else:
|
||||
@ -191,7 +179,7 @@ def get_versions():
|
||||
'PyPdf': PVersion,
|
||||
'lxml':XVersion,
|
||||
'Wand': WVersion,
|
||||
'Pillow': PILVersion,
|
||||
# 'Pillow': PILVersion,
|
||||
'Comic_API': ComicVersion}
|
||||
|
||||
|
||||
|
@ -26,7 +26,6 @@ SQLAlchemy-Utils>=0.33.5,<0.37.0
|
||||
|
||||
# extracting metadata
|
||||
lxml>=3.8.0,<4.6.0
|
||||
Pillow>=4.0.0,<7.2.0
|
||||
rarfile>=2.7
|
||||
|
||||
# other
|
||||
|
Loading…
Reference in New Issue
Block a user