🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
4.5 KiB

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <vector>
  4. #include "tinyexr.h"
  5. #include "cxxopts.hpp"
  6. int main(int argc, char** argv)
  7. {
  8. float min_value = -std::numeric_limits<float>::max();
  9. float max_value = std::numeric_limits<float>::max();
  10. float rgb_min[3] = {min_value, min_value, min_value};
  11. float rgb_max[3] = {max_value, max_value, max_value};
  12. cxxopts::Options options("normalmap", "help");
  13. options.show_positional_help();
  14. options.add_options()
  15. ("max", "Max intensity(apply all RGB channels)", cxxopts::value<float>())
  16. ("rmax", "Max Red intensity", cxxopts::value<float>())
  17. ("gmax", "Max Green intensity", cxxopts::value<float>())
  18. ("bmax", "Max Blue intensity", cxxopts::value<float>())
  19. ("min", "Min intensity(apply all RGB channels)", cxxopts::value<float>())
  20. ("rmin", "Min Red intensity", cxxopts::value<float>())
  21. ("gmin", "Min Green intensity", cxxopts::value<float>())
  22. ("bmin", "Min Blue intensity", cxxopts::value<float>())
  23. ("i,input", "Input filename", cxxopts::value<std::string>())
  24. ("o,output", "Output filename", cxxopts::value<std::string>())
  25. ("help", "Print help")
  26. ;
  27. auto result = options.parse(argc, argv);
  28. if (result.count("help")) {
  29. std::cout << options.help() << std::endl;
  30. }
  31. if (result.count("input") == 0) {
  32. std::cerr << "input filename missing" << std::endl;
  33. std::cout << options.help() << std::endl;
  34. return EXIT_FAILURE;
  35. }
  36. if (result.count("output") == 0) {
  37. std::cerr << "output filename missing" << std::endl;
  38. std::cout << options.help() << std::endl;
  39. return EXIT_FAILURE;
  40. }
  41. std::string input_filename = result["input"].as<std::string>();
  42. std::string output_filename = result["output"].as<std::string>();
  43. if (result.count("max")) {
  44. rgb_max[0] = result["max"].as<float>();
  45. rgb_max[1] = result["max"].as<float>();
  46. rgb_max[2] = result["max"].as<float>();
  47. }
  48. if (result.count("rmax")) {
  49. rgb_max[0] = result["rmax"].as<float>();
  50. }
  51. if (result.count("gmax")) {
  52. rgb_max[1] = result["gmax"].as<float>();
  53. }
  54. if (result.count("bmax")) {
  55. rgb_max[2] = result["bmax"].as<float>();
  56. }
  57. if (result.count("min")) {
  58. rgb_min[0] = result["min"].as<float>();
  59. rgb_min[1] = result["min"].as<float>();
  60. rgb_min[2] = result["min"].as<float>();
  61. }
  62. if (result.count("rmin")) {
  63. rgb_min[0] = result["rmin"].as<float>();
  64. }
  65. if (result.count("gmin")) {
  66. rgb_min[1] = result["gmin"].as<float>();
  67. }
  68. if (result.count("bmin")) {
  69. rgb_min[2] = result["bmin"].as<float>();
  70. }
  71. float *rgba = nullptr;
  72. int width, height;
  73. const char *err = nullptr;
  74. {
  75. int ret = LoadEXR(&rgba, &width, &height, input_filename.c_str(), &err);
  76. if (TINYEXR_SUCCESS != ret) {
  77. std::cerr << "Failed to load EXR file [" << input_filename << "] code = " << ret << std::endl;
  78. if (err) {
  79. std::cerr << err << std::endl;
  80. FreeEXRErrorMessage(err);
  81. }
  82. return EXIT_FAILURE;
  83. }
  84. }
  85. // clip pixel values.
  86. // ignore alpha channel for now.
  87. std::vector<float> rgb;
  88. rgb.resize(width * height * 3);
  89. float v_max[3] = {
  90. -std::numeric_limits<float>::max(),
  91. -std::numeric_limits<float>::max(),
  92. -std::numeric_limits<float>::max()};
  93. float v_min[3] = {
  94. std::numeric_limits<float>::max(),
  95. std::numeric_limits<float>::max(),
  96. std::numeric_limits<float>::max()};
  97. {
  98. for (size_t i = 0; i < width * height; i++) {
  99. rgb[3 * i + 0] = std::max(rgb_min[0], std::min(rgb_max[0], rgba[4 * i + 0]));
  100. rgb[3 * i + 1] = std::max(rgb_min[1], std::min(rgb_max[1], rgba[4 * i + 1]));
  101. rgb[3 * i + 2] = std::max(rgb_min[2], std::min(rgb_max[2], rgba[4 * i + 2]));
  102. v_max[0] = std::max(rgb[3 * i + 0], v_max[0]);
  103. v_max[1] = std::max(rgb[3 * i + 1], v_max[1]);
  104. v_max[2] = std::max(rgb[3 * i + 2], v_max[2]);
  105. v_min[0] = std::min(rgb[3 * i + 0], v_min[0]);
  106. v_min[1] = std::min(rgb[3 * i + 1], v_min[1]);
  107. v_min[2] = std::min(rgb[3 * i + 2], v_min[2]);
  108. }
  109. }
  110. std::cout << "v min = " << v_min[0] << ", " << v_min[1] << ", " << v_min[2] << std::endl;
  111. std::cout << "v max = " << v_max[0] << ", " << v_max[1] << ", " << v_max[2] << std::endl;
  112. {
  113. int ret = SaveEXR(rgb.data(), width, height, /* component */3, /* fp16 */0, output_filename.c_str(), &err);
  114. if (TINYEXR_SUCCESS != ret) {
  115. if (err) {
  116. std::cerr << err << std::endl;
  117. FreeEXRErrorMessage(err);
  118. }
  119. std::cerr << "Failed to save EXR file [" << input_filename << "] code = " << ret << std::endl;
  120. return EXIT_FAILURE;
  121. }
  122. }
  123. return EXIT_SUCCESS;
  124. }