Skip to content

Commit 3c2e174

Browse files
authored
fix: Relax OpenColorIO exception handling (#5164)
In PR #5114, just a few weeks ago, I was trying to catch every possible OCIO exception. That was a good idea, but I was over-eager and treated every OCIO exception as if something really bad happened. I should have recognized that OCIO enjoys throwing exceptions for things where I would have just used an empty return value to indicate a simple failure to do what was asked. So this patch is revising the approach as follows: * Exceptions thrown because it couldn't read a config properly (it was missing or broken), or couldn't produce a ColorProcessor when asked -- those are real problems that we should treat as serious errors. * Exceptions thrown because it can't satisfy a simple request (like "what is the name of the color space for this role" in a case where the role you passed is not known by the config) -- we should catch those exceptions, but it's not an "error" for OIIO, we just return an empty string because there is no color space for that role. Also beefed up some of the documentation of our ColorConfig class methods to describe what happens with certain kinds of failures. Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 3602148 commit 3c2e174

2 files changed

Lines changed: 48 additions & 63 deletions

File tree

src/include/OpenImageIO/color.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,27 @@ class OIIO_API ColorConfig {
121121
int getColorSpaceIndex(string_view name) const;
122122

123123
/// Get the name of the color space representing the named role,
124-
/// or NULL if none could be identified.
124+
/// or nullptr if none could be identified.
125125
const char* getColorSpaceNameByRole(string_view role) const;
126126

127127
/// Get the data type that OCIO thinks this color space is. The name
128-
/// may be either a color space name or a role.
128+
/// may be either a color space name or a role. For an unknown space or
129+
/// any error, return TypeUnknown.
129130
OIIO::TypeDesc getColorSpaceDataType(string_view name, int* bits) const;
130131

131132
/// Retrieve the full list of known color space names, as a vector
132133
/// of strings.
133134
std::vector<std::string> getColorSpaceNames() const;
134135

135136
/// Get the name of the color space family of the named color space,
136-
/// or NULL if none could be identified.
137+
/// or nullptr if none could be identified.
137138
const char* getColorSpaceFamilyByName(string_view name) const;
138139

139140
// Get the number of Roles defined in this configuration
140141
int getNumRoles() const;
141142

142-
/// Query the name of the specified Role.
143+
/// Query the name of the specified Role, or return nullptr if there is no
144+
/// role with that index.
143145
const char* getRoleByIndex(int index) const;
144146

145147
/// Retrieve the full list of known Roles, as a vector of strings.
@@ -148,7 +150,8 @@ class OIIO_API ColorConfig {
148150
/// Get the number of Looks defined in this configuration
149151
int getNumLooks() const;
150152

151-
/// Query the name of the specified Look.
153+
/// Query the name of the specified Look, or return nullptr if there is no
154+
/// look with that index.
152155
const char* getLookNameByIndex(int index) const;
153156

154157
/// Retrieve the full list of known look names, as a vector of strings.
@@ -157,7 +160,8 @@ class OIIO_API ColorConfig {
157160
/// Get the number of NamedTransforms defined in this configuration
158161
int getNumNamedTransforms() const;
159162

160-
/// Query the name of the specified NamedTransform.
163+
/// Query the name of the specified NamedTransform, or nullptr if there is
164+
/// no NamedTransform with that index.
161165
const char* getNamedTransformNameByIndex(int index) const;
162166

163167
/// Retrieve the full list of known NamedTransforms, as a vector of strings
@@ -221,7 +225,8 @@ class OIIO_API ColorConfig {
221225
/// Get the number of displays defined in this configuration
222226
int getNumDisplays() const;
223227

224-
/// Query the name of the specified display.
228+
/// Query the name of the specified display, or nullptr if there is no
229+
/// display with that index.
225230
const char* getDisplayNameByIndex(int index) const;
226231

227232
/// Retrieve the full list of known display names, as a vector of
@@ -236,7 +241,9 @@ class OIIO_API ColorConfig {
236241
/// display will be used.
237242
int getNumViews(string_view display = "") const;
238243

239-
/// Query the name of the specified view for the specified display
244+
/// Query the name of the specified view for the specified display, or
245+
/// nullptr if there is no view with that index or if the display is not
246+
/// found.
240247
const char* getViewNameByIndex(string_view display, int index) const;
241248

242249
/// Retrieve the full list of known view names for the display, as a
@@ -247,12 +254,14 @@ class OIIO_API ColorConfig {
247254
/// Query the name of the default view for the specified display. If the
248255
/// display is empty or not specified, the default display will be used.
249256
/// This version does not consider the input color space.
257+
/// Returns nullptr for failure.
250258
const char* getDefaultViewName(string_view display = "") const;
251259

252260
/// Query the name of the default view for the specified display, given
253261
/// the input color space. If `display` is "default" or an empty string,
254262
/// the default display will be used. The input color space is used to
255263
/// determine the most appropriate default view for the given display.
264+
/// Returns nullptr for failure.
256265
const char* getDefaultViewName(string_view display,
257266
string_view inputColorSpace) const;
258267

src/libOpenImageIO/color_ocio.cpp

Lines changed: 31 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,7 @@ ColorConfig::Impl::inventory()
446446
scene_linear_alias = lin->getName();
447447
return; // If any non-"raw" spaces were defined, we're done
448448
}
449-
} catch (OCIO::Exception& e) {
450-
error("Exception from OCIO: {}", e.what());
449+
} catch (...) {
451450
}
452451
}
453452

@@ -684,8 +683,7 @@ ColorConfig::Impl::classify_by_conversions(CSInfo& cs)
684683
cs.setflag(CSInfo::is_ACEScg | CSInfo::is_linear_response,
685684
ACEScg_alias);
686685
}
687-
} catch (OCIO::Exception& e) {
688-
error("Exception from OCIO: {}", e.what());
686+
} catch (...) {
689687
}
690688
}
691689

@@ -782,8 +780,7 @@ ColorConfig::Impl::IdentifyBuiltinColorSpace(const char* name) const
782780
try {
783781
return OCIO::Config::IdentifyBuiltinColorSpace(config_, builtinconfig_,
784782
name);
785-
} catch (OCIO::Exception& e) {
786-
error("Exception from OCIO: {}", e.what());
783+
} catch (...) {
787784
}
788785
return nullptr;
789786
}
@@ -952,8 +949,7 @@ ColorConfig::getColorSpaceFamilyByName(string_view name) const
952949
std::string(name).c_str());
953950
if (c)
954951
return c->getFamily();
955-
} catch (OCIO::Exception& e) {
956-
getImpl()->error("Exception from OCIO: {}", e.what());
952+
} catch (...) {
957953
}
958954
}
959955
return nullptr;
@@ -986,8 +982,7 @@ ColorConfig::getRoleByIndex(int index) const
986982
try {
987983
if (getImpl()->config_ && !disable_ocio)
988984
return getImpl()->config_->getRoleName(index);
989-
} catch (OCIO::Exception& e) {
990-
getImpl()->error("Exception from OCIO: {}", e.what());
985+
} catch (...) {
991986
}
992987
return nullptr;
993988
}
@@ -1010,8 +1005,7 @@ ColorConfig::getNumLooks() const
10101005
try {
10111006
if (getImpl()->config_ && !disable_ocio)
10121007
return getImpl()->config_->getNumLooks();
1013-
} catch (OCIO::Exception& e) {
1014-
getImpl()->error("Exception from OCIO: {}", e.what());
1008+
} catch (...) {
10151009
}
10161010
return 0;
10171011
}
@@ -1024,8 +1018,7 @@ ColorConfig::getLookNameByIndex(int index) const
10241018
try {
10251019
if (getImpl()->config_ && !disable_ocio)
10261020
return getImpl()->config_->getLookNameByIndex(index);
1027-
} catch (OCIO::Exception& e) {
1028-
getImpl()->error("Exception from OCIO: {}", e.what());
1021+
} catch (...) {
10291022
}
10301023
return nullptr;
10311024
}
@@ -1060,8 +1053,7 @@ ColorConfig::Impl::isColorSpaceLinear(string_view name) const
10601053
OCIO::REFERENCE_SPACE_SCENE)
10611054
|| config_->isColorSpaceLinear(c_str(name),
10621055
OCIO::REFERENCE_SPACE_DISPLAY);
1063-
} catch (const std::exception& e) {
1064-
error("ColorConfig error: {}", e.what());
1056+
} catch (...) {
10651057
return false;
10661058
}
10671059
}
@@ -1121,9 +1113,7 @@ ColorConfig::getColorSpaceNameByRole(string_view role) const
11211113
// role);
11221114
return c->getName();
11231115
}
1124-
} catch (OCIO::Exception& e) {
1125-
getImpl()->error("Exception from OCIO: {}", e.what());
1126-
return nullptr;
1116+
} catch (...) {
11271117
}
11281118
}
11291119

