Skip to content

Commit fe9f7f8

Browse files
authored
perf(oiiotool): use pointer not static for internal color config (AcademySoftwareFoundation#4433)
Basically, this switches to creating the colorconfig that oiiotool uses from statically constructed to build-on-demand, which should slightly lower runtime overhead for oiiotool invocations that don't need to do any color transformations. Signed-off-by: Larry Gritz <[email protected]>
1 parent d950d03 commit fe9f7f8

File tree

3 files changed

+75
-41
lines changed

3 files changed

+75
-41
lines changed

src/oiiotool/oiiotool.cpp

Lines changed: 62 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,27 @@ Oiiotool::clear_options()
202202

203203

204204

205+
ColorConfig&
206+
Oiiotool::colorconfig()
207+
{
208+
// It's safe to check the pointer and if it exists, return it, since
209+
// once it's created, it will never be changed.
210+
if (ColorConfig* cc = m_colorconfig.get())
211+
return *cc;
212+
213+
// Otherwise, we need to create it. But we need to be thread-safe.
214+
static std::mutex colorconfig_mutex;
215+
std::lock_guard lock(colorconfig_mutex);
216+
if (!m_colorconfig) {
217+
if (debug)
218+
print("oiiotool Creating ColorConfig\n");
219+
m_colorconfig.reset(new ColorConfig);
220+
}
221+
return *m_colorconfig.get();
222+
}
223+
224+
225+
205226
void
206227
Oiiotool::clear_input_config()
207228
{
@@ -2192,9 +2213,9 @@ static void
21922213
set_colorconfig(Oiiotool& ot, cspan<const char*> argv)
21932214
{
21942215
OIIO_DASSERT(argv.size() == 2);
2195-
ot.colorconfig.reset(argv[1]);
2196-
if (ot.colorconfig.has_error()) {
2197-
ot.errorfmt("--colorconfig", "{}", ot.colorconfig.geterror());
2216+
ot.colorconfig().reset(argv[1]);
2217+
if (ot.colorconfig().has_error()) {
2218+
ot.errorfmt("--colorconfig", "{}", ot.colorconfig().geterror());
21982219
}
21992220
}
22002221

@@ -2279,7 +2300,7 @@ class OpColorConvert final : public OiiotoolOp {
22792300
}
22802301
bool ok = ImageBufAlgo::colorconvert(*img[0], *img[1], fromspace,
22812302
tospace, unpremult, contextkey,
2282-
contextvalue, &ot.colorconfig);
2303+
contextvalue, &ot.colorconfig());
22832304
if (!ok && !strict) {
22842305
// The color transform failed, but we were told not to be
22852306
// strict, so ignore the error and just copy destination to
@@ -2354,7 +2375,7 @@ OIIOTOOL_OP(ociolook, 1, [&](OiiotoolOp& op, span<ImageBuf*> img) {
23542375
tospace = img[1]->spec().get_string_attribute("oiio:Colorspace");
23552376
return ImageBufAlgo::ociolook(*img[0], *img[1], lookname, fromspace,
23562377
tospace, unpremult, inverse, contextkey,
2357-
contextvalue, &ot.colorconfig);
2378+
contextvalue, &ot.colorconfig());
23582379
});
23592380

23602381

@@ -2373,7 +2394,8 @@ OIIOTOOL_OP(ociodisplay, 1, [&](OiiotoolOp& op, span<ImageBuf*> img) {
23732394
fromspace = img[1]->spec().get_string_attribute("oiio:Colorspace");
23742395
return ImageBufAlgo::ociodisplay(*img[0], *img[1], displayname, viewname,
23752396
fromspace, looks, unpremult, inverse,
2376-
contextkey, contextvalue, &ot.colorconfig);
2397+
contextkey, contextvalue,
2398+
&ot.colorconfig());
23772399
});
23782400

23792401

@@ -2384,7 +2406,7 @@ OIIOTOOL_OP(ociofiletransform, 1, [&](OiiotoolOp& op, span<ImageBuf*> img) {
23842406
bool inverse = op.options().get_int("inverse");
23852407
bool unpremult = op.options().get_int("unpremult");
23862408
return ImageBufAlgo::ociofiletransform(*img[0], *img[1], name, unpremult,
2387-
inverse, &ot.colorconfig);
2409+
inverse, &ot.colorconfig());
23882410
});
23892411

23902412

@@ -2398,7 +2420,7 @@ OIIOTOOL_OP(ocionamedtransform, 1, [&](OiiotoolOp& op, span<ImageBuf*> img) {
23982420
bool inverse = op.options().get_int("inverse");
23992421
return ImageBufAlgo::ocionamedtransform(*img[0], *img[1], name, unpremult,
24002422
inverse, contextkey, contextvalue,
2401-
&ot.colorconfig);
2423+
&ot.colorconfig());
24022424
});
24032425

