Repository navigation
OpenEXR: read PIZ-compressed files (Poly Haven EXRs) - #887
Merged
Merged
Conversation
A pure-Aether PIZ block decoder. Not wired in yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PXR24, B44, B44A, DWAA and DWAB are still refused by name. half_to_float returned +0 for 0x8000 (0 - 0), so a decode could not equal the OpenEXR library's bit for bit; it is negated by a product now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 small PIZ files plus two Poly Haven 1k assets (CC0): hashes of the OpenEXR library's decode in test_envimage, the fuzz loops over the small ones, damaged bit counts. tools/exr_reference is the development tool that wrote them (not built, not linked). coded_piz.exr (a header only) is replaced by header-only PXR24, B44 and DWAA refusals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_environment holds the renderer's irradiance for two assets to the decoded picture's integral on OpenGL and Vulkan; test_backend_parity draws one with both and holds the frames equal (0 of 147456 channels at one sample). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/test_environment.ae: both sides added checks after ground(); keep the Poly Haven PIZ assets (this branch) and the environment-map yaw checks (#888). test_envimage 170/170 and test_environment pass on both backends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
paul-hammant
added a commit
that referenced
this pull request
Oct 30, 2026
#886 and #887's linux jobs were cut off at 25 minutes in their last step, the benchmarks, after merging main rebuilt most of the shard. That job takes 10 to 24 minutes on recent pull requests, and #888's first run also stopped at 25. The change to ci.yml starts a run on main, which saves the cache pull requests restore. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
OpenEXR PIZ for
ae3d.openexr, as Nic asked (875-1). Every Poly Haven EXR is PIZ, soengine_set_environment/AE3D_ENVcould not load any of them; they do now. Pure Aether (ae3d.exrpiz, ~480 lines), no C helper.Format coverage
coded_{pxr24,b44,dwaa}.exr)The change in
ae3d.openexris a 3-line branch plus the refusal threshold;half_to_floatnow keeps a half's -0 as -0 (it returned +0), needed for bit equality.How equality to OpenEXR was established
Official OpenEXR 3.5.2 (brew, reference only; nothing linked into ae3d or built by ci) via
tools/exr_reference/exrref.cpp:writemakes PIZ files,dumpprints two position-sensitive hashes of the library's decode (RGBA float32 bits).test_envimagecomputes the same hashes overae3d.openexr's decode and compares: 25 small PIZ files + the 2 Poly Haven assets, bit for bit. Also 250 randomly sized/patterned/channelled files (sizes 1..1000, offset windows, all patterns, HALF/FLOAT/Y) compared to the library's decode: 0 differ.Covered: RGB, RGBA, Y; HALF and FLOAT (the library does write PIZ FLOAT); widths 1, 4, 37, 1000; heights 1, 32, 33, 45, 64; single scanline; flat and all-zero images (degenerate tables); data window off the origin; both wavelet forms (14-bit below 16384 distinct values, 16-bit above, via a bit-pattern ramp: the first version of the 16-bit step was wrong and only that fixture caught it; the Poly Haven files never reach it); long (>14-bit) Huffman codes; run codes of zero and nonzero words; blocks the library stored raw.
tests/fixtures/env/PIZ.mdtabulates each fixture;tools/exr_reference/blocks.pysays per block whether a file is really PIZ or stored raw (small and noisy files are raw; I found that out the hard way and replaced fixtures that were silently raw).Negative controls (each fails test_envimage)
wavelet one level short / one level too many; value table reversed; block height 16 not 32; one Huffman code-length bit flipped; canonical codes assigned shortest-first; codes over 14 bits not decoded; run code repeats one word too few; 14-bit form for every range; 16-bit form for every range; 14-bit odd-bit term dropped; 16-bit difference halved the wrong way; 16-bit half-range offset dropped; FLOAT read as one plane; bitmap placed at offset 0; lines laid wrong; -0 turned back to +0; Huffman count check dropped. 18 of 18 caught (the first pass caught 15 of 18 and led to the ramp fixture and the damaged-bit-count checks).
Costs (M6, release)
measure_environmenton the 4k FLOAT file: set_environment 357/388 ms (GL/Vulkan) PIZ against 355/376 ZIP; first frame and per-frame cost unchanged.Verification
engine_set_environmentintest_environment(renderer irradiance onto 4 normals = decoded integral to 10%, both backends);test_backend_paritydraws one with GL and Vulkan: 0 of 147,456 channels differ at AE3D_MSAA=0, 719 at 4x (edges; the gradient case has 681).VK_LAYER_ENABLES=...SYNCHRONIZATION_VALIDATION_EXT, VUID-/SYNC-HAZARD- counted): 0 over test_backend_parity, test_environment, street_drive and zombie_city with a Poly Haven map, at 1x and 4x.AE3D_MSL=1 MVK_CONFIG_FAST_MATH_ENABLED=0both sides: 0 differ.leaks(0 leaks) and Guard Malloc (libgmalloc defaults to 16-byte alignment, so small overruns can slip through)../ci.shgreen (8 skipped: DLSS, ray query, one leak report, as on this machine before).Fixtures and licences
tests/fixtures/env/polyhaven/:abandoned_tank_farm_05_1k.exrandaerodynamics_workshop_1k.exr, 1k PIZ FLOAT, unchanged from polyhaven.com, CC0; URLs intests/fixtures/env/PIZ.md. The OpenEXR library is BSD-3-Clause; the decoder follows its structure (wavelet level loop and Haar steps, code-length table run codes, canonical code assignment), so its notice is in theae3d.exrpizheader andTHIRD_PARTY_LICENSES.md.Not done / notes
coded_piz.exr(header only) with header-only PXR24/B44/DWAA refusals;test_environmentnow usescoded_b44.exras its not-a-picture file (one line, may overlap the 2:1 refusal PR).tools/exr_reference/exrref.cpp(+blocks.py) in the tree as a dev-only tool? Four 4k-class timings were measured locally only; no 4k file is committed.🤖 Generated with Claude Code