Add AVIF image support via libavif#289
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds end-to-end AVIF support: CI/CMake/vcpkg updates, llimage AVIF codec (encode/decode/update), dimension extraction, snapshot/live-preview and UI wiring, file picker filters, and viewer upload/save integration. ChangesAVIF Image Format Support
Sequence Diagram(s)sequenceDiagram
participant UI as Snapshot/UI
participant Factory as LLImageFormatted Factory
participant LLImageAVIF
participant LibAVIF
participant Storage as File/Buffer
UI->>Factory: request formatted image (AVIF)
Factory->>LLImageAVIF: createFromType(IMG_CODEC_AVIF)
LLImageAVIF->>LibAVIF: avifDecoderCreate / avifPeekCompatibleFileType
LibAVIF-->>LLImageAVIF: metadata (width,height,alpha)
UI->>LLImageAVIF: decode() / encode()
LLImageAVIF->>LibAVIF: avifDecoderNextImage / avifImageYUVToRGB / avifImageRGBToYUV / avifEncoderWrite
LibAVIF-->>LLImageAVIF: image frames / bitstream
LLImageAVIF->>LLImageAVIF: vertical flip (in-place)
LLImageAVIF->>Storage: store encoded bitstream / fill raw buffer
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Infer (1.2.0)indra/llimage/llimageavif.cppindra/llimage/llimageavif.cpp:26:10: fatal error: 'linden_common.h' file not found ... [truncated 1081 characters] ... stall/lib/clang/18/include" Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
4d3a08b to
f153985
Compare
Add an AVIF codec (LLImageAVIF) to llimage backed by libavif with dav1d (decode) and aom (encode), and wire it into the image upload and save/snapshot paths, mirroring the existing WebP integration. - llimage: IMG_CODEC_AVIF and LLImageAVIF (lossy quality-based encode, 8-bit RGB/RGBA decode with vertical flip); extension, MIME, and dimensions-info registration - build: libavif[aom,dav1d] vcpkg dependency and AVIF.cmake module - upload: file picker load filters, IMAGE_EXTENSIONS, local bitmaps - save: FFSAVE_AVIF, snapshot format (combo box, encode switches, quality slider) and texture save-as Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f153985 to
fc56e08
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@indra/llimage/llimageavif.cpp`:
- Around line 214-257: The AVIF encoder currently assumes non-4-component images
are RGB which breaks for 1-channel grayscale; update the logic after
avifRGBImageSetDefaults(&rgb, image) to handle components explicitly: set
rgb.format = AVIF_RGB_FORMAT_RGBA for components==4, rgb.format =
AVIF_RGB_FORMAT_GRAY (or the correct libavif constant for 1-channel gray) for
components==1 and keep rgb.depth/rowBytes as width*components, and for any other
components value (e.g., 2) call setLastError("LLImageAVIF::Unsupported component
count") and return false so we fail fast; ensure the change references
rgb.format, rgb.rowBytes, avifRGBImageSetDefaults, and setLastError.
In `@indra/llimage/llimageavif.h`:
- Around line 37-48: The header comment and getters/setters for LLImageAVIF
incorrectly describe quality=100 as "lossless"; update the wording to "best
quality" (or similar) instead of "lossless" in LLImageAVIF, mEncodeQuality,
setEncodeQuality, and getEncodeQuality declarations and the mEncodeQuality
comment to avoid implying a true lossless encode (since encode() currently uses
AVIF_PIXEL_FORMAT_YUV420 and encoder->quality/qualityAlpha). Alternatively, if
you want to support true lossless, implement a lossless encode path in
LLImageAVIF::encode() (select a lossless pixel format and set the encoder to
lossless mode) and adjust the header docs accordingly; otherwise change all
occurrences of "lossless" to "best quality" to reflect current behavior.
In `@indra/llimage/llimagedimensionsinfo.cpp`:
- Around line 203-212: The getImageDimensionsAVIF implementation currently reads
the entire file into memory (using LLFile::size, std::make_unique<U8[]>, and
mInfile.read) which breaks the lightweight dimensions-only contract; change
LLImageDimensionsInfo::getImageDimensionsAVIF to perform bounded metadata
parsing using file-backed IO instead of full-file buffering: open/seek/read only
the header/metadata regions needed (using mInfile and mSrcFilename) and feed
those limited buffers to the AVIF probe routine (or use a stream/reader API from
the AVIF parser that accepts a file callback), and apply the same bounded-read
approach to the related code in the 224-240 region so you never allocate the
full image in memory.
In `@indra/newview/llfilepicker.cpp`:
- Line 56: The material-texture aggregate filter constant
FFLOAD_MATERIAL_TEXTURE is missing the *.avif pattern so AVIF files are hidden
in the default material/texture picker; update the filter string(s) that build
FFLOAD_MATERIAL_TEXTURE (and the other occurrence noted) to include *.avif in
both the human-readable description and the semicolon-separated pattern list
(e.g., add ;*.avif to the pattern section and add .avif to the parenthesis list
in the display text) so AVIF files appear in the aggregate material-texture
picker on Windows/SDL.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: ef4019f1-ece5-48c2-a553-72544894e74d
📒 Files selected for processing (24)
.github/workflows/build.yamlindra/CMakeLists.txtindra/cmake/AVIF.cmakeindra/cmake/CMakeLists.txtindra/llimage/CMakeLists.txtindra/llimage/llimage.cppindra/llimage/llimage.hindra/llimage/llimageavif.cppindra/llimage/llimageavif.hindra/llimage/llimagedimensionsinfo.cppindra/llimage/llimagedimensionsinfo.hindra/newview/llfilepicker.cppindra/newview/llfilepicker.hindra/newview/lllocalbitmaps.cppindra/newview/lllocalbitmaps.hindra/newview/llpanelsnapshotlocal.cppindra/newview/llpreviewtexture.cppindra/newview/llsnapshotlivepreview.cppindra/newview/llsnapshotmodel.hindra/newview/llviewermenufile.cppindra/newview/llviewerwindow.cppindra/newview/skins/default/xui/en/panel_snapshot_local.xmlindra/newview/skins/default/xui/en/strings.xmlindra/vcpkg.json
LLImageAVIF::encode() now produces mathematically lossless output at quality 100 (identity matrix + YUV 4:4:4); the lossy path keeps 4:2:0 with a BT.601 matrix. Expose a distinct "AVIF (Lossless)" snapshot format alongside the lossy "AVIF" option, mirroring the WebP (Lossless) treatment: - SNAPSHOT_FORMAT_AVIF_LOSSLESS enum and combo box item - encode, size-estimate, and save-dispatch switches - no quality slider for the lossless variant Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Encode 1- and 2-component raw images as monochrome (4:0:0) AVIF via AVIF_RGB_FORMAT_GRAY / AVIF_RGB_FORMAT_GRAYA, selecting the pixel and RGB format by component count instead of assuming RGB/RGBA. Monochrome uses a BT.601 matrix (identity requires three planes); luma maps directly to Y so quality 100 remains lossless. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Description
Adds support for the AVIF (AV1 Image File Format) image format, letting users upload
.avifimages as texture sources and save snapshots/textures as.avif. AVIF offers substantially better compression than JPEG/PNG/WebP at equivalent quality, with alpha support.A new
LLImageAVIFcodec is added tollimage, backed by libavif via vcpkg using dav1d (decode) and aom (encode). It mirrors the existing WebP integration point-for-point. Encoding is lossy with a quality control (libavif'squalityAPI, likeLLImageJPEG), since lossy is where AVIF's size advantage lies.Core (
llimage)IMG_CODEC_AVIF+LLImageAVIF: dav1d decode to 8-bit RGB/RGBA (with vertical flip for SL's OpenGL convention), aom lossy/quality encode (sRGB CICP, YUV420)image/avif), andLLImageDimensionsInforegistrationBuild
libavifvcpkg dependency withaom+dav1dfeatures; newindra/cmake/AVIF.cmake. Resolves from the existing pinned vcpkg baseline (libavif 1.4.1) — no custom port needed.Upload / load paths
IMAGE_EXTENSIONS, and local-bitmap loading. Factory-driven paths (upload preview,createUploadFile, bulk upload) work automatically via codec registration.Save / snapshot paths
FFSAVE_AVIFsave filters (all platforms),SNAPSHOT_FORMAT_AVIF, snapshot format combo box + encode switches + quality-slider visibility, viewer-window save dispatch, and texture "Save As".Related Issues
No tracking issue yet — happy to link one if desired.
Issue Link: N/A
Checklist
Please ensure the following before requesting review:
Additional Notes
Verification: Full viewer builds clean (
cmake --preset vs2026-os→--build --config Release, exit 0). vcpkg builtlibavif[aom,core,dav1d]@1.4.1;llimageavif.cppcompiles against the real libavif headers; all changednewviewTUs recompile andAlchemyTest.exelinks and packages. All pre-commit hooks pass.Design decisions:
libaviffeatures.MATERIAL_TEXTURES_FILTER, the GLTF-import filter, and the FFLOAD_ALL/EXE "Images" hint untouched (WebP isn't in them either); localized snapshot XUI needs no edits (name-merge surfaces theenAVIF combo item with its acronym label).Known limitation: HDR / >8-bit / wide-gamut AVIFs are down-converted to 8-bit sRGB on decode (LLImageRaw is 8-bit).