From bde846bc3ee4893c0bd76bf6582914f32012a222 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Thu, 6 Nov 2025 17:58:35 +0100 Subject: [PATCH] example in use --- README.md | 44 +++- ereader_bookmarks/test_bookmarks.json | 12 ++ ereader_bookmarks/test_position.json | 10 + examples/generate_ereader_gifs.py | 286 ++++++++++++++++++++++++++ examples/gifs/README.md | 100 +++++++++ 5 files changed, 446 insertions(+), 6 deletions(-) create mode 100644 ereader_bookmarks/test_bookmarks.json create mode 100644 ereader_bookmarks/test_position.json create mode 100644 examples/generate_ereader_gifs.py create mode 100644 examples/gifs/README.md diff --git a/README.md b/README.md index e83a7f3..ec187a1 100644 --- a/README.md +++ b/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: + + + + + + + + + + +
+ Page Navigation
+ Page Navigation
+ Forward and backward navigation through pages +
+ Font Size Adjustment
+ Font Size
+ Dynamic font size scaling with position preservation +
+ Chapter Navigation
+ Chapter Navigation
+ Jump directly to chapters by title or index +
+ Bookmarks & Positions
+ Bookmarks
+ Save and restore reading positions anywhere in the book +
+ ### 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 diff --git a/ereader_bookmarks/test_bookmarks.json b/ereader_bookmarks/test_bookmarks.json new file mode 100644 index 0000000..3d85313 --- /dev/null +++ b/ereader_bookmarks/test_bookmarks.json @@ -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 + } +} \ No newline at end of file diff --git a/ereader_bookmarks/test_position.json b/ereader_bookmarks/test_position.json new file mode 100644 index 0000000..526dc5f --- /dev/null +++ b/ereader_bookmarks/test_position.json @@ -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 +} \ No newline at end of file diff --git a/examples/generate_ereader_gifs.py b/examples/generate_ereader_gifs.py new file mode 100644 index 0000000..94383dc --- /dev/null +++ b/examples/generate_ereader_gifs.py @@ -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() diff --git a/examples/gifs/README.md b/examples/gifs/README.md new file mode 100644 index 0000000..5a5d500 --- /dev/null +++ b/examples/gifs/README.md @@ -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 [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 +![Page Navigation](examples/gifs/ereader_page_navigation.gif) +``` + +To embed in HTML with size control: +```html +Page Navigation +```