Skip to content

Commit

Permalink
Implement channel selection for color correction
Browse files Browse the repository at this point in the history
closes #67
  • Loading branch information
averne committed Oct 19, 2024
1 parent 424b6d1 commit f7b1b2d
Show file tree
Hide file tree
Showing 20 changed files with 237 additions and 153 deletions.
8 changes: 5 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"files.exclude": {
"**/build": true,
"**/out": true,
"*.elf": true,
"*.nacp": true,
"*.nro": true
"**/*.elf": true,
"**/*.nacp": true,
"**/*.nro": true,
"**/*.nso": true,
"**/*.ips": true,
},
}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export FZ_VERSION = 2.6.0
export FZ_VERSION = 2.7.0
export FZ_COMMIT = $(shell git rev-parse --short HEAD)
export FZ_TID = 0100000000000F12

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ Adjust the color of the screen of your Nintendo Switch.

# Images
<p float="left">
<img src="https://github.com/averne/Fizeau/assets/45773016/028b1554-da6b-4efa-be76-af05ede066b0" width="400" />
<img src="https://github.com/averne/Fizeau/assets/45773016/561e17a3-cd71-4d9e-bbee-1d2a9408df37" width="400" />
<img src="https://github.com/averne/Fizeau/assets/45773016/b3ad91b6-3e6c-4d47-a2af-26ef58496aa7" width="400" />
<img src="https://github.com/averne/Fizeau/assets/45773016/a5c4e32d-c7cd-4ef4-8298-d33e4984b79a" width="400" />
<img src="https://github.com/user-attachments/assets/9c3fd0a2-1af2-44a8-a9a2-445b36610d7e" width="410" />
<img src="https://github.com/user-attachments/assets/3564a11f-b7eb-4d01-a20e-0491443b7978" width="410" />
<img src="https://github.com/user-attachments/assets/bb469aca-fee4-4a4b-8616-1d3258d837b8" width="410" />
<img src="https://github.com/averne/Fizeau/assets/45773016/a5c4e32d-c7cd-4ef4-8298-d33e4984b79a" width="410" />
</p>

# Installation
Expand Down
20 changes: 12 additions & 8 deletions application/src/gfx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,10 @@ void render(int slot) {
s_queue.presentImage(s_swapchain, slot);
}

