mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-02 15:47:19 +00:00
Some checks failed
Build and push containers / metadata (push) Has been cancelled
Build and push containers / build-push-containers (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built 📦 package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
ChangeDetection.io Container Build Test / test-container-build (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
74 lines
2.7 KiB
Python
74 lines
2.7 KiB
Python
# Pages with a vertical height longer than this will use the 'stitch together' method.
|
||
|
||
# - Many GPUs have a max texture size of 16384x16384px (or lower on older devices).
|
||
# - If a page is taller than ~8000–10000px, it risks exceeding GPU memory limits.
|
||
# - This is especially important on headless Chromium, where Playwright may fail to allocate a massive full-page buffer.
|
||
|
||
from loguru import logger
|
||
|
||
from changedetectionio.content_fetchers import SCREENSHOT_MAX_HEIGHT_DEFAULT, SCREENSHOT_DEFAULT_QUALITY
|
||
|
||
|
||
def stitch_images_worker(pipe_conn, chunks_bytes, original_page_height, capture_height):
|
||
import os
|
||
import io
|
||
from PIL import Image, ImageDraw, ImageFont
|
||
|
||
try:
|
||
|
||
# Load images from byte chunks
|
||
images = [Image.open(io.BytesIO(b)) for b in chunks_bytes]
|
||
total_height = sum(im.height for im in images)
|
||
max_width = max(im.width for im in images)
|
||
|
||
# Create stitched image
|
||
stitched = Image.new('RGB', (max_width, total_height))
|
||
y_offset = 0
|
||
for im in images:
|
||
stitched.paste(im, (0, y_offset))
|
||
y_offset += im.height
|
||
|
||
# Draw caption on top (overlaid, not extending canvas)
|
||
draw = ImageDraw.Draw(stitched)
|
||
|
||
if original_page_height > capture_height:
|
||
caption_text = f"WARNING: Screenshot was {original_page_height}px but trimmed to {capture_height}px because it was too long"
|
||
padding = 10
|
||
font_size = 35
|
||
font_color = (255, 0, 0)
|
||
background_color = (255, 255, 255)
|
||
|
||
|
||
# Try to load a proper font
|
||
try:
|
||
font = ImageFont.truetype("arial.ttf", font_size)
|
||
except IOError:
|
||
font = ImageFont.load_default()
|
||
|
||
bbox = draw.textbbox((0, 0), caption_text, font=font)
|
||
text_width = bbox[2] - bbox[0]
|
||
text_height = bbox[3] - bbox[1]
|
||
|
||
# Draw white rectangle background behind text
|
||
rect_top = 0
|
||
rect_bottom = text_height + 2 * padding
|
||
draw.rectangle([(0, rect_top), (max_width, rect_bottom)], fill=background_color)
|
||
|
||
# Draw text centered horizontally, 10px padding from top of the rectangle
|
||
text_x = (max_width - text_width) // 2
|
||
text_y = padding
|
||
draw.text((text_x, text_y), caption_text, font=font, fill=font_color)
|
||
|
||
# Encode and send image
|
||
output = io.BytesIO()
|
||
stitched.save(output, format="JPEG", quality=int(os.getenv("SCREENSHOT_QUALITY", SCREENSHOT_DEFAULT_QUALITY)))
|
||
pipe_conn.send_bytes(output.getvalue())
|
||
|
||
stitched.close()
|
||
except Exception as e:
|
||
pipe_conn.send(f"error:{e}")
|
||
finally:
|
||
pipe_conn.close()
|
||
|
||
|