Skip to content

feat(image): add JPEG XL (jxl) image filter backed by libvips#36224

Open
wezell wants to merge 1 commit into
mainfrom
issue-36223-jpegxl-image-filter
Open

feat(image): add JPEG XL (jxl) image filter backed by libvips#36224
wezell wants to merge 1 commit into
mainfrom
issue-36223-jpegxl-image-filter

Conversation

@wezell

@wezell wezell commented Jun 18, 2026

Copy link
Copy Markdown
Member

What

Adds a JPEG XL (.jxl) image filter backed by libvips, mirroring the existing AVIF filter. JPEG XL is a modern format the legacy pure-JVM (AWT/TwelveMonkeys) engine cannot produce; libvips encodes it via its libjxl delegate.

URL contract: filter=jxl&jxl_q=75 (also aliased as filter=jpegxl), with optional jxl_lossless and jxl_effort (1–9).

How

  • VipsJpegXlImageFilter — new filter extending VipsImageFilter, encoding to .jxl with Q (quality, default 75), lossless (default off), and effort (default 7). Modeled directly on VipsAvifImageFilter.
  • VipsImageFilterApiImpl — registers the filter under jxl and jpegxl in the "libvips-only capabilities with no legacy equivalent" block, next to avif/smartcrop.
  • VipsParityTest — adds a test that validates the JPEG XL output signature (raw codestream FF 0A or JXL ISO-BMFF box) and skips cleanly when the host libvips lacks the libjxl delegate.

Only available when libvips is enabled

ImageEngine.resolve() returns the libvips engine only when IMAGE_API_USE_LIBVIPS=true and native libvips is available. The jxl/jpegxl keys live solely in VipsImageFilterApiImpl — the legacy ImageFilterApiImpl has no knowledge of them, so when libvips is disabled the filter simply doesn't resolve (no error). Because JPEG XL has no pure-JVM equivalent, no VipsLegacyFilters fallback entry is added (same approach as avif).

Testing

  • ./mvnw compile -pl :dotcms-core passes.
  • VipsParityTest#jxl_encoder_produces_valid_jxl validates the output; it Assume-skips on hosts whose libvips lacks libjxl, keeping CI green.

Fixes #36223

🤖 Generated with Claude Code

Adds a libvips-only JPEG XL encoder filter, mirroring the existing AVIF
filter. Encodes via libvips' libjxl delegate (inferred from the .jxl
extension) with q/lossless/effort parameters under the jxl_ prefix.

Registered under both "jxl" and "jpegxl" keys in VipsImageFilterApiImpl,
so it is only reachable when the libvips engine is active
(IMAGE_API_USE_LIBVIPS=true and native libvips available, via
ImageEngine.resolve()). The legacy engine has no knowledge of these keys,
so the filter is simply unavailable when libvips is disabled. No
VipsLegacyFilters fallback is wired since JPEG XL has no pure-JVM
equivalent.

Adds a parity test validating the JPEG XL output signature that skips
cleanly when the host libvips lacks the libjxl delegate.

Fixes #36223

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@claude

claude Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @wezell's task in 58s —— View job


Rollback Safety Analysis

  • Read rollback-unsafe categories reference
  • Get full PR diff
  • Analyze diff against all unsafe categories

Result: ✅ Safe to Roll Back

All three changed files are pure application-layer code — no database schema, no Elasticsearch mapping, no content model, no stored procedures, and no API contract changes.

Category Check Result
C-1 Structural Data Model No runonce task, no core table changes ✅ Safe
C-2 ES Mapping Change No ESMappingAPIImpl / putMapping changes ✅ Safe
C-3 Content JSON Version Bump No CURRENT_MODEL_VERSION change ✅ Safe
C-4 DROP TABLE / DROP COLUMN None ✅ Safe
H-1 One-Way Data Migration None ✅ Safe
H-2 RENAME TABLE / COLUMN None ✅ Safe
H-3 PK Restructuring None ✅ Safe
H-4 New ContentType FieldType Not a field type — image filter only ✅ Safe
H-5 Storage Provider Change None ✅ Safe
H-6 DROP PROCEDURE / FUNCTION None ✅ Safe
H-7 NOT NULL column without default No schema change ✅ Safe
H-8 VTL Viewtool Contract Change No viewtool changes ✅ Safe
M-1 Column Type Change None ✅ Safe
M-2 Push Publishing Bundle Format None ✅ Safe
M-3 REST/GraphQL API Contract New jxl/jpegxl filter keys are purely additive and only reachable when libvips is enabled — no existing contract changed ✅ Safe
M-4 OSGi Interface Change None ✅ Safe

Rollback behavior: If this PR is deployed and then rolled back, filter=jxl and filter=jpegxl requests will simply not resolve (same as before deployment). No persistent state was written; no data is orphaned.

Label added: AI: Safe To Rollback

@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

🤖 Bedrock Review — deepseek.v3.2

[🟡 Medium] dotCMS/src/main/java/com/dotmarketing/image/vips/VipsJpegXlImageFilter.java:29 — The parameter key for lossless is constructed using getPrefix(), but getPrefix() is not defined in this class or its parent VipsImageFilter. This will cause a NullPointerException when checking for the lossless parameter. The key should likely be just "lossless" without a prefix, consistent with how "q" and "effort" are retrieved.

[🟡 Medium] dotCMS/src/main/java/com/dotmarketing/image/vips/VipsJpegXlImageFilter.java:33 — The VipsOption.Int and VipsOption.Boolean calls may throw runtime exceptions if the underlying libvips library does not support these options for the JPEG XL format. While the test attempts to detect support, the production code lacks a graceful fallback or clear error handling, which could cause image processing to fail abruptly.

[🟡 Medium] dotCMS/src/test/java/com/dotmarketing/image/vips/VipsParityTest.java:340 — The test helper jxlEncodeSupported() catches all Exception types, which could mask unrelated errors (e.g., I/O problems) and incorrectly report that JPEG XL encoding is supported. It should catch a more specific exception, such as one thrown by the libvips bindings when the delegate is missing.


Run: #27732344799 · tokens: in: 1915 · out: 319 · total: 2234

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Backend PR changes Java/Maven backend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Add JPEG XL (jxl) image filter backed by libvips

1 participant