Migration of application to own repo
This commit is contained in:
@@ -0,0 +1,361 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Example: Word Selection and Highlighting
|
||||
|
||||
This example demonstrates how to:
|
||||
1. Query a pixel location to find a word
|
||||
2. Select a range of words between two points
|
||||
3. Highlight selected words by drawing overlays
|
||||
4. Handle tap gestures to select words
|
||||
|
||||
This is useful for:
|
||||
- Word definition lookup
|
||||
- Text highlighting/annotation
|
||||
- Copy/paste functionality
|
||||
- Interactive reading features
|
||||
"""
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
import numpy as np
|
||||
|
||||
from pyweblayout_ereader import EbookReader
|
||||
from pyWebLayout.io.gesture import TouchEvent, GestureType
|
||||
from pyWebLayout.core.query import QueryResult
|
||||
|
||||
|
||||
def draw_highlight(image: Image.Image, bounds: tuple, color: tuple = (255, 255, 0, 100)):
|
||||
"""
|
||||
Draw a highlight overlay on an image at the given bounds.
|
||||
|
||||
Args:
|
||||
image: PIL Image to draw on
|
||||
bounds: (x, y, width, height) tuple
|
||||
color: RGBA color tuple (with alpha for transparency)
|
||||
"""
|
||||
# Create a semi-transparent overlay
|
||||
overlay = Image.new('RGBA', image.size, (255, 255, 255, 0))
|
||||
draw = ImageDraw.Draw(overlay)
|
||||
|
||||
x, y, w, h = bounds
|
||||
# Draw rectangle with rounded corners for nicer appearance
|
||||
draw.rectangle([x, y, x + w, y + h], fill=color)
|
||||
|
||||
# Composite the overlay onto the original image
|
||||
image = Image.alpha_composite(image.convert('RGBA'), overlay)
|
||||
return image
|
||||
|
||||
|
||||
def example_1_single_word_selection():
|
||||
"""Example 1: Select and highlight a single word by tapping"""
|
||||
print("=" * 60)
|
||||
print("Example 1: Single Word Selection")
|
||||
print("=" * 60)
|
||||
|
||||
# Create reader and load a book
|
||||
reader = EbookReader(page_size=(800, 1000))
|
||||
success = reader.load_epub("tests/data/test.epub")
|
||||
|
||||
if not success:
|
||||
print("Failed to load EPUB")
|
||||
return
|
||||
|
||||
print(f"Loaded: {reader.book_title} by {reader.book_author}")
|
||||
|
||||
# Get current page as image
|
||||
page_img = reader.get_current_page()
|
||||
if not page_img:
|
||||
print("No page rendered")
|
||||
return
|
||||
|
||||
# Simulate a tap at coordinates (200, 300)
|
||||
tap_x, tap_y = 200, 300
|
||||
print(f"\nSimulating tap at ({tap_x}, {tap_y})")
|
||||
|
||||
# Query what's at that location
|
||||
result = reader.query_pixel(tap_x, tap_y)
|
||||
|
||||
if result and result.text:
|
||||
print(f"Found word: '{result.text}'")
|
||||
print(f"Type: {result.object_type}")
|
||||
print(f"Bounds: {result.bounds}")
|
||||
print(f"Is interactive: {result.is_interactive}")
|
||||
|
||||
# Highlight the word
|
||||
highlighted_img = draw_highlight(page_img, result.bounds, color=(255, 255, 0, 80))
|
||||
highlighted_img.save("output_single_word_highlight.png")
|
||||
print(f"\nSaved highlighted image to: output_single_word_highlight.png")
|
||||
else:
|
||||
print("No word found at that location")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
def example_2_range_selection():
|
||||
"""Example 2: Select and highlight a range of words (text selection)"""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Range Selection (Multi-word)")
|
||||
print("=" * 60)
|
||||
|
||||
# Create reader and load a book
|
||||
reader = EbookReader(page_size=(800, 1000))
|
||||
success = reader.load_epub("tests/data/test.epub")
|
||||
|
||||
if not success:
|
||||
print("Failed to load EPUB")
|
||||
return
|
||||
|
||||
# Get current page
|
||||
page_img = reader.get_current_page()
|
||||
if not page_img:
|
||||
return
|
||||
|
||||
# Simulate dragging from (100, 200) to (400, 250)
|
||||
start_x, start_y = 100, 200
|
||||
end_x, end_y = 400, 250
|
||||
|
||||
print(f"Simulating selection from ({start_x}, {start_y}) to ({end_x}, {end_y})")
|
||||
|
||||
# Create drag gesture events
|
||||
drag_start = TouchEvent(GestureType.DRAG_START, start_x, start_y)
|
||||
drag_move = TouchEvent(GestureType.DRAG_MOVE, end_x, end_y)
|
||||
drag_end = TouchEvent(GestureType.DRAG_END, end_x, end_y)
|
||||
|
||||
# Handle the gesture (business logic)
|
||||
reader.handle_touch(drag_start)
|
||||
reader.handle_touch(drag_move)
|
||||
response = reader.handle_touch(drag_end)
|
||||
|
||||
if response.action == "selection_complete":
|
||||
selected_text = response.data.get('text', '')
|
||||
bounds_list = response.data.get('bounds', [])
|
||||
word_count = response.data.get('word_count', 0)
|
||||
|
||||
print(f"\nSelected {word_count} words:")
|
||||
print(f"Text: \"{selected_text}\"")
|
||||
|
||||
# Highlight all selected words
|
||||
highlighted_img = page_img
|
||||
for bounds in bounds_list:
|
||||
highlighted_img = draw_highlight(
|
||||
highlighted_img,
|
||||
bounds,
|
||||
color=(100, 200, 255, 80) # Light blue highlight
|
||||
)
|
||||
|
||||
highlighted_img.save("output_range_highlight.png")
|
||||
print(f"\nSaved highlighted image to: output_range_highlight.png")
|
||||
else:
|
||||
print(f"Selection action: {response.action}")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
def example_3_interactive_word_lookup():
|
||||
"""Example 3: Interactive word lookup with gesture handling"""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 3: Interactive Word Lookup (with Gestures)")
|
||||
print("=" * 60)
|
||||
|
||||
# Create reader
|
||||
reader = EbookReader(page_size=(800, 1000))
|
||||
success = reader.load_epub("tests/data/test.epub")
|
||||
|
||||
if not success:
|
||||
print("Failed to load EPUB")
|
||||
return
|
||||
|
||||
# Get page
|
||||
page_img = reader.get_current_page()
|
||||
if not page_img:
|
||||
return
|
||||
|
||||
# Define some simulated touch events
|
||||
test_gestures = [
|
||||
("Tap at (250, 300)", TouchEvent(GestureType.TAP, 250, 300)),
|
||||
("Long press at (250, 300)", TouchEvent(GestureType.LONG_PRESS, 250, 300)),
|
||||
("Swipe left", TouchEvent(GestureType.SWIPE_LEFT, 600, 500)),
|
||||
]
|
||||
|
||||
for description, event in test_gestures:
|
||||
print(f"\n{description}:")
|
||||
response = reader.handle_touch(event)
|
||||
print(f" Action: {response.action}")
|
||||
|
||||
if response.action == "word_selected":
|
||||
word = response.data.get('word', '')
|
||||
bounds = response.data.get('bounds', (0, 0, 0, 0))
|
||||
print(f" Selected word: '{word}'")
|
||||
print(f" Bounds: {bounds}")
|
||||
|
||||
# Highlight the word
|
||||
highlighted_img = draw_highlight(page_img, bounds, color=(255, 200, 0, 100))
|
||||
filename = f"output_word_lookup_{word}.png"
|
||||
highlighted_img.save(filename)
|
||||
print(f" Saved: {filename}")
|
||||
|
||||
elif response.action == "define":
|
||||
word = response.data.get('word', '')
|
||||
print(f" Show definition for: '{word}'")
|
||||
# In real app, you'd call a dictionary API here
|
||||
|
||||
elif response.action == "page_turn":
|
||||
direction = response.data.get('direction', '')
|
||||
progress = response.data.get('progress', 0)
|
||||
print(f" Page turn {direction}, progress: {progress:.1%}")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
def example_4_multi_word_annotation():
|
||||
"""Example 4: Annotate multiple words with different colors"""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 4: Multi-word Annotation")
|
||||
print("=" * 60)
|
||||
|
||||
# Create reader
|
||||
reader = EbookReader(page_size=(800, 1000))
|
||||
success = reader.load_epub("tests/data/test.epub")
|
||||
|
||||
if not success:
|
||||
print("Failed to load EPUB")
|
||||
return
|
||||
|
||||
# Get page
|
||||
page_img = reader.get_current_page()
|
||||
if not page_img:
|
||||
return
|
||||
|
||||
# Simulate multiple taps at different locations
|
||||
tap_locations = [
|
||||
(150, 200, "Important word", (255, 100, 100, 80)), # Red
|
||||
(300, 200, "Key concept", (100, 255, 100, 80)), # Green
|
||||
(450, 200, "Notable term", (100, 100, 255, 80)), # Blue
|
||||
]
|
||||
|
||||
annotated_img = page_img
|
||||
annotations = []
|
||||
|
||||
for x, y, label, color in tap_locations:
|
||||
result = reader.query_pixel(x, y)
|
||||
|
||||
if result and result.text:
|
||||
print(f"\nFound word at ({x}, {y}): '{result.text}'")
|
||||
print(f" Annotation: {label}")
|
||||
|
||||
# Highlight with specific color
|
||||
annotated_img = draw_highlight(annotated_img, result.bounds, color)
|
||||
|
||||
annotations.append({
|
||||
'word': result.text,
|
||||
'label': label,
|
||||
'bounds': result.bounds
|
||||
})
|
||||
|
||||
# Save annotated image
|
||||
annotated_img.save("output_multi_annotation.png")
|
||||
print(f"\nSaved annotated image with {len(annotations)} highlights")
|
||||
print("File: output_multi_annotation.png")
|
||||
|
||||
# Print annotation summary
|
||||
print("\nAnnotation Summary:")
|
||||
for i, ann in enumerate(annotations, 1):
|
||||
print(f" {i}. '{ann['word']}' - {ann['label']}")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
def example_5_link_highlighting():
|
||||
"""Example 5: Find and highlight all links on a page"""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 5: Find and Highlight All Links")
|
||||
print("=" * 60)
|
||||
|
||||
# Create reader
|
||||
reader = EbookReader(page_size=(800, 1000))
|
||||
success = reader.load_epub("tests/data/test.epub")
|
||||
|
||||
if not success:
|
||||
print("Failed to load EPUB")
|
||||
return
|
||||
|
||||
# Get page
|
||||
page_img = reader.get_current_page()
|
||||
if not page_img:
|
||||
return
|
||||
|
||||
# Get the page object to scan for links
|
||||
page = reader.manager.get_current_page()
|
||||
|
||||
# Scan through all rendered content to find links
|
||||
links_found = []
|
||||
from pyWebLayout.concrete.text import Line
|
||||
from pyWebLayout.concrete.functional import LinkText
|
||||
|
||||
for child in page._children:
|
||||
if isinstance(child, Line):
|
||||
for text_obj in child._text_objects:
|
||||
if isinstance(text_obj, LinkText):
|
||||
origin = text_obj._origin
|
||||
size = text_obj.size
|
||||
bounds = (
|
||||
int(origin[0]),
|
||||
int(origin[1]),
|
||||
int(size[0]),
|
||||
int(size[1])
|
||||
)
|
||||
links_found.append({
|
||||
'text': text_obj._text,
|
||||
'target': text_obj._link.location,
|
||||
'bounds': bounds
|
||||
})
|
||||
|
||||
print(f"Found {len(links_found)} links on page")
|
||||
|
||||
# Highlight all links
|
||||
highlighted_img = page_img
|
||||
for link in links_found:
|
||||
print(f"\nLink: '{link['text']}' → {link['target']}")
|
||||
highlighted_img = draw_highlight(
|
||||
highlighted_img,
|
||||
link['bounds'],
|
||||
color=(0, 150, 255, 100) # Blue for links
|
||||
)
|
||||
|
||||
if links_found:
|
||||
highlighted_img.save("output_links_highlighted.png")
|
||||
print(f"\nSaved image with {len(links_found)} highlighted links")
|
||||
print("File: output_links_highlighted.png")
|
||||
else:
|
||||
print("\nNo links found on this page")
|
||||
|
||||
reader.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Word Selection and Highlighting Examples")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print("These examples demonstrate the query system for:")
|
||||
print("- Single word selection")
|
||||
print("- Range selection (multiple words)")
|
||||
print("- Interactive gesture handling")
|
||||
print("- Multi-word annotation")
|
||||
print("- Link detection and highlighting")
|
||||
print()
|
||||
|
||||
try:
|
||||
# Run all examples
|
||||
example_1_single_word_selection()
|
||||
example_2_range_selection()
|
||||
example_3_interactive_word_lookup()
|
||||
example_4_multi_word_annotation()
|
||||
example_5_link_highlighting()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("All examples completed successfully!")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError running examples: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
Reference in New Issue
Block a user