- 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>
60 lines
1.8 KiB
C++
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
|