Skip to content

Accept SVG marker uploads via cairosvg rasterisation (#804)#945

Open
vjpixel wants to merge 1 commit into
developfrom
claude/fix-804-svg-marker
Open

Accept SVG marker uploads via cairosvg rasterisation (#804)#945
vjpixel wants to merge 1 commit into
developfrom
claude/fix-804-svg-marker

Conversation

@vjpixel
Copy link
Copy Markdown
Member

@vjpixel vjpixel commented Apr 25, 2026

Summary

Marker.source is a Django ImageField, so its form-level validation delegated to Pillow — and Pillow can't open SVG. Any user trying to upload an SVG hit "Upload a valid image" before any of our own code ran.

Override UploadMarkerForm.source with a plain FileField so the strict ImageField check is bypassed, and run our own validation in clean_source:

  • SVG: rasterise to PNG with cairosvg at 1024 px width and hand the rest of the pipeline (pymarker, storage) the PNG.
  • Everything else: run Pillow's verify() to reject non-image uploads with our own message.

JPG was already accepted (Pillow opens JPG natively) — the issue's main practical blocker was SVG.

Verified locally

Upload Result
test.svg (rect 100×100) accepted; cleaned file is test.png, 3147 bytes
test.jpg accepted unchanged
foo.pdf rejected with "Upload a valid image"

Dependencies

  • cairosvg ~= 2.7 added to pyproject.toml.
  • libcairo2 added to the Dockerfile's base apt-get install (cairosvg needs libcairo at runtime).

Test plan

  • Upload a real-world SVG (e.g. simple logo) as a marker → preview shows the marker generated from the rasterised PNG, no error.
  • Upload PNG/JPG/GIF still works.
  • Upload a PDF or text file → rejected with the friendly error.

Closes #804

https://claude.ai/code/session_01XC1THLWgnGXGf5wgRhdyvB


Generated by Claude Code

Marker.source is an ImageField, so its form-level validation
delegated to Pillow — and Pillow can't open SVG. Anyone trying
to upload an SVG hit "Upload a valid image" before any of our
own code ran.

Override UploadMarkerForm.source as a plain FileField so the
ImageField check is bypassed, and validate ourselves in
clean_source:

- For .svg, rasterise to PNG via cairosvg at 1024 px wide and
  hand the rest of the pipeline (pymarker, storage) the PNG.
- For everything else, run Pillow's own verify() to reject
  non-images with our own message.

Verified manually:
- SVG (rect 100x100) → cleaned file is test.png, 3147 bytes
- JPG → accepted unchanged
- PDF → rejected with "Upload a valid image"

Adds:
- cairosvg ~2.7 to project dependencies
- libcairo2 to the Dockerfile base apt-get install (cairosvg
  needs libcairo at runtime)

JPG support was already working (Pillow opens JPG natively); the
issue's main blocker was SVG.

Closes #804

https://claude.ai/code/session_01XC1THLWgnGXGf5wgRhdyvB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

We should be able to upload JPG and SVG files to create markers

2 participants