Compare commits

...

2 Commits

Author SHA1 Message Date
Chris Coutinho 34fd17ba55 fix: Use alpha_composite for proper RGBA highlight blending
Drawing directly with ImageDraw on RGBA mode doesn't blend alpha
properly. Use Image.alpha_composite() with a transparent overlay
to achieve correct semi-transparent highlight fills.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 17:04:29 +01:00
Chris Coutinho 8baa07db84 fix: Remove pymupdf.layout.activate() to fix page_chunks behavior
pymupdf.layout.activate() causes pymupdf4llm.to_markdown() to ignore the
page_chunks=True option, returning a single string instead of list[dict].
This broke per-page chunking needed for semantic search indexing.

See: https://github.com/pymupdf/pymupdf4llm/issues/323

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 16:58:35 +01:00
3 changed files with 18 additions and 11 deletions
+1
View File
@@ -18,6 +18,7 @@ RUN uv sync --locked --no-dev --no-editable --no-cache
ENV PYTHONUNBUFFERED=1
ENV VIRTUAL_ENV=/app/.venv
ENV PATH=/app/.vnev/bin:$PATH
ENV TESSDATA_PREFIX=/usr/share/tesseract-ocr/5/tessdata
ENTRYPOINT ["/app/.venv/bin/nextcloud-mcp-server", "--host", "0.0.0.0"]
@@ -6,15 +6,15 @@ import tempfile
from collections.abc import Awaitable, Callable
from typing import Any, Optional
# NOTE: Do NOT call pymupdf.layout.activate() here!
# It changes the behavior of pymupdf4llm.to_markdown() when page_chunks=True,
# causing it to return a string instead of a list[dict].
# See: https://github.com/pymupdf/pymupdf4llm/issues/323
import pymupdf
import pymupdf.layout
import pymupdf4llm
from .base import DocumentProcessor, ProcessingResult, ProcessorError
# Activate layout analysis for better text extraction
pymupdf.layout.activate()
import pymupdf4llm # noqa
logger = logging.getLogger(__name__)
+12 -6
View File
@@ -845,9 +845,8 @@ class PDFHighlighter:
logger.warning(f"Chunk {chunk_index}: could not find bbox")
continue
# Copy base image and draw highlight using PIL (fast!)
# Copy base image for this chunk
chunk_image = base_image.copy()
draw = ImageDraw.Draw(chunk_image, "RGBA")
# Scale bbox coordinates to pixmap coordinates
scale_x = base_pix.width / page_rect.width
@@ -859,10 +858,17 @@ class PDFHighlighter:
int(bbox[3] * scale_y),
)
# Draw semi-transparent fill
draw.rectangle(pil_bbox, fill=fill_color)
# Draw dashed border (PIL doesn't support dashes, use solid)
draw.rectangle(pil_bbox, outline=pil_color, width=3)
# Create transparent overlay for fill (proper alpha blending)
overlay = Image.new("RGBA", chunk_image.size, (0, 0, 0, 0))
overlay_draw = ImageDraw.Draw(overlay)
overlay_draw.rectangle(pil_bbox, fill=fill_color)
# Alpha composite the overlay onto the chunk image
chunk_image = Image.alpha_composite(chunk_image, overlay)
# Draw border on top (solid, not transparent)
border_draw = ImageDraw.Draw(chunk_image)
border_draw.rectangle(pil_bbox, outline=pil_color, width=3)
# Convert back to PNG bytes
output = BytesIO()