Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

certify_tests.cpp

v0.1.0-build.85 Latest Commit ede38f5

Size
9.2 KB
Lines
143
Language
cpp
SHA-256
f65b5eaf86d2…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1// Style policies and optical certification (specification §4; acceptance
2// criteria 5 and 6): certification comes from a modelled scan, transparent
3// output is never certified without the host's backdrop, adaptive repairs
4// are reported, and override renders but does not certify.
5#include "ckey/ckey.h"
6#include "check.h"
7
8#include <chrono>
9#include <cstdio>
10#include <cstring>
11#include <string>
12#include <vector>
13
14namespace {
15
16ckey_scalable_symbol encode(uint32_t version, const char *text, ckey_ecc_level level = CKEY_ECC_M) {
17 ckey_scalable_symbol s{}; ckey_diagnostics d{};
18 CKEY_CHECK(ckey_encode_scalable(reinterpret_cast<const uint8_t *>(text), std::strlen(text), version, level, CKEY_LAYOUT_STANDARD, &s, &d) == CKEY_OK);
19 return s;
20}
21
22bool renders(const ckey_scalable_symbol &s, const ckey_style &st, bool transparent = false) {
23 ckey_raster_options o; ckey_raster_options_default(&o); o.size_px = 128; o.transparent = transparent ? 1 : 0;
24 std::vector<uint8_t> px(128 * 128 * 4); size_t need = 0;
25 return ckey_render_scalable_raster(&s, &st, &o, px.data(), px.size(), &need) == CKEY_OK;
26}
27
28} // namespace
29
30int main() {
31 const char *url = "https://openckey.org/tour";
32 ckey_style plain; ckey_style_default(&plain);
33 CKEY_CHECK(plain.policy == CKEY_POLICY_STRICT);
34 ckey_certification c{};
35
36 // The default style certifies, with the best grade, through the realistic photo sweep
37 // (clutter, tilt, glare, defocus, noise, and the full find -> refine -> decode pipeline).
38 for (uint32_t v : {1u, 11u, 31u}) {
39 const auto s = encode(v, url);
40 const auto t0 = std::chrono::steady_clock::now();
41 CKEY_CHECK(ckey_certify_scalable_style(&s, nullptr, 0, nullptr, nullptr, nullptr, &c) == CKEY_OK);
42 const double ms = std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - t0).count();
43 CKEY_CHECK(c.certified == 1 && c.trials > 0 && c.trials_passed > 0 && c.feature_separation > 0.5 && c.min_contrast > 20);
44 CKEY_CHECK(std::string(c.message).find("certified (excellent)") == 0);
45 std::printf("v%u plain: %s (%.0f ms)\n", v, c.message, ms);
46 }
47 const auto s = encode(6, url);
48
49 // The model's px_per_module is the resolution a style must decode at: asking for 2.5 px per
50 // module (below the sweep's smallest step) with heavy blur fails even plain black on white.
51 {
52 const auto dense = encode(31, url);
53 ckey_scan_model hard; ckey_scan_model_default(&hard); hard.px_per_module = 2.5; hard.blur_px = 1.6;
54 CKEY_CHECK(ckey_certify_scalable_style(&dense, nullptr, 0, nullptr, &hard, nullptr, &c) == CKEY_INVALID_ARGUMENT && c.certified == 0);
55 std::printf("v31 under a 2.5 px/module blurred model: %s\n", c.message);
56 hard.trials = 0; CKEY_CHECK(ckey_certify_scalable_style(&dense, nullptr, 0, nullptr, &hard, nullptr, &c) == CKEY_INVALID_ARGUMENT);
57 }
58
59 // Strict refuses near-invisible marks everywhere: check, render, certify.
60 ckey_style grey = plain; grey.ink = grey.ink_shade = {0xe8, 0xe8, 0xe8};
61 ckey_diagnostics d{};
62 CKEY_CHECK(ckey_check_scalable_style(&s, &grey, &d) == CKEY_INVALID_ARGUMENT);
63 CKEY_CHECK(!renders(s, grey));
64 CKEY_CHECK(ckey_certify_scalable_style(&s, &grey, 0, nullptr, nullptr, nullptr, &c) == CKEY_INVALID_ARGUMENT && c.certified == 0);
65 std::printf("strict near-invisible: %s\n", c.message);
66 // Low but visible contrast is only a warning: it renders, and the photo sweep decides.
67 ckey_style faint = plain; faint.ink = faint.ink_shade = {0xbb, 0xbb, 0xbb};
68 CKEY_CHECK(ckey_check_scalable_style(&s, &faint, &d) == CKEY_OK && std::string(d.message).find("only 1.9:1") != std::string::npos);
69 CKEY_CHECK(renders(s, faint));
70 CKEY_CHECK(ckey_certify_scalable_style(&s, &faint, 0, nullptr, nullptr, nullptr, &c) == CKEY_INVALID_ARGUMENT && c.certified == 0);
71 std::printf("strict #bbbbbb: %s\n", c.message);
72 // A dark custom background with concept's lighter accents scans: certified despite a 2.9:1 accent.
73 ckey_style slate; ckey_style_preset_fill(&slate, CKEY_PRESET_CONCEPT); slate.background = {0x55, 0x55, 0x55};
74 CKEY_CHECK(ckey_certify_scalable_style(&s, &slate, 0, nullptr, nullptr, nullptr, &c) == CKEY_OK && c.certified == 1);
75 CKEY_CHECK(std::string(c.message).find("note: ink") != std::string::npos);
76 std::printf("concept on #555555: %s\n", c.message);
77
78 // Override renders it, says so, and never certifies it.
79 ckey_style forced = grey; forced.policy = CKEY_POLICY_OVERRIDE;
80 CKEY_CHECK(ckey_check_scalable_style(&s, &forced, &d) == CKEY_OK && std::string(d.message).find("NOT scan-safe") != std::string::npos);
81 CKEY_CHECK(renders(s, forced));
82 CKEY_CHECK(ckey_certify_scalable_style(&s, &forced, 0, nullptr, nullptr, nullptr, &c) == CKEY_OK && c.certified == 0);
83 std::printf("override grey: %s\n", c.message);
84 ckey_style junk = forced; junk.modules = static_cast<ckey_module_shape>(9);
85 CKEY_CHECK(!renders(s, junk)); // structural problems are refused under every policy
86 junk = plain; junk.policy = 7; CKEY_CHECK(ckey_check_scalable_style(&s, &junk, &d) == CKEY_INVALID_ARGUMENT);
87
88 // Adaptive repairs and reports; renderers draw the repaired style.
89 ckey_style adaptive = grey; adaptive.policy = CKEY_POLICY_ADAPTIVE;
90 adaptive.accents[0] = {0xfe, 0xfe, 0xfe}; adaptive.accent_count = 1; adaptive.accent_percent = 20;
91 adaptive.shadow = 0.9;
92 CKEY_CHECK(renders(s, adaptive));
93 ckey_style repaired{};
94 CKEY_CHECK(ckey_certify_scalable_style(&s, &adaptive, 0, nullptr, nullptr, &repaired, &c) == CKEY_OK && c.certified == 1);
95 CKEY_CHECK((c.adjustments & CKEY_ADJUST_INK) && (c.adjustments & CKEY_ADJUST_ACCENTS) && (c.adjustments & CKEY_ADJUST_EFFECTS));
96 CKEY_CHECK(repaired.ink.r == 0 && repaired.accent_percent == 0 && repaired.shadow <= 0.4 && repaired.policy == CKEY_POLICY_STRICT);
97 CKEY_CHECK(ckey_check_scalable_style(&s, &repaired, &d) == CKEY_OK && renders(s, repaired));
98 std::printf("adaptive grey: %s\n", c.message);
99
100 // Transparent output: no backdrop, no certification (and no false claim).
101 CKEY_CHECK(renders(s, plain, true));
102 CKEY_CHECK(ckey_certify_scalable_style(&s, nullptr, 1, nullptr, nullptr, nullptr, &c) == CKEY_INVALID_ARGUMENT && c.certified == 0);
103 CKEY_CHECK(std::string(c.message).find("background unknown") != std::string::npos);
104 ckey_style over = plain; over.policy = CKEY_POLICY_OVERRIDE;
105 CKEY_CHECK(ckey_certify_scalable_style(&s, &over, 1, nullptr, nullptr, nullptr, &c) == CKEY_OK && c.certified == 0);
106 std::printf("transparent, no backdrop: %s\n", c.message);
107
108 // With the host's backdrop: white passes; dark grey fails black ink strictly; adaptive flips the ink.
109 const ckey_rgb white[1] = {{255, 255, 255}}, dark[1] = {{0x33, 0x33, 0x33}};
110 ckey_backdrop on_white{white, 1, nullptr, 0, 0, 0}, on_dark{dark, 1, nullptr, 0, 0, 0};
111 CKEY_CHECK(ckey_certify_scalable_style(&s, nullptr, 1, &on_white, nullptr, nullptr, &c) == CKEY_OK && c.certified == 1);
112 CKEY_CHECK(ckey_certify_scalable_style(&s, nullptr, 1, &on_dark, nullptr, nullptr, &c) == CKEY_INVALID_ARGUMENT && c.certified == 0);
113 std::printf("transparent black ink on #333333: %s\n", c.message);
114 ckey_style flip = plain; flip.policy = CKEY_POLICY_ADAPTIVE;
115 CKEY_CHECK(ckey_certify_scalable_style(&s, &flip, 1, &on_dark, nullptr, &repaired, &c) == CKEY_OK && c.certified == 1 && repaired.ink.r == 255);
116 std::printf("adaptive on #333333: %s\n", c.message);
117
118 // A busy host image: half black, half white. No single ink works, and certification says so.
119 std::vector<uint8_t> photo(64 * 64 * 4, 255);
120 for (int y = 0; y < 64; ++y) for (int x = 0; x < 32; ++x) { uint8_t *p = &photo[(y * 64 + x) * 4]; p[0] = p[1] = p[2] = 0; }
121 ckey_backdrop busy{nullptr, 0, photo.data(), 64, 64, 0};
122 CKEY_CHECK(ckey_certify_scalable_style(&s, nullptr, 1, &busy, nullptr, nullptr, &c) == CKEY_INVALID_ARGUMENT && c.certified == 0);
123 std::printf("transparent on a half-black image: %s\n", c.message);
124
125 // The concept preset (light on dark, depth, grain, accents) certifies opaque.
126 ckey_style art; ckey_style_preset_fill(&art, CKEY_PRESET_CONCEPT);
127 const auto s11 = encode(11, url);
128 CKEY_CHECK(ckey_certify_scalable_style(&s11, &art, 0, nullptr, nullptr, nullptr, &c) == CKEY_OK && c.certified == 1);
129 std::printf("concept preset: %s\n", c.message);
130 // Grades rank styles by how much larger than plain black on white they must be to scan.
131 {
132 const auto v11 = encode(11, url);
133 ckey_style faint = plain; faint.ink = faint.ink_shade = {0xaa, 0xaa, 0xaa}; faint.policy = CKEY_POLICY_OVERRIDE;
134 CKEY_CHECK(ckey_certify_scalable_style(&v11, &faint, 0, nullptr, nullptr, nullptr, &c) == CKEY_OK && c.certified == 0);
135 CKEY_CHECK(std::string(c.message).find("fails scan margin") != std::string::npos);
136 std::printf("faint #aaaaaa (override): %s\n", c.message);
137 ckey_style decorated; ckey_style_preset_fill(&decorated, CKEY_PRESET_CONCEPT);
138 CKEY_CHECK(ckey_certify_scalable_style(&v11, &decorated, 0, nullptr, nullptr, nullptr, &c) == CKEY_OK && c.certified == 1);
139 CKEY_CHECK(std::string(c.message).find("plain black on white down to") != std::string::npos);
140 }
141 std::printf("certification tests passed\n");
142 return 0;
143}