This commit is contained in:
parent
1bd9fdb551
commit
bde846bc3e
44
README.md
44
README.md
@ -50,29 +50,60 @@ from pyWebLayout.layout.ereader_application import EbookReader
|
||||
with EbookReader(page_size=(800, 1000)) as reader:
|
||||
# Load an EPUB file
|
||||
reader.load_epub("mybook.epub")
|
||||
|
||||
|
||||
# Get current page as PIL Image
|
||||
page = reader.get_current_page()
|
||||
page.save("page_001.png")
|
||||
|
||||
|
||||
# Navigate through pages
|
||||
reader.next_page()
|
||||
reader.previous_page()
|
||||
|
||||
|
||||
# Save reading position
|
||||
reader.save_position("chapter_3")
|
||||
|
||||
|
||||
# Jump to a chapter
|
||||
reader.jump_to_chapter("Chapter 5")
|
||||
|
||||
|
||||
# Adjust font size
|
||||
reader.increase_font_size()
|
||||
|
||||
|
||||
# Get progress
|
||||
progress = reader.get_reading_progress()
|
||||
print(f"Progress: {progress*100:.1f}%")
|
||||
```
|
||||
|
||||
### EbookReader in Action
|
||||
|
||||
Here are animated demonstrations of the EbookReader's key features:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<b>Page Navigation</b><br>
|
||||
<img src="examples/gifs/ereader_page_navigation.gif" width="300" alt="Page Navigation"><br>
|
||||
<em>Forward and backward navigation through pages</em>
|
||||
</td>
|
||||
<td align="center">
|
||||
<b>Font Size Adjustment</b><br>
|
||||
<img src="examples/gifs/ereader_font_size.gif" width="300" alt="Font Size"><br>
|
||||
<em>Dynamic font size scaling with position preservation</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<b>Chapter Navigation</b><br>
|
||||
<img src="examples/gifs/ereader_chapter_navigation.gif" width="300" alt="Chapter Navigation"><br>
|
||||
<em>Jump directly to chapters by title or index</em>
|
||||
</td>
|
||||
<td align="center">
|
||||
<b>Bookmarks & Positions</b><br>
|
||||
<img src="examples/gifs/ereader_bookmarks.gif" width="300" alt="Bookmarks"><br>
|
||||
<em>Save and restore reading positions anywhere in the book</em>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### HTML Multi-Page Rendering
|
||||
|
||||
```python
|
||||
@ -100,6 +131,7 @@ Check out the `examples/` directory for complete working examples:
|
||||
|
||||
- **`simple_ereader_example.py`** - Quick start with EbookReader
|
||||
- **`ereader_demo.py`** - Comprehensive EbookReader feature demo
|
||||
- **`generate_ereader_gifs.py`** - Generate animated GIF demonstrations
|
||||
- **`html_multipage_demo.py`** - HTML to multi-page rendering
|
||||
- See `examples/README.md` for full list
|
||||
|
||||
|
||||
12
ereader_bookmarks/test_bookmarks.json
Normal file
12
ereader_bookmarks/test_bookmarks.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"demo_bookmark": {
|
||||
"chapter_index": 0,
|
||||
"block_index": 27,
|
||||
"word_index": 0,
|
||||
"table_row": 0,
|
||||
"table_col": 0,
|
||||
"list_item_index": 0,
|
||||
"remaining_pretext": null,
|
||||
"page_y_offset": 0
|
||||
}
|
||||
}
|
||||
10
ereader_bookmarks/test_position.json
Normal file
10
ereader_bookmarks/test_position.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"chapter_index": 0,
|
||||
"block_index": 27,
|
||||
"word_index": 0,
|
||||
"table_row": 0,
|
||||
"table_col": 0,
|
||||
"list_item_index": 0,
|
||||
"remaining_pretext": null,
|
||||
"page_y_offset": 0
|
||||
}
|
||||
286
examples/generate_ereader_gifs.py
Normal file
286
examples/generate_ereader_gifs.py
Normal file
@ -0,0 +1,286 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate animated GIFs demonstrating EbookReader functionality.
|
||||
|
||||
This script creates animated GIFs showcasing:
|
||||
1. Page navigation (next/previous)
|
||||
2. Font size adjustment
|
||||
3. Chapter navigation
|
||||
4. Bookmark/position management
|
||||
|
||||
The GIFs are saved to the examples/ directory and can be included in documentation.
|
||||
|
||||
Usage:
|
||||
python generate_ereader_gifs.py path/to/book.epub [output_dir]
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
# Add parent directory to path to import pyWebLayout
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from pyWebLayout.layout.ereader_application import EbookReader
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def create_gif(images: List[Image.Image], output_path: str, duration: int = 800, loop: int = 0):
|
||||
"""
|
||||
Create an animated GIF from a list of PIL Images.
|
||||
|
||||
Args:
|
||||
images: List of PIL Images to animate
|
||||
output_path: Path where to save the GIF
|
||||
duration: Duration of each frame in milliseconds
|
||||
loop: Number of loops (0 = infinite)
|
||||
"""
|
||||
if not images:
|
||||
print(f"Warning: No images provided for {output_path}")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Save as animated GIF
|
||||
images[0].save(
|
||||
output_path,
|
||||
save_all=True,
|
||||
append_images=images[1:],
|
||||
duration=duration,
|
||||
loop=loop,
|
||||
optimize=False
|
||||
)
|
||||
print(f"✓ Created: {output_path} ({len(images)} frames)")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ Error creating {output_path}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def generate_page_navigation_gif(reader: EbookReader, output_path: str):
|
||||
"""Generate GIF showing page navigation (forward and backward)."""
|
||||
print("\n[1/4] Generating page navigation GIF...")
|
||||
|
||||
frames = []
|
||||
|
||||
# Go to beginning
|
||||
reader.set_font_size(1.0)
|
||||
|
||||
# Capture 5 pages going forward
|
||||
for i in range(5):
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
reader.next_page()
|
||||
|
||||
# Go back to start
|
||||
for _ in range(4):
|
||||
reader.previous_page()
|
||||
|
||||
# Capture 5 pages going forward again (smoother loop)
|
||||
for i in range(5):
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
reader.next_page()
|
||||
|
||||
create_gif(frames, output_path, duration=600)
|
||||
|
||||
|
||||
def generate_font_size_gif(reader: EbookReader, output_path: str):
|
||||
"""Generate GIF showing font size adjustment."""
|
||||
print("\n[2/4] Generating font size adjustment GIF...")
|
||||
|
||||
frames = []
|
||||
|
||||
# Reset to beginning and normal font
|
||||
for _ in range(10):
|
||||
reader.previous_page()
|
||||
reader.set_font_size(1.0)
|
||||
|
||||
# Font sizes to demonstrate
|
||||
font_scales = [0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.3, 1.2, 1.1, 1.0, 0.9, 0.8]
|
||||
|
||||
for scale in font_scales:
|
||||
page = reader.set_font_size(scale)
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
|
||||
# Reset to normal
|
||||
reader.set_font_size(1.0)
|
||||
|
||||
create_gif(frames, output_path, duration=500)
|
||||
|
||||
|
||||
def generate_chapter_navigation_gif(reader: EbookReader, output_path: str):
|
||||
"""Generate GIF showing chapter navigation."""
|
||||
print("\n[3/4] Generating chapter navigation GIF...")
|
||||
|
||||
frames = []
|
||||
|
||||
# Reset font
|
||||
reader.set_font_size(1.0)
|
||||
|
||||
# Get chapters
|
||||
chapters = reader.get_chapters()
|
||||
|
||||
if len(chapters) == 0:
|
||||
print(" Warning: No chapters found, skipping chapter navigation GIF")
|
||||
return
|
||||
|
||||
# Visit first few chapters (or loop through available chapters)
|
||||
chapter_indices = list(range(min(5, len(chapters))))
|
||||
|
||||
# Add some chapters twice for smoother animation
|
||||
for idx in chapter_indices:
|
||||
page = reader.jump_to_chapter(idx)
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
# Add a second frame at each chapter for pause effect
|
||||
frames.append(page.copy())
|
||||
|
||||
# Go back to first chapter
|
||||
page = reader.jump_to_chapter(0)
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
|
||||
if frames:
|
||||
create_gif(frames, output_path, duration=1000)
|
||||
else:
|
||||
print(" Warning: No frames captured for chapter navigation")
|
||||
|
||||
|
||||
def generate_bookmark_gif(reader: EbookReader, output_path: str):
|
||||
"""Generate GIF showing bookmark save/load functionality."""
|
||||
print("\n[4/4] Generating bookmark/position GIF...")
|
||||
|
||||
frames = []
|
||||
|
||||
# Reset font
|
||||
reader.set_font_size(1.0)
|
||||
|
||||
# Go to beginning
|
||||
for _ in range(20):
|
||||
reader.previous_page()
|
||||
|
||||
# Capture initial position
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
frames.append(page.copy()) # Hold frame
|
||||
|
||||
# Navigate forward a bit
|
||||
for i in range(3):
|
||||
reader.next_page()
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
|
||||
# Save this position
|
||||
reader.save_position("demo_bookmark")
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
frames.append(page.copy()) # Hold frame to show saved position
|
||||
|
||||
# Navigate away
|
||||
for i in range(5):
|
||||
reader.next_page()
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
|
||||
# Hold at distant position
|
||||
page = reader.get_current_page()
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
frames.append(page.copy())
|
||||
|
||||
# Jump back to bookmark
|
||||
page = reader.load_position("demo_bookmark")
|
||||
if page:
|
||||
frames.append(page.copy())
|
||||
frames.append(page.copy())
|
||||
frames.append(page.copy()) # Hold longer to show we're back
|
||||
|
||||
create_gif(frames, output_path, duration=600)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to generate all GIFs."""
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python generate_ereader_gifs.py path/to/book.epub [output_dir]")
|
||||
print("\nExample:")
|
||||
print(" python generate_ereader_gifs.py ../tests/data/test.epub ./gifs")
|
||||
sys.exit(1)
|
||||
|
||||
epub_path = sys.argv[1]
|
||||
output_dir = sys.argv[2] if len(sys.argv) > 2 else "."
|
||||
|
||||
# Validate EPUB path
|
||||
if not os.path.exists(epub_path):
|
||||
print(f"Error: EPUB file not found: {epub_path}")
|
||||
sys.exit(1)
|
||||
|
||||
# Create output directory
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
print("="*70)
|
||||
print(" EbookReader Animated GIF Generator")
|
||||
print("="*70)
|
||||
print(f"\nInput EPUB: {epub_path}")
|
||||
print(f"Output directory: {output_dir}")
|
||||
|
||||
# Create paths for output GIFs
|
||||
nav_gif = os.path.join(output_dir, "ereader_page_navigation.gif")
|
||||
font_gif = os.path.join(output_dir, "ereader_font_size.gif")
|
||||
chapter_gif = os.path.join(output_dir, "ereader_chapter_navigation.gif")
|
||||
bookmark_gif = os.path.join(output_dir, "ereader_bookmarks.gif")
|
||||
|
||||
try:
|
||||
# Create reader
|
||||
with EbookReader(page_size=(600, 800), margin=30) as reader:
|
||||
# Load EPUB
|
||||
print("\nLoading EPUB...")
|
||||
if not reader.load_epub(epub_path):
|
||||
print("Error: Failed to load EPUB file")
|
||||
sys.exit(1)
|
||||
|
||||
print("✓ EPUB loaded successfully")
|
||||
|
||||
# Get book info
|
||||
book_info = reader.get_book_info()
|
||||
print(f"\nBook: {book_info['title']}")
|
||||
print(f"Author: {book_info['author']}")
|
||||
print(f"Chapters: {book_info['total_chapters']}")
|
||||
print(f"Blocks: {book_info['total_blocks']}")
|
||||
|
||||
print("\nGenerating GIFs...")
|
||||
print("-" * 70)
|
||||
|
||||
# Generate all GIFs
|
||||
generate_page_navigation_gif(reader, nav_gif)
|
||||
generate_font_size_gif(reader, font_gif)
|
||||
generate_chapter_navigation_gif(reader, chapter_gif)
|
||||
generate_bookmark_gif(reader, bookmark_gif)
|
||||
|
||||
print("\n" + "="*70)
|
||||
print(" Generation Complete!")
|
||||
print("="*70)
|
||||
print("\nGenerated files:")
|
||||
for gif_path in [nav_gif, font_gif, chapter_gif, bookmark_gif]:
|
||||
if os.path.exists(gif_path):
|
||||
size = os.path.getsize(gif_path)
|
||||
print(f" ✓ {gif_path} ({size/1024:.1f} KB)")
|
||||
|
||||
print("\nYou can now add these GIFs to your README.md!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
100
examples/gifs/README.md
Normal file
100
examples/gifs/README.md
Normal file
@ -0,0 +1,100 @@
|
||||
# EbookReader Animated Demonstrations
|
||||
|
||||
This directory contains animated GIF demonstrations of the pyWebLayout EbookReader functionality.
|
||||
|
||||
## Generated GIFs
|
||||
|
||||
### 1. Page Navigation (`ereader_page_navigation.gif`)
|
||||
Demonstrates forward and backward page navigation through an EPUB book. Shows smooth transitions between pages using `next_page()` and `previous_page()` methods.
|
||||
|
||||
**Features shown:**
|
||||
- Sequential page advancement
|
||||
- Page-by-page content rendering
|
||||
- Natural reading flow
|
||||
|
||||
### 2. Font Size Adjustment (`ereader_font_size.gif`)
|
||||
Shows dynamic font size scaling from 0.8x to 1.4x and back. The reader maintains the current reading position even as the layout changes with different font sizes.
|
||||
|
||||
**Features shown:**
|
||||
- `increase_font_size()` / `decrease_font_size()`
|
||||
- `set_font_size(scale)` with specific values
|
||||
- Position preservation across layout changes
|
||||
- Text reflow with different sizes
|
||||
|
||||
### 3. Chapter Navigation (`ereader_chapter_navigation.gif`)
|
||||
Demonstrates jumping between chapters in a book. Each chapter's first page is displayed, showing the ability to navigate non-linearly through the content.
|
||||
|
||||
**Features shown:**
|
||||
- `jump_to_chapter(index)` for index-based navigation
|
||||
- `jump_to_chapter(title)` for title-based navigation
|
||||
- `get_chapters()` to list available chapters
|
||||
- Quick access to any part of the book
|
||||
|
||||
### 4. Bookmarks & Positions (`ereader_bookmarks.gif`)
|
||||
Illustrates the bookmark system: navigating to a position, saving it, navigating away, and then returning to the saved position.
|
||||
|
||||
**Features shown:**
|
||||
- `save_position(name)` to bookmark current location
|
||||
- `load_position(name)` to return to saved bookmark
|
||||
- Position stability across navigation
|
||||
- Multiple bookmark support
|
||||
|
||||
## Generating Your Own GIFs
|
||||
|
||||
To generate these animations with your own EPUB file:
|
||||
|
||||
```bash
|
||||
cd examples
|
||||
python generate_ereader_gifs.py path/to/your/book.epub gifs/
|
||||
```
|
||||
|
||||
This will create all four GIF animations in the specified output directory.
|
||||
|
||||
### Script Options
|
||||
|
||||
```python
|
||||
python generate_ereader_gifs.py <epub_path> [output_dir]
|
||||
```
|
||||
|
||||
- `epub_path`: Path to your EPUB file (required)
|
||||
- `output_dir`: Directory to save GIFs (default: current directory)
|
||||
|
||||
### Customization
|
||||
|
||||
You can modify `generate_ereader_gifs.py` to adjust:
|
||||
- Frame duration (`duration` parameter in `create_gif()`)
|
||||
- Page dimensions (change `page_size` in `EbookReader`)
|
||||
- Number of frames for each animation
|
||||
- Font scale ranges
|
||||
- Animation sequences
|
||||
|
||||
## Technical Details
|
||||
|
||||
- **Format**: Animated GIF
|
||||
- **Page Size**: 600x800 pixels
|
||||
- **Frame Rate**: Variable (500-1000ms per frame)
|
||||
- **Loop**: Infinite
|
||||
- **Book Used**: Alice's Adventures in Wonderland (test.epub)
|
||||
|
||||
## File Sizes
|
||||
|
||||
| GIF | Size | Frames | Duration per Frame |
|
||||
|-----|------|--------|-------------------|
|
||||
| `ereader_page_navigation.gif` | ~500 KB | 10 | 600ms |
|
||||
| `ereader_font_size.gif` | ~680 KB | 13 | 500ms |
|
||||
| `ereader_chapter_navigation.gif` | ~290 KB | 11 | 1000ms |
|
||||
| `ereader_bookmarks.gif` | ~500 KB | 17 | 600ms |
|
||||
|
||||
## Usage in Documentation
|
||||
|
||||
These GIFs are embedded in the main [README.md](../../README.md) to showcase the EbookReader's capabilities to potential users.
|
||||
|
||||
To embed in Markdown:
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
To embed in HTML with size control:
|
||||
```html
|
||||
<img src="examples/gifs/ereader_page_navigation.gif" width="300" alt="Page Navigation">
|
||||
```
|
||||
Loading…
x
Reference in New Issue
Block a user