@@ -1132,7 +1122,7 @@ ColorConfig::getColorSpaceNameByRole(string_view role) const
11321122
|| Strutil::iequals(role, "scene_linear"))
11331123
return "linear";
11341124

1135-
return NULL; // Dunno what role
1125+
return nullptr; // Dunno what role
11361126
}
11371127

11381128

@@ -1168,8 +1158,7 @@ ColorConfig::getColorSpaceDataType(string_view name, int* bits) const
11681158
case OCIO::BIT_DEPTH_F32: *bits = 32; return TypeDesc::FLOAT;
11691159
}
11701160
}
1171-
} catch (OCIO::Exception& e) {
1172-
getImpl()->error("Exception from OCIO: {}", e.what());
1161+
} catch (...) {
11731162
}
11741163
}
11751164
return TypeUnknown;
@@ -1183,8 +1172,7 @@ ColorConfig::getNumDisplays() const
11831172
try {
11841173
if (getImpl()->config_ && !disable_ocio)
11851174
return getImpl()->config_->getNumDisplays();
1186-
} catch (OCIO::Exception& e) {
1187-
getImpl()->error("Exception from OCIO: {}", e.what());
1175+
} catch (...) {
11881176
}
11891177
return 0;
11901178
}
@@ -1197,8 +1185,7 @@ ColorConfig::getDisplayNameByIndex(int index) const
11971185
try {
11981186
if (getImpl()->config_ && !disable_ocio)
11991187
return getImpl()->config_->getDisplay(index);
1200-
} catch (OCIO::Exception& e) {
1201-
getImpl()->error("Exception from OCIO: {}", e.what());
1188+
} catch (...) {
12021189
}
12031190
return nullptr;
12041191
}
@@ -1225,8 +1212,7 @@ ColorConfig::getNumViews(string_view display) const
12251212
if (getImpl()->config_ && !disable_ocio)
12261213
return getImpl()->config_->getNumViews(
12271214
std::string(display).c_str());
1228-
} catch (OCIO::Exception& e) {
1229-
getImpl()->error("Exception from OCIO: {}", e.what());
1215+
} catch (...) {
12301216
}
12311217
return 0;
12321218
}
@@ -1242,8 +1228,7 @@ ColorConfig::getViewNameByIndex(string_view display, int index) const
12421228
if (getImpl()->config_ && !disable_ocio)
12431229
return getImpl()->config_->getView(std::string(display).c_str(),
12441230
index);
1245-
} catch (OCIO::Exception& e) {
1246-
getImpl()->error("Exception from OCIO: {}", e.what());
1231+
} catch (...) {
12471232
}
12481233
return nullptr;
12491234
}
@@ -1269,8 +1254,7 @@ ColorConfig::getDefaultDisplayName() const
12691254
try {
12701255
if (getImpl()->config_ && !disable_ocio)
12711256
return getImpl()->config_->getDefaultDisplay();
1272-
} catch (OCIO::Exception& e) {
1273-
getImpl()->error("Exception from OCIO: {}", e.what());
1257+
} catch (...) {
12741258
}
12751259
return nullptr;
12761260
}
@@ -1285,8 +1269,7 @@ ColorConfig::getDefaultViewName(string_view display) const
12851269
try {
12861270
if (getImpl()->config_ && !disable_ocio)
12871271
return getImpl()->config_->getDefaultView(c_str(display));
1288-
} catch (OCIO::Exception& e) {
1289-
getImpl()->error("Exception from OCIO: {}", e.what());
1272+
} catch (...) {
12901273
}
12911274
return nullptr;
12921275
}
@@ -1305,8 +1288,7 @@ ColorConfig::getDefaultViewName(string_view display,
13051288
if (getImpl()->config_ && !disable_ocio)
13061289
return getImpl()->config_->getDefaultView(c_str(display),
13071290
c_str(inputColorSpace));
1308-
} catch (OCIO::Exception& e) {
1309-
getImpl()->error("Exception from OCIO: {}", e.what());
1291+
} catch (...) {
13101292
}
13111293
return nullptr;
13121294
}
@@ -1324,8 +1306,7 @@ ColorConfig::getDisplayViewColorSpaceName(const std::string& display,
13241306
if (strcmp(c_str(name), "<USE_DISPLAY_NAME>") == 0)
13251307
name = display;
13261308
return c_str(name);
1327-
} catch (OCIO::Exception& e) {
1328-
getImpl()->error("Exception from OCIO: {}", e.what());
1309+
} catch (...) {
13291310
}
13301311
}
13311312
return nullptr;
@@ -1341,8 +1322,7 @@ ColorConfig::getDisplayViewLooks(const std::string& display,
13411322
if (getImpl()->config_ && !disable_ocio)
13421323
return getImpl()->config_->getDisplayViewLooks(display.c_str(),
13431324
view.c_str());
1344-
} catch (OCIO::Exception& e) {
1345-
getImpl()->error("Exception from OCIO: {}", e.what());
1325+
} catch (...) {
13461326
}
13471327
return nullptr;
13481328
}
@@ -1355,8 +1335,7 @@ ColorConfig::getNumNamedTransforms() const
13551335
try {
13561336
if (getImpl()->config_ && !disable_ocio)
13571337
return getImpl()->config_->getNumNamedTransforms();
1358-
} catch (OCIO::Exception& e) {
1359-
getImpl()->error("Exception from OCIO: {}", e.what());
1338+
} catch (...) {
13601339
}
13611340
return 0;
13621341
}
@@ -1369,8 +1348,7 @@ ColorConfig::getNamedTransformNameByIndex(int index) const
13691348
try {
13701349
if (getImpl()->config_ && !disable_ocio)
13711350
return getImpl()->config_->getNamedTransformNameByIndex(index);
1372-
} catch (OCIO::Exception& e) {
1373-
getImpl()->error("Exception from OCIO: {}", e.what());
1351+
} catch (...) {
13741352
}
13751353
return nullptr;
13761354
}
@@ -1432,8 +1410,7 @@ ColorConfig::Impl::resolve(string_view name) const
14321410
OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(c_str(name));
14331411
if (cs)
14341412
return cs->getName();
1435-
} catch (OCIO::Exception& e) {
1436-
error("Exception from OCIO: {}", e.what());
1413+
} catch (...) {
14371414
}
14381415
}
14391416
// OCIO did not know this name as a color space, role, or alias.
@@ -1559,7 +1536,9 @@ class ColorProcessor_OCIO final : public ColorProcessor {
15591536
chanstride, xstride, ystride);
15601537
m_cpuproc->apply(pid);
15611538
} catch (OCIO::Exception& e) {
1562-
OIIO::print("OCIO error in apply: {}\n", e.what());
1539+
OIIO::errorfmt("OCIO error in apply: {}\n", e.what());
1540+
// FIXME -- some day, we should make ColorProcessor::apply return
1541+
// a status, and we should indicate here that it failed.
15631542
}
15641543
}
15651544

