+77
-3
@@ -7,6 +7,9 @@ from typing import List, Dict, Optional
|
||||
from dreader import create_ebook_reader
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
import ebooklib
|
||||
from ebooklib import epub
|
||||
|
||||
|
||||
def scan_book_directory(directory: Path) -> List[Dict[str, str]]:
|
||||
@@ -53,9 +56,9 @@ def extract_book_metadata(epub_path: Path, include_cover: bool = True) -> Option
|
||||
'author': reader.book_author or 'Unknown Author',
|
||||
}
|
||||
|
||||
# Extract cover image if requested
|
||||
# Extract cover image if requested - use direct EPUB extraction
|
||||
if include_cover:
|
||||
cover_data = extract_cover_as_base64(reader)
|
||||
cover_data = extract_cover_from_epub(epub_path)
|
||||
metadata['cover_data'] = cover_data
|
||||
|
||||
return metadata
|
||||
@@ -75,6 +78,9 @@ def extract_cover_as_base64(reader, max_width: int = 300, max_height: int = 450)
|
||||
"""
|
||||
Extract cover image from reader and return as base64 encoded string.
|
||||
|
||||
This function is kept for backward compatibility but now uses extract_cover_from_epub
|
||||
internally if the reader has an epub_path attribute.
|
||||
|
||||
Args:
|
||||
reader: EbookReader instance with loaded book
|
||||
max_width: Maximum width for cover image
|
||||
@@ -84,7 +90,11 @@ def extract_cover_as_base64(reader, max_width: int = 300, max_height: int = 450)
|
||||
Base64 encoded PNG image string or None
|
||||
"""
|
||||
try:
|
||||
# Get first page as cover
|
||||
# If the reader has an epub path, try to extract actual cover
|
||||
if hasattr(reader, '_epub_path') and reader._epub_path:
|
||||
return extract_cover_from_epub(reader._epub_path, max_width, max_height)
|
||||
|
||||
# Fallback to first page as cover
|
||||
cover_image = reader.get_current_page()
|
||||
|
||||
# Resize if needed
|
||||
@@ -104,6 +114,70 @@ def extract_cover_as_base64(reader, max_width: int = 300, max_height: int = 450)
|
||||
return None
|
||||
|
||||
|
||||
def extract_cover_from_epub(epub_path: Path, max_width: int = 300, max_height: int = 450) -> Optional[str]:
|
||||
"""
|
||||
Extract the actual cover image from an EPUB file.
|
||||
|
||||
Args:
|
||||
epub_path: Path to EPUB file
|
||||
max_width: Maximum width for cover image
|
||||
max_height: Maximum height for cover image
|
||||
|
||||
Returns:
|
||||
Base64 encoded PNG image string or None
|
||||
"""
|
||||
try:
|
||||
# Read the EPUB
|
||||
book = epub.read_epub(str(epub_path))
|
||||
|
||||
# Look for cover image
|
||||
cover_image = None
|
||||
|
||||
# First, try to find item marked as cover
|
||||
for item in book.get_items():
|
||||
if item.get_type() == ebooklib.ITEM_COVER:
|
||||
cover_image = Image.open(BytesIO(item.get_content()))
|
||||
break
|
||||
|
||||
# If not found, look for files with 'cover' in the name
|
||||
if not cover_image:
|
||||
for item in book.get_items():
|
||||
if item.get_type() == ebooklib.ITEM_IMAGE:
|
||||
name = item.get_name().lower()
|
||||
if 'cover' in name:
|
||||
cover_image = Image.open(BytesIO(item.get_content()))
|
||||
break
|
||||
|
||||
# If still not found, get the first image
|
||||
if not cover_image:
|
||||
for item in book.get_items():
|
||||
if item.get_type() == ebooklib.ITEM_IMAGE:
|
||||
try:
|
||||
cover_image = Image.open(BytesIO(item.get_content()))
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not cover_image:
|
||||
return None
|
||||
|
||||
# Resize if needed (maintain aspect ratio)
|
||||
if cover_image.width > max_width or cover_image.height > max_height:
|
||||
cover_image.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)
|
||||
|
||||
# Convert to base64
|
||||
buffer = BytesIO()
|
||||
cover_image.save(buffer, format='PNG')
|
||||
img_bytes = buffer.getvalue()
|
||||
img_base64 = base64.b64encode(img_bytes).decode('utf-8')
|
||||
|
||||
return img_base64
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error extracting cover from EPUB {epub_path}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_chapter_list(reader) -> List[Dict]:
|
||||
"""
|
||||
Get formatted chapter list from reader.
|
||||
|
||||
Reference in New Issue
Block a user