24042426

@@ -5161,7 +5183,7 @@ input_file(Oiiotool& ot, cspan<const char*> argv)
51615183
if (autocc) {
51625184
// Try to deduce the color space it's in
51635185
std::string colorspace(
5164-
ot.colorconfig.getColorSpaceFromFilepath(filename));
5186+
ot.colorconfig().getColorSpaceFromFilepath(filename));
51655187
if (colorspace.size() && ot.debug)
51665188
print(" From {}, we deduce color space \"{}\"\n", filename,
51675189
colorspace);
@@ -5173,9 +5195,9 @@ input_file(Oiiotool& ot, cspan<const char*> argv)
51735195
print(" Metadata of {} indicates color space \"{}\"\n",
51745196
colorspace, filename);
51755197
}
5176-
std::string linearspace = ot.colorconfig.resolve("linear");
5198+
std::string linearspace = ot.colorconfig().resolve("linear");
51775199
if (colorspace.size()
5178-
&& !ot.colorconfig.equivalent(colorspace, linearspace)) {
5200+
&& !ot.colorconfig().equivalent(colorspace, linearspace)) {
51795201
std::string cmd = "colorconvert:strict=0";
51805202
if (autoccunpremult)
51815203
cmd += ":unpremult=1";
@@ -5459,12 +5481,12 @@ output_file(Oiiotool& ot, cspan<const char*> argv)
54595481
// automatically set -d based on the name if --autocc is used.
54605482
bool autocc = fileoptions.get_int("autocc", ot.autocc);
54615483
bool autoccunpremult = fileoptions.get_int("unpremult", ot.autoccunpremult);
5462-
std::string outcolorspace = ot.colorconfig.getColorSpaceFromFilepath(
5484+
std::string outcolorspace = ot.colorconfig().getColorSpaceFromFilepath(
54635485
filename);
54645486
if (autocc && outcolorspace.size()) {
54655487
TypeDesc type;
54665488
int bits;
5467-
type = ot.colorconfig.getColorSpaceDataType(outcolorspace, &bits);
5489+
type = ot.colorconfig().getColorSpaceDataType(outcolorspace, &bits);
54685490
if (type.basetype != TypeDesc::UNKNOWN) {
54695491
if (ot.debug)
54705492
std::cout << " Deduced data type " << type << " (" << bits
@@ -5482,7 +5504,7 @@ output_file(Oiiotool& ot, cspan<const char*> argv)
54825504
}
54835505
}
54845506
if (autocc) {
5485-
string_view linearspace = ot.colorconfig.resolve("linear");
5507+
string_view linearspace = ot.colorconfig().resolve("linear");
54865508
std::string currentspace
54875509
= ir->spec()->get_string_attribute("oiio:ColorSpace", linearspace);
54885510
// Special cases where we know formats should be particular color
@@ -5978,66 +6000,66 @@ print_ocio_info(Oiiotool& ot, std::ostream& out)
59786000
using Strutil::print;
59796001
int columns = Sysutil::terminal_columns() - 1;
59806002

5981-
int ociover = ot.colorconfig.OpenColorIO_version_hex();
5982-
if (ociover)
6003+
ColorConfig& colorconfig = ot.colorconfig();
6004+
if (int ociover = colorconfig.OpenColorIO_version_hex())
59836005
out << "OpenColorIO " << (ociover >> 24) << '.'
59846006
<< ((ociover >> 16) & 0xff) << '.' << ((ociover >> 8) & 0xff);
59856007
else
59866008
out << "No OpenColorIO";
5987-
out << "\nColor config: " << ot.colorconfig.configname() << "\n";
6009+
out << "\nColor config: " << colorconfig.configname() << "\n";
59886010
out << "Known color spaces: \n";
5989-
const char* linear = ot.colorconfig.getColorSpaceNameByRole("linear");
5990-
for (int i = 0, e = ot.colorconfig.getNumColorSpaces(); i < e; ++i) {
5991-
const char* n = ot.colorconfig.getColorSpaceNameByIndex(i);
6011+
const char* linear = colorconfig.getColorSpaceNameByRole("linear");
6012+
for (int i = 0, e = colorconfig.getNumColorSpaces(); i < e; ++i) {
6013+
const char* n = colorconfig.getColorSpaceNameByIndex(i);
59926014
out << " - " << quote_if_spaces(n);
5993-
if ((linear && !ot.colorconfig.equivalent(n, "linear")
5994-
&& ot.colorconfig.equivalent(n, linear))
5995-
|| ot.colorconfig.isColorSpaceLinear(n))
6015+
if ((linear && !colorconfig.equivalent(n, "linear")
6016+
&& colorconfig.equivalent(n, linear))
6017+
|| colorconfig.isColorSpaceLinear(n))
59966018
out << " (linear)";
59976019
out << "\n";
5998-
auto aliases = ot.colorconfig.getAliases(n);
6020+
auto aliases = colorconfig.getAliases(n);
59996021
if (aliases.size()) {
60006022
std::stringstream s;
60016023
s << " aliases: " << join_with_quotes(aliases, ", ");
60026024
out << Strutil::wordwrap(s.str(), columns, 6) << "\n";
60036025
}
60046026
}
60056027

6006-
int roles = ot.colorconfig.getNumRoles();
6028+
int roles = colorconfig.getNumRoles();
60076029
if (roles) {
60086030
print(out, "Known roles:\n");
60096031
for (int i = 0; i < roles; ++i) {
6010-
const char* r = ot.colorconfig.getRoleByIndex(i);
6032+
const char* r = colorconfig.getRoleByIndex(i);
60116033
print(out, " - {} -> {}\n", quote_if_spaces(r),
6012-
quote_if_spaces(ot.colorconfig.getColorSpaceNameByRole(r)));
6034+
quote_if_spaces(colorconfig.getColorSpaceNameByRole(r)));
60136035
}
60146036
}
60156037

6016-
int nlooks = ot.colorconfig.getNumLooks();
6038+
int nlooks = colorconfig.getNumLooks();
60176039
if (nlooks) {
60186040
print(out, "Known looks:\n");
60196041
for (int i = 0; i < nlooks; ++i)
60206042
print(out, " - {}\n",
6021-
quote_if_spaces(ot.colorconfig.getLookNameByIndex(i)));
6043+
quote_if_spaces(colorconfig.getLookNameByIndex(i)));
60226044
}
60236045

6024-
const char* default_display = ot.colorconfig.getDefaultDisplayName();
6025-
int ndisplays = ot.colorconfig.getNumDisplays();
6046+
const char* default_display = colorconfig.getDefaultDisplayName();
6047+
int ndisplays = colorconfig.getNumDisplays();
60266048
if (ndisplays) {
60276049
out << "Known displays: (* indicates default)\n";
60286050
for (int i = 0; i < ndisplays; ++i) {
6029-
const char* d = ot.colorconfig.getDisplayNameByIndex(i);
6051+
const char* d = colorconfig.getDisplayNameByIndex(i);
60306052
out << " - " << quote_if_spaces(d);
60316053
if (!strcmp(d, default_display))
60326054
out << " (*)";
6033-
const char* default_view = ot.colorconfig.getDefaultViewName(d);
6034-
int nviews = ot.colorconfig.getNumViews(d);
6055+
const char* default_view = colorconfig.getDefaultViewName(d);
6056+
int nviews = colorconfig.getNumViews(d);
60356057
if (nviews) {
60366058
out << "\n ";
60376059
std::stringstream s;
60386060
s << "views: ";
60396061
for (int i = 0; i < nviews; ++i) {
6040-
const char* v = ot.colorconfig.getViewNameByIndex(d, i);
6062+
const char* v = colorconfig.getViewNameByIndex(d, i);
60416063
s << quote_if_spaces(v);
60426064
if (!strcmp(v, default_view))
60436065
s << " (*)";
@@ -6050,15 +6072,15 @@ print_ocio_info(Oiiotool& ot, std::ostream& out)
60506072
}
60516073
}
60526074

6053-
int nnamed_transforms = ot.colorconfig.getNumNamedTransforms();
6075+
int nnamed_transforms = colorconfig.getNumNamedTransforms();
60546076
if (nnamed_transforms) {
60556077
out << "Named transforms:\n";
60566078
for (int i = 0; i < nnamed_transforms; ++i) {
6057-
const char* x = ot.colorconfig.getNamedTransformNameByIndex(i);
6079+
const char* x = colorconfig.getNamedTransformNameByIndex(i);
60586080
out << " - " << quote_if_spaces(x) << "\n";
60596081
}
60606082
}
6061-
if (!ot.colorconfig.supportsOpenColorIO())
6083+
if (!colorconfig.supportsOpenColorIO())
60626084
out << "No OpenColorIO support was enabled at build time.\n";
60636085
}
60646086

@@ -6115,12 +6137,12 @@ print_help_end(Oiiotool& ot, std::ostream& out)
61156137
out << formatted_format_list("Input", "input_format_list") << "\n";
61166138
out << formatted_format_list("Output", "output_format_list") << "\n";
61176139

6118-
if (int ociover = ot.colorconfig.OpenColorIO_version_hex())
6140+
if (int ociover = ot.colorconfig().OpenColorIO_version_hex())
61196141
print(out, "OpenColorIO {}.{}.{}\n", (ociover >> 24),
61206142
((ociover >> 16) & 0xff), ((ociover >> 8) & 0xff));
61216143
else
61226144
print(out, "No OpenColorIO\n");
6123-
print(out, " Color config: {}\n", ot.colorconfig.configname());
6145+
print(out, " Color config: {}\n", ot.colorconfig().configname());
61246146
print(out, " Run `oiiotool --colorconfiginfo` for a "
61256147
"full color management inventory.\n");
61266148

src/oiiotool/oiiotool.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class Oiiotool {
141141
std::vector<ImageRecRef> image_stack; // stack of previous images
142142
std::map<std::string, ImageRecRef> image_labels; // labeled images
143143
std::shared_ptr<ImageCache> imagecache; // back ptr to ImageCache
144-
ColorConfig colorconfig; // OCIO color config
144+
std::unique_ptr<ColorConfig> m_colorconfig; // OCIO color config
145145
Timer total_runtime;
146146
// total_readtime is the amount of time for direct reads, and does not
147147
// count time spent inside ImageCache.
@@ -370,6 +370,8 @@ class Oiiotool {
370370
// Merge stats from another Oiiotool
371371
void merge_stats(const Oiiotool& ot);
372372

373+
ColorConfig& colorconfig();
374+
373375
private:
374376
CallbackFunction m_pending_callback;
375377
std::vector<const char*> m_pending_argv;

testsuite/oiiotool-control/ref/out.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,69 +176,79 @@ Begin sequence iteration 0
176176
copyB.#.jpg -> copyB.0001.jpg
177177
Reading ./copyA.0001.jpg
178178
Output: copyB.0001.jpg
179+
oiiotool Creating ColorConfig
179180
Writing copyB.0001.jpg
180181

181182
Begin sequence iteration 1
182183
copyA.#.jpg -> ./copyA.0002.jpg
183184
copyB.#.jpg -> copyB.0002.jpg
184185
Reading ./copyA.0002.jpg
185186
Output: copyB.0002.jpg
187+
oiiotool Creating ColorConfig
186188
Writing copyB.0002.jpg
187189

188190
Begin sequence iteration 2
189191
copyA.#.jpg -> ./copyA.0003.jpg
190192
copyB.#.jpg -> copyB.0003.jpg
191193
Reading ./copyA.0003.jpg
192194
Output: copyB.0003.jpg
195+
oiiotool Creating ColorConfig
193196
Writing copyB.0003.jpg
194197

195198
Begin sequence iteration 3
196199
copyA.#.jpg -> ./copyA.0004.jpg
197200
copyB.#.jpg -> copyB.0004.jpg
198201
Reading ./copyA.0004.jpg
199202
Output: copyB.0004.jpg
203+
oiiotool Creating ColorConfig
200204
Writing copyB.0004.jpg
201205

202206
Begin sequence iteration 4
203207
copyA.#.jpg -> ./copyA.0005.jpg
204208
copyB.#.jpg -> copyB.0005.jpg
205209
Reading ./copyA.0005.jpg
206210
Output: copyB.0005.jpg
211+
oiiotool Creating ColorConfig
207212
Writing copyB.0005.jpg
208213

209214
Begin sequence iteration 5
210215
copyA.#.jpg -> ./copyA.0006.jpg
211216
copyB.#.jpg -> copyB.0006.jpg
212217
Reading ./copyA.0006.jpg
213218
Output: copyB.0006.jpg
219+
oiiotool Creating ColorConfig
214220
Writing copyB.0006.jpg
215221

216222
Begin sequence iteration 6
217223
copyA.#.jpg -> ./copyA.0007.jpg
218224
copyB.#.jpg -> copyB.0007.jpg
219225
Reading ./copyA.0007.jpg
220226
Output: copyB.0007.jpg
227+
oiiotool Creating ColorConfig
221228
Writing copyB.0007.jpg
222229

223230
Begin sequence iteration 7
224231
copyA.#.jpg -> ./copyA.0008.jpg
225232
copyB.#.jpg -> copyB.0008.jpg
226233
Reading ./copyA.0008.jpg
227234
Output: copyB.0008.jpg
235+
oiiotool Creating ColorConfig
228236
Writing copyB.0008.jpg
229237

230238
Begin sequence iteration 8
231239
copyA.#.jpg -> ./copyA.0009.jpg
232240
copyB.#.jpg -> copyB.0009.jpg
233241
Reading ./copyA.0009.jpg
234242
Output: copyB.0009.jpg
243+
oiiotool Creating ColorConfig
235244
Writing copyB.0009.jpg
236245

237246
Begin sequence iteration 9
238247
copyA.#.jpg -> ./copyA.0010.jpg
239248
copyB.#.jpg -> copyB.0010.jpg
240249
Reading ./copyA.0010.jpg
241250
Output: copyB.0010.jpg
251+
oiiotool Creating ColorConfig
242252
Writing copyB.0010.jpg
243253

244254
copyA.0001.jpg : 128 x 96, 3 channel, uint8 jpeg

0 commit comments

Comments
 (0)