Skip to content

Commit 25fac3c

Browse files
committed
feat(openexr): better error messages for each failure case of ACES Container compliance
Signed-off-by: glowies <[email protected]>
1 parent c177142 commit 25fac3c

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

src/openexr.imageio/exroutput.cpp

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ is_spec_aces_container_channels_only(const OIIO::ImageSpec& spec)
330330

331331

332332
bool
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

372374
bool
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

428454
bool
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
}

testsuite/openexr-suite/ref/out.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,12 @@ strict-out.exr : 4 x 4, 3 channel, half openexr
360360
oiio:subimages: 1
361361
openexr:ACESContainerPolicy: "strict"
362362
openexr:lineOrder: "increasingY"
363-
oiiotool ERROR: -o : Cannot output non-compliant ACES Container in 'strict' mode.
363+
oiiotool ERROR: -o : Cannot output non-compliant ACES Container in 'strict' mode. REASON: Spec channel names do not match those required for an ACES Container.
364364
Full command line was:
365365
> oiiotool --create 4x4 3 -d half --compression none --ch left.R=R,G,B -sattrib openexr:ACESContainerPolicy strict -o strict-fail.exr
366-
oiiotool ERROR: -o : Cannot output non-compliant ACES Container in 'strict' mode.
366+
oiiotool ERROR: -o : Cannot output non-compliant ACES Container in 'strict' mode. REASON: Compression is not 'none' as required for an ACES Container.
367367
Full command line was:
368368
> oiiotool --create 4x4 3 -d half --compression zip -sattrib openexr:ACESContainerPolicy strict -o strict-fail.exr
369-
oiiotool ERROR: -o : Cannot output non-compliant ACES Container in 'strict' mode.
369+
oiiotool ERROR: -o : Cannot output non-compliant ACES Container in 'strict' mode. REASON: EXR data type is not 'HALF' as required for an ACES Container.
370370
Full command line was:
371371
> oiiotool --create 4x4 3 -d float --compression none -sattrib openexr:ACESContainerPolicy strict -o strict-fail.exr

0 commit comments

Comments
 (0)