Fix EXR encoder to write scaled values

Merged
JI
24d ago
+34-5

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules :cop:.
  • I have provided test coverage for my change (where applicable)

Description

Related to #3194

The EXR decoder and encoder did not agree. The decoder writes scaled values into the pixel format with FromAssociatedScaledVector4. The encoder read native values with ToAssociatedVector4().

For a pixel format whose native range is [0, 1], both values are equal, so the output was correct. For a pixel format with a different native range, the encoder wrote wrong values. For example, HalfVector4 maps the scaled range [0, 1] to the native range [-65504, 65504]. A scaled red value of 0.25 went to the file as -32752, and an opaque alpha went to the file as 65504.

The encoder now reads ToAssociatedScaledVector4() in the floating-point path and in the unsigned integer path. Rgba128.FromVector4 in the unsigned integer path also expects components in [0, 1].

I added a test that saves an Image<HalfVector4> as Half, Float, and UnsignedInt, loads the result as RgbaVector, and compares the scaled values. The test uses an alpha of 0.5, so the clamp in the decoder cannot hide a wrong alpha value.

This change does not add HDR support. Values outside [0, 1] still clamp in 4.x. I track that work in #3194 for v5.