mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 07:13:02 +00:00 
			
		
		
		
	Merge remote-tracking branch 'image_formats/dev'
This commit is contained in:
		| @@ -62,6 +62,8 @@ except ImportError as e: | ||||
|     logger.warning('cannot import fb2, extracting fb2 metadata will not work: %s', e) | ||||
|     use_fb2_meta = False | ||||
|  | ||||
| from PIL import Image | ||||
|  | ||||
|  | ||||
| def process(tmp_file_path, original_file_name, original_file_extension): | ||||
|     meta = None | ||||
| @@ -131,6 +133,47 @@ def pdf_preview(tmp_file_path, tmp_dir): | ||||
|     if use_generic_pdf_cover: | ||||
|         return None | ||||
|     else: | ||||
|         try: | ||||
|             input1 = PdfFileReader(open(tmp_file_path, 'rb'), strict=False) | ||||
|             page0 = input1.getPage(0) | ||||
|             xObject = page0['/Resources']['/XObject'].getObject() | ||||
|  | ||||
|             for obj in xObject: | ||||
|                 if xObject[obj]['/Subtype'] == '/Image': | ||||
|                     size = (xObject[obj]['/Width'], xObject[obj]['/Height']) | ||||
|                     data = xObject[obj]._data # xObject[obj].getData() | ||||
|                     if xObject[obj]['/ColorSpace'] == '/DeviceRGB': | ||||
|                         mode = "RGB" | ||||
|                     else: | ||||
|                         mode = "P" | ||||
|                     if '/Filter' in xObject[obj]: | ||||
|                         if xObject[obj]['/Filter'] == '/FlateDecode': | ||||
|                             img = Image.frombytes(mode, size, data) | ||||
|                             cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.png" | ||||
|                             img.save(filename=os.path.join(tmp_dir, cover_file_name)) | ||||
|                             return cover_file_name | ||||
|                             # img.save(obj[1:] + ".png") | ||||
|                         elif xObject[obj]['/Filter'] == '/DCTDecode': | ||||
|                             cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.jpg" | ||||
|                             img = open(cover_file_name, "wb") | ||||
|                             img.write(data) | ||||
|                             img.close() | ||||
|                             return cover_file_name | ||||
|                         elif xObject[obj]['/Filter'] == '/JPXDecode': | ||||
|                             cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.jp2" | ||||
|                             img = open(cover_file_name, "wb") | ||||
|                             img.write(data) | ||||
|                             img.close() | ||||
|                             return cover_file_name | ||||
|                     else: | ||||
|                         img = Image.frombytes(mode, size, data) | ||||
|                         cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.png" | ||||
|                         img.save(filename=os.path.join(tmp_dir, cover_file_name)) | ||||
|                         return cover_file_name | ||||
|                         # img.save(obj[1:] + ".png") | ||||
|         except Exception as ex: | ||||
|             print(ex) | ||||
|  | ||||
|         try: | ||||
|             cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.jpg" | ||||
|             with Image(filename=tmp_file_path + "[0]", resolution=150) as img: | ||||
|   | ||||
| @@ -24,6 +24,7 @@ import ub | ||||
| from flask import current_app as app | ||||
| from tempfile import gettempdir | ||||
| import sys | ||||
| import io | ||||
| import os | ||||
| import re | ||||
| import unicodedata | ||||
| @@ -34,6 +35,7 @@ from flask_babel import gettext as _ | ||||
| from flask_login import current_user | ||||
| from babel.dates import format_datetime | ||||
| from datetime import datetime | ||||
| from PIL import Image | ||||
| import shutil | ||||
| import requests | ||||
| try: | ||||
| @@ -442,27 +444,66 @@ def get_book_cover(cover_path): | ||||
|         return send_from_directory(os.path.join(ub.config.config_calibre_dir, cover_path), "cover.jpg") | ||||
|  | ||||
|  | ||||
| # saves book cover to gdrive or locally | ||||
| def save_cover(url, book_path): | ||||
| # saves book cover from url | ||||
| def save_cover_from_url(url, book_path): | ||||
|     img = requests.get(url) | ||||
|     if img.headers.get('content-type') != 'image/jpeg': | ||||
|         web.app.logger.error("Cover is no jpg file, can't save") | ||||
|     return save_cover(img, book_path) | ||||
|  | ||||
|  | ||||
| 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() | ||||
|     else: | ||||
|         # check if file path exists, otherwise create it, copy file to calibre path and delete temp file | ||||
|         if not os.path.exists(filepath): | ||||
|             try: | ||||
|                 os.makedirs(filepath) | ||||
|             except OSError: | ||||
|                 web.app.logger.error(u"Failed to create path for cover") | ||||
|                 return False | ||||
|         try: | ||||
|             img.save(os.path.join(filepath, saved_filename)) | ||||
|         except OSError: | ||||
|             web.app.logger.error(u"Failed to store cover-file") | ||||
|             return False | ||||
|         except IOError: | ||||
|             web.app.logger.error(u"Cover-file is not a valid image file") | ||||
|             return False | ||||
|     return True | ||||
|  | ||||
|  | ||||
| # saves book cover to gdrive or locally | ||||
| def save_cover(img, book_path): | ||||
|     content_type = img.headers.get('content-type') | ||||
|     if content_type not in ('image/jpeg', 'image/png', 'image/webp'): | ||||
|         web.app.logger.error("Only jpg/jpeg/png/webp files are supported as coverfile") | ||||
|         return False | ||||
|  | ||||
|     # convert to jpg because calibre only supports jpg | ||||
|     if content_type in ('image/png', 'image/webp'): | ||||
|         if hasattr(img,'stream'): | ||||
|             imgc = Image.open(img.stream) | ||||
|         else: | ||||
|             imgc = Image.open(io.BytesIO(img.content)) | ||||
|         im = imgc.convert('RGB') | ||||
|         tmp_bytesio = io.BytesIO() | ||||
|         im.save(tmp_bytesio, format='JPEG') | ||||
|         img._content = tmp_bytesio.getvalue() | ||||
|  | ||||
|     if ub.config.config_use_google_drive: | ||||
|         tmpDir = gettempdir() | ||||
|         f = open(os.path.join(tmpDir, "uploaded_cover.jpg"), "wb") | ||||
|         f.write(img.content) | ||||
|         f.close() | ||||
|         gd.uploadFileToEbooksFolder(os.path.join(book_path, 'cover.jpg'), os.path.join(tmpDir, f.name)) | ||||
|         if save_cover_from_filestorage(tmpDir, "uploaded_cover.jpg", img) is True: | ||||
|             gd.uploadFileToEbooksFolder(os.path.join(book_path, 'cover.jpg'), | ||||
|                                         os.path.join(tmpDir, "uploaded_cover.jpg")) | ||||
|             web.app.logger.info("Cover is saved on Google Drive") | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|     else: | ||||
|         return save_cover_from_filestorage(os.path.join(ub.config.config_calibre_dir, book_path), "cover.jpg", img) | ||||
|  | ||||
|     f = open(os.path.join(ub.config.config_calibre_dir, book_path, "cover.jpg"), "wb") | ||||
|     f.write(img.content) | ||||
|     f.close() | ||||
|     web.app.logger.info("Cover is saved") | ||||
|     return True | ||||
|  | ||||
|  | ||||
| def do_download_file(book, book_format, data, headers): | ||||
| @@ -487,7 +528,6 @@ def do_download_file(book, book_format, data, headers): | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| def check_unrar(unrarLocation): | ||||
|     error = False | ||||
|     if os.path.exists(unrarLocation): | ||||
|   | ||||
| @@ -90,7 +90,7 @@ | ||||
|     <div class="form-group" aria-label="Upload cover from local drive"> | ||||
|         <label class="btn btn-primary btn-file" for="btn-upload-cover">{{ _('Upload Cover from local drive') }}</label> | ||||
|         <div class="upload-cover-input-text" id="upload-cover"></div> | ||||
|         <input id="btn-upload-cover" name="btn-upload-cover" type="file"> | ||||
|         <input id="btn-upload-cover" name="btn-upload-cover" type="file" accept=".jpg, .jpeg, .png, .webp"> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
|       <label for="pubdate">{{_('Publishing date')}}</label> | ||||
|   | ||||
							
								
								
									
										37
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								cps/web.py
									
									
									
									
									
								
							| @@ -3558,33 +3558,19 @@ def upload_single_file(request, book, book_id): | ||||
