/src/apps/ociocheck/main.cpp

http://github.com/imageworks/OpenColorIO · C++ · 318 lines · 278 code · 38 blank · 2 comment · 33 complexity · 140ba4ef08535bde600751f73ff0edca MD5 · raw file

  1. // SPDX-License-Identifier: BSD-3-Clause
  2. // Copyright Contributors to the OpenColorIO Project.
  3. #include <cstdlib>
  4. #include <iostream>
  5. #include <fstream>
  6. #include <set>
  7. #include <vector>
  8. #include <OpenColorIO/OpenColorIO.h>
  9. namespace OCIO = OCIO_NAMESPACE;
  10. #include "apputils/argparse.h"
  11. const char * DESC_STRING = "\n\n"
  12. "ociocheck is useful to validate that the specified OCIO configuration\n"
  13. "is valid, and that all the color transforms are defined.\n"
  14. "For example, it is possible that the configuration may reference\n"
  15. "lookup tables that do not exist. ociocheck will find these cases.\n\n"
  16. "ociocheck can also be used to clean up formatting on an existing profile\n"
  17. "that has been manually edited, using the '-o' option.\n";
  18. int main(int argc, const char **argv)
  19. {
  20. bool help = false;
  21. int errorcount = 0;
  22. std::string inputconfig;
  23. std::string outputconfig;
  24. ArgParse ap;
  25. ap.options("ociocheck -- validate an OpenColorIO configuration\n\n"
  26. "usage: ociocheck [options]\n",
  27. "--help", &help, "Print help message",
  28. "--iconfig %s", &inputconfig, "Input .ocio configuration file (default: $OCIO)",
  29. "--oconfig %s", &outputconfig, "Output .ocio file",
  30. NULL);
  31. if (ap.parse(argc, argv) < 0)
  32. {
  33. std::cout << ap.geterror() << std::endl;
  34. ap.usage();
  35. std::cout << DESC_STRING;
  36. return 1;
  37. }
  38. if (help)
  39. {
  40. ap.usage();
  41. std::cout << DESC_STRING;
  42. return 1;
  43. }
  44. try
  45. {
  46. OCIO::ConstConfigRcPtr config;
  47. std::cout << std::endl;
  48. std::cout << "OpenColorIO Library Version: " << OCIO::GetVersion() << std::endl;
  49. std::cout << "OpenColorIO Library VersionHex: " << OCIO::GetVersionHex() << std::endl;
  50. if(!inputconfig.empty())
  51. {
  52. std::cout << "Loading " << inputconfig << std::endl;
  53. config = OCIO::Config::CreateFromFile(inputconfig.c_str());
  54. }
  55. else if(OCIO::GetEnvVariable("OCIO"))
  56. {
  57. std::cout << "Loading $OCIO " << OCIO::GetEnvVariable("OCIO") << std::endl;
  58. config = OCIO::Config::CreateFromEnv();
  59. }
  60. else
  61. {
  62. std::cout << "ERROR: You must specify an input OCIO configuration ";
  63. std::cout << "(either with --iconfig or $OCIO).\n";
  64. ap.usage ();
  65. std::cout << DESC_STRING;
  66. return 1;
  67. }
  68. std::cout << std::endl;
  69. std::cout << "** General **" << std::endl;
  70. std::cout << "Search Path: " << config->getSearchPath() << std::endl;
  71. std::cout << "Working Dir: " << config->getWorkingDir() << std::endl;
  72. std::cout << std::endl;
  73. if (config->getNumDisplays() == 0)
  74. {
  75. std::cout << "Error: At least one (display, view) pair must be defined." << std::endl;
  76. errorcount += 1;
  77. }
  78. else
  79. {
  80. std::cout << "Default Display: " << config->getDefaultDisplay() << std::endl;
  81. std::cout << "Default View: " << config->getDefaultView(config->getDefaultDisplay()) << std::endl;
  82. }
  83. {
  84. std::cout << std::endl;
  85. std::cout << "** Roles **" << std::endl;
  86. std::set<std::string> usedroles;
  87. const char * allroles[] = { OCIO::ROLE_DEFAULT, OCIO::ROLE_SCENE_LINEAR,
  88. OCIO::ROLE_DATA, OCIO::ROLE_REFERENCE,
  89. OCIO::ROLE_COMPOSITING_LOG, OCIO::ROLE_COLOR_TIMING,
  90. OCIO::ROLE_COLOR_PICKING,
  91. OCIO::ROLE_TEXTURE_PAINT, OCIO::ROLE_MATTE_PAINT,
  92. NULL };
  93. int MAXROLES=256;
  94. for(int i=0;i<MAXROLES; ++i)
  95. {
  96. const char * role = allroles[i];
  97. if(!role) break;
  98. usedroles.insert(role);
  99. OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(role);
  100. if(cs)
  101. {
  102. std::cout << cs->getName() << " (" << role << ")" << std::endl;
  103. }
  104. else
  105. {
  106. std::cout << "ERROR: NOT DEFINED" << " (" << role << ")" << std::endl;
  107. errorcount += 1;
  108. }
  109. }
  110. for(int i=0; i<config->getNumRoles(); ++i)
  111. {
  112. const char * role = config->getRoleName(i);
  113. if(usedroles.find(role) != usedroles.end()) continue;
  114. OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(role);
  115. if(cs)
  116. {
  117. std::cout << cs->getName() << " (" << role << ": user)" << std::endl;
  118. }
  119. else
  120. {
  121. std::cout << "ERROR: NOT DEFINED" << " (" << role << ")" << std::endl;
  122. errorcount += 1;
  123. }
  124. }
  125. }
  126. std::cout << std::endl;
  127. std::cout << "** ColorSpaces **" << std::endl;
  128. OCIO::ConstColorSpaceRcPtr lin = config->getColorSpace(OCIO::ROLE_SCENE_LINEAR);
  129. if(!lin)
  130. {
  131. std::cout << "Error: scene_linear role must be defined." << std::endl;
  132. errorcount += 1;
  133. }
  134. else
  135. {
  136. for(int i=0; i<config->getNumColorSpaces(); ++i)
  137. {
  138. OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(config->getColorSpaceNameByIndex(i));
  139. bool convertsToLinear = true;
  140. std::string convertsToLinearErrorText;
  141. bool convertsFromLinear = true;
  142. std::string convertsFromLinearErrorText;
  143. try
  144. {
  145. OCIO::ConstProcessorRcPtr p = config->getProcessor(cs, lin);
  146. }
  147. catch(OCIO::Exception & exception)
  148. {
  149. convertsToLinear = false;
  150. convertsToLinearErrorText = exception.what();
  151. }
  152. try
  153. {
  154. OCIO::ConstProcessorRcPtr p = config->getProcessor(lin, cs);
  155. }
  156. catch(OCIO::Exception & exception)
  157. {
  158. convertsFromLinear = false;
  159. convertsFromLinearErrorText = exception.what();
  160. }
  161. if(convertsToLinear && convertsFromLinear)
  162. {
  163. std::cout << cs->getName() << std::endl;
  164. }
  165. else if(!convertsToLinear && !convertsFromLinear)
  166. {
  167. std::cout << cs->getName();
  168. std::cout << " -- error" << std::endl;
  169. std::cout << "\t" << convertsToLinearErrorText << std::endl;
  170. std::cout << "\t" << convertsFromLinearErrorText << std::endl;
  171. errorcount += 1;
  172. }
  173. else if(convertsToLinear)
  174. {
  175. std::cout << cs->getName();
  176. std::cout << " -- input only" << std::endl;
  177. }
  178. else if(convertsFromLinear)
  179. {
  180. std::cout << cs->getName();
  181. std::cout << " -- output only" << std::endl;
  182. }
  183. }
  184. }
  185. std::cout << std::endl;
  186. std::cout << "** Looks **" << std::endl;
  187. if(config->getNumLooks()>0)
  188. {
  189. for(int i=0; i<config->getNumLooks(); ++i)
  190. {
  191. std::cout << config->getLookNameByIndex(i) << std::endl;
  192. OCIO::ConstLookRcPtr look = config->getLook(config->getLookNameByIndex(i));
  193. OCIO::ConstTransformRcPtr transform = look->getTransform();
  194. if(transform)
  195. {
  196. try
  197. {
  198. OCIO::ConstProcessorRcPtr process = config->getProcessor(transform);
  199. std::cout << "src file found" << std::endl;
  200. }
  201. catch(OCIO::Exception & exception)
  202. {
  203. std::cerr << "ERROR: " << exception.what() << std::endl;
  204. errorcount += 1;
  205. }
  206. }
  207. OCIO::ConstTransformRcPtr invTransform = look->getInverseTransform();
  208. if(invTransform)
  209. {
  210. try
  211. {
  212. OCIO::ConstProcessorRcPtr process = config->getProcessor(invTransform);
  213. std::cout << "src file found" << std::endl;
  214. }
  215. catch(OCIO::Exception & exception)
  216. {
  217. std::cerr << "ERROR: " << exception.what() << std::endl;
  218. errorcount += 1;
  219. }
  220. }
  221. }
  222. }
  223. else
  224. {
  225. std::cout << "no looks defined" << std::endl;
  226. }
  227. std::cout << std::endl;
  228. std::cout << "** Sanity Check **" << std::endl;
  229. try
  230. {
  231. config->sanityCheck();
  232. std::cout << "passed" << std::endl;
  233. }
  234. catch(OCIO::Exception & exception)
  235. {
  236. std::cout << "ERROR" << std::endl;
  237. errorcount += 1;
  238. std::cout << exception.what() << std::endl;
  239. }
  240. if(!outputconfig.empty())
  241. {
  242. std::ofstream output;
  243. output.open(outputconfig.c_str());
  244. if(!output.is_open())
  245. {
  246. std::cout << "Error opening " << outputconfig << " for writing." << std::endl;
  247. }
  248. else
  249. {
  250. config->serialize(output);
  251. output.close();
  252. std::cout << "Wrote " << outputconfig << std::endl;
  253. }
  254. }
  255. }
  256. catch(OCIO::Exception & exception)
  257. {
  258. std::cout << "ERROR: " << exception.what() << std::endl;
  259. return 1;
  260. } catch (std::exception& exception) {
  261. std::cout << "ERROR: " << exception.what() << "\n";
  262. return 1;
  263. }
  264. catch(...)
  265. {
  266. std::cout << "Unknown error encountered." << std::endl;
  267. return 1;
  268. }
  269. std::cout << std::endl;
  270. if(errorcount == 0)
  271. {
  272. std::cout << "Tests complete." << std::endl << std::endl;
  273. return 0;
  274. }
  275. else
  276. {
  277. std::cout << errorcount << " tests failed." << std::endl << std::endl;
  278. return 1;
  279. }
  280. }