@@ -330,7 +330,8 @@ is_spec_aces_container_channels_only(const OIIO::ImageSpec& spec)
330330
331331
332332bool
333- is_aces_container_attributes_non_empty (const OIIO::ImageSpec& spec)
333+ is_aces_container_attributes_non_empty (const OIIO::ImageSpec& spec,
334+ std::string& non_compliant_attr)
334335{
335336 // attributes in this list should NOT be empty if they exist
336337 static const std::vector<std::string> nonEmptyAttribs = {
@@ -360,6 +361,7 @@ is_aces_container_attributes_non_empty(const OIIO::ImageSpec& spec)
360361 const ParamValue* value = spec.find_attribute (label,
361362 OIIO::TypeDesc::STRING);
362363 if (value && value->get <std::string>().empty ()) {
364+ non_compliant_attr = label;
363365 return false ;
364366 }
365367 }
@@ -370,31 +372,52 @@ is_aces_container_attributes_non_empty(const OIIO::ImageSpec& spec)
370372
371373
372374bool
373- is_aces_container_compliant (const OIIO::ImageSpec& spec)
375+ is_aces_container_compliant (const OIIO::ImageSpec& spec, std::string& reason )
374376{
375- if (!is_spec_aces_container_channels_only (spec))
377+ if (!is_spec_aces_container_channels_only (spec)) {
378+ reason
379+ = " Spec channel names do not match those required for an ACES Container." ;
376380 return false ;
381+ }
377382
378383 // Check data type
379- if (spec.format != OIIO::TypeDesc::HALF)
384+ if (spec.format != OIIO::TypeDesc::HALF) {
385+ reason
386+ = " EXR data type is not 'HALF' as required for an ACES Container." ;
380387 return false ;
388+ }
381389
382390 // Check compression
383391 std::string compression = spec.get_string_attribute (" compression" , " zip" );
384- if (compression != " none" )
392+ if (compression != " none" ) {
393+ reason = " Compression is not 'none' as required for an ACES Container." ;
385394 return false ;
395+ }
386396
387397 // Check non-empty attributes
388- if (!is_aces_container_attributes_non_empty (spec))
398+ std::string non_compliant_attr = " " ;
399+ if (!is_aces_container_attributes_non_empty (spec, non_compliant_attr)) {
400+ reason = " Spec contains an empty string attribute (" ;
401+ reason += non_compliant_attr;
402+ reason += " ) that is required to be non-empty in an ACES Container." ;
389403 return false ;
404+ }
390405
391406 // Check attributes with exact values if they exist
392407 if (spec.get_string_attribute (" oiio:ColorSpace" , ACES_AP0_colorInteropId)
393408 != ACES_AP0_colorInteropId
394409 || spec.get_string_attribute (" colorInteropId" , ACES_AP0_colorInteropId)
395- != ACES_AP0_colorInteropId
396- || spec.get_int_attribute (" acesImageContainerFlag" , 1 ) != 1 )
410+ != ACES_AP0_colorInteropId) {
411+ reason
412+ = " Color space is not lin_ap0_scene as required for an ACES Container." ;
397413 return false ;
414+ }
415+
416+ if (spec.get_int_attribute (" acesImageContainerFlag" , 1 ) != 1 ) {
417+ reason
418+ = " acesImageContainerFlag is not set to '1' as required for an ACES Container." ;
419+ return false ;
420+ }
398421
399422 // Check chromaticities
400423 float chromaticities[8 ] = { 0 ., 0 ., 0 ., 0 ., 0 ., 0 ., 0 ., 0 . };
@@ -406,8 +429,11 @@ is_aces_container_compliant(const OIIO::ImageSpec& spec)
406429 std::end (chromaticities),
407430 std::begin (ACES_AP0_chromaticities));
408431
409- if (chroms_found && !chroms_equal)
432+ if (chroms_found && !chroms_equal) {
433+ reason
434+ = " Chromaticities are not set to AP0 chromaticities as required for an ACES Container." ;
410435 return false ;
436+ }
411437
412438 return true ;
413439}
@@ -426,10 +452,12 @@ set_aces_container_attributes(OIIO::ImageSpec& spec)
426452
427453
428454bool
429- process_aces_container (OIIO::ImageSpec& spec, std::string policy, int flag)
455+ process_aces_container (OIIO::ImageSpec& spec, std::string policy, int flag,
456+ std::string& non_compliance_reason)
430457{
431458 bool treat_as_aces_container = policy == " strict" || flag == 1 ;
432- bool is_compliant = is_aces_container_compliant (spec);
459+ bool is_compliant = is_aces_container_compliant (spec,
460+ non_compliance_reason);
433461
434462 if (treat_as_aces_container && !is_compliant) {
435463 return false ;
@@ -980,12 +1008,15 @@ OpenEXROutput::spec_to_header(ImageSpec& spec, int subimage,
9801008 = spec.get_string_attribute (" openexr:ACESContainerPolicy" , " none" );
9811009
9821010 if (aces_container_policy != " none" || aces_container_flag == 1 ) {
1011+ std::string non_compliance_reason = " " ;
9831012 bool should_panic = !process_aces_container (spec, aces_container_policy,
984- aces_container_flag);
1013+ aces_container_flag,
1014+ non_compliance_reason);
9851015
9861016 if (should_panic) {
9871017 errorfmt (
988- " Cannot output non-compliant ACES Container in 'strict' mode." );
1018+ " Cannot output non-compliant ACES Container in 'strict' mode. REASON: {}" ,
1019+ non_compliance_reason);
9891020 return false ;
9901021 }
9911022 }
0 commit comments