Files
negative-converter/src/converter/invert/Inverter.cpp
Christoph K. 65b411b23d chore: initial project scaffold from architecture design
- Add CLAUDE.md with project overview, tech stack, build commands,
  architecture description, coding standards, and sample images section
- Add full directory structure: src/, docs/, tests/, import/
- Add CMakeLists.txt with C++20, OpenCV/LibRaw/Qt6 dependencies,
  converter_core static lib, optional GUI, and GTest tests
- Add architecture documentation: ARCHITECTURE.md, PIPELINE.md, MODULES.md
- Add source skeletons for all pipeline stages:
  RawLoader, Preprocessor, NegativeDetector, Inverter, ColorCorrector,
  CropProcessor, OutputWriter, Pipeline, MainWindow, CliRunner, main.cpp
- Add initial test stubs for pipeline and rawloader
- Add sample ARW files in import/ for integration testing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:28:32 +01:00

60 lines
1.8 KiB
C++

#include "Inverter.h"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <format>
#include <iostream>
namespace photoconv {
StageResult Inverter::process(ImageData data) const {
if (data.rgb.empty()) {
return std::unexpected(make_error(
ErrorCode::InversionFailed, "Inverter received empty image"));
}
switch (data.film_type) {
case FilmType::ColorNegative:
std::cout << "[Invert] Inverting color negative (C-41)" << std::endl;
return invert_color_negative(std::move(data));
case FilmType::BWNegative:
std::cout << "[Invert] Inverting B&W negative" << std::endl;
return invert_bw_negative(std::move(data));
case FilmType::ColorPositive:
case FilmType::BWPositive:
std::cout << "[Invert] Positive detected, skipping inversion" << std::endl;
return data;
case FilmType::Unknown:
std::cout << "[Invert] Unknown film type, applying default inversion" << std::endl;
return invert_color_negative(std::move(data));
}
return data; // Unreachable, but satisfies compiler
}
StageResult Inverter::invert_color_negative(ImageData data) {
// TODO: Implement proper C-41 orange mask removal.
// Strategy:
// 1. Sample unexposed border regions to characterize the orange mask
// 2. Compute per-channel mask color (typically R > G > B)
// 3. Subtract mask contribution from each channel
// 4. Apply bitwise_not inversion
// 5. Apply per-channel scaling to normalize levels
// Basic inversion for now
cv::bitwise_not(data.rgb, data.rgb);
return data;
}
StageResult Inverter::invert_bw_negative(ImageData data) {
cv::bitwise_not(data.rgb, data.rgb);
return data;
}
} // namespace photoconv