Skip to content

Commit 674470e

Browse files
committed
Refactorizing all 2
1 parent c991bf9 commit 674470e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1573
-842
lines changed

CMakeLists.txt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,26 @@ set(CORE_SOURCES
7272
src/core/arguments/parsing/OptionsConverter.cpp
7373
src/core/engine/Engine.cpp
7474
src/core/engine/Initialization.cpp
75+
src/core/engine/initialization/CalibrationHandler.cpp
76+
src/core/engine/initialization/ConfigReporter.cpp
77+
src/core/engine/initialization/FileSorter.cpp
78+
src/core/engine/initialization/InputFileFilter.cpp
7579
src/core/engine/PatchAnalysisStrategy.cpp
80+
src/core/engine/processing/AnalysisLoopRunner.cpp
7681
src/core/engine/processing/CornerDetectionHandler.cpp
7782
src/core/engine/processing/Processing.cpp
7883
src/core/engine/processing/ResultAggregator.cpp
7984
src/core/engine/Reporting.cpp
8085
src/core/engine/Validation.cpp
8186
src/core/graphics/ChartGenerator.cpp
8287
src/core/graphics/detection/ChartCornerDetector.cpp
88+
src/core/graphics/drawing/AxisDrawer.cpp
89+
src/core/graphics/drawing/AxisLabelDrawer.cpp
8390
src/core/graphics/drawing/CurveDrawer.cpp
91+
src/core/graphics/drawing/FooterDrawer.cpp
92+
src/core/graphics/drawing/GridDrawer.cpp
8493
src/core/graphics/drawing/LabelDrawer.cpp
94+
src/core/graphics/drawing/TitleDrawer.cpp
8595
src/core/graphics/FontManager.cpp
8696
src/core/graphics/geometry/KeystoneCorrection.cpp
8797
src/core/graphics/ImageProcessing.cpp
@@ -92,11 +102,13 @@ set(CORE_SOURCES
92102
src/core/graphics/PlotOrchestrator.cpp
93103
src/core/graphics/Plotting.cpp
94104
src/core/io/OutputWriter.cpp
95-
src/core/io/RawFile.cpp
105+
src/core/io/raw/RawFile.cpp
106+
src/core/io/raw/RawImageAccessor.cpp
107+
src/core/io/raw/RawLoader.cpp
108+
src/core/io/raw/RawMetadataExtractor.cpp
96109
src/core/math/Math.cpp
97110
src/core/setup/CalibrationEstimator.cpp
98111
src/core/setup/ChartProfile.cpp
99-
src/core/setup/FileSorter.cpp
100112
src/core/setup/MetadataExtractor.cpp
101113
src/core/setup/PlotLabelGenerator.cpp
102114
src/core/setup/SensorResolution.cpp

src/core/analysis/RawProcessor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* calibration.
66
*/
77
#include "RawProcessor.hpp"
8-
#include "../io/RawFile.hpp"
8+
#include "../io/raw/RawFile.hpp"
99
#include "../math/Math.hpp"
1010
#include <iomanip>
1111
#include <iostream>

src/core/engine/Initialization.cpp

Lines changed: 19 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,214 +1,56 @@
11
// File: src/core/engine/Initialization.cpp
22
/**
33
* @file src/core/engine/Initialization.cpp
4-
* @brief Implementation of the analysis initialization process.
4+
* @brief Implementation of the analysis initialization process orchestration.
55
*/
66
#include "Initialization.hpp"
7-
#include "../analysis/RawProcessor.hpp"
8-
#include "../setup/CalibrationEstimator.hpp"
9-
#include "../setup/FileSorter.hpp"
7+
#include "initialization/InputFileFilter.hpp"
8+
#include "initialization/CalibrationHandler.hpp"
9+
#include "initialization/ConfigReporter.hpp"
10+
#include "initialization/FileSorter.hpp"
1011
#include "../setup/MetadataExtractor.hpp"
1112
#include "../setup/PlotLabelGenerator.hpp"
1213
#include "../setup/SensorResolution.hpp"
1314
#include "../utils/CommandGenerator.hpp"
14-
#include <algorithm>
15-
#include <cstring>
16-
#include <filesystem>
17-
#include <iomanip>
1815
#include <libintl.h>
19-
#include <set>
2016

2117
#define _(string) gettext(string)
2218

23-
namespace fs = std::filesystem;
24-
2519
bool InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream) {
20+
21+
const DynaRange::Engine::Initialization::InputFileFilter file_filter;
22+
file_filter.Filter(opts, log_stream);
2623

27-
// --- 1. Exclude Calibration Files from Analysis ---
28-
if (!opts.dark_file_path.empty() || !opts.sat_file_path.empty()) {
29-
std::set<std::string> calibration_files;
30-
if (!opts.dark_file_path.empty()) {
31-
calibration_files.insert(opts.dark_file_path);
32-
}
33-
if (!opts.sat_file_path.empty()) {
34-
calibration_files.insert(opts.sat_file_path);
35-
}
36-
37-
std::vector<std::string> files_to_remove;
38-
auto original_size = opts.input_files.size();
39-
40-
opts.input_files.erase(
41-
std::remove_if(opts.input_files.begin(), opts.input_files.end(),
42-
[&](const std::string& input_file) {
43-
if (calibration_files.count(input_file)) {
44-
files_to_remove.push_back(input_file);
45-
return true;
46-
}
47-
return false;
48-
}),
49-
opts.input_files.end()
50-
);
51-
52-
if (!files_to_remove.empty()) {
53-
log_stream << _("[INFO] The following files were excluded from the analysis because they are used for calibration:") << std::endl;
54-
for (const auto& file : files_to_remove) {
55-
log_stream << " - " << fs::path(file).filename().string() << std::endl;
56-
}
57-
}
58-
}
59-
60-
// --- 2. Deduplicate Input Files ---
61-
if (!opts.input_files.empty()) {
62-
std::vector<std::string> unique_files;
63-
std::set<std::string> seen_files;
64-
unique_files.reserve(opts.input_files.size());
65-
for (const auto& file : opts.input_files) {
66-
if (seen_files.insert(file).second) {
67-
unique_files.push_back(file);
68-
} else {
69-
log_stream << _("Warning: Duplicate input file ignored: ") << file << std::endl;
70-
}
71-
}
72-
opts.input_files = unique_files;
24+
if (opts.input_files.empty()) {
25+
log_stream << _("Error: No valid input files remain after filtering for calibration files.") << std::endl;
26+
return false;
7327
}
7428

75-
// --- 3. Pre-analysis of all files to get metadata (moved to the beginning) ---
7629
log_stream << _("Pre-analyzing files to extract metadata...") << std::endl;
7730
auto file_info = ExtractFileInfo(opts.input_files, log_stream);
7831
if (file_info.empty()) {
7932
log_stream << _("Error: None of the input files could be processed.") << std::endl;
8033
return false;
8134
}
8235

83-
// --- 4. DEFAULT CALIBRATION ESTIMATION (now uses pre-analyzed data) ---
84-
if (opts.dark_file_path.empty() && opts.black_level_is_default) {
85-
log_stream << _("[INFO] Black level not specified. Attempting to estimate from RAW file...") << std::endl;
86-
auto estimated_black = CalibrationEstimator::EstimateBlackLevel(opts, file_info, log_stream);
87-
if (estimated_black) {
88-
opts.dark_value = *estimated_black;
89-
} else {
90-
log_stream << _("[Warning] Could not estimate black level. Using fallback default value: ")
91-
<< opts.dark_value << std::endl;
92-
}
93-
}
94-
95-
if (opts.sat_file_path.empty() && opts.saturation_level_is_default) {
96-
log_stream << _("[INFO] Saturation level not specified. Attempting to estimate from RAW file...") << std::endl;
97-
auto estimated_sat = CalibrationEstimator::EstimateSaturationLevel(opts, file_info, log_stream);
98-
if (estimated_sat) {
99-
opts.saturation_value = *estimated_sat;
100-
} else {
101-
log_stream << _("[Warning] Could not estimate saturation level. Using fallback default value: ")
102-
<< opts.saturation_value << std::endl;
103-
}
104-
}
105-
106-
// --- 5. CALIBRATION FROM EXPLICIT FILES ---
107-
if (!opts.dark_file_path.empty()) {
108-
auto dark_val_opt = ProcessDarkFrame(opts.dark_file_path, log_stream);
109-
if (!dark_val_opt) { log_stream << _("Fatal error processing dark frame.") << std::endl; return false;
110-
}
111-
opts.dark_value = *dark_val_opt;
112-
}
113-
if (!opts.sat_file_path.empty()) {
114-
auto sat_val_opt = ProcessSaturationFrame(opts.sat_file_path, log_stream);
115-
if (!sat_val_opt) { log_stream << _("Fatal error processing saturation frame.") << std::endl; return false;
116-
}
117-
opts.saturation_value = *sat_val_opt;
118-
}
119-
120-
// --- 6. SETUP PROCESS ORCHESTRATION (using already extracted metadata) ---
121-
// --- Print table with dynamic widths ---
122-
size_t max_file_width = strlen("File");
123-
size_t max_bright_width = strlen("Brightness");
124-
size_t max_iso_width = strlen("ISO");
125-
126-
for (const auto& info : file_info) {
127-
max_file_width = std::max(max_file_width, fs::path(info.filename).filename().string().length());
128-
std::stringstream bright_ss;
129-
bright_ss << std::fixed << std::setprecision(2) << info.mean_brightness;
130-
max_bright_width = std::max(max_bright_width, bright_ss.str().length());
131-
132-
std::stringstream iso_ss;
133-
iso_ss << static_cast<int>(info.iso_speed);
134-
max_iso_width = std::max(max_iso_width, iso_ss.str().length());
135-
}
136-
137-
max_file_width += 2;
138-
max_bright_width += 2;
139-
max_iso_width += 2;
140-
log_stream << "\n" << _("Sorting files based on pre-analyzed data:") << std::endl;
141-
log_stream << " " << std::left << std::setw(max_file_width) << "File"
142-
<< std::right << std::setw(max_bright_width) << "Brightness"
143-
<< std::right << std::setw(max_iso_width) << "ISO" << std::endl;
144-
log_stream << " " << std::string(max_file_width + max_bright_width + max_iso_width, '-') << std::endl;
145-
for (const auto& info : file_info) {
146-
log_stream << " " << std::left << std::setw(max_file_width) << fs::path(info.filename).filename().string()
147-
<< std::right << std::setw(max_bright_width) << std::fixed << std::setprecision(2) << info.mean_brightness
148-
<< std::right << std::setw(max_iso_width) << static_cast<int>(info.iso_speed) << std::endl;
36+
const DynaRange::Engine::Initialization::CalibrationHandler calib_handler;
37+
if (!calib_handler.HandleCalibration(opts, file_info, log_stream)) {
38+
return false; // Fatal error during calibration file processing
14939
}
15040

41+
const DynaRange::Engine::Initialization::ConfigReporter reporter;
42+
reporter.PrintPreAnalysisTable(file_info, log_stream);
43+
15144
FileOrderResult order = DetermineFileOrder(file_info, log_stream);
152-
std::map<std::string, std::string> labels = GeneratePlotLabels(
153-
order.sorted_filenames,
154-
file_info,
155-
order.was_exif_sort_possible
156-
);
15745
opts.input_files = order.sorted_filenames;
158-
opts.plot_labels = labels;
46+
opts.plot_labels = GeneratePlotLabels(order.sorted_filenames, file_info, order.was_exif_sort_possible);
15947

16048
if (opts.sensor_resolution_mpx == 0.0) {
16149
opts.sensor_resolution_mpx = DetectSensorResolution(opts.input_files, log_stream);
16250
}
163-
164-
// --- 7. PRINT FINAL CONFIGURATION ---
165-
log_stream << std::fixed << std::setprecision(2);
166-
log_stream << "\n" << _("[Final configuration]") << std::endl;
167-
log_stream << _("Black level: ") << opts.dark_value
168-
<< (opts.black_level_is_default ? _(" (estimated)") : "") << std::endl;
169-
log_stream << _("Saturation point: ") << opts.saturation_value
170-
<< (opts.saturation_level_is_default ? _(" (estimated)") : "") << std::endl;
171-
// New logic to dynamically build the list of channels to be analyzed.
172-
std::vector<std::string> selected_channels;
173-
if (opts.raw_channels.R) selected_channels.push_back("R");
174-
if (opts.raw_channels.G1) selected_channels.push_back("G1");
175-
if (opts.raw_channels.G2) selected_channels.push_back("G2");
176-
if (opts.raw_channels.B) selected_channels.push_back("B");
177-
if (opts.raw_channels.AVG) selected_channels.push_back("AVG");
178-
179-
std::stringstream channels_ss;
180-
for(size_t i = 0; i < selected_channels.size(); ++i) {
181-
channels_ss << selected_channels[i] << (i < selected_channels.size() - 1 ? ", " : "");
182-
}
18351

184-
std::string channel_label = (selected_channels.size() > 1) ?
185-
_("Analysis channels: ") : _("Analysis channel: ");
186-
log_stream << channel_label << channels_ss.str() << std::endl;
187-
if (opts.sensor_resolution_mpx > 0.0) {
188-
log_stream << _("Sensor resolution: ") << opts.sensor_resolution_mpx << _(" Mpx") << std::endl;
189-
}
190-
log_stream << _("SNR threshold(s): ");
191-
for(size_t i = 0; i < opts.snr_thresholds_db.size(); ++i) {
192-
log_stream << opts.snr_thresholds_db[i] << (i == opts.snr_thresholds_db.size() - 1 ? "" : ", ");
193-
}
194-
log_stream << _(" dB") << std::endl;
195-
log_stream << _("DR normalization: ") << opts.dr_normalization_mpx << _(" Mpx") << std::endl;
196-
log_stream << _("Polynomic order: ") << opts.poly_order << std::endl;
197-
log_stream << _("Patch ratio: ") << opts.patch_ratio << std::endl;
198-
log_stream << _("Plotting: ");
199-
if (!opts.generate_plot) {
200-
log_stream << _("No graphics") << std::endl;
201-
} else {
202-
switch (opts.plot_command_mode) {
203-
case 1: log_stream << _("Graphics without command CLI") << std::endl;
204-
break;
205-
case 2: log_stream << _("Graphics with short command CLI") << std::endl; break;
206-
case 3: log_stream << _("Graphics with long command CLI") << std::endl; break;
207-
default: log_stream << _("Graphics enabled") << std::endl; break;
208-
}
209-
}
52+
reporter.PrintFinalConfiguration(opts, log_stream);
21053

211-
log_stream << _("Output file: ") << opts.output_filename << "\n" << std::endl;
21254
if (opts.plot_command_mode == 2) {
21355
opts.generated_command = CommandGenerator::GenerateCommand(CommandFormat::PlotShort);
21456
} else if (opts.plot_command_mode == 3) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// File: src/core/engine/initialization/CalibrationHandler.cpp
2+
/**
3+
* @file CalibrationHandler.cpp
4+
* @brief Implements the sensor calibration logic.
5+
*/
6+
#include "CalibrationHandler.hpp"
7+
#include "../../analysis/RawProcessor.hpp"
8+
#include "../../setup/CalibrationEstimator.hpp"
9+
#include <libintl.h>
10+
11+
#define _(string) gettext(string)
12+
13+
namespace DynaRange::Engine::Initialization {
14+
15+
bool CalibrationHandler::HandleCalibration(ProgramOptions& opts, const std::vector<FileInfo>& file_info, std::ostream& log_stream) const
16+
{
17+
// --- 1. DEFAULT CALIBRATION ESTIMATION ---
18+
if (opts.dark_file_path.empty() && opts.black_level_is_default) {
19+
log_stream << _("[INFO] Black level not specified. Attempting to estimate from RAW file...") << std::endl;
20+
auto estimated_black = CalibrationEstimator::EstimateBlackLevel(opts, file_info, log_stream);
21+
if (estimated_black) {
22+
opts.dark_value = *estimated_black;
23+
} else {
24+
log_stream << _("[Warning] Could not estimate black level. Using fallback default value: ")
25+
<< opts.dark_value << std::endl;
26+
}
27+
}
28+
29+
if (opts.sat_file_path.empty() && opts.saturation_level_is_default) {
30+
log_stream << _("[INFO] Saturation level not specified. Attempting to estimate from RAW file...") << std::endl;
31+
auto estimated_sat = CalibrationEstimator::EstimateSaturationLevel(opts, file_info, log_stream);
32+
if (estimated_sat) {
33+
opts.saturation_value = *estimated_sat;
34+
} else {
35+
log_stream << _("[Warning] Could not estimate saturation level. Using fallback default value: ")
36+
<< opts.saturation_value << std::endl;
37+
}
38+
}
39+
40+
// --- 2. CALIBRATION FROM EXPLICIT FILES (overwrites estimates) ---
41+
if (!opts.dark_file_path.empty()) {
42+
auto dark_val_opt = ProcessDarkFrame(opts.dark_file_path, log_stream);
43+
if (!dark_val_opt) {
44+
log_stream << _("Fatal error processing dark frame.") << std::endl;
45+
return false;
46+
}
47+
opts.dark_value = *dark_val_opt;
48+
}
49+
if (!opts.sat_file_path.empty()) {
50+
auto sat_val_opt = ProcessSaturationFrame(opts.sat_file_path, log_stream);
51+
if (!sat_val_opt) {
52+
log_stream << _("Fatal error processing saturation frame.") << std::endl;
53+
return false;
54+
}
55+
opts.saturation_value = *sat_val_opt;
56+
}
57+
58+
return true;
59+
}
60+
61+
} // namespace DynaRange::Engine::Initialization
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// File: src/core/engine/initialization/CalibrationHandler.hpp
2+
/**
3+
* @file CalibrationHandler.hpp
4+
* @brief Declares a component for handling sensor calibration.
5+
* @details This module adheres to SRP by encapsulating all logic related to
6+
* determining the black and saturation levels, either by estimating them or by
7+
* processing dedicated calibration files.
8+
*/
9+
#pragma once
10+
11+
#include "../../arguments/ArgumentsOptions.hpp"
12+
#include "../../setup/MetadataExtractor.hpp" // For FileInfo
13+
#include <ostream>
14+
15+
namespace DynaRange::Engine::Initialization {
16+
17+
/**
18+
* @class CalibrationHandler
19+
* @brief Manages the determination of black and saturation levels.
20+
*/
21+
class CalibrationHandler {
22+
public:
23+
/**
24+
* @brief Determines the final black and saturation values.
25+
* @details This function follows a clear priority:
26+
* 1. If explicit calibration files are provided in `opts`, it processes them.
27+
* 2. Otherwise, if default values are being used, it attempts to estimate them.
28+
* 3. If estimation fails, it falls back to the hardcoded default values.
29+
* The function modifies the ProgramOptions object directly.
30+
* @param opts A reference to the program options, which will be updated.
31+
* @param file_info A vector of pre-analyzed file metadata for estimation.
32+
* @param log_stream The output stream for logging messages.
33+
* @return true on success, false if a fatal error occurs during processing.
34+
*/
35+
bool HandleCalibration(ProgramOptions& opts, const std::vector<FileInfo>& file_info, std::ostream& log_stream) const;
36+
};
37+
38+
} // namespace DynaRange::Engine::Initialization

0 commit comments

Comments
 (0)