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

image.cpp 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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) {
  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. // try to read EXIF data
  39. {
  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. }
  49. return true;
  50. } else {
  51. cerr << "Can not read \"" << file_path << "\" as an image." << endl;
  52. return false;
  53. }
  54. stbi_image_free(data);
  55. }
  56. bool Image::save_as_ppm_file(const char *file_path, bool ascii) const {
  57. if (ascii) {
  58. // ASCII
  59. ofstream out(file_path);
  60. out << "P3\n";
  61. out << m_width << ' ' << m_height << '\n';
  62. out << "255\n";
  63. unsigned int pixels = m_width * m_height;
  64. unsigned int index = 0;
  65. for (unsigned int i = 0; i < pixels; i++) {
  66. out << (int)m_image_data[index] << ' ' << (int)m_image_data[index + 1] << ' ' << (int)m_image_data[index + 2] << '\n';
  67. index += 3;
  68. }
  69. out.close();
  70. return true;
  71. } else {
  72. // binary
  73. ofstream out(file_path);
  74. out << "P6\n";
  75. out << m_width << ' ' << m_height << '\n';
  76. out << "255\n";
  77. unsigned int pixels = m_width * m_height;
  78. unsigned int index = 0;
  79. for (unsigned int i = 0; i < pixels; i++) {
  80. out << m_image_data[index] << m_image_data[index + 1] << m_image_data[index + 2];
  81. index += 3;
  82. }
  83. out.close();
  84. return true;
  85. }
  86. }
  87. LdrHistogram Image::histogram() const {
  88. LdrHistogram hist;
  89. hist.m_bins.resize(256, 0);
  90. if (m_image_data.size() == 0) {
  91. return hist;
  92. }
  93. for (unsigned int i = 0; i < m_image_data.size(); i++) {
  94. hist.m_bins[m_image_data[i]]++;
  95. }
  96. hist.m_max_freq = 0;
  97. for (unsigned int i = 0; i < 256; i++) {
  98. hist.m_max_freq = max_number(hist.m_max_freq, hist.m_bins[i]);
  99. }
  100. return hist;
  101. }
  102. unsigned int Image::get_width() const {
  103. return m_width;
  104. }
  105. unsigned int Image::get_height() const {
  106. return m_height;
  107. }
  108. unsigned int Image::get_components() const {
  109. return m_components;
  110. }
  111. bool Image::has_equal_dimensions(const Image &other) const {
  112. return (m_width == other.m_width &&
  113. m_height == other.m_height &&
  114. m_components == other.m_components);
  115. }
  116. double Image::get_exposure_time() const {
  117. return m_exposure_time;
  118. }
  119. const unsigned char* Image::get_const_image_data() const {
  120. return m_image_data.data();
  121. }
  122. unsigned char* Image::get_image_data() {
  123. return m_image_data.data();
  124. }