void render_preview(FizeauSettings &settings, int width, int height, int src_image_id, int dst_image_id) {
void render_preview(FizeauSettings &settings, Component components, Component filter,
int width, int height, int src_image_id, int dst_image_id) {
// Calculate initial coefficients
auto coeffs = filter_matrix(settings.filter);
auto coeffs = filter_matrix(filter);

// Apply temperature color correction
ColorMatrix wp = {};
Expand All @@ -353,12 +354,15 @@ void render_preview(FizeauSettings &settings, int width, int height, int src_ima
// Apply hue rotation
coeffs = dot(coeffs, hue_matrix(settings.hue));

auto colormatrix = glm::mat4(
coeffs[0], coeffs[1], coeffs[2], 0,
coeffs[3], coeffs[4], coeffs[5], 0,
coeffs[6], coeffs[7], coeffs[8], 0,
0, 0, 0, 1
);
auto colormatrix = glm::mat4(1.0f);

// Copy calculated coefficients if they are enabled
if (components & Component_Red)
std::copy_n(coeffs.begin() + 0, 3, &colormatrix[0][0]);
if (components & Component_Green)
std::copy_n(coeffs.begin() + 3, 3, &colormatrix[1][0]);
if (components & Component_Blue)
std::copy_n(coeffs.begin() + 6, 3, &colormatrix[2][0]);

s_cmdBuf.pushConstants(s_uniformMemBlock.getGpuAddr(), s_uniformMemBlock.getSize(), 0, sizeof(colormatrix), &colormatrix);
s_cmdBuf.bindUniformBuffer(DkStage_Compute, 0, s_uniformMemBlock.getGpuAddr(), s_uniformMemBlock.getSize());
Expand Down
3 changes: 2 additions & 1 deletion application/src/gfx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ void render(int slot);
void wait();
void exit();

void render_preview(FizeauSettings &settings, int width, int height, int src_image_id, int dst_image_id);
void render_preview(FizeauSettings &settings, Component components, Component filter,
int width, int height, int src_image_id, int dst_image_id);

void create_texture(dk::MemBlock &memblk, dk::Image &image, int width, int height, DkImageFormat fmt,
std::uint32_t sampler_id, std::uint32_t image_id);
Expand Down
34 changes: 20 additions & 14 deletions application/src/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// along with Fizeau. If not, see <http://www.gnu.org/licenses/>.

#include <algorithm>
#include <bit>
#include <tuple>
#include <imgui.h>
#include <imgui_deko3d.h>
Expand Down Expand Up @@ -72,14 +73,6 @@ bool new_slider(auto name, auto label, T &val, T min, T max, auto fmt, Args &&..
return ret;
};

template <std::size_t N>
bool new_combo(auto name, auto label, auto &val, const std::array<const char *, N> &names) {
auto [width, height] = im::GetIO().DisplaySize;
auto slider_pos = im::GetWindowPos().x + 0.04f * width;
im::TextUnformatted(name); im::SameLine(); im::SetCursorPosX(slider_pos);
return im::Combo(label, reinterpret_cast<int *>(&val), names.data(), names.size());
}

bool new_times(auto name, auto labelh, auto labelm, Time &t) {
auto [width, height] = im::GetIO().DisplaySize;
im::PushItemWidth(im::GetWindowWidth() * 0.2f);
Expand Down Expand Up @@ -232,10 +225,23 @@ Result draw_color_tab(Config &ctx) {
ctx.is_editing_day_profile |= new_slider("Day:", "##hued", ctx.profile.day_settings.hue, MIN_HUE, MAX_HUE, "%.2f");
ctx.is_editing_night_profile |= new_slider("Night:", "##huen", ctx.profile.night_settings.hue, MIN_HUE, MAX_HUE, "%.2f");

// Filter combos
im::SeparatorText("Filter");
ctx.is_editing_day_profile |= new_combo("Day:", "##filterd", ctx.profile.day_settings.filter, filters_names);
ctx.is_editing_night_profile |= new_combo("Night:", "##filtern", ctx.profile.night_settings.filter, filters_names);
// Components checkboxes
im::SeparatorText("Channels");

auto items_pos = im::GetWindowPos().x + 0.09f * width;

std::uint32_t c = ctx.profile.components;
im::TextUnformatted("Components:"); im::SameLine(); im::SetCursorPosX(items_pos);
im::CheckboxFlags("Red##compr", &c, Component_Red); im::SameLine();
im::CheckboxFlags("Green##compg", &c, Component_Green); im::SameLine();
im::CheckboxFlags("Blue##compb", &c, Component_Blue);
ctx.profile.components = static_cast<Component>(c);

int filter = (ctx.profile.filter == Component_None) ? 0 : std::countr_zero(static_cast<std::uint32_t>(ctx.profile.filter)) + 1;
im::TextUnformatted("Filter:"); im::SameLine(); im::SetCursorPosX(items_pos);
im::SetNextItemWidth(0.2f * width);
if (im::Combo("##filter", &filter, filters_names.data(), filters_names.size()))
ctx.profile.filter = static_cast<Component>(filter ? BIT(filter - 1) : filter);

im::EndTabItem();
return 0;
Expand Down Expand Up @@ -383,8 +389,8 @@ Result draw_main_window(Config &ctx) {
FZ_SCOPEGUARD([] { im::End(); });

auto [width, height] = im::GetIO().DisplaySize;
im::SetWindowPos( { 0.03f * width, 0.09f * height }, ImGuiCond_Always);
im::SetWindowSize({ 0.40f * width, 0.82f * height }, ImGuiCond_Always);
im::SetWindowPos( { 0.03f * width, 0.05f * height }, ImGuiCond_Always);
im::SetWindowSize({ 0.40f * width, 0.90f * height }, ImGuiCond_Always);

auto *imctx = im::GetCurrentContext();
if (!imctx->NavWindow)
Expand Down
3 changes: 2 additions & 1 deletion application/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ int main(int argc, char **argv) {
}

auto &settings = config.is_editing_day_profile ? config.profile.day_settings : config.profile.night_settings;
fz::gfx::render_preview(settings, preview.width, preview.height, 2, 3);
fz::gfx::render_preview(settings, config.profile.components, config.profile.filter,
preview.width, preview.height, 2, 3);
}

fz::gfx::render(slot);
Expand Down
2 changes: 1 addition & 1 deletion common/include/color.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ constexpr ColorMatrix dot(const ColorMatrix &r, const ColorMatrix &l) {
};
}

ColorMatrix filter_matrix(ColorFilter filter);
ColorMatrix filter_matrix(Component filter);
std::tuple<float, float, float> whitepoint(Temperature temperature);
ColorMatrix hue_matrix(Hue hue);
ColorMatrix saturation_matrix(Saturation sat);
Expand Down
7 changes: 4 additions & 3 deletions common/include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ class Config {
public:
constexpr static FizeauSettings default_settings = {
.temperature = DEFAULT_TEMP,
.gamma = DEFAULT_GAMMA,
.hue = DEFAULT_HUE,
.saturation = DEFAULT_SAT,
.hue = DEFAULT_HUE,
.gamma = DEFAULT_GAMMA,
.luminance = DEFAULT_LUMA,
.range = DEFAULT_RANGE,
.filter = ColorFilter_None,
};

public:
Expand All @@ -54,6 +53,8 @@ class Config {
FizeauProfile profile = {
.day_settings = Config::default_settings,
.night_settings = Config::default_settings,
.components = Component_All,
.filter = Component_None,
};

void (*parse_profile_switch_action)(Config *, FizeauProfileId) = nullptr;
Expand Down
7 changes: 4 additions & 3 deletions common/include/fizeau.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,17 @@ typedef enum {

typedef struct {
Temperature temperature;
Gamma gamma;
Hue hue;
Saturation saturation;
Hue hue;
Gamma gamma;
Luminance luminance;
ColorRange range;
ColorFilter filter;
} FizeauSettings;

typedef struct {
FizeauSettings day_settings, night_settings;
Component components;
Component filter;

Time dusk_begin, dusk_end;
Time dawn_begin, dawn_end;
Expand Down
11 changes: 6 additions & 5 deletions common/include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ typedef uint32_t Temperature;
#define DEFAULT_TEMP D65_TEMP

typedef enum {
ColorFilter_None,
ColorFilter_Red,
ColorFilter_Green,
ColorFilter_Blue,
} ColorFilter;
Component_None = 0,
Component_Red = BIT(0),
Component_Green = BIT(1),
Component_Blue = BIT(2),
Component_All = Component_Red | Component_Green | Component_Blue,
} Component;

typedef float Gamma;
#define MIN_GAMMA 0.0f
Expand Down
10 changes: 5 additions & 5 deletions common/src/color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@

namespace fz {

ColorMatrix filter_matrix(ColorFilter filter) {
ColorMatrix filter_matrix(Component filter) {
ColorMatrix arr = {};

static constexpr std::array luma_components = {
0.2126f, 0.7152f, 0.0722f,
};

if (filter == ColorFilter_None) {
if (filter == Component_None) {
arr[0] = arr[4] = arr[8] = 1.0f;
return arr;
}

std::size_t offset = 0;
switch (filter) {
default:
case ColorFilter_Red: offset = 0; break;
case ColorFilter_Green: offset = 3; break;
case ColorFilter_Blue: offset = 6; break;
case Component_Red: offset = 0; break;
case Component_Green: offset = 3; break;
case Component_Blue: offset = 6; break;
}

for (std::size_t i = 0; i < 3; ++i)
Expand Down
71 changes: 46 additions & 25 deletions common/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <cstring>
#include <algorithm>
#include <bit>
#include <string>
#include <ini.h>
#include <common.hpp>
Expand Down Expand Up @@ -74,6 +75,10 @@ void Config::sanitize_profile() {
sanitize_minmax(range.hi, MIN_RANGE, MAX_RANGE);
};

auto sanitize_filter = [&](Component filter) {
return std::popcount(static_cast<std::uint32_t>(filter)) >= 1;
};

sanitize_time(this->profile.dusk_begin);
sanitize_time(this->profile.dusk_end);
sanitize_time(this->profile.dawn_begin);
Expand All @@ -82,23 +87,23 @@ void Config::sanitize_profile() {
sanitize_minmax(this->profile.day_settings .temperature, MIN_TEMP, MAX_TEMP);
sanitize_minmax(this->profile.night_settings.temperature, MIN_TEMP, MAX_TEMP);

sanitize_minmax(this->profile.day_settings .gamma, MIN_GAMMA, MAX_GAMMA);
sanitize_minmax(this->profile.night_settings.gamma, MIN_GAMMA, MAX_GAMMA);

sanitize_minmax(this->profile.day_settings .saturation, MIN_SAT, MAX_SAT);
sanitize_minmax(this->profile.night_settings.saturation, MIN_SAT, MAX_SAT);

sanitize_minmax(this->profile.day_settings .hue, MIN_HUE, MAX_HUE);
sanitize_minmax(this->profile.night_settings.hue, MIN_HUE, MAX_HUE);

sanitize_minmax(this->profile.components, Component_None, Component_All);
sanitize_filter(this->profile.filter);

sanitize_minmax(this->profile.day_settings .gamma, MIN_GAMMA, MAX_GAMMA);
sanitize_minmax(this->profile.night_settings.gamma, MIN_GAMMA, MAX_GAMMA);

sanitize_minmax(this->profile.day_settings .luminance, MIN_LUMA, MAX_LUMA);
sanitize_minmax(this->profile.night_settings.luminance, MIN_LUMA, MAX_LUMA);

sanitize_colorrange(this->profile.day_settings .range);
sanitize_colorrange(this->profile.night_settings.range);

sanitize_minmax(this->profile.day_settings .filter, ColorFilter_None, ColorFilter_Blue);
sanitize_minmax(this->profile.night_settings.filter, ColorFilter_None, ColorFilter_Blue);
}

std::string Config::make() {
Expand All @@ -112,12 +117,26 @@ std::string Config::make() {
return format("profile%u", id + 1);
};

auto format_filter = [](ColorFilter f) -> std::string {
auto format_filter = [](Component f) -> std::string {
switch (f) {
case ColorFilter_Red: return "red";
case ColorFilter_Green: return "green";
case ColorFilter_Blue: return "blue";
default: return "none";
case Component_Red: return "red";
case Component_Green: return "green";
case Component_Blue: return "blue";
default: return "none";
}
};

auto format_components = [](Component c) -> std::string {
if (c == Component_None) {
return "none";
} else if (c == Component_All) {
return "all";
} else {
std::string s;
if (c & Component_Red) s.push_back('r');
if (c & Component_Green) s.push_back('g');
if (c & Component_Blue) s.push_back('b');
return s;
}
};

Expand Down Expand Up @@ -158,25 +177,26 @@ std::string Config::make() {
str += "dawn_begin = " + format_time(this->profile.dawn_begin) + '\n';
str += "dawn_end = " + format_time(this->profile.dawn_end) + '\n';

str += "temperature_day = " + std::to_string(this->profile.day_settings.temperature) + '\n';
str += "temperature_day = " + std::to_string(this->profile.day_settings .temperature) + '\n';
str += "temperature_night = " + std::to_string(this->profile.night_settings.temperature) + '\n';

str += "filter_day = " + format_filter(this->profile.day_settings.filter) + '\n';
str += "filter_night = " + format_filter(this->profile.night_settings.filter) + '\n';

str += "gamma_day = " + std::to_string(this->profile.day_settings.gamma) + '\n';
str += "gamma_night = " + std::to_string(this->profile.night_settings.gamma) + '\n';

str += "saturation_day = " + std::to_string(this->profile.day_settings.saturation) + '\n';
str += "saturation_day = " + std::to_string(this->profile.day_settings .saturation) + '\n';
str += "saturation_night = " + std::to_string(this->profile.night_settings.saturation) + '\n';

str += "hue_day = " + std::to_string(this->profile.day_settings.hue) + '\n';
str += "hue_day = " + std::to_string(this->profile.day_settings .hue) + '\n';
str += "hue_night = " + std::to_string(this->profile.night_settings.hue) + '\n';

str += "luminance_day = " + std::to_string(this->profile.day_settings.luminance) + '\n';
str += "components = " + format_components(this->profile.components) + '\n';

str += "filter = " + format_filter(this->profile.filter) + '\n';

str += "gamma_day = " + std::to_string(this->profile.day_settings .gamma) + '\n';
str += "gamma_night = " + std::to_string(this->profile.night_settings.gamma) + '\n';

str += "luminance_day = " + std::to_string(this->profile.day_settings .luminance) + '\n';
str += "luminance_night = " + std::to_string(this->profile.night_settings.luminance) + '\n';

str += "range_day = " + format_range(this->profile.day_settings.range) + '\n';
str += "range_day = " + format_range(this->profile.day_settings .range) + '\n';
str += "range_night = " + format_range(this->profile.night_settings.range) + '\n';

str += "dimming_timeout = " + format_time({ this->profile.dimming_timeout.m, this->profile.dimming_timeout.s }) + '\n';
Expand Down Expand Up @@ -221,12 +241,13 @@ Result Config::apply() {

Result Config::reset() {
this->profile.day_settings.temperature = DEFAULT_TEMP, this->profile.night_settings.temperature = DEFAULT_TEMP;
this->profile.day_settings.gamma = DEFAULT_GAMMA, this->profile.night_settings.gamma = DEFAULT_GAMMA;
this->profile.day_settings.hue = DEFAULT_HUE, this->profile.night_settings.hue = DEFAULT_HUE;
this->profile.day_settings.saturation = DEFAULT_SAT, this->profile.night_settings.saturation = DEFAULT_SAT;
this->profile.day_settings.hue = DEFAULT_HUE, this->profile.night_settings.hue = DEFAULT_HUE;
this->profile.day_settings.gamma = DEFAULT_GAMMA, this->profile.night_settings.gamma = DEFAULT_GAMMA;
this->profile.day_settings.luminance = DEFAULT_LUMA, this->profile.night_settings.luminance = DEFAULT_LUMA;
this->profile.day_settings.range = DEFAULT_RANGE, this->profile.night_settings.range = DEFAULT_RANGE;
this->profile.day_settings.filter = ColorFilter_None, this->profile.night_settings.filter = ColorFilter_None;
this->profile.components = Component_All;
this->profile.filter = Component_None;
return this->apply();
}

Expand Down
Loading

0 comments on commit f7b1b2d

Please sign in to comment.