Image pipeline: resize + compress on upload #26

Open
opened 2026-05-13 21:38:52 +02:00 by arne · 0 comments
Owner

Why

`POST /api/v1/uploads` (#22) stores bytes verbatim with a 10 MiB cap.
Phones routinely produce 4-12 MP photos that are 3-6 MiB even encoded
as JPEG; recipients on mobile data pay for that bandwidth twice
(uploader pushes, recipient pulls). A server-side pipeline that:

  1. Decodes JPEG/PNG → `image.Image`.
  2. Resizes the long edge to a sensible cap (1600px? 2048px?).
  3. Re-encodes as JPEG at quality ~80.

…would bring typical photo uploads to ~200-500 KiB without visible
quality loss in chat.

Scope considerations

  • Only applies to images (the only thing accepted today). If the
    pipeline opens up to other media (e.g. video, PDFs) later, the
    encoder selection becomes per-mediatype.
  • Re-encoding invalidates the content hash: the URL the API returns
    reflects the post-pipeline bytes, not the uploaded bytes. Clients
    must use the response URL — they already do.
  • Strip EXIF as part of the same pass (related issue: EXIF stripping).
    A decode/re-encode round-trip drops most metadata for free, but
    belt-and-suspenders is fine.
  • Probably want to keep the original 10 MiB request cap but document
    that the stored file will be smaller.

Out of scope

  • HEIC support on the server (clients transcode to JPEG before upload).
  • Animated formats (no GIF/APNG accepted today).
  • Video.

Acceptance

  • A 4000x3000 JPEG uploaded at 5 MiB is stored at ≤500 KiB and ≤2048px
    long edge.
  • A small image (under the resize threshold) passes through with
    quality preserved.
  • Test fixtures cover the resize threshold and the quality target.

Related: #22.

### Why \`POST /api/v1/uploads\` (#22) stores bytes verbatim with a 10 MiB cap. Phones routinely produce 4-12 MP photos that are 3-6 MiB even encoded as JPEG; recipients on mobile data pay for that bandwidth twice (uploader pushes, recipient pulls). A server-side pipeline that: 1. Decodes JPEG/PNG → \`image.Image\`. 2. Resizes the long edge to a sensible cap (1600px? 2048px?). 3. Re-encodes as JPEG at quality ~80. …would bring typical photo uploads to ~200-500 KiB without visible quality loss in chat. ### Scope considerations - Only applies to images (the only thing accepted today). If the pipeline opens up to other media (e.g. video, PDFs) later, the encoder selection becomes per-mediatype. - Re-encoding invalidates the content hash: the URL the API returns reflects the *post-pipeline* bytes, not the uploaded bytes. Clients must use the response URL — they already do. - Strip EXIF as part of the same pass (related issue: EXIF stripping). A decode/re-encode round-trip drops most metadata for free, but belt-and-suspenders is fine. - Probably want to keep the original 10 MiB request cap but document that the *stored* file will be smaller. ### Out of scope - HEIC support on the server (clients transcode to JPEG before upload). - Animated formats (no GIF/APNG accepted today). - Video. ### Acceptance - A 4000x3000 JPEG uploaded at 5 MiB is stored at ≤500 KiB and ≤2048px long edge. - A small image (under the resize threshold) passes through with quality preserved. - Test fixtures cover the resize threshold and the quality target. Related: #22.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
posta/server#26
No description provided.