@@ -1238,6 +1238,46 @@ OCIO_ADD_TEST(Lut1DRenderer, lut_1d_special_values)
12381238 OCIO_CHECK_EQUAL (outImage[7 ], 1 .0f );
12391239}
12401240
1241+ OCIO_ADD_TEST (Lut1DRenderer, lut_1d_hd_above_half_max)
1242+ {
1243+ // Test the processing of half-domain Lut1D for float input values that are greater than
1244+ // HALF_MAX but round down to HALF_MAX. These are the values 65504 < x < 65520.
1245+ // In other words, half(65519) rounds down to 65504 and half(65520) rounds up to Inf.
1246+ // There was a bug where these values were not processed correctly.
1247+
1248+ OCIO::ConfigRcPtr config = OCIO::Config::Create ();
1249+
1250+ const std::string ctfLUT (" lut1d_hd_16f_16i_1chan.ctf" );
1251+ OCIO::FileTransformRcPtr fileTransform = OCIO::CreateFileTransform (ctfLUT);
1252+
1253+ OCIO::ConstProcessorRcPtr proc;
1254+ OCIO_CHECK_NO_THROW (proc = config->getProcessor (fileTransform));
1255+
1256+ OCIO::ConstCPUProcessorRcPtr cpuFwd;
1257+ OCIO_CHECK_NO_THROW (cpuFwd = proc->getDefaultCPUProcessor ());
1258+
1259+ float inImage[] = {
1260+ 65505 .0f , 65519 .0f , 65520 .0f , 0 .0f ,
1261+ -65505 .0f , -65519 .0f , -65520 .0f , 1 .0f
1262+ };
1263+
1264+ std::vector<float > outImage (2 * 4 , -12 .345f );
1265+ OCIO::PackedImageDesc srcImgDesc ((void *)&inImage[0 ], 2 , 1 , 4 );
1266+ OCIO::PackedImageDesc dstImgDesc ((void *)&outImage[0 ], 2 , 1 , 4 );
1267+ cpuFwd->apply (srcImgDesc, dstImgDesc);
1268+
1269+ static const float rtol = 1e-5f ;
1270+ OCIO_CHECK_CLOSE (outImage[0 ], 0 .7785763f , rtol);
1271+ OCIO_CHECK_CLOSE (outImage[1 ], 0 .7785763f , rtol);
1272+ OCIO_CHECK_CLOSE (outImage[2 ], 0 .7785763f , rtol);
1273+ OCIO_CHECK_EQUAL (outImage[3 ], 0 .0f );
1274+
1275+ OCIO_CHECK_CLOSE (outImage[4 ], 0 .f , rtol);
1276+ OCIO_CHECK_CLOSE (outImage[5 ], 0 .f , rtol);
1277+ OCIO_CHECK_CLOSE (outImage[6 ], 0 .f , rtol);
1278+ OCIO_CHECK_EQUAL (outImage[7 ], 1 .0f );
1279+ }
1280+
12411281namespace
12421282{
12431283constexpr OCIO::OptimizationFlags DefaultNoLutInvFast =
0 commit comments