🛠️🐜 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.

111 lines
3.1 KiB

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <vector>
  4. #ifdef __clang__
  5. #pragma clang diagnostic push
  6. #pragma clang diagnostic ignored "-Weverything"
  7. #endif
  8. #define STB_IMAGE_RESIZE_IMPLEMENTATION
  9. #include "stb_image_resize.h"
  10. #define STB_IMAGE_WRITE_IMPLEMENTATION
  11. #include "stb_image_write.h"
  12. #ifdef __clang__
  13. #pragma clang diagnostic pop
  14. #endif
  15. #include "tinyexr.h"
  16. inline unsigned char ftouc(float f, float gamma)
  17. {
  18. int i = static_cast<int>(255.0f * powf(f, 1.0f / gamma));
  19. if (i > 255) i = 255;
  20. if (i < 0) i = 0;
  21. return static_cast<unsigned char>(i);
  22. }
  23. bool SaveImage(const char* filename, const float* rgba, float scale, float gamma, int width, int height, bool ignore_alpha) {
  24. std::vector<unsigned char> dst(width * height * 4);
  25. // alpha channel is also affected by `scale` parameter.
  26. if(ignore_alpha) {
  27. for (size_t i = 0; i < width * height; i++) {
  28. dst[i * 4 + 0] = ftouc(rgba[i * 4 + 0] * scale, gamma);
  29. dst[i * 4 + 1] = ftouc(rgba[i * 4 + 1] * scale, gamma);
  30. dst[i * 4 + 2] = ftouc(rgba[i * 4 + 2] * scale, gamma);
  31. dst[i * 4 + 3] = 255;
  32. }
  33. } else {
  34. for (size_t i = 0; i < width * height * 4; i++) {
  35. dst[i] = ftouc(rgba[i] * scale, gamma);
  36. }
  37. }
  38. int ret = stbi_write_png(filename, width, height, 4, static_cast<const void*>(dst.data()), width * 4);
  39. return (ret > 0);
  40. }
  41. int main(int argc, char** argv)
  42. {
  43. if (argc < 3) {
  44. printf("Usage: exr2ldr input.exr output.png (scale) (resize_factor) (gammavalue) (-i or --ignore-alpha).\n");
  45. printf(" Pixel value [0.0, 1.0] in EXR is mapped to [0, 255] for LDR image.\n");
  46. printf(" You can adjust pixel value by `scale`(default = 1.0).\n");
  47. printf(" Resize image using `resize_factor`(default = 1.0). 2 = create half size image, 4 = 1/4 image, and so on\n");
  48. printf(" gammmavalue will be used for gamma correction when saving png image(default = 2.2).\n");
  49. printf(" Ignore alpha value of input using -i or --ignore-alpha flag, and alpha of output is set to 255.\n");
  50. exit(-1);
  51. }
  52. float scale = 1.0f;
  53. if (argc > 3) {
  54. scale = atof(argv[3]);
  55. }
  56. float resize_factor = 1.0f;
  57. if (argc > 4) {
  58. resize_factor = atof(argv[4]);
  59. }
  60. float gamma = 2.2f;
  61. if (argc > 5) {
  62. gamma = atof(argv[5]);
  63. }
  64. bool ignore_alpha = false;
  65. if (argc > 6 && (strcmp(argv[6], "-i") == 0 || strcmp(argv[6], "--ignore-alpha") == 0)) {
  66. ignore_alpha = true;
  67. }
  68. int width, height;
  69. float* rgba;
  70. const char* err;
  71. {
  72. int ret = LoadEXR(&rgba, &width, &height, argv[1], &err);
  73. if (ret != 0) {
  74. printf("err: %s\n", err);
  75. return -1;
  76. }
  77. }
  78. int dst_width = width / resize_factor;
  79. int dst_height = height / resize_factor;
  80. printf("dst = %d, %d\n", dst_width, dst_height);
  81. std::vector<float> buf(dst_width * dst_height * 4);
  82. int ret = stbir_resize_float(rgba, width, height, width*4*sizeof(float), &buf.at(0), dst_width, dst_height,dst_width*4*sizeof(float), 4);
  83. assert(ret != 0);
  84. bool ok = SaveImage(argv[2], &buf.at(0), scale, gamma, dst_width, dst_height, ignore_alpha);
  85. free(rgba);
  86. return (ok ? 0 : -1);
  87. }