Files
immich-frame/test/test_native/test_photo_queue.cpp
cottongin 065d80ca89 fix: eliminate diagonal dither pattern from display driver
Root cause: Panel_ED2208's epd_quality mode applies _dither_row_rgb_pair
(diagonal bias pattern with dither=140) during _exec_transfer(). Since our
ImagePipeline already does proper Floyd-Steinberg dithering, the driver's
additional dithering was creating visible diagonal artifacts.

Fix: setEpdMode(epd_fastest) selects _dither_row_none (clean nearest-color
lookup, no spatial bias). On Panel_ED2208 this only affects the dither
function — NOT refresh quality or waveform.

Also: default dither_noise setting to OFF since error scatter was targeting
the wrong layer (it made gradient areas fuzzier without fixing the real
problem in the display driver).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 19:52:22 -04:00

130 lines
3.8 KiB
C++

#include <unity.h>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstring>
// Minimal test of queue cycling logic (extracted, platform-independent)
// We test the shuffling and cycling algorithms without hardware dependencies
struct QueueState {
std::vector<std::string> ids;
size_t cursor;
};
// Simulate random cycling: advance through shuffled list
std::string advanceRandom(QueueState& state) {
if (state.ids.empty()) return "";
if (state.cursor >= state.ids.size()) {
state.cursor = 0; // Wrap around (would reshuffle in real impl)
}
return state.ids[state.cursor++];
}
// Simulate chronological: just advance sequentially (assumes pre-sorted)
std::string advanceChrono(QueueState& state) {
if (state.ids.empty()) return "";
if (state.cursor >= state.ids.size()) {
state.cursor = 0;
}
return state.ids[state.cursor++];
}
// Favorites weighting: insert duplicates
std::vector<std::string> applyFavoritesWeight(
const std::vector<std::string>& all,
const std::vector<std::string>& favorites,
int weight) {
std::vector<std::string> result = all;
for (const auto& fav : favorites) {
for (int i = 1; i < weight; i++) {
result.push_back(fav);
}
}
return result;
}
void test_advance_random_no_repeats_until_wrap() {
QueueState state;
state.ids = {"a", "b", "c", "d", "e"};
state.cursor = 0;
std::vector<std::string> seen;
for (size_t i = 0; i < state.ids.size(); i++) {
std::string id = advanceRandom(state);
// Should not have seen this one yet
TEST_ASSERT_TRUE(std::find(seen.begin(), seen.end(), id) == seen.end());
seen.push_back(id);
}
TEST_ASSERT_EQUAL(5, seen.size());
}
void test_advance_wraps_at_end() {
QueueState state;
state.ids = {"a", "b", "c"};
state.cursor = 0;
advanceRandom(state); // a
advanceRandom(state); // b
advanceRandom(state); // c
std::string wrapped = advanceRandom(state); // wraps to a
TEST_ASSERT_EQUAL_STRING("a", wrapped.c_str());
}
void test_empty_queue_returns_empty() {
QueueState state;
state.cursor = 0;
std::string result = advanceRandom(state);
TEST_ASSERT_EQUAL_STRING("", result.c_str());
}
void test_favorites_weighting() {
std::vector<std::string> all = {"a", "b", "c"};
std::vector<std::string> favs = {"b"};
auto weighted = applyFavoritesWeight(all, favs, 3);
// "b" should appear 3 times total (1 original + 2 extra)
int count = 0;
for (const auto& id : weighted) {
if (id == "b") count++;
}
TEST_ASSERT_EQUAL(3, count);
TEST_ASSERT_EQUAL(5, weighted.size()); // 3 original + 2 extra
}
void test_nearest_color_black();
void test_nearest_color_white();
void test_nearest_color_red();
void test_nearest_color_green();
void test_nearest_color_blue();
void test_nearest_color_yellow();
void test_dither_solid_black();
void test_dither_solid_white();
void test_dither_produces_valid_indices();
void test_blue_noise_breaks_pattern_regularity();
void test_blue_noise_dither_valid_indices();
void setUp() {}
void tearDown() {}
int main() {
UNITY_BEGIN();
RUN_TEST(test_advance_random_no_repeats_until_wrap);
RUN_TEST(test_advance_wraps_at_end);
RUN_TEST(test_empty_queue_returns_empty);
RUN_TEST(test_favorites_weighting);
RUN_TEST(test_nearest_color_black);
RUN_TEST(test_nearest_color_white);
RUN_TEST(test_nearest_color_red);
RUN_TEST(test_nearest_color_green);
RUN_TEST(test_nearest_color_blue);
RUN_TEST(test_nearest_color_yellow);
RUN_TEST(test_dither_solid_black);
RUN_TEST(test_dither_solid_white);
RUN_TEST(test_dither_produces_valid_indices);
RUN_TEST(test_blue_noise_breaks_pattern_regularity);
RUN_TEST(test_blue_noise_dither_valid_indices);
UNITY_END();
return 0;
}