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
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 | "ckey/ckey.h" |
| 6 | "check.h" |
| 7 | |
| 8 | <chrono> |
| 9 | <cstdio> |
| 10 | <cstring> |
| 11 | <string> |
| 12 | <vector> |
| 13 | |
| 14 | namespace { |
| 15 | |
| 16 | ckey_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 | |
| 22 | bool 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 | |
| 30 | int 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 | } |