|             helper.global_WorkerThread.add_upload(current_user.nickname, | ||||
|                 "<a href=\"" + url_for('show_book', book_id=book.id) + "\">" + uploadText + "</a>") | ||||
|  | ||||
|  | ||||
| def upload_cover(request, book): | ||||
|     if 'btn-upload-cover' in request.files: | ||||
|         requested_file = request.files['btn-upload-cover'] | ||||
|         # check for empty request | ||||
|         if requested_file.filename != '': | ||||
|             file_ext = requested_file.filename.rsplit('.', 1)[-1].lower() | ||||
|             filepath = os.path.normpath(os.path.join(config.config_calibre_dir, book.path)) | ||||
|             saved_filename = os.path.join(filepath,  'cover.' + file_ext) | ||||
|  | ||||
|             # check if file path exists, otherwise create it, copy file to calibre path and delete temp file | ||||
|             if not os.path.exists(filepath): | ||||
|                 try: | ||||
|                     os.makedirs(filepath) | ||||
|                 except OSError: | ||||
|                     flash(_(u"Failed to create path for cover %(path)s (Permission denied).", cover=filepath), | ||||
|                           category="error") | ||||
|                     return redirect(url_for('show_book', book_id=book.id)) | ||||
|             try: | ||||
|                 requested_file.save(saved_filename) | ||||
|                 # im=Image.open(saved_filename) | ||||
|                 book.has_cover = 1 | ||||
|             except OSError: | ||||
|                 flash(_(u"Failed to store cover-file %(cover)s.", cover=saved_filename), category="error") | ||||
|                 return redirect(url_for('show_book', book_id=book.id)) | ||||
|             except IOError: | ||||
|                 flash(_(u"Cover-file is not a valid image file" % saved_filename), category="error") | ||||
|                 return redirect(url_for('show_book', book_id=book.id)) | ||||
|             if helper.save_cover(requested_file, book.path) is True: | ||||
|                 return True | ||||
|             else: | ||||
|                 # ToDo Message not always coorect | ||||
|                 flash(_(u"Cover is not a supported imageformat (jpg/png/webp), can't save"), category="error") | ||||
|                 return False | ||||
|     return None | ||||
|  | ||||
| @app.route("/admin/book/<int:book_id>", methods=['GET', 'POST']) | ||||
| @login_required_if_no_ano | ||||
| @@ -3605,7 +3591,8 @@ def edit_book(book_id): | ||||
|         return redirect(url_for("index")) | ||||
|  | ||||
|     upload_single_file(request, book, book_id) | ||||
|     upload_cover(request, book) | ||||
|     if upload_cover(request, book) is True: | ||||
|         book.has_cover = 1 | ||||
|     try: | ||||
|         to_save = request.form.to_dict() | ||||
|         # Update book | ||||
| @@ -3651,10 +3638,10 @@ def edit_book(book_id): | ||||
|  | ||||
|         if not error: | ||||
|             if to_save["cover_url"]: | ||||
|                 if helper.save_cover(to_save["cover_url"], book.path) is True: | ||||
|                 if helper.save_cover_from_url(to_save["cover_url"], book.path) is True: | ||||
|                     book.has_cover = 1 | ||||
|                 else: | ||||
|                     flash(_(u"Cover is not a jpg file, can't save"), category="error") | ||||
|                     flash(_(u"Cover is not a supported imageformat (jpg/png/webp), can't save"), category="error") | ||||
|  | ||||
|             if book.series_index != to_save["series_index"]: | ||||
|                 book.series_index = to_save["series_index"] | ||||
|   | ||||
| @@ -13,3 +13,4 @@ SQLAlchemy>=1.1.0 | ||||
| tornado>=4.1 | ||||
| Wand>=0.4.4 | ||||
| unidecode>=0.04.19 | ||||
| Pillow>=5.4.0 | ||||
		Reference in New Issue
	
	Block a user
	 Ozzieisaacs
					Ozzieisaacs