feat(image): enable the libvips image engine by default (#35989) - #36885
Queued
wezell wants to merge 5 commits into
Queued
feat(image): enable the libvips image engine by default (#35989)#36885wezell wants to merge 5 commits into
wezell wants to merge 5 commits into
Conversation
Flips IMAGE_API_USE_LIBVIPS from false to true. The engine still requires the native libvips library at runtime — VipsManager.isEnabled() ANDs the flag with isAvailable(), so installs without libvips keep using the legacy Java2D engine, and IMAGE_API_LIBVIPS_FALLBACK=true still catches per-op failures. Set IMAGE_API_USE_LIBVIPS=false (env: DOT_IMAGE_API_USE_LIBVIPS=false) to force the legacy engine. Follow-up to #35990 and #36284. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7 tasks
Contributor
|
Claude finished @wezell's task in 1m 20s —— View job Code Review
Reviewed the 5 changed files against New Issues
Notes (non-blocking)
Overall this is a clean, well-scoped default flip. The one Medium above is non-blocking — worth a look but the fallback design makes the change safe. |
erickgonzalez
approved these changes
Aug 4, 2026
wezell
enabled auto-merge
August 4, 2026 21:02
The two Scale Filter tests pinned Content-Length to a byte-exact value (980852 / 355062) produced by the Java2D engine. libvips uses a different resampler, so enabling it by default makes those renditions byte-different (961776 for the 900x500 case) and the Postman Default suite fails. Read width/height from the PNG IHDR chunk instead, which is what the test name claimed to check all along and is independent of the engine that produced the bytes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
When native libvips is absent, the class initializer of
app.photofox.vipsffm.Vips fails with ExceptionInInitializerError, and
every subsequent touch throws NoClassDefFoundError. Both are
LinkageErrors, and io.vavr's Try classifies LinkageError as fatal
(Try.java isFatal) — it sneaky-throws instead of capturing a Failure.
So VipsManager.isAvailable() never returned false: it propagated the
error to the caller and never cached a result, re-probing (and
re-throwing) on every call. With the engine enabled by default that
turned "no native libvips" from a graceful fallback into a hard
failure for anything resolving through ImageEngine:
- BinaryExporterServletTest.requestWebpImage -> NoClassDefFoundError
- FileMetadataAPITest -> MetadataGeneratorImpl.calculateDimensions
swallows the Throwable and reports 0x0 dimensions
Use a plain try/catch (Throwable) so a LinkageError is captured, false
is cached, and callers get the pure-JVM engine — which is what the
feature-flag contract always claimed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
wezell
added this pull request to the merge queue
Aug 6, 2026
Any commits made after this event will not be merged.
|
Tick the box to add this pull request to the merge queue (same as
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Flips the libvips image engine on by default:
IMAGE_API_USE_LIBVIPSgoes fromfalsetotrue.This is the follow-up switch for the work merged in:
SHARED_COMPLETEDdotGenerated mode (issue libvips: SHARED_COMPLETED dotGenerated mode + register rotate filter #36283)Nothing else changes — no new filters, no behavioural code, just the default.
Changes
VipsManager.javaConfig.getBooleanProperty(USE_LIBVIPS, false)→truedotmarketing-config.propertiesIMAGE_API_USE_LIBVIPS=false→true(comment updated)image/vips/README.mdfalse→trueImageFilterExporterEngineSelectionTest.javaWhy this is safe to flip
VipsManager.isEnabled()isflag && isAvailable():isAvailable()isfalse, the legacy Java2D engine is used exactly as today. Turning the flag on cannot break an install that lacks the library.IMAGE_API_LIBVIPS_FALLBACKstill defaults totrue, so the legacy filter runs for that op.IMAGE_API_USE_LIBVIPS=false, or envDOT_IMAGE_API_USE_LIBVIPS=false(theDOT_prefix is required for env overrides).The dotCMS Docker image installs
libvips42, so containerized installs get the libvips path; the AVIF encoder plugin is already wired in CI/Docker from #35990.Rollout note
This changes the engine that serves resized/filtered images by default. Renditions are byte-different from Java2D output (different resampler), so caches regenerate on first request after upgrade — no rendition invalidation is required, but expect a warm-up on first hit per rendition.
Checklist
image/vips/README.md, config comment)ConfigImageFilterExporterEngineSelectionTest(both engines exercised explicitly)🤖 Generated with Claude Code