174 Commits
Author SHA1 Message Date
Viktor Scharf ae4970d92c chore: bump reva to 2.52.0 (#3820) 2026-10-27 12:46:43 +01:00
André Duffeck a2d729bb06 Hold a 0x0 box to the maximum thumbnail size as well
0x0 returns the source at its own size, which skipped the check and let anything up to the input limit through.
2026-10-26 09:34:30 +01:00
André Duffeck 481cd40646 Hold a free thumbnail axis to the maximum thumbnail size
A box like 0x2048 passed the check, and the aspect ratio of a very wide source then sized the other side without a bound.
2026-10-23 14:15:51 +02:00
Dominik Schmidt 6d7dd34f1c fix(thumbnails): apply an embedded color profile in the pure Go build
png.Decode and gif.Decode hand back the source colors untouched, so a wide gamut image came out oversaturated where a jpeg, read through imaging, was converted. Real imagor passes the profile on to the client instead.
2026-10-21 12:22:25 +02:00
Dominik Schmidt 9c327dc34a docs: let the comments say what the code does, not what it used to do
A comment that explains a decision by what another branch or the previous service did stops being true the moment this merges.
2026-10-20 20:22:10 +02:00
Dominik Schmidt c6ac8748d8 refactor: name the thumbnail settings after the service, THUMBNAILS
The service is thumbnails and its released variables say so; the new ones said THUMBNAIL. None of them has shipped yet, so they are renamed rather than aliased. The input file size gains the shared OC_THUMBNAILS_ name, because webdav and the generator have to agree on it.
2026-10-20 18:08:34 +02:00
Dominik Schmidt 575a17967f fix(thumbnails): decode one frame of a png asked for as a still
An animated png carried every frame through imaging.Decode, which only the gif path guarded: a 465 KB file with 200 full-canvas frames allocated 226 MB, now 10 MB. png.Decode reads IDAT and ignores an animation's fdAT chunks.
2026-10-20 17:58:01 +02:00
Dominik Schmidt 951917e87f test(thumbnails): hand every limit to imagor in the parity suite
imagor's own defaults are looser, so a difference could pass as agreement. With the frame limit set it truncates the animation where the built-in refuses the file, which the override now records.
2026-10-20 17:45:45 +02:00
Dominik Schmidt 0070f031fa fix(thumbnails): give the thumbnail size its own ceiling
The source ceiling had to stand in for the box a request may ask for, two limits with different reasons under one name. webdav decides the preview size and never asks for more than its largest resolution; this is the net for everything else.
2026-10-20 17:37:58 +02:00
Dominik Schmidt 9b9b5ab6a2 Revert "fix(thumbnails): cap the box a request may ask for at 2048 per axis"
This reverts commit 89b5bdf964.
2026-10-20 16:55:57 +02:00
Dominik Schmidt 89b5bdf964 fix(thumbnails): cap the box a request may ask for at 2048 per axis
Only the source was bounded, while fill and stretch upscale, so a tiny image asked for at 7680 allocated accordingly. The pixel budget for animations and webdav's ladder above this are a follow-up.
2026-10-20 16:06:30 +02:00
Dominik Schmidt 97e8031935 fix(thumbnails): take a slot once the image is in, not before
The slots bound the decoding and the resizing, so a slow upload no longer occupies one while nothing is being computed.
2026-10-20 16:05:34 +02:00
Dominik Schmidt e871ebb64a fix(thumbnails): read the image part without the multipart form
The handler holds the whole image in memory to decode it; the form kept a second copy, on disk for anything past its memory limit, for no gain.
2026-10-20 16:03:42 +02:00
Dominik Schmidt 3ff5a34ceb fix(thumbnails): decode one frame of a gif asked for as a still
imaging.Decode is DecodeAll plus SingleFrame, so a gif renamed to .png held every frame in memory; the frame limit only guards the gif output path.
2026-10-20 14:58:31 +02:00
Dominik Schmidt 48f9990a41 fix(webdav): ask the generator for the smart crop
A cropping resize now carries imagor's smart segment, which is how the libvips
build and a real imagor keep the region that carries the image, the way main
cropped before the generator moved out. A build without libvips answers the
same request with a centre crop, and the parity suite records that.
2026-10-19 14:57:36 +02:00
Dominik Schmidt c980083938 docs: say less in the comments, and name what matchOperation returns 2026-10-19 14:57:36 +02:00
Dominik Schmidt 999ad6fb7c fix: answer the review from @orgaralf
Both builds and imagor now crop the same region, a gif is bounded by its
declared frames, the posted body by THUMBNAILS_MAX_INPUT_IMAGE_FILE_SIZE and an
image extracted from a container by the configured input size. The s3 cache
reads a miss where minio reports it.

The push endpoint's HTTP behaviour is asserted in the parity suite now, where
imagor answers the same request, so 41 duplicated service specs are gone and
the 32 that remain are what a non-default config or a helper decides.
2026-10-19 14:57:36 +02:00
Dominik Schmidt 4da8971ca7 docs: say what the code does, in the places that still described something else
The aspect-ignored header blamed a processor for a decision the free axis can make too. fit-in does not letterbox, it answers smaller than the box. The s3 cache checks bucket, region and credentials, not the endpoint. A mapping onto a type the generator cannot write is refused at startup instead of quietly becoming a JPEG. And a processor name nobody knows resolves like none, which three comments and a readme line still denied.
2026-10-19 14:57:35 +02:00
Dominik Schmidt e981a06f87 refactor(thumbnails): one table for the output formats, one fit-in
The four writable formats were a whitelist in the filter parser and a second list of content types in the encode step; they are one map now, so a format nobody writes stays a 400 and one without an encoder in this build stays a 406. The fit-in shape existed twice since the gif loop started rounding like vips, it lives in box.go now. And the push routes are back inline: mountPushRoutes only existed so a test mux could not drift from them, and the specs go through the real NewService instead.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 1da9fa8013 fix: answer the third review round
With previews off a thumbnail path answered 405, because the REPORT patterns match the same paths and the GET routes were left out; the routes stay now and the shared parse step answers 404, which is what the setting promises. The deprecated cache directory is read again: its default no longer sits in the config struct, where it made the fallback unreachable. A processor nobody knows is treated like none, in the parser too. A comma-joined resolutions entry in yaml keeps working. Plus the comments and the readme line that described something else than the code does.
2026-10-19 14:57:35 +02:00
Dominik Schmidt c5c5ec2e2c refactor(webdav): own the list of types a preview is announced for
The thumbnails service kept a single map of supported mime types that nothing in that service used any more, only webdav read it, and the comment still claimed reva reads it there. It is webdav's announcement, so DefaultSourceTypes lives next to SourceTypes now, the leftover package is gone, and no webdav file imports the thumbnails service any longer.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 67856fdf6d fix: the small things the review left over
A processor that needs the whole box is not a cropping one, so targetsExactBox says what it decides. An output format without an encoder answers 406 like every other thing this build cannot write. The configured defaults are no longer seeded twice, the constructors merge them anyway, like they do for the source types. And webp needs no build tag: both builds read it, the pure Go one answers the JPEG the mapping asks for, which the parity suite pins.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 18c5d726db refactor(thumbnails): let the backend answer for the image it decodes
The dimension guard and the input-format detection used Go's decoder registry in both builds, so with libvips they were silently skipped for everything Go cannot read, and a webp source came back as a JPEG where imagor keeps it a webp. Each build now reads the header with the library that will decode the image, the guard runs on that, and the animated gif path is shared instead of living in both encoders. The hook names stay per build, the function variables are typed per build, so the any and its seven type assertions are gone.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 3572410fc4 fix: answer the review, and read imagor's path the way imagor does
The push endpoint takes an empty filters segment, ignores an image key behind the box and computes a side given as 0 from the other one, all measured against both imagors and pinned in the parity suite. Plus the review leftovers: no em dashes, the request test on ginkgo, comments that contradicted the code, one stat for Head and generate, one thumbnail handler, the gif fit-in rounding of vips, and the new env names last so they win.
2026-10-19 14:57:35 +02:00
Dominik Schmidt eb6d1021a3 test(thumbnails): put the push endpoint on ginkgo
The repeated post-and-assert bodies collapse into tables, and the sources
are built without gomega because they run while the spec tree is built.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 9b4e173020 test(thumbnails): compare the built-in generator against two real imagors
The same image goes to the built-in generator and to both imagor images,
and status, dimensions, format, frames and alpha are compared. A generator
that answers differently is held to that answer by a recorded override, so
the test fails once the divergence disappears. It runs once per resize
implementation, because make test builds the pure Go path while the images
ship vips.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 6c9dc28599 refactor: one gif resize, a request struct, half the routes
The gif loop is shared by both builds, the executor takes a request
struct, the route table halves, the aspect flag is a pointer instead of
two bools, and the cache's budget is named after what it is.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 2267b6d3bc fix(thumbnails): answer like imagor, and write what imagor writes
The upload part has to be typed, a malformed request is a 400 while a
source it cannot read is a 406, an animated gif flattens when the output
is still, a still source can be written as a gif, libvips writes webp, and
fit-in rounds the way vips and imagor round it.
2026-10-19 14:57:35 +02:00
Dominik Schmidt 4c0768cb83 fix(webdav): name the thumbnail config fields after what they configure
The yaml keys stay as they are, so a config file written against them keeps
working, and OC_DISABLE_PREVIEWS is back without disabling search.
2026-10-19 14:57:35 +02:00
Jörn Friedrich Dreyer 203708474e refactor(thumbnails): remove the pull-based pipeline
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2026-10-19 14:57:35 +02:00
Jörn Friedrich Dreyer 924d7428ed feat(thumbnails): add imagor-compatible push-based thumbnail endpoint
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2026-10-19 14:56:58 +02:00
Dominik Schmidt 65f19b5d71 fix(thumbnails): close rejected vips ref, map oversized convert error to forbidden 2026-09-08 15:28:37 +02:00
Dominik Schmidt 7f687ea288 fix(thumbnails): bound declared image dimensions before decoding
The imaging build decodes the full pixel buffer from the header-declared
dimensions before the existing MaxInputWidth/MaxInputHeight guard runs, so a
tiny crafted file whose header declares huge dimensions forces a multi-GB
allocation and can OOM the worker. Read the header with DecodeConfig and reject
oversized sources before the decode allocates, in both the imaging and vips
builds, and thread the limit through the audio cover-art and geogebra decoders
that decode a second attacker-controlled image.
2026-09-08 15:28:37 +02:00
Jannik Stehle ec4d5b7e6b Merge pull request #3386 from opencloud-eu/feat/extend-thumbnail-service-resolutions
feat(thumbnails): extend list of default resolutions
2026-08-21 14:03:23 +02:00
Jannik Stehle 1e5de6e01b feat(thumbnails): extend list of default resolutions
Extend the list by these resolutions:

"500x280", "280x500", "1000x560", "560x1000", "512x2048"

This allows for a more granular thumbnail generation for requested previews
between 128 and 1080 px.
2026-08-21 09:04:59 +02:00
Jannik Stehle d562d44edf fix(thumbnails): respect the requested height in libvips builds
The libvips generator passed 0 as the target height to vips_thumbnail,
so the value was rejected and dropped.

As a result, a preview of a 4000x5000 portrait image requested with e.g.
x=500&y=500 returned a ...x1920 image instead of a ...x1080 one, which
would be the next correct size in the pre-defined resolutions list. This
was due to the missing height, so it used the width (=1920) to determine
the longest side.

This also aligns it with the non-libvips behavior.
2026-08-20 19:11:28 +02:00
Ralf Haferkamp fab1986fb6 Revert "fix: disallow thumbnails for tiff and jpeg2000 images"
The alpine base images now has a fixed libvips. So we can enable
previews for these formats again.

This reverts commit c40629dd85.
2026-06-18 11:53:03 +02:00
Ralf Haferkamp c40629dd85 fix: disallow thumbnails for tiff and jpeg2000 images 2026-05-13 13:28:10 +02:00
Florian Schade d0e3f14539 chore: remove loop var references 2026-04-23 17:11:55 +02:00
Florian Schade 288e67cc39 chore: replace interface with any 2026-04-23 09:31:11 +02:00
Christian Richter 30c4fb2b51 consolidate log config in thumbnails
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2026-01-08 13:38:14 +01:00
Florian Schade 9c651af32d fix(thumbnailer): missing font panic 2025-12-31 12:17:11 +01:00
Florian Schade 01b768d33c fix(thumbnailer): respect image boundaries and text wrappings for TxtToImageConverter string drawing 2025-12-22 15:57:25 +01:00
Christian Richter 0372869b8b refactor remaining code from urfave/cli
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2025-12-15 16:40:27 +01:00
Christian Richter 7be33b0607 refactor interims DefaultAppCobra to DefaultApp
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2025-12-15 16:40:26 +01:00
Christian Richter 7e1ab4f34f migrate thumbnails from urfave/cli to spf13/cobra
Signed-off-by: Christian Richter <c.richter@opencloud.eu>
2025-12-15 16:40:26 +01:00
Jörn Friedrich Dreyer 10913ca00a Merge pull request #1918 from opencloud-eu/otlp-tracing
update otlp tracing
2025-11-27 12:57:26 +01:00
Jörn Friedrich Dreyer a3ef7f6d79 update otlp tracing
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
2025-11-27 12:28:15 +01:00
Ralf Haferkamp 3badc66d4a fix: adapt to new function signatures
To allow to bump to latest kovidgoyal/imaging release
2025-11-26 14:46:30 +01:00
Michael Barz 3b27d8f580 change: use 404 as status when thumbnail can not be fetched (#1582) 2025-09-30 20:40:31 +02:00