@@ -2032,8 +2011,7 @@ ColorConfig::getColorSpaceFromFilepath(string_view str) const
20322011
string_view r = getImpl()->config_->getColorSpaceFromFilepath(
20332012
s.c_str());
20342013
return r;
2035-
} catch (OCIO::Exception& e) {
2036-
getImpl()->error("Exception from OCIO: {}", e.what());
2014+
} catch (...) {
20372015
}
20382016
}
20392017
// Fall back on parseColorSpaceFromString
@@ -2051,8 +2029,7 @@ ColorConfig::getColorSpaceFromFilepath(string_view str, string_view default_cs,
20512029
s.c_str());
20522030
if (!getImpl()->config_->filepathOnlyMatchesDefaultRule(s.c_str()))
20532031
return r;
2054-
} catch (OCIO::Exception& e) {
2055-
getImpl()->error("Exception from OCIO: {}", e.what());
2032+
} catch (...) {
20562033
}
20572034
}
20582035
if (cs_name_match) {
@@ -2068,8 +2045,7 @@ ColorConfig::filepathOnlyMatchesDefaultRule(string_view str) const
20682045
{
20692046
try {
20702047
return getImpl()->config_->filepathOnlyMatchesDefaultRule(c_str(str));
2071-
} catch (OCIO::Exception& e) {
2072-
getImpl()->error("Exception from OCIO: {}", e.what());
2048+
} catch (...) {
20732049
}
20742050
return false;
20752051
}
@@ -2248,8 +2224,8 @@ ColorConfig::get_color_interop_id(string_view colorspace) const
22482224
std::string(resolve(colorspace)).c_str());
22492225
if (c)
22502226
interop_id = c->getInteropID();
2251-
} catch (OCIO::Exception& e) {
2252-
getImpl()->error("Exception from OCIO: {}", e.what());
2227+
} catch (...) {
2228+
interop_id = nullptr;
22532229
}
22542230
if (interop_id) {
22552231
return interop_id;

0 commit comments

Comments
 (0)