#include #include #include #include #include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" #include "image.h" #include "exif.h" #define max_number(a, b) (a) > (b) ? (a) : (b) #define min_number(a, b) (a) < (b) ? (a) : (b) using namespace std; using namespace haader; Image::Image(): m_width(0), m_height(0), m_components(0), m_exposure_time(0.0) { } void Image::to_string(string &s) const { stringstream ss; ss << "Image("; ss << m_width << 'x' << m_height << 'x' << m_components << ")"; s = ss.str(); } bool Image::read_from_file(const char *file_path) { int x = 0; int y = 0; int components = 0; unsigned char *data = stbi_load(file_path, &x, &y, &components, 0); if (data) { m_width = x; m_height = y; m_components = components; size_t size = (size_t)x * (size_t)y * (size_t)components; m_image_data.assign(data, data + size); // try to read EXIF data { ExifTags tags; ifstream stream; stream.open(file_path); if (stream.is_open() and ExifTags::read_from_jpeg(stream, tags)) { if (tags.get_exposure_time(m_exposure_time)) { cout << "Exposure time: " << m_exposure_time << " sec" << endl; } } } return true; } else { cerr << "Can not read \"" << file_path << "\" as an image." << endl; return false; } stbi_image_free(data); } bool Image::save_as_ppm_file(const char *file_path, bool ascii) const { if (ascii) { // ASCII ofstream out(file_path); out << "P3\n"; out << m_width << ' ' << m_height << '\n'; out << "255\n"; unsigned int pixels = m_width * m_height; unsigned int index = 0; for (unsigned int i = 0; i < pixels; i++) { out << (int)m_image_data[index] << ' ' << (int)m_image_data[index + 1] << ' ' << (int)m_image_data[index + 2] << '\n'; index += 3; } out.close(); return true; } else { // binary ofstream out(file_path); out << "P6\n"; out << m_width << ' ' << m_height << '\n'; out << "255\n"; unsigned int pixels = m_width * m_height; unsigned int index = 0; for (unsigned int i = 0; i < pixels; i++) { out << m_image_data[index] << m_image_data[index + 1] << m_image_data[index + 2]; index += 3; } out.close(); return true; } } LdrHistogram Image::histogram() const { LdrHistogram hist; hist.m_bins.resize(256, 0); if (m_image_data.size() == 0) { return hist; } for (unsigned int i = 0; i < m_image_data.size(); i++) { hist.m_bins[m_image_data[i]]++; } hist.m_max_freq = 0; for (unsigned int i = 0; i < 256; i++) { hist.m_max_freq = max_number(hist.m_max_freq, hist.m_bins[i]); } return hist; } unsigned int Image::get_width() const { return m_width; } unsigned int Image::get_height() const { return m_height; } unsigned int Image::get_components() const { return m_components; } bool Image::has_equal_dimensions(const Image &other) const { return (m_width == other.m_width && m_height == other.m_height && m_components == other.m_components); } double Image::get_exposure_time() const { return m_exposure_time; } const unsigned char* Image::get_const_image_data() const { return m_image_data.data(); } unsigned char* Image::get_image_data() { return m_image_data.data(); }