A tool to construct HDR-images from a series of exposures.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <fstream>
  4. #include <sstream>
  5. #include <vector>
  6. #define STB_IMAGE_IMPLEMENTATION
  7. #include "stb_image.h"
  8. #include "image.h"
  9. #include "exif.h"
  10. #define max_number(a, b) (a) > (b) ? (a) : (b)
  11. #define min_number(a, b) (a) < (b) ? (a) : (b)
  12. using namespace std;
  13. using namespace haader;
  14. Image::Image():
  15. m_width(0),
  16. m_height(0),
  17. m_components(0),
  18. m_exposure_time(0.0)
  19. {
  20. }
  21. void Image::to_string(string &s) const {
  22. stringstream ss;
  23. ss << "Image(";
  24. ss << m_width << 'x' << m_height << 'x' << m_components << ")";
  25. s = ss.str();
  26. }
  27. bool Image::read_from_file(const char *file_path, double exposure_time) {
  28. int x = 0;
  29. int y = 0;
  30. int components = 0;
  31. unsigned char *data = stbi_load(file_path, &x, &y, &components, 0);
  32. if (data) {
  33. m_width = x;
  34. m_height = y;
  35. m_components = components;
  36. size_t size = (size_t)x * (size_t)y * (size_t)components;
  37. m_image_data.assign(data, data + size);
  38. if (exposure_time <= 0.0) {
  39. // try to read EXIF data
  40. ExifTags tags;
  41. ifstream stream;
  42. stream.open(file_path);
  43. if (stream.is_open() and ExifTags::read_from_jpeg(stream, tags)) {
  44. if (tags.get_exposure_time(m_exposure_time)) {
  45. cout << "Exposure time: " << m_exposure_time << " sec" << endl;
  46. }
  47. }
  48. } else {
  49. m_exposure_time = exposure_time;
  50. }
  51. return true;
  52. } else {
  53. cerr << "Can not read \"" << file_path << "\" as an image." << endl;
  54. return false;
  55. }
  56. stbi_image_free(data);
  57. }
  58. bool Image::save_as_ppm_file(const char *file_path, bool ascii) const {
  59. if (ascii) {
  60. // ASCII
  61. ofstream out(file_path);
  62. out << "P3\n";
  63. out << m_width << ' ' << m_height << '\n';
  64. out << "255\n";
  65. unsigned int pixels = m_width * m_height;
  66. unsigned int index = 0;
  67. for (unsigned int i = 0; i < pixels; i++) {
  68. out << (int)m_image_data[index] << ' ' << (int)m_image_data[index + 1] << ' ' << (int)m_image_data[index + 2] << '\n';
  69. index += 3;
  70. }
  71. out.close();
  72. return true;
  73. } else {
  74. // binary
  75. ofstream out(file_path);
  76. out << "P6\n";
  77. out << m_width << ' ' << m_height << '\n';
  78. out << "255\n";
  79. unsigned int pixels = m_width * m_height;
  80. unsigned int index = 0;
  81. for (unsigned int i = 0; i < pixels; i++) {
  82. out << m_image_data[index] << m_image_data[index + 1] << m_image_data[index + 2];
  83. index += 3;
  84. }
  85. out.close();
  86. return true;
  87. }
  88. }
  89. LdrHistogram Image::histogram() const {
  90. LdrHistogram hist;
  91. hist.m_bins.resize(256, 0);
  92. if (m_image_data.size() == 0) {
  93. return hist;
  94. }
  95. for (unsigned int i = 0; i < m_image_data.size(); i++) {
  96. hist.m_bins[m_image_data[i]]++;
  97. }
  98. hist.m_max_freq = 0;
  99. for (unsigned int i = 0; i < 256; i++) {
  100. hist.m_max_freq = max_number(hist.m_max_freq, hist.m_bins[i]);
  101. }
  102. return hist;
  103. }
  104. unsigned int Image::get_width() const {
  105. return m_width;
  106. }
  107. unsigned int Image::get_height() const {
  108. return m_height;
  109. }
  110. unsigned int Image::get_components() const {
  111. return m_components;
  112. }
  113. bool Image::has_equal_dimensions(const Image &other) const {
  114. return (m_width == other.m_width &&
  115. m_height == other.m_height &&
  116. m_components == other.m_components);
  117. }
  118. double Image::get_exposure_time() const {
  119. return m_exposure_time;
  120. }
  121. const unsigned char* Image::get_const_image_data() const {
  122. return m_image_data.data();
  123. }
  124. unsigned char* Image::get_image_data() {
  125. return m_image_data.data();
  126. }