Monochrome is the fourth effect and the third that declares needsSources() false, so it works as a filter stage at the end of a cascade and can also lead one, filling the canvas from a source the way blur and grain do. Its knobs are the channel weighting, the contrast, a toner and the strength: the weighting offers the mixes a photographer would make behind the lens, so the colour names weigh that channel most and "red" darkens a sky the way a red filter does; contrast pulls the greys away from mid grey; the toners tint the finished greys warm (sepia), barely (selenium) or cold (cyanotype); and strength mixes the result back over the colour input, which at 0 is a pass through. Contrast and toner only ever see one grey, so the whole tail of the conversion is folded into a 256-entry table per channel, built once before the parallel pass; the per-pixel work is then integer only, with the weights as 1024ths and the tints as 256ths. The Rng is touched only for the source pick and the crop offset, serially, before any threading. The tests gain a `monochrome` section: neutrality of the output, each weighting measured on a pure red field, the contrast pivot at mid grey, both toner directions, strength as a pass through and as a midpoint, and the sourceless render that stays black. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
58 lines
1.8 KiB
CMake
58 lines
1.8 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
project(effector VERSION 0.1.0 LANGUAGES CXX)
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
endif()
|
|
|
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
|
|
|
|
find_package(PkgConfig REQUIRED)
|
|
pkg_check_modules(GTKMM REQUIRED IMPORTED_TARGET gtkmm-4.0)
|
|
pkg_check_modules(GDKPIXBUF REQUIRED IMPORTED_TARGET gdk-pixbuf-2.0)
|
|
|
|
find_package(Threads REQUIRED)
|
|
|
|
# --- core: effects and image handling, no GUI ---------------------------------
|
|
add_library(effector_core STATIC
|
|
src/core/chain.cpp
|
|
src/core/effect.cpp
|
|
src/core/image.cpp
|
|
src/core/params.cpp
|
|
src/core/project.cpp
|
|
src/core/registry.cpp
|
|
src/core/rng.cpp
|
|
src/effects/blur.cpp
|
|
src/effects/grain.cpp
|
|
src/effects/monochrome.cpp
|
|
src/effects/scanlines.cpp
|
|
)
|
|
target_include_directories(effector_core PUBLIC src)
|
|
# The core is GUI-free: it only needs gdk-pixbuf for decoding and encoding,
|
|
# so headless rendering works without a display.
|
|
target_link_libraries(effector_core PUBLIC PkgConfig::GDKPIXBUF Threads::Threads)
|
|
target_compile_options(effector_core PRIVATE -Wall -Wextra -Wpedantic)
|
|
|
|
# --- application --------------------------------------------------------------
|
|
add_executable(effector
|
|
src/main.cpp
|
|
src/cli/options.cpp
|
|
src/gui/app.cpp
|
|
src/gui/window.cpp
|
|
)
|
|
target_link_libraries(effector PRIVATE effector_core PkgConfig::GTKMM)
|
|
target_compile_options(effector PRIVATE -Wall -Wextra -Wpedantic)
|
|
|
|
install(TARGETS effector RUNTIME DESTINATION bin)
|
|
|
|
# --- tests --------------------------------------------------------------------
|
|
include(CTest)
|
|
if(BUILD_TESTING)
|
|
add_subdirectory(tests)
|
|
endif()
|