diff --git a/.gitignore b/.gitignore index ebf1e49..958952a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules -venv/ .venv/ +venv/ +__pycache__ diff --git a/README.md b/README.md index e06c5e3..ba1a2e6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ An online version of this tool is live at [http://javl.github.io/image2cpp/](http://javl.github.io/image2cpp/) -image2cpp is a simple tool to change images into byte arrays (or your array back into an image) for use with (monochrome) displays suchs as OLEDs, like those from Adafruit or Sparkfun. While searching for a way to generate these arrays, I mostly found links to a piece of Windows software. Both the flakey results and the hassle of having to boot a virtual machine just to convert an image lead to me writing this pure html + javascript solution. +image2cpp is a simple tool to convert images into byte arrays (and vice versa) for use with (monochrome) displays suchs as OLEDs, like those from Adafruit or Sparkfun. While searching for a way to generate these arrays, I mostly found links to a piece of Windows software. Both the flakey results and the hassle of having to boot a virtual machine just to convert an image lead to me writing this pure html + javascript solution. Alternatively you can also enter a byte array as input to turn it back into an image. This might be useful for debugging, or when you want to write the byte array yourself. I don't know. @@ -20,6 +20,8 @@ You can find a simple Arduino example sketch [over here](https://github.com/javl ### Screen types I wrote the code with my 128x64 pixel monochrome OLED display in mind, but it should work with most similar displays. You might need to change some export settings; those are explained in the tool. +### Running tests +A simple test suite lives in the `tests` directory. See [`tests/`](tests/README.md) for instructions. ### Credit Initial code by [javl](https://github.com/javl) with aditional code by (in alphabetical order): diff --git a/css/style.css b/css/style.css index 96d4400..35a8da2 100644 --- a/css/style.css +++ b/css/style.css @@ -1,178 +1,743 @@ +:root { + /* Colors (from restyle design tokens) */ + --primary: #006b58; + --primary-container: #1abc9c; + --on-primary: #ffffff; + --on-primary-container: #e5fff7; + --secondary: #4e6073; + --on-secondary: #ffffff; + --background: #f7f9fb; + --surface-container-lowest: #ffffff; + --surface-container-low: #f2f4f6; + --surface-container: #eceef0; + --surface-container-high: #e6e8ea; + /* --on-surface: #191c1e; */ + --on-surface: #000000; + /* --on-surface-variant: #3c4a45; */ + --on-surface-variant: #000000; + /* --on-background: #191c1e; */ + --on-background: #000000; + --text-muted: #64748b; + --border-subtle: #e2e8f0; + --border-hard: #1abc9c; + --outline-variant: #bbcac3; + --editor-bg: #ffffff; + --error: #ba1a1a; + --focus-ring: rgba(0, 107, 88, 0.25); + + /* Radii */ + --radius-lg: 0.25rem; + --radius-xl: 0.5rem; + + /* Spacing scale (use these for margin/padding/gap instead of magic numbers) */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-7: 32px; + --space-8: 48px; + --space-9: 64px; + + /* Fonts */ + --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; + --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + --font-size: 14px; +} + * { margin: 0; padding: 0; + box-sizing: border-box; } -body{ - font-family: arial; +body { + font-family: var(--font-body); + font-size: var(--font-size); + line-height: 24px; + color: var(--on-background); + background-color: var(--background); + min-height: 100vh; +} + +/* ---- Top nav bar ---- */ + +.topnav { + position: sticky; + top: 0; + z-index: 50; + background: var(--surface-container-lowest); + border-bottom: 1px solid var(--border-subtle); +} + +.topnav-inner { + max-width: 1200px; + margin: auto; + height: 64px; + padding: 0 var(--space-6); + display: flex; + align-items: center; + justify-content: space-between; +} + +.topnav-left { + display: flex; + align-items: center; + gap: var(--space-7); +} + +.brand { + font-size: 20px; + font-weight: 700; + color: var(--primary); +} + +.topnav-links { + display: flex; + gap: var(--space-6); +} + +.topnav-links a { + color: var(--secondary); + font-weight: 500; + font-size: var(--font-size); + text-decoration: underline; +} + +.topnav-links a:hover { + color: var(--primary); + text-decoration: none; +} + +.topnav-right { + display: flex; + align-items: center; + gap: var(--space-3); +} + +.icon-btn { + background: transparent; + color: var(--secondary); + border: none; + font-size: 18px; + line-height: 1; + padding: 6px; + margin: 0; + border-radius: var(--radius-lg); + cursor: pointer; +} + +.icon-btn:hover { + color: var(--primary); + background: var(--surface-container); + opacity: 1; +} + +.theme-icon-light { + display: none; +} + +.btn-reset { + margin: 0; +} + +/* ---- Layout: main ---- */ + +.layout { + display: flex; + gap: var(--space-7); + max-width: 1200px; + margin: auto; + padding: var(--space-7) var(--space-6) var(--space-9); + align-items: flex-start; } .wrapper { display: flex; flex-direction: column; - margin: auto; - width: 900px; + gap: var(--space-6); + flex: 1; + min-width: 0; } -.section { - margin: 10px 0; +/* ---- Step number rail ---- */ + +.section.step { + position: relative; + /* padding-left: 72px; */ + padding: var(--space-4); + scroll-margin-top: 88px; } -.bottom-divider { - border-bottom: 2px solid #000000; - padding-bottom: 20px; + +.step-num { + position: absolute; + left: 16px; + top: var(--space-4); + width: 40px; + height: 40px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + background: var(--surface-container-high); + color: var(--secondary); + border: 1px solid var(--border-hard); + z-index: 2; } -.sub-section { - clear: both; - margin-bottom: 1px; +.active .step-num { + background: var(--primary); + color: var(--on-primary); + border-color: var(--primary); } -.section, -.sub-section { - width: 100%; +/* .step::before { + content: ""; + position: absolute; + left: 35px; + top: 40px; + bottom: -24px; + width: 2px; + background: var(--border-hard); + z-index: 1; +} */ + +/* #step-0.step::before, #step-4.step::before { + display: none; +} */ + +/* step-3 (Preview) lives as a pinned side panel next to Settings, not + inline in the vertical step flow, so it doesn't carry a connecting rail */ +/* #step-3.step::before { + display: none; +} */ + +/* ---- Typography ---- */ + +h1 { + font-size: 30px; + line-height: 38px; + letter-spacing: -0.02em; + font-weight: 600; + color: var(--primary); + margin-bottom: var(--space-2); } -.column { - float: left; +.v2 { + font-size: 18px; + line-height: 22px; + font-weight: 500; + color: var(--secondary); } -.column-center { - min-width: 160px; - text-align: center; -} - -.column-right { - float: right; +h2 { + font-size: 20px; + line-height: 28px; + font-weight: 600; + color: var(--on-surface); } .sub-section-title { - margin: 0 0 10px; + font-family: var(--font-mono); + font-size: 13px; + line-height: 16px; + font-weight: 500; + color: var(--primary); + margin: 0 0 var(--space-3); } p { - margin: 20px 0; + margin: var(--space-4) 0; + color: var(--on-surface-variant); } +a { + color: var(--primary); + text-decoration: underline; + font-weight: 500; +} + +a:hover { + text-decoration: none; +} + +code { + font-family: var(--font-mono); + font-size: 0.9em; + background: var(--surface-container); + padding: 1px 5px; + border-radius: var(--radius-lg); +} + +/* ---- Section cards ---- */ + +.section { + background: var(--surface-container-lowest); + border: 1px solid var(--border-hard); + border-radius: var(--radius-xl); + padding: var(--space-2); +} + +/* First (intro) section: keep it flush/light */ +.section.first-step { + background: transparent; + border: none; + /* padding: var(--space-5) 0 0; */ + /* border: 10px solid red; */ + padding: 0; +} + +.section.first-step p { + margin-top: 0; + padding-top: 0; +} + +.section h2 { + margin-bottom: var(--space-1); +} + +/* Legacy divider no longer needed; cards separate content */ +/* .bottom-divider { */ + /* border-bottom: none; */ + /* padding-bottom: var(--space-7); */ +/* } */ + +.sub-section { + clear: both; + width: 100%; +} + +.section { + width: 100%; +} + +/* ---- Settings + live preview layout (step 2 + step 3) ---- + Preview sits pinned next to Settings so the effect of dithering / + threshold / invert etc is visible without scrolling away from the + controls that change it. */ + +.settings-preview-row { + display: flex; + align-items: flex-start; + gap: var(--space-6); +} + +.settings-preview-row #step-2 { + flex: 1 1 auto; + min-width: 0; +} + +.settings-preview-row #step-3 { + flex: 0 0 300px; + width: 300px; + position: sticky; + top: 96px; +} + +/* ---- Multi-column (select image row) ---- */ + +.input-methods-row { + display: flex; + align-items: space-between; + gap: var(--space-5); +} + +.input-methods-row .column-left { + width: 50%; +} +.input-methods-row .column-right { + width: 50%; +} + +.column-left { + border-right: 1px solid var(--border-subtle); + padding-right: var(--space-3); +} + +.column-right { + border-right: none; +} + +/* ---- Table layout for settings ---- */ + .table { display: table; - margin: 10px 0 0; + /* margin: var(--space-2) 0 0; */ width: 100%; + border-collapse: collapse; } .table-row { display: table-row; width: 100%; + border-bottom: 1px solid var(--border-subtle); } .table-cell { display: table-cell; - padding: 5px 0; + padding: var(--space-2) 0; + vertical-align: top; } .table-cell:first-child { - width: 30%; + width: 20%; + padding-right: var(--space-4); } .table-cell:last-child { width: 70%; } -.table-cell:first-child label { - font-weight: bold; +.table-cell:first-child > label { + font-family: var(--font-mono); + font-size: 13px; + /* font-weight: 500; */ + color: var(--primary); } -.table-cell:last-child label { - margin-right: 10px; +.table-cell:last-child > label { + margin-right: var(--space-2); + color: var(--on-surface-variant); + font-size: var(--font-size); } .nested-table { margin: 0; } +/* ---- Settings rows (step 2) ---- + Single-column label-left / value-right rows, hairline-divided. Denser + than the old 2-up grid, and keeps each setting's note attached under + its label instead of floating below the control in the value column. */ + +.settings-grid { + display: block; + margin: var(--space-2) 0 0; +} + +.settings-grid .table-row { + display: flex; + align-items: flex-start; + gap: var(--space-6); + padding: var(--space-1) 0; + border-top: 1px solid var(--border-subtle); +} + +.settings-grid .table-row:first-child { + border-top: none; + padding-top: 0; +} + +.settings-grid .table-cell { + padding: 0; +} + +.settings-grid .table-cell:first-child { + width: 250px; + flex-shrink: 0; +} + +.settings-grid .table-cell:last-child { + width: auto; + flex: 1; + min-width: 0; +} + +.settings-grid .table-cell:first-child .note { + font-size: 13px; + line-height: 1.45em; + margin: var(--space-1) 0 0; +} + .nested-table .table-cell { - color: #666; - font-size: .9em; - width: 200px; + color: var(--text-muted); + font-size: 0.9em; + /* width: 200px; */ +} + +/* #format-caption-container { */ + /* Reserve space for the longest caption so switching output format + doesn't shift the fields/buttons below it. */ + /* min-height: 100px; */ +/* } */ + +#extra-settings-container { + /* Reserve space for the tallest combination (Adafruit GFX shows both its + own fields and the Arduino identifier fields) so the Generate/Copy/ + Download buttons don't jump around when switching output format. */ + /* min-height: 278px; */ + transition: min-height 0.15s ease; } #format-caption-container div { - color: #505050; + color: var(--text-muted); display: none; - font-size: .9em; - line-height: 1.4em; - padding: 10px 0 15px; + font-size: var(--font-size); + line-height: 1.5em; + padding: var(--space-2) 0 var(--space-4); width: 100%; } -.upload-note { - max-width: 300px; +/* ---- Notes / messages ---- */ + +.note { + color: var(--text-muted); + font-size: var(--font-size); + line-height: 1.5em; + margin: var(--space-1) 0; + font-style: italic; +} + +#glyph-name-note { + display: none; +} + +/* .upload-note { + max-width: 320px; +} */ + +#continue-note { + display: none; + margin-top: var(--space-7); +} + +.msg { + font-size: 16px; + color: var(--text-muted); +} + +.error-msg { + color: var(--error); + display: none; +} + +/* ---- Form controls ---- */ + +input[type="text"], +input[type="number"], +textarea, +select { + font-family: var(--font-body); + font-size: var(--font-size); + color: var(--on-surface-variant); + background: var(--surface-container); + border: 1px solid transparent; + border-radius: var(--radius-lg); + padding: 4px 4px; + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} + +input[type="text"]:focus, +input[type="number"]:focus, +textarea:focus, +select:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 2px var(--focus-ring); +} + +select { + cursor: pointer; +} + +input[type="checkbox"], +input[type="radio"] { + accent-color: var(--primary); + width: 16px; + height: 16px; + vertical-align: middle; + cursor: pointer; } .byte-input { min-height: 160px; min-width: 360px; -} - -.code-output { - height: 200px; width: 100%; + font-family: var(--font-mono); + font-size: var(--font-size); + line-height: 22px; + resize: vertical; +} +#text-input-error { + color: var(--error); + font-size: var(--font-size); + margin-top: var(--space-2); + display: none; } -.note { - color: #666666; - font-size: .9em; - line-height: 1.4em; - margin: 3px 0; +.text-input-preview-canvas { + display: none; + border: 1px solid var(--outline-variant); + border-radius: var(--radius-lg); + /* background: var(--primary-container); */ + margin: var(--space-2) 0; + /* padding: 4px; */ + max-width: 100%; } -.file-input-entry { +#read-images-note { + display: none; +} + +.text-input-size { + margin: var(--space-2) 0; + color: var(--on-surface-variant); + font-size: var(--font-size); +} + +.size-input { + width: 72px; +} + +.sub-field { display: flex; - justify-content: space-between; - margin-bottom: 10px; + align-items: center; + gap: var(--space-2); + margin-top: var(--space-2); } -button, -input[type="file"] { - background: #00CB99; - border-radius: 3px; - border: none; - color: #fff; - font-size: .9em; - font-weight: bold; - margin: 10px 0 0 0; - padding: 4px 8px; +.sub-field:first-child { + margin-top: 0; } -input[type="file"] { - font-size: 1.0em; - padding: 6px 20px; -} - -.generate-button { - margin: 40px 0 20px; -} - -.remove-button { - margin: 0 0 0 10px; - padding: 1px 4px; -} - -.file-info { - color: #505050; - font-size: .7em; - margin-left: 20px; - max-width: 300px; - white-space: pre; -} - -.size-input{ - width: 45px; +.sub-field-label { + min-width: 200px; + font-family: var(--font-mono); + font-size: 13px; + color: var(--primary); } .glyph-input { - width: 80px; - margin-left: 10px; + width: 300px; + margin-left: var(--space-2); +} + +.text-input { + font-family: var(--font-mono); +} + +/* ---- Buttons ---- */ + +button { + font-family: var(--font-mono); + font-size: 13px; + font-weight: 500; + background: var(--primary-container); + color: var(--on-primary-container); + border: none; + border-radius: var(--radius-lg); + padding: 8px 16px; + margin: var(--space-2) var(--space-2) 0 0; + cursor: pointer; + transition: opacity 0.15s ease, background-color 0.15s ease; +} + +button:hover { + opacity: 0.9; +} + +button:active { + opacity: 0.8; +} + +input[type="file"] { + background: var(--surface-container); + color: var(--on-surface-variant); + /* border: 2px dashed var(--outline-variant); */ + border-radius: var(--radius-lg); + font-size: var(--font-size); + padding: 4px 4px; + margin: var(--space-2) 0 0; + cursor: pointer; + width: 100%; + max-width: 360px; +} + +input[type="file"]:hover { + background: var(--surface-container-high); +} + +input[type="file"]::file-selector-button { + font-family: var(--font-mono); + font-weight: 500; + background: var(--primary-container); + color: var(--on-primary-container); + border: none; + border-radius: var(--radius-lg); + padding: 6px 12px; + margin-right: var(--space-3); + cursor: pointer; +} + +.generate-button { + background: var(--primary); + color: var(--on-primary); + padding: 10px 20px; +} + +#copy-button, +#download-button { + background: var(--secondary); + color: var(--on-secondary); +} + +/* Same margin rhythm across all three action buttons so the gap above + them and before the code output box is consistent regardless of which + buttons happen to be in view. */ +.generate-button, +#copy-button, +#download-button { + margin: var(--space-7) var(--space-2) var(--space-6) 0; +} + +.remove-button { + margin: 0 0 0 var(--space-2); + padding: 2px 8px; + /* background: var(--surface-container-high); */ + /* color: var(--on-surface-variant); */ +} + +#no-images-error { + margin-bottom: var(--space-2); +} +/* ---- File info / size list ---- */ + +.file-input-entry { + border: 1px solid var(--border-subtle); + padding: var(--space-1); + display: flex; + align-items: center; + gap: var(--space-2); + margin: var(--space-2) 0; +} + +.file-input-entry span { + flex: 1; + min-width: 0; +} + +.file-info { + color: var(--text-muted); + font-size: 12px; +} + +.file-name { + flex: 1; + min-width: 0; + margin: 0; + font-weight: 500; + color: var(--on-surface-variant); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Tighten gap between a row and the explanatory note row that follows */ +.note-row .table-cell { + padding-top: 0; } #image-size-settings { @@ -180,47 +745,212 @@ input[type="file"] { } #image-size-settings li { - margin: 4px 0; + display: flex; + flex-direction: column; + gap: var(--space-2); + margin: var(--space-2) 0; + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + padding: var(--space-2) var(--space-3); } -#images-canvas-container canvas { - border: 3px solid #88DAC5; - margin: 10px 15px; +.image-size-thumb-container { + display: flex; + align-items: center; + gap: var(--space-2); } +.image-size-thumb { + width: auto; + height: auto; + max-width: 48px; + max-height: 48px; + border: 1px solid var(--outline-variant); + border-radius: var(--radius-md, 4px); + background: var(--surface-variant, #fff); + flex-shrink: 0; + vertical-align: middle; +} + +.image-size-row { + display: flex; + align-items: center; + gap: var(--space-2); +} + +.image-size-header { + justify-content: space-between; +} + +/* ---- Preview canvases ---- */ + #images-canvas-container { align-items: flex-start; display: flex; flex-wrap: wrap; } +#images-canvas-container canvas { + border: 1px solid var(--outline-variant); + border-radius: var(--radius-lg); + /* background: var(--primary-container); */ + margin: var(--space-2) var(--space-4) var(--space-2) 0; + max-width: 100%; + cursor: pointer; + /* Display width/height are set in JS (setCanvasDisplaySize), capped to + 128px on the largest side while preserving aspect ratio, and never + scaled up beyond the canvas' actual pixel size. */ + image-rendering: crisp-edges; + image-rendering: pixelated; +} + +#preview-note { + display: none; +} + +.inlineImg { + border-radius: var(--radius-lg); + margin-top: var(--space-2); +} + +/* ---- Code output (dark editor look) ---- */ + +.code-output { + height: 400px; + width: 100%; + /* margin-top: 16px; */ + background: var(--editor-bg); + color: var(--on-surface); + border: 1px solid var(--on-surface-variant); + border-radius: var(--radius-xl); + font-family: var(--font-mono); + font-size: var(--font-size); + line-height: 22px; + padding: 20px; + resize: vertical; +} + +.code-output:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 2px var(--focus-ring); +} + +/* ---- Hidden by default (toggled via JS) ---- */ + #arduino-identifier, #adafruit-gfx-settings, #all-same-size { display: none; } -.msg { - font-size: 1.2em; +/* ---- Sponsor block ---- */ + +.sp-block { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--space-3); } -.error-msg { - color: #ff0000; +.sp-block img { + vertical-align: middle; +} + +/* ---- Responsive ---- */ + +@media (max-width: 900px) { + .layout { + flex-direction: column; + } + + .settings-preview-row { + flex-direction: column; + } + + .settings-preview-row #step-3 { + position: static; + width: 100%; + flex: none; + } +} + +@media (max-width: 640px) { + .topnav-links { + display: none; + } + + /* .section.step { + padding-left: 32px; + } */ + + .step-num { + position: static; + margin-bottom: var(--space-4); + } + + /* .step::before { + display: none; + } */ + + .input-methods-row { + flex-direction: column; + } + + .column-left, + .column-right { + width: 100%; + margin-left: 0; + } + + .byte-input { + min-width: 0; + } + + .table-cell:first-child, + .table-cell:last-child { + display: block; + width: 100%; + } + + .table-cell:first-child { + padding-bottom: 0; + } + + .settings-grid .table-row { + flex-direction: column; + gap: var(--space-1); + } +} + +/* ---- Dark theme ---- */ + +:root[data-theme="dark"] { + --primary: #4eddbb; + --primary-container: #1abc9c; + --on-primary: #003a2e; + --on-primary-container: #e5fff7; + --secondary: #b5c8df; + --on-secondary: #17293b; + --background: #0f1416; + --surface-container-lowest: #171d1f; + --surface-container-low: #1a2124; + --surface-container: #22282b; + --surface-container-high: #2a3033; + --on-surface: #e0e3e5; + --on-surface-variant: #c3d0c9; + --on-background: #e0e3e5; + --text-muted: #8a9a94; + --border-subtle: #2d3133; + --outline-variant: #414a47; + --editor-bg: #0b0e0f; + --focus-ring: rgba(78, 221, 187, 0.35); +} + +:root[data-theme="dark"] .theme-icon-dark { display: none; } -h1{ - padding: 10px; - color: white; - background-color: #00cb99; +:root[data-theme="dark"] .theme-icon-light { + display: inline; } - -/*.sp-block { - border: 1px solid rgb(65, 65, 65); - padding: .5rem; - border-radius: 1rem; -} -.sp-btn { - display: block; - margin-top: .5rem; -}*/ diff --git a/index.html b/index.html index 0f3bcaa..b2ae168 100644 --- a/index.html +++ b/index.html @@ -3,73 +3,136 @@ image2cpp + + + -
-
-

image2cpp

-

image2cpp is a simple tool to change images into byte arrays (or arrays back into an images) for use with (monochrome) displays such as OLEDs on your Arduino or Raspberry Pi.
- It was originally made to work with the Adafruit OLED library (for which your can find an example sketch for Arduino here) but - has been expanded by the community to be useful in all kind of (embedded) projects.

-

More info (and credits) can be found in the Github repository. This is also where you can report any issues you might come across.

-

- Did you find this tool useful? Feel free to support my open source software on Github, especially if used commercially.
- - GitHub Sponsor - - - Buy Me A Coffee - +

+
+
+ image2cpp v2 + +
+
+ + +
+
+
-

-
+
-
-
-
-

1. Select image

-
All processing is done locally in your browser; your images are not uploaded or stored anywhere online.
-
+ +
+
+
+
+

image2cpp is a simple tool to convert images into byte arrays (and vice versa) for use with small (monochrome) displays such as OLEDs on your Arduino or ESP.
+ It was originally made to work with the Adafruit OLED library (for which your can find an example Arduino sketch here) but + has been expanded by the community.

-
-

or

-
-
-

1. Paste byte array

-
-
- x - px -
-
- - -
-
Read images appear at step 3 below
+
+

More info (and credits) can be found in the Github repository. This is also where you can report any issues you might come across.

+

+ Did you find this tool useful? Feel free to support my open source software on Github, especially if used commercially. +

+

+ GitHub Sponsor BMC +

-
+
+ +
+
+

1. Select image

+
You can import multiple images at once.
All processing is done locally in your browser: your images are not uploaded or stored anywhere online.
+
+
Only images file type are allowed
+
+ +
Add more images or continue to step 2
+
+
+ +

1. Paste existing byte array

+
+
+ x + px +
+
Set this to the size of your image.
Common sizes: 16x16 32x32 64x48 128x32 128x64.
+
+ + +
+ +
Byte array is invalid (or empty).
+
If your image looks glitchy try changing the dimensions above and press the read button again.
Read images also appear at step 3 below for further processing.
+
+
+
+ +
+
+

2. Image Settings

-
+
-
+
+
+ Glyph name is used to identify the image in the output code. +
+
    -
    Only images file type are allowed
    -
    No files selected
    + +
    Select one or more images at step 1 first.
    -
    +
    + +
    Used for parts of the canvas that are not covered by your image.
    +
    @@ -81,35 +144,7 @@
    -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    - -
    -
    -
    - -
    - 0 - 255; if the brightness of a pixel is above the given level the pixel becomes white, otherwise they become black. When using alpha, opaque and transparent are used instead.
    -
    -
    - -
    -
    +
    @@ -132,12 +170,36 @@
    -
    +
    - Centering the image only works when using a canvas larger than the original image. +
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    Pixels with brightness above threshold turn white, below turn black (opaque/transparent for alpha mode).
    +
    +
    + +
    +
    + +
    @@ -147,7 +209,7 @@ - +
    @@ -165,40 +227,67 @@
    -
    -

    3. Preview

    +
    + +

    Preview

    +
    Click image to view at actual size
    -
    No files selected
    +
    No files selected
    +
    -
    -

    4. Output

    +
    + +

    3. Output

    -
    +
    +
    + + +
    + If your image looks all messed up on your display, like the image below, try using a different mode. +
    +
    + +
    +
    + +
    +
    +
    + Outputs just the raw bytes of the image(s). +
    - Adds some extra Arduino code around the output for easy copy-paste into - this example. - If multiple images are loaded, generates a byte array for each and appends a counter to the identifier. + Adds some extra Arduino code around the output. + If multiple images are loaded, generates a byte array for each and appends its glyph name (from step 2 above) to the identifier.
    - Adds some extra Arduino code around the output for easy copy-paste. - If multiple images are loaded, generates a single byte array. + Adds some extra Arduino code around the output. + If multiple images are loaded, generates a single byte array.
    - Creates a GFXbitmapFont formatted ouput. Used by a modified version of the Adafruit GFX library. - GitHub project and example here. + Creates a GFXbitmapFont formatted ouput. Used by a modified version of the Adafruit GFX library. + GitHub project and example here.
    First ASCII character value is used only if a glyph identifier of length equal to 1 is not provided for each image. The value itself will be incremented by 1 for each glyph.
    @@ -208,13 +297,13 @@
    - +
    - +
    @@ -222,7 +311,21 @@
    - + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + +
    @@ -230,49 +333,38 @@
    -
    -
    -
    - - -
    - If your image looks all messed up on your display, like the image below, try using a different mode. -
    - - -
    -
    - -
    -
    -
    - - -
    -
    - -
    -
    -
    - Useful when working with the u8g2 library. -
    -
    - - -
    +
    - - +
    + + +
    +
    + + + MSB -> LSB. Useful when working with the u8g2 library. +
    + +
    + + +
    +
    + + +
    +
    + + + Set to 0 to wrap using the image's width instead, e.g. an 8px wide image adds a newline every 8th byte. +
    +
    + + + Add an ascii-art comment after each row of bytes. Forces one image row per output line, regardless of "Bytes per row". +
    +
    @@ -281,12 +373,53 @@
    - + +
    Select one or more images at step 1 first.
    +
    + diff --git a/js/script.js b/js/script.js index 1ad9b06..db2e4bf 100644 --- a/js/script.js +++ b/js/script.js @@ -14,12 +14,18 @@ const settings = { backgroundColor: 'white', scale: 1, drawMode: 'horizontal', - removeZeroesCommas: false, + prefix: '0x', ditheringThreshold: 128, ditheringMode: 0, outputFormat: 'plain', + separator: ', ', + outputComments: true, invertColors: false, rotation: 0, + esp32Format: false, + fullExample: false, + bytesPerRow: 16, + showAsciiPreview: false, }; function bitswap(b) { @@ -34,60 +40,103 @@ function bitswap(b) { return b; } +// settings.bytesPerRow of 0 means "wrap using the image's width instead", +// so a 8px-wide image gets a newline every 8 bytes. +function resolveWrapWidth(canvasWidth) { + return settings.bytesPerRow > 0 ? settings.bytesPerRow : canvasWidth; +} + +// Accumulates formatted bytes (prefix/value/separator, wrapped every +// wrapWidth bytes) so our ConversionFunctions can use this formatting. +// horizontal888 always wraps once per image row (canvasWidth) regardless +// of settings.bytesPerRow. When settings.showAsciiPreview is on, wrapWidth +// is ignored in favor of explicit endRow() calls (see makeAsciiRowTracker). +function makeByteWriter(wrapWidth) { + let out = ''; + let count = 0; + return { + push(value, hexWidth) { + const byteSet = bitswap(value).toString(16).padStart(hexWidth, '0'); + out += `${settings.prefix}${byteSet}${settings.separator}`; + count++; + if (!settings.showAsciiPreview && count >= wrapWidth) { + out += '\n'; + count = 0; + } + }, + // Ends the current line early with a dot/hash ascii-art comment for the + // row of pixels just written. Only called when settings.showAsciiPreview + // is on, so it always wins over wrapWidth-based wrapping. + endRow(asciiRow) { + out += `// ${asciiRow.split('').join(' ')}\n`; + count = 0; + }, + result() { return out; }, + }; +} + +// Builds a per-image-row ascii-art tracker (. for off, # for on) used +// when settings.showAsciiPreview is on. Call once per pixel with the same +// `index` used to read that pixel's channel data; flushes to the writer as +// a comment at the end of each image row, mirroring the row-boundary math +// packBitsHorizontal uses to flush partial bytes. +function makeAsciiRowTracker(canvasWidth, dataLength) { + let row = ''; + return (index, isOn, writer) => { + if (!settings.showAsciiPreview) return; + row += isOn ? '#' : '.'; + const pixelIndex = index / 4; + const isRowEnd = pixelIndex !== 0 && ((pixelIndex + 1) % canvasWidth) === 0; + const isImageEnd = index === dataLength - 4; + if (isRowEnd || isImageEnd) { + writer.endRow(row); + row = ''; + } + }; +} + +// Shared by horizontal1bit/horizontalAlpha: pack 8 samples (one per pixel, +// MSB first) into a byte, resetting early at the end of a row or the image +// so a partial final byte is still zero-padded instead of dropped. +function packBitsHorizontal(data, canvasWidth, writer, sampleAt) { + let byteIndex = 7; + let number = 0; + const trackAscii = makeAsciiRowTracker(canvasWidth, data.length); + for (let index = 0; index < data.length; index += 4) { + const isOn = sampleAt(data, index) > settings.ditheringThreshold; + if (isOn) { + number += 2 ** byteIndex; + } + byteIndex--; + + const isRowEnd = index !== 0 && (((index / 4) + 1) % canvasWidth) === 0; + const isImageEnd = index === data.length - 4; + if (isRowEnd || isImageEnd) { + byteIndex = -1; + } + + if (byteIndex < 0) { + writer.push(number, 2); + number = 0; + byteIndex = 7; + } + + trackAscii(index, isOn, writer); + } +} + const ConversionFunctions = { // Output the image as a string for horizontally drawing displays horizontal1bit(data, canvasWidth) { - let stringFromBytes = ''; - let outputIndex = 0; - let byteIndex = 7; - let number = 0; - - // format is RGBA, so move 4 steps per pixel - for (let index = 0; index < data.length; index += 4) { - // Get the average of the RGB (we ignore A) - const avg = (data[index] + data[index + 1] + data[index + 2]) / 3; - if (avg > settings.ditheringThreshold) { - number += 2 ** byteIndex; - } - byteIndex--; - - // if this was the last pixel of a row or the last pixel of the - // image, fill up the rest of our byte with zeros so it always contains 8 bits - if ((index !== 0 && (((index / 4) + 1) % (canvasWidth)) === 0) || (index === data.length - 4)) { - // for(var i=byteIndex;i>-1;i--){ - // number += Math.pow(2, i); - // } - byteIndex = -1; - } - - // When we have the complete 8 bits, combine them into a hex value - if (byteIndex < 0) { - let byteSet = bitswap(number).toString(16); - if (byteSet.length === 1) { byteSet = `0${byteSet}`; } - if (!settings.removeZeroesCommas) { - stringFromBytes += `0x${byteSet}, `; - } else { - stringFromBytes += byteSet; - } - outputIndex++; - if (outputIndex >= 16) { - if (!settings.removeZeroesCommas) { - stringFromBytes += '\n'; - } - outputIndex = 0; - } - number = 0; - byteIndex = 7; - } - } - return stringFromBytes; + const writer = makeByteWriter(resolveWrapWidth(canvasWidth)); + const avgRgb = (d, i) => (d[i] + d[i + 1] + d[i + 2]) / 3; + packBitsHorizontal(data, canvasWidth, writer, avgRgb); + return writer.result(); }, // Output the image as a string for vertically drawing displays - // eslint-disable-next-line no-unused-vars vertical1bit(data, canvasWidth, canvasHeight) { - let stringFromBytes = ''; - let outputIndex = 0; + const writer = makeByteWriter(resolveWrapWidth(canvasWidth)); for (let p = 0; p < Math.ceil(canvasHeight / 8); p++) { for (let x = 0; x < canvasWidth; x++) { let byteIndex = 7; @@ -101,142 +150,77 @@ const ConversionFunctions = { } byteIndex--; } - let byteSet = bitswap(number).toString(16); - if (byteSet.length === 1) { byteSet = `0${byteSet}`; } - if (!settings.removeZeroesCommas) { - stringFromBytes += `0x${byteSet.toString(16)}, `; - } else { - stringFromBytes += byteSet.toString(16); - } - outputIndex++; - if (outputIndex >= 16) { - stringFromBytes += '\n'; - outputIndex = 0; - } + writer.push(number, 2); } } - return stringFromBytes; + return writer.result(); }, // Output the image as a string for 565 displays (horizontally) // eslint-disable-next-line no-unused-vars horizontal565(data, canvasWidth) { - let stringFromBytes = ''; - let outputIndex = 0; - + const writer = makeByteWriter(resolveWrapWidth(canvasWidth)); + const trackAscii = makeAsciiRowTracker(canvasWidth, data.length); // format is RGBA, so move 4 steps per pixel for (let index = 0; index < data.length; index += 4) { - // Get the RGB values const r = data[index]; const g = data[index + 1]; const b = data[index + 2]; - // calculate the 565 color value + // Calculate the 565 color value // eslint-disable-next-line no-bitwise const rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | ((b & 0b11111000) >> 3); - // Split up the color value in two bytes - // const firstByte = (rgb >> 8) & 0xff; - // const secondByte = rgb & 0xff; - - let byteSet = bitswap(rgb).toString(16); - while (byteSet.length < 4) { byteSet = `0${byteSet}`; } - if (!settings.removeZeroesCommas) { - stringFromBytes += `0x${byteSet}, `; - } else { - stringFromBytes += byteSet; - } - // add newlines every 16 bytes - outputIndex++; - if (outputIndex >= 16) { - stringFromBytes += '\n'; - outputIndex = 0; - } + writer.push(rgb, 4); + trackAscii(index, (r + g + b) / 3 > settings.ditheringThreshold, writer); } - return stringFromBytes; + return writer.result(); }, - // Output the image as a string for rgb888 displays (horizontally) + // Output the image as a string for rgb888 displays (horizontally), one + // image row per output line horizontal888(data, canvasWidth) { - let stringFromBytes = ''; - let outputIndex = 0; - + const writer = makeByteWriter(canvasWidth); + const trackAscii = makeAsciiRowTracker(canvasWidth, data.length); // format is RGBA, so move 4 steps per pixel for (let index = 0; index < data.length; index += 4) { - // Get the RGB values + // Split into RGB and pack into a single 24-bit value (MSB first) const r = data[index]; const g = data[index + 1]; const b = data[index + 2]; - // calculate the 565 color value // eslint-disable-next-line no-bitwise const rgb = (r << 16) | (g << 8) | (b); - // Split up the color value in two bytes - // const firstByte = (rgb >> 8) & 0xff; - // const secondByte = rgb & 0xff; - - let byteSet = bitswap(rgb).toString(16); - while (byteSet.length < 8) { byteSet = `0${byteSet}`; } - if (!settings.removeZeroesCommas) { - stringFromBytes += `0x${byteSet}, `; - } else { - stringFromBytes += byteSet; - } - - // add newlines every 16 bytes - outputIndex++; - if (outputIndex >= canvasWidth) { - stringFromBytes += '\n'; - outputIndex = 0; - } + writer.push(rgb, 8); + trackAscii(index, (r + g + b) / 3 > settings.ditheringThreshold, writer); } - return stringFromBytes; + return writer.result(); }, // Output the alpha mask as a string for horizontally drawing displays horizontalAlpha(data, canvasWidth) { - let stringFromBytes = ''; - let outputIndex = 0; - let byteIndex = 7; - let number = 0; - - // format is RGBA, so move 4 steps per pixel - for (let index = 0; index < data.length; index += 4) { - // Get alpha part of the image data - const alpha = data[index + 3]; - if (alpha > settings.ditheringThreshold) { - number += 2 ** byteIndex; - } - byteIndex--; - - // if this was the last pixel of a row or the last pixel of the - // image, fill up the rest of our byte with zeros so it always contains 8 bits - if ((index !== 0 && (((index / 4) + 1) % (canvasWidth)) === 0) || (index === data.length - 4)) { - byteIndex = -1; - } - - // When we have the complete 8 bits, combine them into a hex value - if (byteIndex < 0) { - let byteSet = bitswap(number).toString(16); - if (byteSet.length === 1) { byteSet = `0${byteSet}`; } - if (!settings.removeZeroesCommas) { - stringFromBytes += `0x${byteSet}, `; - } else { - stringFromBytes += byteSet; - } - outputIndex++; - if (outputIndex >= 16) { - stringFromBytes += '\n'; - outputIndex = 0; - } - number = 0; - byteIndex = 7; - } - } - return stringFromBytes; + const writer = makeByteWriter(resolveWrapWidth(canvasWidth)); + packBitsHorizontal(data, canvasWidth, writer, (d, i) => d[i + 3]); + return writer.result(); }, }; settings.conversionFunction = ConversionFunctions.horizontal1bit; +// Bytes per output value for each conversion function, matching the +// hexWidth passed to writer.push() in that function (hexWidth / 2). +// Needed by downloadBinFile() to reconstruct the true byte stream instead +// of truncating multi-byte values (565/888) down to a single byte. +const CONVERSION_BYTES_PER_VALUE = new Map([ + [ConversionFunctions.horizontal1bit, 1], + [ConversionFunctions.vertical1bit, 1], + [ConversionFunctions.horizontal565, 2], + [ConversionFunctions.horizontal888, 4], + [ConversionFunctions.horizontalAlpha, 1], +]); + // An images collection with helper methods function Images() { const collection = []; - this.push = (img, canvas, glyph) => { collection.push({ img, canvas, glyph }); }; + this.push = (img, canvas, glyph, width, height) => { + collection.push({ + img, canvas, glyph, width, height, + }); + }; this.remove = (image) => { const i = collection.indexOf(image); if (i !== -1) collection.splice(i, 1); @@ -263,8 +247,6 @@ function Images() { const images = new Images(); // Filetypes accepted by the file picker // const fileTypes = ['jpg', 'jpeg', 'png', 'bmp', 'gif', 'svg']; -// Variable name, when "arduino code" is required -const identifier = 'myBitmap'; // Invert the colors of the canvas function invert(canvas, ctx) { @@ -278,15 +260,45 @@ function invert(canvas, ctx) { ctx.putImageData(imageData, 0, 0); } +// Open the canvas' current contents as a full-size image in a new tab, +// like a right-click "open image in new tab" on a regular . +function openCanvasInNewTab(canvas) { + canvas.toBlob((blob) => { + const url = URL.createObjectURL(blob); + window.open(url, '_blank'); + // Give the new tab time to load the image before freeing the blob. + setTimeout(() => URL.revokeObjectURL(url), 30000); + }); +} + +// Size the on-screen canvas, preserving aspect ratio: shown at its actual +// pixel size up to 128px on its largest side, scaled down to fit within +// 128px otherwise. Never scaled up. Wires up click-to-open-in-new-tab +// (the "click to open at actual size" hint lives once in the Preview +// header, not per canvas). +function setCanvasDisplaySize(canvas) { + const maxPreviewSize = 128; + const largestSide = Math.max(canvas.width, canvas.height); + const scale = largestSide > maxPreviewSize ? maxPreviewSize / largestSide : 1; + // eslint-disable-next-line no-param-reassign + canvas.style.width = `${Math.round(canvas.width * scale)}px`; + // eslint-disable-next-line no-param-reassign + canvas.style.height = `${Math.round(canvas.height * scale)}px`; + // eslint-disable-next-line no-param-reassign + canvas.onclick = () => openCanvasInNewTab(canvas); +} + // Draw the image onto the canvas, taking into account color and scaling function placeImage(_image) { const { img } = _image; const { canvas } = _image; const ctx = canvas.getContext('2d'); - // reset canvas size - canvas.width = Number.isFinite(settings.screenWidth) && settings.screenWidth > 0 ? settings.screenWidth : 1; - canvas.height = Number.isFinite(settings.screenHeight) && settings.screenHeight > 0 ? settings.screenHeight : 1; + // reset canvas size (falls back to the canvas' current size for images, + // like a re-imported byte array, that aren't tracked in the image list + // with their own width/height) + canvas.width = Number.isFinite(_image.width) && _image.width > 0 ? _image.width : canvas.width; + canvas.height = Number.isFinite(_image.height) && _image.height > 0 ? _image.height : canvas.height; // eslint-disable-next-line no-param-reassign _image.ctx = ctx; ctx.save(); @@ -425,8 +437,8 @@ function placeImage(_image) { ctx.fillRect(0, 0, canvas.width, canvas.height); if (settings.rotation === 90) { - canvas.width = settings.screenHeight; - canvas.height = settings.screenWidth; + canvas.width = clone.height; + canvas.height = clone.width; ctx.setTransform(1, 0, 0, 1, canvas.width, 0); ctx.rotate(Math.PI / 2); ctx.drawImage(clone, 0, 0); @@ -435,8 +447,8 @@ function placeImage(_image) { ctx.rotate(Math.PI); ctx.drawImage(clone, 0, 0); } else if (settings.rotation === 270) { - canvas.width = settings.screenHeight; - canvas.height = settings.screenWidth; + canvas.width = clone.height; + canvas.height = clone.width; ctx.setTransform(1, 0, 0, 1, 0, canvas.height); ctx.rotate(Math.PI * 1.5); ctx.drawImage(clone, 0, 0); @@ -456,6 +468,8 @@ function placeImage(_image) { ctx.drawImage(clone, 0, 0); ctx.setTransform(1, 0, 0, 1, 0, 0); } + + setCanvasDisplaySize(canvas); } // Handle drawing each of our images @@ -466,6 +480,7 @@ function updateAllImages() { } // Easy way to update settings controlled by a textfield +// eslint-disable-next-line no-unused-vars function updateInteger(fieldName) { settings[fieldName] = parseInt(document.getElementById(fieldName).value); updateAllImages(); @@ -478,46 +493,33 @@ function updateBoolean(fieldName) { updateAllImages(); } +// Easy way to update settings controlled by a text input +// eslint-disable-next-line no-unused-vars +function updateString(fieldName) { + settings[fieldName] = document.getElementById(fieldName).value; + updateAllImages(); +} + // Convert hex to binary function hexToBinary(s) { - let i; let ret = ''; - // lookup table for easier conversion. "0" characters are padded for "1" to "7" - const lookupTable = { - 0: '0000', - 1: '0001', - 2: '0010', - 3: '0011', - 4: '0100', - 5: '0101', - 6: '0110', - 7: '0111', - 8: '1000', - 9: '1001', - a: '1010', - b: '1011', - c: '1100', - d: '1101', - e: '1110', - f: '1111', - A: '1010', - B: '1011', - C: '1100', - D: '1101', - E: '1110', - F: '1111', - }; - for (i = 0; i < s.length; i += 1) { - // eslint-disable-next-line no-prototype-builtins - if (lookupTable.hasOwnProperty(s[i])) { - ret += lookupTable[s[i]]; - } else { + for (let i = 0; i < s.length; i += 1) { + const nibble = parseInt(s[i], 16); + if (Number.isNaN(nibble)) { return { valid: false, s }; } + ret += nibble.toString(2).padStart(4, '0'); } return { valid: true, result: ret }; } +// The plain byte type, independent of drawMode (used by output formats, +// like adafruit_gfx, that are always byte-packed regardless of the current +// conversion function). +function getByteType() { + return settings.esp32Format ? 'uint8_t' : 'unsigned char'; +} + // get the type (in arduino code) of the output image // this is a bit of a hack, it's better to make this a property of the conversion function (should probably turn it into objects) function getImageType() { @@ -526,13 +528,61 @@ function getImageType() { } if (settings.conversionFunction === ConversionFunctions.horizontal888) { return 'unsigned long'; } - return 'unsigned char'; + return getByteType(); +} + +// PROGMEM is an AVR-ism: it's a no-op on ESP32 (flash is memory-mapped +// there), so the ESP32 output toggle drops it instead of emitting a keyword +// that does nothing. +function progmemKeyword() { + return settings.esp32Format ? '' : ' PROGMEM'; +} + +// Use the horizontally oriented list to draw the image +// Validates and decodes a comma-split list of pasted hex byte strings into +// one contiguous bit string (MSB first, each entry padded to a full byte). +// Returns { valid: true, bits } or { valid: false, s } naming the bad entry. +function hexListToBits(list) { + let bits = ''; + for (let i = 0; i < list.length; i++) { + const binString = hexToBinary(list[i]); + if (!binString.valid) { + return binString; + } + bits += binString.result.length === 4 ? `${binString.result}0000` : binString.result; + } + return { valid: true, bits }; +} + +function reportInvalidByteArray(s) { + const errorEl = document.getElementById('text-input-error'); + errorEl.textContent = 'Something went wrong converting the string. Make sure there are no comments in your input.'; + errorEl.style.display = 'block'; + // eslint-disable-next-line no-console + console.error('invalid hexToBinary: ', s); +} + +// Save the canvas contents inside the (first) image object so it can be +// reused when scaling/inverting/etc. +function commitCanvasToFirstImage(canvas) { + const img = new Image(); + img.onload = () => { + images.first().img = img; + }; + img.src = canvas.toDataURL('image/png'); } // Use the horizontally oriented list to draw the image function listToImageHorizontal(list, canvas) { const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); + + const decoded = hexListToBits(list); + if (!decoded.valid) { + reportInvalidByteArray(decoded.s); + return false; + } + const imgData = ctx.createImageData(canvas.width, canvas.height); let index = 0; @@ -541,51 +591,25 @@ function listToImageHorizontal(list, canvas) { let widthCounter = 0; // Move the list into the imageData object - for (let i = 0; i < list.length; i++) { - let binString = hexToBinary(list[i]); - if (!binString.valid) { - // eslint-disable-next-line no-alert - alert('Something went wrong converting the string. Make sure there are no comments in your input?'); - // eslint-disable-next-line no-console - console.error('invalid hexToBinary: ', binString.s); - return; + for (let k = 0; k < decoded.bits.length; k++, widthCounter++) { + // if we've counted enough bits, reset counter for next line + if (widthCounter >= widthRoundedUp) { + widthCounter = 0; } - binString = binString.result; - if (binString.length === 4) { - binString += '0000'; - } - - // Check if pixel is white or black - for (let k = 0; k < binString.length; k++, widthCounter++) { - // if we've counted enough bits, reset counter for next line - if (widthCounter >= widthRoundedUp) { - widthCounter = 0; - } - // skip 'artifact' pixels due to rounding up to a byte - if (widthCounter < canvas.width) { - let color = 0; - if (binString.charAt(k) === '1') { - color = 255; - } - imgData.data[index] = color; - imgData.data[index + 1] = color; - imgData.data[index + 2] = color; - imgData.data[index + 3] = 255; - - index += 4; - } + // skip 'artifact' pixels due to rounding up to a byte + if (widthCounter < canvas.width) { + const color = decoded.bits.charAt(k) === '1' ? 255 : 0; + imgData.data[index] = color; + imgData.data[index + 1] = color; + imgData.data[index + 2] = color; + imgData.data[index + 3] = 255; + index += 4; } } - // Draw the image onto the canvas, then save the canvas contents - // inside the img object. This way we can reuse the img object when - // we want to scale / invert, etc. ctx.putImageData(imgData, 0, 0); - const img = new Image(); - img.onload = () => { - images.first().img = img; - }; - img.src = canvas.toDataURL('image/png'); + commitCanvasToFirstImage(canvas); + return true; } // Quick and effective way to draw single pixels onto the canvas @@ -606,55 +630,84 @@ function listToImageVertical(list, canvas) { const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); + const decoded = hexListToBits(list); + if (!decoded.valid) { + reportInvalidByteArray(decoded.s); + return false; + } + let page = 0; let x = 0; let y = 7; // Move the list into the imageData object - for (let i = 0; i < list.length; i++) { - let binString = hexToBinary(list[i]); - if (!binString.valid) { - // eslint-disable-next-line no-alert - alert('Something went wrong converting the string. Did you forget to remove any comments from the input?'); - // eslint-disable-next-line no-console - console.error('invalid hexToBinary: ', binString.s); - return; - } - binString = binString.result; - if (binString.length === 4) { - binString += '0000'; - } - - // Check if pixel is white or black - for (let k = 0; k < binString.length; k++) { - let color = 0; - if (binString.charAt(k) === '1') { - color = 255; - } - drawPixel(ctx, x, (page * 8) + y, color); - y--; - if (y < 0) { - y = 7; - x++; - if (x >= settings.screenWidth) { - x = 0; - page++; - } + for (let k = 0; k < decoded.bits.length; k++) { + const color = decoded.bits.charAt(k) === '1' ? 255 : 0; + drawPixel(ctx, x, (page * 8) + y, color); + y--; + if (y < 0) { + y = 7; + x++; + if (x >= settings.screenWidth) { + x = 0; + page++; } } } - // Save the canvas contents inside the img object. This way we can - // reuse the img object when we want to scale / invert, etc. - const img = new Image(); - img.onload = () => { - images.first().img = img; - }; - img.src = canvas.toDataURL('image/png'); + + commitCanvasToFirstImage(canvas); + return true; +} + +// Set width/height preset for byte array text input +// eslint-disable-next-line no-unused-vars +function setTextInputSize(width, height) { + document.getElementById('text-input-width').value = width; + document.getElementById('text-input-height').value = height; +} + +// Show/hide the "no images" error and report whether images are available +function checkImagesAvailable() { + const error = document.getElementById('no-images-error'); + const glyphNameNote = document.getElementById('glyph-name-note'); + const previewNote = document.getElementById('preview-note'); + const hasImages = images.length() > 0; + error.style.display = hasImages ? 'none' : 'block'; + glyphNameNote.style.display = hasImages ? 'block' : 'none'; + previewNote.style.display = hasImages ? 'block' : 'none'; + return hasImages; } // Handle inserting an image by pasting code // eslint-disable-next-line no-unused-vars function handleTextInput(drawMode) { + let input = document.getElementById('byte-input').value; + + // Remove Arduino code + input = input.replace(/const\s+(unsigned\s+char|uint8_t)\s+[a-zA-Z0-9]+\s*\[\]\s*(PROGMEM\s*)?=\s*/g, ''); + input = input.replace(/\};|\{/g, ''); + + // Remove comments (while newlines are still newlines, so the whole + // comment is dropped even if it contains a comma, e.g. "// 'name', 8x8px") + input = input.replace(/\/\/.*$/gm, ''); + // Convert newlines to comma + input = input.replace(/\r\n|\r|\n/g, ','); + // Convert multiple commas in a row into a single one + input = input.replace(/,{2,}/g, ','); + // Remove whitespace + input = input.replace(/\s/g, ''); + // Remove "0x" + input = input.replace(/0[xX]/g, ''); + // Split into list + const list = input.split(','); + + if (list.length === 1 && list[0] === '') { + const errorEl = document.getElementById('text-input-error'); + errorEl.textContent = 'Byte array is empty or invalid. Make sure there are no comments in your input.'; + errorEl.style.display = 'block'; + return; + } + const canvasContainer = document.getElementById('images-canvas-container'); const canvas = document.createElement('canvas'); @@ -671,29 +724,29 @@ function handleTextInput(drawMode) { const image = new Image(); images.setByIndex(0, { img: image, canvas, ctx: canvas.getContext('2d') }); - let input = document.getElementById('byte-input').value; + const success = drawMode === 'horizontal' + ? listToImageHorizontal(list, canvas) + : listToImageVertical(list, canvas); - // Remove Arduino code - input = input.replace(/const\s+(unsigned\s+char|uint8_t)\s+[a-zA-Z0-9]+\s*\[\]\s*(PROGMEM\s*)?=\s*/g, ''); - input = input.replace(/\};|\{/g, ''); + if (success) { + setCanvasDisplaySize(canvas); + document.getElementById('text-input-error').style.display = 'none'; + document.querySelectorAll('.no-file-selected').forEach((el) => { + // eslint-disable-next-line no-param-reassign + el.style.display = 'none'; + }); + checkImagesAvailable(); - // Convert newlines to comma (helps to remove comments later) - input = input.replace(/\r\n|\r|\n/g, ','); - // Convert multiple commas in a row into a single one - input = input.replace(/,{2,}/g, ','); - // Remove whitespace - input = input.replace(/\s/g, ''); - // Remove comments - input = input.replace(/\/\/(.+?),/g, ''); - // Remove "0x" - input = input.replace(/0[xX]/g, ''); - // Split into list - const list = input.split(','); + // Mirror the result onto a small preview canvas right below the + // buttons, so the pasted array is visible without scrolling to step 3. + const previewCanvas = document.getElementById('text-input-preview-canvas'); + previewCanvas.width = canvas.width; + previewCanvas.height = canvas.height; + previewCanvas.getContext('2d').drawImage(canvas, 0, 0); + previewCanvas.style.display = 'block'; - if (drawMode === 'horizontal') { - listToImageHorizontal(list, canvas); - } else { - listToImageVertical(list, canvas); + const readImagesNoteEl = document.getElementById('read-images-note'); + readImagesNoteEl.style.display = 'block'; } } @@ -738,6 +791,12 @@ function handleImageSelection(evt) { }); } + if (files.length > 0) { + document.getElementById('continue-note').style.display = 'block'; + } else { + document.getElementById('continue-note').style.display = 'none'; + } + for (let i = 0; files[i]; i++) { // Only process image files. if (!files[i].type.match('image.*')) { @@ -755,72 +814,54 @@ function handleImageSelection(evt) { const img = new Image(); img.onload = () => { - const fileInputColumnEntry = document.createElement('div'); - fileInputColumnEntry.className = 'file-input-entry'; + const fileInputEntryTemplate = document.getElementById('file-input-entry-template'); + const fileInputEntryFragment = fileInputEntryTemplate.content.cloneNode(true); + const fileInputColumnEntry = fileInputEntryFragment.querySelector('.file-input-entry'); - const fileInputColumnEntryLabel = document.createElement('span'); - fileInputColumnEntryLabel.textContent = file.name; + const fileInputColumnEntryThumb = fileInputColumnEntry.querySelector('.image-size-thumb'); + fileInputColumnEntryThumb.src = img.src; + fileInputColumnEntryThumb.alt = file.name; - const fileInputColumnEntryRemoveButton = document.createElement('button'); - fileInputColumnEntryRemoveButton.className = 'remove-button'; - fileInputColumnEntryRemoveButton.innerHTML = 'remove'; + fileInputColumnEntry.querySelector('.js-label').textContent = file.name; + + const fileInputColumnEntryRemoveButton = fileInputColumnEntry.querySelector('.js-remove'); const canvas = document.createElement('canvas'); - const imageEntry = document.createElement('li'); + const entryTemplate = document.getElementById('image-size-entry-template'); + const entryFragment = entryTemplate.content.cloneNode(true); + const imageEntry = entryFragment.querySelector('li'); imageEntry.setAttribute('data-img', file.name); - const w = document.createElement('input'); - w.type = 'number'; - w.name = 'width'; - w.id = 'screenWidth'; - w.min = 0; - w.className = 'size-input'; + const thumb = imageEntry.querySelector('.image-size-thumb'); + thumb.src = img.src; + thumb.alt = file.name; + + const w = imageEntry.querySelector('.js-width'); w.value = img.width; - settings.screenWidth = img.width; w.oninput = () => { - canvas.width = this.value; - updateAllImages(); - updateInteger('screenWidth'); + const image = images.get(img); + image.width = parseInt(w.value, 10); + placeImage(image); }; - const h = document.createElement('input'); - h.type = 'number'; - h.name = 'height'; - h.id = 'screenHeight'; - h.min = 0; - h.className = 'size-input'; + const h = imageEntry.querySelector('.js-height'); h.value = img.height; - settings.screenHeight = img.height; h.oninput = () => { - canvas.height = this.value; - updateAllImages(); - updateInteger('screenHeight'); + const image = images.get(img); + image.height = parseInt(h.value, 10); + placeImage(image); }; - const gil = document.createElement('span'); - gil.innerHTML = 'glyph'; - gil.className = 'file-info'; - - const gi = document.createElement('input'); - gi.type = 'text'; - gi.name = 'glyph'; - gi.className = 'glyph-input'; + const gi = imageEntry.querySelector('.js-glyph'); + const [fileName] = file.name.split('.'); + gi.value = fileName; gi.onchange = () => { const image = images.get(img); image.glyph = gi.value; }; - const fn = document.createElement('span'); - fn.className = 'file-info'; - fn.innerHTML = `${file.name} (file resolution: ${img.width} x ${img.height})`; - fn.innerHTML += '
    '; - - const rb = document.createElement('button'); - rb.className = 'remove-button'; - rb.innerHTML = 'remove'; - - const fileInputColumn = document.getElementById('file-input-column'); + const fileInputColumn = document.getElementById('file-input-column-items'); const imageSizeSettings = document.getElementById('image-size-settings'); const canvasContainer = document.getElementById('images-canvas-container'); @@ -835,40 +876,35 @@ function handleImageSelection(evt) { document.getElementById('all-same-size').style.display = 'none'; } if (images.length() === 0) { + document.getElementById('file-input').value = ''; noFileSelected.forEach((el) => { // eslint-disable-next-line no-param-reassign el.style.display = 'block'; }); } updateAllImages(); + checkImagesAvailable(); }; - rb.onclick = removeButtonOnClick; + imageEntry.querySelector('.js-file-name').textContent = `${file.name} (image size: ${img.width} x ${img.height} px)`; + imageEntry.querySelector('.js-remove').onclick = removeButtonOnClick; + fileInputColumnEntryRemoveButton.onclick = removeButtonOnClick; - fileInputColumnEntry.appendChild(fileInputColumnEntryLabel); - fileInputColumnEntry.appendChild(fileInputColumnEntryRemoveButton); fileInputColumn.appendChild(fileInputColumnEntry); - imageEntry.appendChild(fn); - imageEntry.appendChild(w); - imageEntry.appendChild(document.createTextNode(' x ')); - imageEntry.appendChild(h); - imageEntry.appendChild(gil); - imageEntry.appendChild(gi); - imageEntry.appendChild(rb); - imageSizeSettings.appendChild(imageEntry); canvas.width = img.width; canvas.height = img.height; canvasContainer.appendChild(canvas); - images.push(img, canvas, file.name.split('.')[0]); + images.push(img, canvas, file.name.split('.')[0], img.width, img.height); if (images.length() > 1) { document.getElementById('all-same-size').style.display = 'block'; } placeImage(images.last()); + checkImagesAvailable(); }; img.src = file.target.result; }; @@ -890,12 +926,70 @@ function imageToString(image) { // Get the custom arduino output variable name, if any function getIdentifier() { const vn = document.getElementById('identifier'); - return (vn && vn.value.length) ? vn.value : identifier; + return (vn && vn.value.length) ? vn.value : ''; +} + +// Builds the "// 'glyph', WxHpx" comment line placed before each image's +// byte array, or '' when comments are disabled. Indent is prefixed when given. +function glyphComment(image, indent = '') { + if (!settings.outputComments) return ''; + return `${indent}// '${image.glyph}', ${image.canvas.width}x${image.canvas.height}px\n`; +} + +// Wraps generated bitmap array code in a full Arduino sketch, based on +// oled_example/oled_example.ino, that compiles against the Adafruit +// SSD1306/GFX libraries and draws the first bitmap on the display. +function wrapFullExample(arrayCode, varName, width, height) { + return `#include +#include +#include +#include + +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 64 + +// Initialize display with standard I2C reset pin config (-1) +Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); + +${arrayCode} +void setup() { + Serial.begin(9600); + + // Initialize with I2C address 0x3C. You might have to change this to 0x3D for your display. + if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { + Serial.println(F("SSD1306 allocation failed. Check your wiring or I2C address!")); + for(;;); + } + + display.clearDisplay(); // Make sure the display is cleared + + // drawBitmap(x_coordinate, y_coordinate, array_name, width, height, color) + display.drawBitmap(0, 0, ${varName}, ${width}, ${height}, SSD1306_WHITE); + + // Push the memory buffer out to the physical display + display.display(); +} + +void loop() { + +}`; +} + +// Removes the trailing separator comma left after the last byte value. +// When settings.showAsciiPreview is on, the string always ends with a +// dot/hash ascii-art comment line instead (see makeAsciiRowTracker), so the +// comma sits just before that comment rather than at the true end. +function stripTrailingComma(str) { + return settings.showAsciiPreview + ? str.replace(/,(\s*\/\/[^\n]*)\n?\s*$/, '$1') + : str.replace(/,\s*$/, ''); } // Output the image string to the textfield // eslint-disable-next-line no-unused-vars function generateOutputString() { + if (!checkImagesAvailable()) return; + let outputString = ''; let code = ''; @@ -908,23 +1002,35 @@ function generateOutputString() { code = imageToString(image); // Trim whitespace from end and remove trailing comma - code = code.replace(/,\s*$/, ''); + code = stripTrailingComma(code); code = `\t${code.split('\n').join('\n\t')}\n`; // const variableCount = images.length() > 1 ? count++ : ''; - const comment = `// '${image.glyph}', ${image.canvas.width}x${image.canvas.height}px\n`; - bytesUsed += code.split('\n').length * 16; // 16 bytes per line. + const comment = glyphComment(image); + bytesUsed += code.split('\n').length * resolveWrapWidth(image.canvas.width); - const varname = getIdentifier() + (image.glyph ? image.glyph.replace(/[^a-zA-Z0-9]/g, '_') : ''); + const varname = getIdentifier() + (image.glyph ? `${image.glyph.replace(/[^a-zA-Z0-9]/g, '_')}` : ''); varQuickArray.push(varname); - code = `${comment}const ${getImageType()} ${varname} [] PROGMEM = {\n${code}};\n`; + code = `${comment}const ${getImageType()} ${varname} []${progmemKeyword()} = {\n${code}};\n`; outputString += code; }); varQuickArray.sort(); - outputString += `\n// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = ${bytesUsed})\n`; - outputString += `const int ${getIdentifier()}_allArray_LEN = ${varQuickArray.length};\n`; - outputString += `const ${getImageType()}* ${getIdentifier()}_allArray[${varQuickArray.length}] = {\n\t${varQuickArray.join(',\n\t')}\n};\n`; + if (outputString.length > 0) { + outputString += '\n'; + } + if (settings.outputComments) { + const storageNote = settings.esp32Format ? '' : ' in PROGMEM'; + outputString += `// Array of all bitmaps for convenience. (Total bytes used to store images${storageNote} = ${bytesUsed})\n`; + } + outputString += `const int ${getIdentifier()}allArray_LEN = ${varQuickArray.length};\n`; + outputString += `const ${getImageType()}* ${getIdentifier()}allArray[${varQuickArray.length}] = {\n\t${varQuickArray.join(',\n\t')}\n};\n`; + + if (settings.fullExample) { + const first = images.first(); + const firstVarName = getIdentifier() + (first.glyph ? `${first.glyph.replace(/[^a-zA-Z0-9]/g, '_')}` : ''); + outputString = wrapFullExample(outputString, firstVarName, first.canvas.width, first.canvas.height); + } break; } @@ -933,16 +1039,21 @@ function generateOutputString() { images.each((image) => { code = imageToString(image); code = `\t${code.split('\n').join('\n\t')}\n`; - comment = `\t// '${image.glyph}, ${image.canvas.width}x${image.canvas.height}px\n`; + comment = glyphComment(image, '\t'); outputString += comment + code; }); - outputString = outputString.replace(/,\s*$/, ''); + outputString = stripTrailingComma(outputString); outputString = `const ${getImageType()} ${ getIdentifier() - } [] PROGMEM = {` + } []${progmemKeyword()} = {` + `\n${outputString}\n};`; + + if (settings.fullExample) { + const first = images.first(); + outputString = wrapFullExample(outputString, getIdentifier(), first.canvas.width, first.canvas.height); + } break; } @@ -952,22 +1063,22 @@ function generateOutputString() { images.each((image) => { code = imageToString(image); code = `\t${code.split('\n').join('\n\t')}\n`; - comment = `\t// '${image.glyph}', ${image.canvas.width}x${image.canvas.height}px\n`; + comment = glyphComment(image, '\t'); outputString += comment + code; if (image.glyph.length === 1) { useGlyphs++; } }); - outputString = outputString.replace(/,\s*$/, ''); - outputString = `const unsigned char ${ + outputString = stripTrailingComma(outputString); + outputString = `const ${getByteType()} ${ getIdentifier() }Bitmap` - + ' [] PROGMEM = {' + + ` []${progmemKeyword()} = {` + `\n${outputString}\n};\n\n` + `const GFXbitmapGlyph ${ getIdentifier() - }Glyphs [] PROGMEM = {\n`; + }Glyphs []${progmemKeyword()} = {\n`; let firstAschiiChar = document.getElementById('first-ascii-char').value; const xAdvance = parseInt(document.getElementById('x-advance').value); @@ -988,7 +1099,7 @@ function generateOutputString() { if (image !== images.last()) { code += ','; } - code += `// '${image.glyph}'\n`; + code += settings.outputComments ? `// '${image.glyph}'\n` : '\n'; offset += image.canvas.width; }); code += '};\n'; @@ -997,7 +1108,7 @@ function generateOutputString() { // GFXbitmapFont outputString += `\nconst GFXbitmapFont ${ getIdentifier() - }Font PROGMEM = {\n` + }Font${progmemKeyword()} = {\n` + `\t(uint8_t *)${ getIdentifier()}Bitmap,\n` + `\t(GFXbitmapGlyph *)${ @@ -1010,10 +1121,7 @@ function generateOutputString() { default: { // plain images.each((image) => { code = imageToString(image); - let comment = ''; - if (image.glyph) { - comment = (`// '${image.glyph}', ${image.canvas.width}x${image.canvas.height}px\n`); - } + let comment = image.glyph ? glyphComment(image) : ''; if (image.img !== images.first().img) { comment = `\n${comment}`; } @@ -1021,32 +1129,56 @@ function generateOutputString() { outputString += code; }); // Trim whitespace from end and remove trailing comma - outputString = outputString.replace(/,\s*$/g, ''); + outputString = stripTrailingComma(outputString); } } document.getElementById('code-output').value = outputString; - document.getElementById('copy-button').disabled = false; } // Copy the final output to the clipboard // eslint-disable-next-line no-unused-vars function copyOutput() { - navigator.clipboard.writeText(document.getElementById('code-output').value); + if (!checkImagesAvailable()) return; + + const output = document.getElementById('code-output'); + if (!output.value) { + generateOutputString(); + } + navigator.clipboard.writeText(output.value); +} + +// Rebuilds the true byte stream for the current images/conversion mode by +// re-splitting each formatted output value (which may be 1, 2 or 4 bytes +// wide, depending on drawMode) back into its individual bytes, most- +// significant first. Exposed standalone so it can be exercised directly in +// tests without going through a real browser file download. +function computeBinData() { + const bytesPerValue = CONVERSION_BYTES_PER_VALUE.get(settings.conversionFunction) || 1; + const raw = []; + images.each((image) => { + const values = imageToString(image) + .split(',') + .map((s) => s.trim()) + .filter(Boolean) + .map((token) => parseInt(token, 16)); + values.forEach((value) => { + // Split back into individual bytes, most-significant first, matching + // the left-to-right digit order produced by toString(16).padStart(). + for (let shift = (bytesPerValue - 1) * 8; shift >= 0; shift -= 8) { + // eslint-disable-next-line no-bitwise + raw.push((value >> shift) & 0xff); + } + }); + }); + return new Uint8Array(raw); } // eslint-disable-next-line no-unused-vars function downloadBinFile() { - let raw = []; - images.each((image) => { - const data = imageToString(image) - .split(',') - .map((s) => s.trim()) - .filter(Boolean) - .map((byte) => parseInt(byte, 16)); - raw = raw.concat(data); - }); - const data = new Uint8Array(raw); + if (!checkImagesAvailable()) return; + + const data = computeBinData(); const a = document.createElement('a'); a.style = 'display: none'; document.body.appendChild(a); @@ -1073,7 +1205,6 @@ function updateOutputFormat(elm) { let caption = document.getElementById('format-caption-container'); const adafruitGfx = document.getElementById('adafruit-gfx-settings'); const arduino = document.getElementById('arduino-identifier'); - const removeZeroesCommasContainer = document.getElementById('remove-zeroes-commas-container'); document.getElementById('code-output').value = ''; for (let i = 0; i < caption.children.length; i++) { @@ -1082,15 +1213,13 @@ function updateOutputFormat(elm) { caption = document.querySelector(`div[data-caption='${elm.value}']`); if (caption) caption.style.display = 'block'; - if (elm.value !== 'plain') { - arduino.style.display = 'block'; - removeZeroesCommasContainer.style.display = 'none'; - settings.removeZeroesCommas = false; - document.getElementById('removeZeroesCommas').checked = false; - } else { - arduino.style.display = 'none'; - removeZeroesCommasContainer.style.display = 'table-row'; - } + arduino.style.display = elm.value !== 'plain' ? 'block' : 'none'; + + settings.prefix = '0x'; + document.getElementById('prefix').value = '0x'; + settings.separator = ', '; + document.getElementById('separator').value = ', '; + if (elm.value === 'adafruit_gfx') { adafruitGfx.style.display = 'block'; } else { @@ -1113,12 +1242,11 @@ function updateRadio(fieldName) { } window.onload = () => { - document.getElementById('copy-button').disabled = true; - // Add events to the file input button const fileInput = document.getElementById('file-input'); fileInput.addEventListener('click', () => { this.value = null; }, false); fileInput.addEventListener('change', handleImageSelection, false); - document.getElementById('outputFormat').value = 'arduino'; - document.getElementById('outputFormat').onchange(); + const outputFormat = document.getElementById('outputFormat'); + outputFormat.value = 'arduino'; + updateOutputFormat(outputFormat); }; diff --git a/package-lock.json b/package-lock.json index 19c9cbe..226f538 100644 --- a/package-lock.json +++ b/package-lock.json @@ -166,10 +166,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -298,10 +299,11 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -376,10 +378,11 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1421,10 +1424,20 @@ } }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -1837,10 +1850,11 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } diff --git a/package.json b/package.json index c9a2257..97cb299 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "image2cpp", - "version": "1.0.0", + "version": "2.0.0", "description": "Use this tool online at http://javl.github.io/image2cpp/ image2cpp is a simple tool to change images into byte arrays (or your array back into an image) for use with (monochrome) displays suchs as OLEDs, like those from Adafruit or Sparkfun. While searching for a way to generate these arrays, I mostly found links to a piece of Windows software. Both the flakey results and the hassle of having to boot a virtual machine just to convert an image lead to me writing this pure html + javascript solution.", "main": "dithering.js", "scripts": { diff --git a/restyle.md b/restyle.md new file mode 100644 index 0000000..7721107 --- /dev/null +++ b/restyle.md @@ -0,0 +1,404 @@ + + + +image2cpp | Image to Byte Array Converter + + + + + + + + + +
    +
    +
    +image2cpp + +
    +
    + + +
    +
    +
    +
    + + + +
    +
    +

    Image to C++ Converter

    +

    Generate monochrome byte arrays for OLED displays on Arduino or Raspberry Pi. All processing happens in your browser.

    +
    Support onfavoritecoffee
    + +
    + +
    +
    +
    1
    +
    +
    +
    + +
    +cloud_upload +

    Drag and drop images here or Browse

    +

    Supports JPG, PNG, BMP, GIF

    + +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    +
    2
    +
    +

    Image Configuration

    +
    + +
    + +
    + +× + +
    +
    + +
    + +
    + + + +
    +
    + +
    + + +
    + +
    + + +
    + +
    + +
    + +128 +
    +
    + +
    + +
    + +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    3
    +
    +
    +

    Preview

    +
    + + +
    +
    +
    +
    +Original +
    + +
    +
    +
    +Converted (1-bit) +
    + + +
    +
    +
    +
    +
    + +
    +
    +
    4
    +
    +
    +
    +

    Output Settings

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    + +
    + + + +
    +
    +
    +
    +
    // Generated by image2cpp
    +// 128x64px, myBitmap
    +
    +const unsigned char myBitmap [] PROGMEM = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; +
    +
    +info +

    If the preview looks scrambled on your hardware, try switching the Draw Mode between Horizontal and Vertical. +

    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..3a6e398 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,37 @@ +# image2cpp test suite + +Test uses the real `index.html` file and scripts in a headless browser +using `Playwright`. Output is compared against known valid (`golden`) files. +This way we are testing the output of the actual tool, not a reimplementation. + +## Setup and running + +``` +python3 -m venv .venv +source .venv/bin/activate +pip install -r tests/requirements.txt +playwright install chromium +``` + +To run: +``` +python3 tests/test_conversions.py +``` + +Prints `ok`/`FAIL` per scenario and exits non-zero if anything doesn't +match. + +## Updating golden files and test image + +To generate the test image again (only needed if we changed the image): +``` +python3 tests/generate_test_image.py +``` + +After an intentional change to the conversion logic, regenerate the +golden output and optionally review the diff before committing: + +``` +python3 tests/test_conversions.py --update +git diff tests/golden +``` diff --git a/tests/fixtures/test_pattern.png b/tests/fixtures/test_pattern.png new file mode 100644 index 0000000..87f9b74 Binary files /dev/null and b/tests/fixtures/test_pattern.png differ diff --git a/tests/generate_test_image.py b/tests/generate_test_image.py new file mode 100644 index 0000000..2d8227a --- /dev/null +++ b/tests/generate_test_image.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +""" Generate a simple test-pattern image for use with the test suite. + This 32x24 image is used to test all the different conversion paths in + js/script.js and js/dithering.js. Different quadrants of the image test + different aspects of the conversion process: + + - top-left: checkerboard -> stresses the threshold/dithering modes + - top-right: horizontal grayscale gradient -> stresses dithering algorithms + - bottom-left: RGB color bars -> stresses 565/888 color output + - bottom-right: diagonal line on white -> asymmetric element to test flip/rotate/mirror + +A 1px red marker in the extreme top-left corner and a 1px blue marker in the +extreme bottom-right corner give an unambiguous orientation reference. +""" +from pathlib import Path + +from PIL import Image + +WIDTH, HEIGHT = 32, 24 +OUT_PATH = Path(__file__).parent / "fixtures" / "test_pattern.png" + + +def build_image(): + img = Image.new("RGB", (WIDTH, HEIGHT), "white") + px = img.load() + if px is None: + raise RuntimeError("Failed to create image object") + + half_w, half_h = WIDTH // 2, HEIGHT // 2 + + # Top-left: checkerboard + for y in range(half_h): + for x in range(half_w): + color = (0, 0, 0) if (x // 2 + y // 2) % 2 == 0 else (255, 255, 255) + px[x, y] = color + + # Top-right: horizontal grayscale gradient + for y in range(half_h): + for x in range(half_w): + v = int((x / max(half_w - 1, 1)) * 255) + px[half_w + x, y] = (v, v, v) + + # Bottom-left: RGB color bars (red, green, blue, white) + bars = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 255)] + bar_w = max(half_w // len(bars), 1) + for y in range(half_h): + for x in range(half_w): + bar = min(x // bar_w, len(bars) - 1) + px[x, half_h + y] = bars[bar] + + # Bottom-right: diagonal line on white background (asymmetric marker) + for y in range(half_h): + for x in range(half_w): + px[half_w + x, half_h + y] = (255, 255, 255) + for i in range(min(half_w, half_h)): + px[half_w + i, half_h + i] = (0, 0, 0) + + # Orientation markers + px[0, 0] = (255, 0, 0) # top-left corner: red + px[WIDTH - 1, HEIGHT - 1] = (0, 0, 255) # bottom-right corner: blue + + return img + + +def main(): + OUT_PATH.parent.mkdir(parents=True, exist_ok=True) + build_image().save(OUT_PATH) + print(f"wrote {OUT_PATH}") + + +if __name__ == "__main__": + main() diff --git a/tests/golden/ascii_preview.txt b/tests/golden/ascii_preview.txt new file mode 100644 index 0000000..00f0683 --- /dev/null +++ b/tests/golden/ascii_preview.txt @@ -0,0 +1,25 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x0f, 0x0f, 0x7f, 0xff, // . . . . # # # # . . . . # # # # . # # # # # # # # # # # # # # # +0x0f, 0x0f, 0xbf, 0xff, // . . . . # # # # . . . . # # # # # . # # # # # # # # # # # # # # +0x0f, 0x0f, 0xdf, 0xff, // . . . . # # # # . . . . # # # # # # . # # # # # # # # # # # # # +0x0f, 0x0f, 0xef, 0xff, // . . . . # # # # . . . . # # # # # # # . # # # # # # # # # # # # +0x0f, 0x0f, 0xf7, 0xff, // . . . . # # # # . . . . # # # # # # # # . # # # # # # # # # # # +0x0f, 0x0f, 0xfb, 0xff, // . . . . # # # # . . . . # # # # # # # # # . # # # # # # # # # # +0x0f, 0x0f, 0xfd, 0xff, // . . . . # # # # . . . . # # # # # # # # # # . # # # # # # # # # +0x0f, 0x0f, 0xfe, 0xff, // . . . . # # # # . . . . # # # # # # # # # # # . # # # # # # # # +0x0f, 0x0f, 0xff, 0x7f, // . . . . # # # # . . . . # # # # # # # # # # # # . # # # # # # # +0x0f, 0x0f, 0xff, 0xbf, // . . . . # # # # . . . . # # # # # # # # # # # # # . # # # # # # +0x0f, 0x0f, 0xff, 0xdf, // . . . . # # # # . . . . # # # # # # # # # # # # # # . # # # # # +0x0f, 0x0f, 0xff, 0xee // . . . . # # # # . . . . # # # # # # # # # # # # # # # . # # # . \ No newline at end of file diff --git a/tests/golden/ascii_preview_arduino.txt b/tests/golden/ascii_preview_arduino.txt new file mode 100644 index 0000000..8be6e07 --- /dev/null +++ b/tests/golden/ascii_preview_arduino.txt @@ -0,0 +1,33 @@ +// 'test_pattern', 32x24px +const unsigned char epd_bitmap_test_pattern [] PROGMEM = { + 0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # + 0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # + 0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # + 0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # + 0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # + 0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # + 0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # + 0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # + 0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # + 0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # + 0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # + 0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # + 0x0f, 0x0f, 0x7f, 0xff, // . . . . # # # # . . . . # # # # . # # # # # # # # # # # # # # # + 0x0f, 0x0f, 0xbf, 0xff, // . . . . # # # # . . . . # # # # # . # # # # # # # # # # # # # # + 0x0f, 0x0f, 0xdf, 0xff, // . . . . # # # # . . . . # # # # # # . # # # # # # # # # # # # # + 0x0f, 0x0f, 0xef, 0xff, // . . . . # # # # . . . . # # # # # # # . # # # # # # # # # # # # + 0x0f, 0x0f, 0xf7, 0xff, // . . . . # # # # . . . . # # # # # # # # . # # # # # # # # # # # + 0x0f, 0x0f, 0xfb, 0xff, // . . . . # # # # . . . . # # # # # # # # # . # # # # # # # # # # + 0x0f, 0x0f, 0xfd, 0xff, // . . . . # # # # . . . . # # # # # # # # # # . # # # # # # # # # + 0x0f, 0x0f, 0xfe, 0xff, // . . . . # # # # . . . . # # # # # # # # # # # . # # # # # # # # + 0x0f, 0x0f, 0xff, 0x7f, // . . . . # # # # . . . . # # # # # # # # # # # # . # # # # # # # + 0x0f, 0x0f, 0xff, 0xbf, // . . . . # # # # . . . . # # # # # # # # # # # # # . # # # # # # + 0x0f, 0x0f, 0xff, 0xdf, // . . . . # # # # . . . . # # # # # # # # # # # # # # . # # # # # + 0x0f, 0x0f, 0xff, 0xee // . . . . # # # # . . . . # # # # # # # # # # # # # # # . # # # . +}; + +// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 400) +const int epd_bitmap_allArray_LEN = 1; +const unsigned char* epd_bitmap_allArray[1] = { + epd_bitmap_test_pattern +}; diff --git a/tests/golden/ascii_preview_bytes_per_row_ignored.txt b/tests/golden/ascii_preview_bytes_per_row_ignored.txt new file mode 100644 index 0000000..00f0683 --- /dev/null +++ b/tests/golden/ascii_preview_bytes_per_row_ignored.txt @@ -0,0 +1,25 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x33, 0x33, 0x00, 0xff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xcc, 0xcc, 0x00, 0xff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x0f, 0x0f, 0x7f, 0xff, // . . . . # # # # . . . . # # # # . # # # # # # # # # # # # # # # +0x0f, 0x0f, 0xbf, 0xff, // . . . . # # # # . . . . # # # # # . # # # # # # # # # # # # # # +0x0f, 0x0f, 0xdf, 0xff, // . . . . # # # # . . . . # # # # # # . # # # # # # # # # # # # # +0x0f, 0x0f, 0xef, 0xff, // . . . . # # # # . . . . # # # # # # # . # # # # # # # # # # # # +0x0f, 0x0f, 0xf7, 0xff, // . . . . # # # # . . . . # # # # # # # # . # # # # # # # # # # # +0x0f, 0x0f, 0xfb, 0xff, // . . . . # # # # . . . . # # # # # # # # # . # # # # # # # # # # +0x0f, 0x0f, 0xfd, 0xff, // . . . . # # # # . . . . # # # # # # # # # # . # # # # # # # # # +0x0f, 0x0f, 0xfe, 0xff, // . . . . # # # # . . . . # # # # # # # # # # # . # # # # # # # # +0x0f, 0x0f, 0xff, 0x7f, // . . . . # # # # . . . . # # # # # # # # # # # # . # # # # # # # +0x0f, 0x0f, 0xff, 0xbf, // . . . . # # # # . . . . # # # # # # # # # # # # # . # # # # # # +0x0f, 0x0f, 0xff, 0xdf, // . . . . # # # # . . . . # # # # # # # # # # # # # # . # # # # # +0x0f, 0x0f, 0xff, 0xee // . . . . # # # # . . . . # # # # # # # # # # # # # # # . # # # . \ No newline at end of file diff --git a/tests/golden/ascii_preview_horizontal565.txt b/tests/golden/ascii_preview_horizontal565.txt new file mode 100644 index 0000000..291b2d2 --- /dev/null +++ b/tests/golden/ascii_preview_horizontal565.txt @@ -0,0 +1,25 @@ +// 'test_pattern', 32x24px +0xf800, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # . # # # # # # # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # . # # # # # # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # . # # # # # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # . # # # # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # . # # # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # # . # # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # # # . # # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # # # # . # # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # # # # # . # # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # # # # # # . # # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // . . . . . . . . . . . . # # # # # # # # # # # # # # . # # # # # +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0x001f // . . . . . . . . . . . . # # # # # # # # # # # # # # # . # # # . \ No newline at end of file diff --git a/tests/golden/ascii_preview_horizontal888.txt b/tests/golden/ascii_preview_horizontal888.txt new file mode 100644 index 0000000..8d1f4e4 --- /dev/null +++ b/tests/golden/ascii_preview_horizontal888.txt @@ -0,0 +1,25 @@ +// 'test_pattern', 32x24px +0x00ff0000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // . . # # . . # # . . # # . . # # . . . . . . . . # # # # # # # # +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, // # # . . # # . . # # . . # # . . . . . . . . . . # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # . # # # # # # # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # . # # # # # # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # . # # # # # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # . # # # # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # . # # # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # # . # # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # # # . # # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # # # # . # # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # # # # # . # # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # # # # # # . # # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, // . . . . . . . . . . . . # # # # # # # # # # # # # # . # # # # # +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x000000ff // . . . . . . . . . . . . # # # # # # # # # # # # # # # . # # # . \ No newline at end of file diff --git a/tests/golden/background_black.txt b/tests/golden/background_black.txt new file mode 100644 index 0000000..928ffe2 --- /dev/null +++ b/tests/golden/background_black.txt @@ -0,0 +1,16 @@ +// 'test_pattern', 48x40px +0x33, 0x33, 0x00, 0xff, 0x00, 0x00, 0x33, 0x33, 0x00, 0xff, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xff, +0x00, 0x00, 0xcc, 0xcc, 0x00, 0xff, 0x00, 0x00, 0x33, 0x33, 0x00, 0xff, 0x00, 0x00, 0x33, 0x33, +0x00, 0xff, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xff, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xff, 0x00, 0x00, +0x33, 0x33, 0x00, 0xff, 0x00, 0x00, 0x33, 0x33, 0x00, 0xff, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xff, +0x00, 0x00, 0xcc, 0xcc, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x7f, 0xff, 0x00, 0x00, 0x0f, 0x0f, +0xbf, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xdf, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xef, 0xff, 0x00, 0x00, +0x0f, 0x0f, 0xf7, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xfb, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xfd, 0xff, +0x00, 0x00, 0x0f, 0x0f, 0xfe, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0x7f, 0x00, 0x00, 0x0f, 0x0f, +0xff, 0xbf, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xdf, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xee, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \ No newline at end of file diff --git a/tests/golden/background_transparent.txt b/tests/golden/background_transparent.txt new file mode 100644 index 0000000..c73451d --- /dev/null +++ b/tests/golden/background_transparent.txt @@ -0,0 +1,16 @@ +// 'test_pattern', 48x40px +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \ No newline at end of file diff --git a/tests/golden/background_white_larger_canvas.txt b/tests/golden/background_white_larger_canvas.txt new file mode 100644 index 0000000..703e81b --- /dev/null +++ b/tests/golden/background_white_larger_canvas.txt @@ -0,0 +1,16 @@ +// 'test_pattern', 48x40px +0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, +0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, +0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x7f, 0xff, 0xff, 0xff, 0x0f, 0x0f, +0xbf, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xef, 0xff, 0xff, 0xff, +0x0f, 0x0f, 0xf7, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xfd, 0xff, +0xff, 0xff, 0x0f, 0x0f, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0x7f, 0xff, 0xff, 0x0f, 0x0f, +0xff, 0xbf, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xdf, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xee, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/bitswap.txt b/tests/golden/bitswap.txt new file mode 100644 index 0000000..3aeab3e --- /dev/null +++ b/tests/golden/bitswap.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0xf0, 0xf0, 0xfe, 0xff, 0xf0, 0xf0, 0xfd, 0xff, 0xf0, 0xf0, 0xfb, 0xff, 0xf0, 0xf0, 0xf7, 0xff, +0xf0, 0xf0, 0xef, 0xff, 0xf0, 0xf0, 0xdf, 0xff, 0xf0, 0xf0, 0xbf, 0xff, 0xf0, 0xf0, 0x7f, 0xff, +0xf0, 0xf0, 0xff, 0xfe, 0xf0, 0xf0, 0xff, 0xfd, 0xf0, 0xf0, 0xff, 0xfb, 0xf0, 0xf0, 0xff, 0x77 \ No newline at end of file diff --git a/tests/golden/bitswap_vertical.txt b/tests/golden/bitswap_vertical.txt new file mode 100644 index 0000000..8a81e1e --- /dev/null +++ b/tests/golden/bitswap_vertical.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x30, 0x30, 0xc0, 0xc0, 0x3f, 0x3f, 0xcf, 0xcf, 0x30, 0x30, 0xc0, 0xc0, 0x3f, 0x3f, 0xcf, 0xcf, +0x07, 0x0b, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xfe \ No newline at end of file diff --git a/tests/golden/center_both_larger_canvas.txt b/tests/golden/center_both_larger_canvas.txt new file mode 100644 index 0000000..db176b4 --- /dev/null +++ b/tests/golden/center_both_larger_canvas.txt @@ -0,0 +1,16 @@ +// 'test_pattern', 48x40px +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, +0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0x33, +0x33, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, +0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0x33, 0x33, 0x00, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, +0xff, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x7f, 0xff, 0xff, 0xff, 0x0f, +0x0f, 0xbf, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xef, 0xff, 0xff, +0xff, 0x0f, 0x0f, 0xf7, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xfd, +0xff, 0xff, 0xff, 0x0f, 0x0f, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0x7f, 0xff, 0xff, 0x0f, +0x0f, 0xff, 0xbf, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xdf, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xee, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/default.txt b/tests/golden/default.txt new file mode 100644 index 0000000..d2b1a12 --- /dev/null +++ b/tests/golden/default.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, +0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, +0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee \ No newline at end of file diff --git a/tests/golden/dithering_atkinson.txt b/tests/golden/dithering_atkinson.txt new file mode 100644 index 0000000..bd8018f --- /dev/null +++ b/tests/golden/dithering_atkinson.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x01, 0xbf, 0x33, 0x33, 0x04, 0xff, 0xcc, 0xcc, 0x04, 0x9f, 0xcc, 0xcc, 0x03, 0x77, +0x33, 0x33, 0x09, 0x7f, 0x33, 0x33, 0x01, 0x9f, 0xcc, 0xcc, 0x06, 0x7f, 0xcc, 0xcc, 0x01, 0xb7, +0x33, 0x33, 0x09, 0xbf, 0x33, 0x33, 0x04, 0x6f, 0xcc, 0xcc, 0x05, 0xbf, 0xcc, 0xcc, 0x01, 0xb7, +0x0d, 0x0f, 0x7f, 0xff, 0x0d, 0x0f, 0xbf, 0xff, 0x4b, 0x0f, 0xdf, 0xff, 0x1a, 0x0f, 0xef, 0xff, +0x26, 0x0f, 0xf7, 0xff, 0x0d, 0x0f, 0xfb, 0xff, 0x49, 0x0f, 0xfd, 0xff, 0x1b, 0x0f, 0xfe, 0xff, +0x0e, 0x0f, 0xff, 0x7f, 0x65, 0x0f, 0xff, 0xbf, 0x0d, 0x0f, 0xff, 0xdf, 0x0b, 0x0f, 0xff, 0xee \ No newline at end of file diff --git a/tests/golden/dithering_bayer.txt b/tests/golden/dithering_bayer.txt new file mode 100644 index 0000000..8987b8a --- /dev/null +++ b/tests/golden/dithering_bayer.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x15, 0x57, 0x33, 0x33, 0x02, 0xbf, 0xcc, 0xcc, 0x15, 0x57, 0xcc, 0xcc, 0x00, 0xff, +0x33, 0x33, 0x15, 0x57, 0x33, 0x33, 0x02, 0xbf, 0xcc, 0xcc, 0x15, 0x57, 0xcc, 0xcc, 0x00, 0xff, +0x33, 0x33, 0x15, 0x57, 0x33, 0x33, 0x02, 0xbf, 0xcc, 0xcc, 0x15, 0x57, 0xcc, 0xcc, 0x00, 0xff, +0x55, 0x1f, 0x7f, 0xff, 0x2b, 0x0f, 0xbf, 0xff, 0x55, 0x0f, 0xdf, 0xff, 0x0a, 0x0f, 0xef, 0xff, +0x55, 0x1f, 0xf7, 0xff, 0x2b, 0x0f, 0xfb, 0xff, 0x55, 0x0f, 0xfd, 0xff, 0x0a, 0x0f, 0xfe, 0xff, +0x55, 0x1f, 0xff, 0x7f, 0x2b, 0x0f, 0xff, 0xbf, 0x55, 0x0f, 0xff, 0xdf, 0x0a, 0x0f, 0xff, 0xee \ No newline at end of file diff --git a/tests/golden/dithering_floyd_steinberg.txt b/tests/golden/dithering_floyd_steinberg.txt new file mode 100644 index 0000000..c86c4ad --- /dev/null +++ b/tests/golden/dithering_floyd_steinberg.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x02, 0xbf, 0x33, 0x33, 0x09, 0x57, 0xcc, 0xcc, 0x05, 0x7f, 0xcc, 0xcc, 0x11, 0x57, +0x33, 0x33, 0x05, 0x5f, 0x33, 0x33, 0x02, 0xb7, 0xcc, 0xcc, 0x14, 0xbf, 0xcc, 0xcc, 0x02, 0xd7, +0x33, 0x33, 0x09, 0x5d, 0x33, 0x33, 0x04, 0xb7, 0xcc, 0xcc, 0x12, 0xbf, 0xcc, 0xcc, 0x02, 0xaf, +0x0a, 0x0f, 0x7f, 0xff, 0x55, 0x0f, 0xbf, 0xff, 0x0b, 0x0f, 0xdf, 0xff, 0x2d, 0x0f, 0xef, 0xff, +0x45, 0x0f, 0xf7, 0xff, 0x15, 0x0f, 0xfb, 0xff, 0x4d, 0x0f, 0xfd, 0xff, 0x15, 0x0f, 0xfe, 0xff, +0x4a, 0x0f, 0xff, 0x7f, 0x0b, 0x0f, 0xff, 0xbf, 0x55, 0x0f, 0xff, 0xdf, 0x0a, 0x2f, 0xff, 0xee \ No newline at end of file diff --git a/tests/golden/dithering_threshold_high.txt b/tests/golden/dithering_threshold_high.txt new file mode 100644 index 0000000..cabebd6 --- /dev/null +++ b/tests/golden/dithering_threshold_high.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x33, 0x33, 0x00, 0x0f, 0x33, 0x33, 0x00, 0x0f, 0xcc, 0xcc, 0x00, 0x0f, 0xcc, 0xcc, 0x00, 0x0f, +0x33, 0x33, 0x00, 0x0f, 0x33, 0x33, 0x00, 0x0f, 0xcc, 0xcc, 0x00, 0x0f, 0xcc, 0xcc, 0x00, 0x0f, +0x33, 0x33, 0x00, 0x0f, 0x33, 0x33, 0x00, 0x0f, 0xcc, 0xcc, 0x00, 0x0f, 0xcc, 0xcc, 0x00, 0x0f, +0x00, 0x0f, 0x7f, 0xff, 0x00, 0x0f, 0xbf, 0xff, 0x00, 0x0f, 0xdf, 0xff, 0x00, 0x0f, 0xef, 0xff, +0x00, 0x0f, 0xf7, 0xff, 0x00, 0x0f, 0xfb, 0xff, 0x00, 0x0f, 0xfd, 0xff, 0x00, 0x0f, 0xfe, 0xff, +0x00, 0x0f, 0xff, 0x7f, 0x00, 0x0f, 0xff, 0xbf, 0x00, 0x0f, 0xff, 0xdf, 0x00, 0x0f, 0xff, 0xee \ No newline at end of file diff --git a/tests/golden/dithering_threshold_low.txt b/tests/golden/dithering_threshold_low.txt new file mode 100644 index 0000000..d046e7c --- /dev/null +++ b/tests/golden/dithering_threshold_low.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xb3, 0x33, 0x0f, 0xff, 0x33, 0x33, 0x0f, 0xff, 0xcc, 0xcc, 0x0f, 0xff, 0xcc, 0xcc, 0x0f, 0xff, +0x33, 0x33, 0x0f, 0xff, 0x33, 0x33, 0x0f, 0xff, 0xcc, 0xcc, 0x0f, 0xff, 0xcc, 0xcc, 0x0f, 0xff, +0x33, 0x33, 0x0f, 0xff, 0x33, 0x33, 0x0f, 0xff, 0xcc, 0xcc, 0x0f, 0xff, 0xcc, 0xcc, 0x0f, 0xff, +0xff, 0x0f, 0x7f, 0xff, 0xff, 0x0f, 0xbf, 0xff, 0xff, 0x0f, 0xdf, 0xff, 0xff, 0x0f, 0xef, 0xff, +0xff, 0x0f, 0xf7, 0xff, 0xff, 0x0f, 0xfb, 0xff, 0xff, 0x0f, 0xfd, 0xff, 0xff, 0x0f, 0xfe, 0xff, +0xff, 0x0f, 0xff, 0x7f, 0xff, 0x0f, 0xff, 0xbf, 0xff, 0x0f, 0xff, 0xdf, 0xff, 0x0f, 0xff, 0xee \ No newline at end of file diff --git a/tests/golden/draw_mode_horizontal565.txt b/tests/golden/draw_mode_horizontal565.txt new file mode 100644 index 0000000..56b0757 --- /dev/null +++ b/tests/golden/draw_mode_horizontal565.txt @@ -0,0 +1,49 @@ +// 'test_pattern', 32x24px +0xf800, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0x001f \ No newline at end of file diff --git a/tests/golden/draw_mode_horizontal888.txt b/tests/golden/draw_mode_horizontal888.txt new file mode 100644 index 0000000..e731596 --- /dev/null +++ b/tests/golden/draw_mode_horizontal888.txt @@ -0,0 +1,25 @@ +// 'test_pattern', 32x24px +0x00ff0000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00111111, 0x00222222, 0x00333333, 0x00444444, 0x00555555, 0x00666666, 0x00777777, 0x00888888, 0x00999999, 0x00aaaaaa, 0x00bbbbbb, 0x00cccccc, 0x00dddddd, 0x00eeeeee, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x000000ff \ No newline at end of file diff --git a/tests/golden/draw_mode_horizontal_alpha.txt b/tests/golden/draw_mode_horizontal_alpha.txt new file mode 100644 index 0000000..fe08dcf --- /dev/null +++ b/tests/golden/draw_mode_horizontal_alpha.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/draw_mode_vertical1bit.txt b/tests/golden/draw_mode_vertical1bit.txt new file mode 100644 index 0000000..790404b --- /dev/null +++ b/tests/golden/draw_mode_vertical1bit.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x0c, 0x0c, 0x03, 0x03, 0xfc, 0xfc, 0xf3, 0xf3, 0x0c, 0x0c, 0x03, 0x03, 0xfc, 0xfc, 0xf3, 0xf3, +0xe0, 0xd0, 0xb0, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0x7f \ No newline at end of file diff --git a/tests/golden/flip_both.txt b/tests/golden/flip_both.txt new file mode 100644 index 0000000..c70700f --- /dev/null +++ b/tests/golden/flip_both.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x77, 0xff, 0xf0, 0xf0, 0xfb, 0xff, 0xf0, 0xf0, 0xfd, 0xff, 0xf0, 0xf0, 0xfe, 0xff, 0xf0, 0xf0, +0xff, 0x7f, 0xf0, 0xf0, 0xff, 0xbf, 0xf0, 0xf0, 0xff, 0xdf, 0xf0, 0xf0, 0xff, 0xef, 0xf0, 0xf0, +0xff, 0xf7, 0xf0, 0xf0, 0xff, 0xfb, 0xf0, 0xf0, 0xff, 0xfd, 0xf0, 0xf0, 0xff, 0xfe, 0xf0, 0xf0, +0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, +0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, +0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc \ No newline at end of file diff --git a/tests/golden/flip_horizontal.txt b/tests/golden/flip_horizontal.txt new file mode 100644 index 0000000..d6b33af --- /dev/null +++ b/tests/golden/flip_horizontal.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, +0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, +0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, +0xff, 0xfe, 0xf0, 0xf0, 0xff, 0xfd, 0xf0, 0xf0, 0xff, 0xfb, 0xf0, 0xf0, 0xff, 0xf7, 0xf0, 0xf0, +0xff, 0xef, 0xf0, 0xf0, 0xff, 0xdf, 0xf0, 0xf0, 0xff, 0xbf, 0xf0, 0xf0, 0xff, 0x7f, 0xf0, 0xf0, +0xfe, 0xff, 0xf0, 0xf0, 0xfd, 0xff, 0xf0, 0xf0, 0xfb, 0xff, 0xf0, 0xf0, 0x77, 0xff, 0xf0, 0xf0 \ No newline at end of file diff --git a/tests/golden/flip_vertical.txt b/tests/golden/flip_vertical.txt new file mode 100644 index 0000000..3c0eaf2 --- /dev/null +++ b/tests/golden/flip_vertical.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x0f, 0x0f, 0xff, 0xee, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0x7f, +0x0f, 0x0f, 0xfe, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xf7, 0xff, +0x0f, 0x0f, 0xef, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0x7f, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff \ No newline at end of file diff --git a/tests/golden/invert_colors.txt b/tests/golden/invert_colors.txt new file mode 100644 index 0000000..ba88886 --- /dev/null +++ b/tests/golden/invert_colors.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, +0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, +0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, +0xf0, 0xf0, 0x80, 0x00, 0xf0, 0xf0, 0x40, 0x00, 0xf0, 0xf0, 0x20, 0x00, 0xf0, 0xf0, 0x10, 0x00, +0xf0, 0xf0, 0x08, 0x00, 0xf0, 0xf0, 0x04, 0x00, 0xf0, 0xf0, 0x02, 0x00, 0xf0, 0xf0, 0x01, 0x00, +0xf0, 0xf0, 0x00, 0x80, 0xf0, 0xf0, 0x00, 0x40, 0xf0, 0xf0, 0x00, 0x20, 0xf0, 0xf0, 0x00, 0x11 \ No newline at end of file diff --git a/tests/golden/kitchen_sink.txt b/tests/golden/kitchen_sink.txt new file mode 100644 index 0000000..58a86a7 --- /dev/null +++ b/tests/golden/kitchen_sink.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x80, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0xff, 0xff, 0x90, 0x4f, 0xb0, 0x4b, 0xb5, 0xff, 0xaa, 0xff, +0x00, 0x01, 0x00, 0x02, 0x08, 0x01, 0x0e, 0x01, 0x0e, 0x03, 0x0d, 0x0e, 0x8b, 0x4f, 0x2f, 0x1f, +0x0c, 0x0c, 0x03, 0x03, 0xfc, 0xfc, 0xf3, 0xf3, 0x1c, 0xac, 0x53, 0x23, 0xdc, 0x7c, 0xd3, 0xf3, +0x00, 0x00, 0x00, 0xaa, 0x00, 0x9a, 0x61, 0x1e, 0xe1, 0x5e, 0xab, 0xfd, 0xb7, 0xff, 0xff, 0xff, +0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33 \ No newline at end of file diff --git a/tests/golden/output_adafruit_gfx.txt b/tests/golden/output_adafruit_gfx.txt new file mode 100644 index 0000000..68216c2 --- /dev/null +++ b/tests/golden/output_adafruit_gfx.txt @@ -0,0 +1,19 @@ +const unsigned char epd_bitmap_Bitmap [] PROGMEM = { + // 'test_pattern', 32x24px + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, + 0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, + 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee +}; + +const GFXbitmapGlyph epd_bitmap_Glyphs [] PROGMEM = { + { 0, 32, 24, 0, '0' }// 'test_pattern' +}; + +const GFXbitmapFont epd_bitmap_Font PROGMEM = { + (uint8_t *)epd_bitmap_Bitmap, + (GFXbitmapGlyph *)epd_bitmap_Glyphs, + 1 +}; diff --git a/tests/golden/output_adafruit_gfx_esp32.txt b/tests/golden/output_adafruit_gfx_esp32.txt new file mode 100644 index 0000000..21ed39f --- /dev/null +++ b/tests/golden/output_adafruit_gfx_esp32.txt @@ -0,0 +1,19 @@ +const uint8_t epd_bitmap_Bitmap [] = { + // 'test_pattern', 32x24px + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, + 0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, + 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee +}; + +const GFXbitmapGlyph epd_bitmap_Glyphs [] = { + { 0, 32, 24, 0, '0' }// 'test_pattern' +}; + +const GFXbitmapFont epd_bitmap_Font = { + (uint8_t *)epd_bitmap_Bitmap, + (GFXbitmapGlyph *)epd_bitmap_Glyphs, + 1 +}; diff --git a/tests/golden/output_arduino.txt b/tests/golden/output_arduino.txt new file mode 100644 index 0000000..306f313 --- /dev/null +++ b/tests/golden/output_arduino.txt @@ -0,0 +1,15 @@ +// 'test_pattern', 32x24px +const unsigned char epd_bitmap_test_pattern [] PROGMEM = { + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, + 0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, + 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee +}; + +// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 112) +const int epd_bitmap_allArray_LEN = 1; +const unsigned char* epd_bitmap_allArray[1] = { + epd_bitmap_test_pattern +}; diff --git a/tests/golden/output_arduino_esp32.txt b/tests/golden/output_arduino_esp32.txt new file mode 100644 index 0000000..450b6d2 --- /dev/null +++ b/tests/golden/output_arduino_esp32.txt @@ -0,0 +1,15 @@ +// 'test_pattern', 32x24px +const uint8_t epd_bitmap_test_pattern [] = { + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, + 0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, + 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee +}; + +// Array of all bitmaps for convenience. (Total bytes used to store images = 112) +const int epd_bitmap_allArray_LEN = 1; +const uint8_t* epd_bitmap_allArray[1] = { + epd_bitmap_test_pattern +}; diff --git a/tests/golden/output_arduino_esp32_565.txt b/tests/golden/output_arduino_esp32_565.txt new file mode 100644 index 0000000..e41ec4f --- /dev/null +++ b/tests/golden/output_arduino_esp32_565.txt @@ -0,0 +1,57 @@ +// 'test_pattern', 32x24px +const uint16_t epd_bitmap_test_pattern [] = { + 0xf800, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, + 0x0000, 0x1082, 0x2104, 0x3186, 0x4228, 0x52aa, 0x632c, 0x73ae, 0x8c51, 0x9cd3, 0xad55, 0xbdd7, 0xce79, 0xdefb, 0xef7d, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xf800, 0xf800, 0xf800, 0xf800, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0x001f +}; + +// Array of all bitmaps for convenience. (Total bytes used to store images = 784) +const int epd_bitmap_allArray_LEN = 1; +const uint16_t* epd_bitmap_allArray[1] = { + epd_bitmap_test_pattern +}; diff --git a/tests/golden/output_arduino_single.txt b/tests/golden/output_arduino_single.txt new file mode 100644 index 0000000..633ec37 --- /dev/null +++ b/tests/golden/output_arduino_single.txt @@ -0,0 +1,9 @@ +const unsigned char epd_bitmap_ [] PROGMEM = { + // 'test_pattern', 32x24px + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, + 0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, + 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee +}; \ No newline at end of file diff --git a/tests/golden/output_arduino_single_esp32.txt b/tests/golden/output_arduino_single_esp32.txt new file mode 100644 index 0000000..55e7fc0 --- /dev/null +++ b/tests/golden/output_arduino_single_esp32.txt @@ -0,0 +1,9 @@ +const uint8_t epd_bitmap_ [] = { + // 'test_pattern', 32x24px + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, + 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, + 0x0f, 0x0f, 0xf7, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfe, 0xff, + 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee +}; \ No newline at end of file diff --git a/tests/golden/remove_zeroes_commas.txt b/tests/golden/remove_zeroes_commas.txt new file mode 100644 index 0000000..53423dd --- /dev/null +++ b/tests/golden/remove_zeroes_commas.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +333300ff333300ffcccc00ffcccc00ff +333300ff333300ffcccc00ffcccc00ff +333300ff333300ffcccc00ffcccc00ff +0f0f7fff0f0fbfff0f0fdfff0f0fefff +0f0ff7ff0f0ffbff0f0ffdff0f0ffeff +0f0fff7f0f0fffbf0f0fffdf0f0fffee diff --git a/tests/golden/rotate_180.txt b/tests/golden/rotate_180.txt new file mode 100644 index 0000000..c70700f --- /dev/null +++ b/tests/golden/rotate_180.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0x77, 0xff, 0xf0, 0xf0, 0xfb, 0xff, 0xf0, 0xf0, 0xfd, 0xff, 0xf0, 0xf0, 0xfe, 0xff, 0xf0, 0xf0, +0xff, 0x7f, 0xf0, 0xf0, 0xff, 0xbf, 0xf0, 0xf0, 0xff, 0xdf, 0xf0, 0xf0, 0xff, 0xef, 0xf0, 0xf0, +0xff, 0xf7, 0xf0, 0xf0, 0xff, 0xfb, 0xf0, 0xf0, 0xff, 0xfd, 0xf0, 0xf0, 0xff, 0xfe, 0xf0, 0xf0, +0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, +0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc, +0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0x33, 0x33, 0xff, 0x00, 0xcc, 0xcc, 0xff, 0x00, 0xcc, 0xcc \ No newline at end of file diff --git a/tests/golden/rotate_180_vertical.txt b/tests/golden/rotate_180_vertical.txt new file mode 100644 index 0000000..18bc55e --- /dev/null +++ b/tests/golden/rotate_180_vertical.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 32x24px +0xfe, 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0d, 0x0b, 0x07, +0xcf, 0xcf, 0x3f, 0x3f, 0xc0, 0xc0, 0x30, 0x30, 0xcf, 0xcf, 0x3f, 0x3f, 0xc0, 0xc0, 0x30, 0x30, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33 \ No newline at end of file diff --git a/tests/golden/rotate_270.txt b/tests/golden/rotate_270.txt new file mode 100644 index 0000000..784e6cc --- /dev/null +++ b/tests/golden/rotate_270.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, +0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0x00, 0x0f, 0xef, 0x00, 0x0f, 0xdf, 0x00, 0x0f, +0xbf, 0x00, 0x0f, 0x7f, 0x00, 0x0e, 0xff, 0x00, 0x0d, 0xff, 0x00, 0x0b, 0xff, 0x00, 0x07, 0xff, +0xcc, 0xcf, 0xff, 0xcc, 0xcf, 0xff, 0x33, 0x3f, 0xff, 0x33, 0x3f, 0xff, 0xcc, 0xc0, 0x00, 0xcc, +0xc0, 0x00, 0x33, 0x30, 0x00, 0x33, 0x30, 0x00, 0xcc, 0xcf, 0xff, 0xcc, 0xcf, 0xff, 0x33, 0x3f, +0xff, 0x33, 0x3f, 0xff, 0xcc, 0xc0, 0x00, 0xcc, 0xc0, 0x00, 0x33, 0x30, 0x00, 0x33, 0x30, 0x00 \ No newline at end of file diff --git a/tests/golden/rotate_270_flip_horizontal.txt b/tests/golden/rotate_270_flip_horizontal.txt new file mode 100644 index 0000000..c303612 --- /dev/null +++ b/tests/golden/rotate_270_flip_horizontal.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xbf, +0xff, 0xff, 0xdf, 0xff, 0xff, 0xef, 0xff, 0xff, 0xf7, 0xf0, 0x00, 0xfb, 0xf0, 0x00, 0xfd, 0xf0, +0x00, 0xfe, 0xf0, 0x00, 0xff, 0x70, 0x00, 0xff, 0xb0, 0x00, 0xff, 0xd0, 0x00, 0xff, 0xe0, 0x00, +0xff, 0xf3, 0x33, 0xff, 0xf3, 0x33, 0xff, 0xfc, 0xcc, 0xff, 0xfc, 0xcc, 0x00, 0x03, 0x33, 0x00, +0x03, 0x33, 0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0xff, 0xf3, 0x33, 0xff, 0xf3, 0x33, 0xff, 0xfc, +0xcc, 0xff, 0xfc, 0xcc, 0x00, 0x03, 0x33, 0x00, 0x03, 0x33, 0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc \ No newline at end of file diff --git a/tests/golden/rotate_270_vertical.txt b/tests/golden/rotate_270_vertical.txt new file mode 100644 index 0000000..71701c7 --- /dev/null +++ b/tests/golden/rotate_270_vertical.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x7f, 0xbf, 0xdf, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, +0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, +0x33, 0x33, 0xcc, 0xcc, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f \ No newline at end of file diff --git a/tests/golden/rotate_90.txt b/tests/golden/rotate_90.txt new file mode 100644 index 0000000..648e5b0 --- /dev/null +++ b/tests/golden/rotate_90.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x03, 0x33, 0x00, 0x03, 0x33, 0xff, 0xfc, 0xcc, 0xff, +0xfc, 0xcc, 0xff, 0xf3, 0x33, 0xff, 0xf3, 0x33, 0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x03, +0x33, 0x00, 0x03, 0x33, 0xff, 0xfc, 0xcc, 0xff, 0xfc, 0xcc, 0xff, 0xf3, 0x33, 0xff, 0xf3, 0x33, +0xff, 0xe0, 0x00, 0xff, 0xd0, 0x00, 0xff, 0xb0, 0x00, 0xff, 0x70, 0x00, 0xfe, 0xf0, 0x00, 0xfd, +0xf0, 0x00, 0xfb, 0xf0, 0x00, 0xf7, 0xf0, 0x00, 0xef, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xbf, 0xff, +0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/rotate_90_flip_both.txt b/tests/golden/rotate_90_flip_both.txt new file mode 100644 index 0000000..784e6cc --- /dev/null +++ b/tests/golden/rotate_90_flip_both.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, +0xff, 0xfd, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xf7, 0x00, 0x0f, 0xef, 0x00, 0x0f, 0xdf, 0x00, 0x0f, +0xbf, 0x00, 0x0f, 0x7f, 0x00, 0x0e, 0xff, 0x00, 0x0d, 0xff, 0x00, 0x0b, 0xff, 0x00, 0x07, 0xff, +0xcc, 0xcf, 0xff, 0xcc, 0xcf, 0xff, 0x33, 0x3f, 0xff, 0x33, 0x3f, 0xff, 0xcc, 0xc0, 0x00, 0xcc, +0xc0, 0x00, 0x33, 0x30, 0x00, 0x33, 0x30, 0x00, 0xcc, 0xcf, 0xff, 0xcc, 0xcf, 0xff, 0x33, 0x3f, +0xff, 0x33, 0x3f, 0xff, 0xcc, 0xc0, 0x00, 0xcc, 0xc0, 0x00, 0x33, 0x30, 0x00, 0x33, 0x30, 0x00 \ No newline at end of file diff --git a/tests/golden/rotate_90_horizontal565.txt b/tests/golden/rotate_90_horizontal565.txt new file mode 100644 index 0000000..30012c7 --- /dev/null +++ b/tests/golden/rotate_90_horizontal565.txt @@ -0,0 +1,49 @@ +// 'test_pattern', 24x32px +0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xffff, 0xffff, 0x0000, 0x0000, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, +0xf800, 0xf800, 0xf800, 0xf800, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, +0xf800, 0xf800, 0xf800, 0xf800, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0xffff, 0xffff, 0x0000, 0x0000, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, +0x07e0, 0x07e0, 0x07e0, 0x07e0, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x07e0, +0x07e0, 0x07e0, 0x07e0, 0x07e0, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0x0000, 0x0000, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, +0x001f, 0x001f, 0x001f, 0x001f, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, 0x001f, +0x001f, 0x001f, 0x001f, 0x001f, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, +0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0x0000, 0xffff, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, 0x1082, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0x2104, 0x2104, 0x2104, 0x2104, +0x2104, 0x2104, 0x2104, 0x2104, 0x2104, 0x2104, 0x2104, 0x2104, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0x0000, 0xffff, 0xffff, 0xffff, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, 0x3186, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x4228, 0x4228, 0x4228, 0x4228, +0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0x4228, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x52aa, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x632c, 0x632c, 0x632c, 0x632c, +0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0x632c, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, +0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x8c51, 0x8c51, 0x8c51, 0x8c51, +0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cd3, +0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xad55, 0xad55, 0xad55, 0xad55, +0xad55, 0xad55, 0xad55, 0xad55, 0xad55, 0xad55, 0xad55, 0xad55, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdd7, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xce79, 0xce79, 0xce79, 0xce79, +0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, 0xdefb, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xef7d, 0xef7d, 0xef7d, 0xef7d, +0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0xef7d, 0x001f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff \ No newline at end of file diff --git a/tests/golden/rotate_90_horizontal888.txt b/tests/golden/rotate_90_horizontal888.txt new file mode 100644 index 0000000..4c33e5f --- /dev/null +++ b/tests/golden/rotate_90_horizontal888.txt @@ -0,0 +1,33 @@ +// 'test_pattern', 24x32px +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ff0000, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, 0x00222222, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, 0x00333333, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, 0x00444444, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, 0x00555555, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, 0x00666666, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, 0x00777777, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, 0x00888888, +0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, 0x00999999, +0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, 0x00aaaaaa, +0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, 0x00bbbbbb, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, 0x00cccccc, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, 0x00dddddd, +0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, 0x00eeeeee, +0x000000ff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff \ No newline at end of file diff --git a/tests/golden/rotate_90_horizontal_alpha.txt b/tests/golden/rotate_90_horizontal_alpha.txt new file mode 100644 index 0000000..b169223 --- /dev/null +++ b/tests/golden/rotate_90_horizontal_alpha.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/rotate_90_resized.txt b/tests/golden/rotate_90_resized.txt new file mode 100644 index 0000000..51cb5c0 --- /dev/null +++ b/tests/golden/rotate_90_resized.txt @@ -0,0 +1,10 @@ +// 'test_pattern', 24x48px +0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x03, 0x33, 0x00, 0x03, 0x33, 0xff, 0xfc, 0xcc, 0xff, +0xfc, 0xcc, 0xff, 0xf3, 0x33, 0xff, 0xf3, 0x33, 0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x03, +0x33, 0x00, 0x03, 0x33, 0xff, 0xfc, 0xcc, 0xff, 0xfc, 0xcc, 0xff, 0xf3, 0x33, 0xff, 0xf3, 0x33, +0xff, 0xe0, 0x00, 0xff, 0xd0, 0x00, 0xff, 0xb0, 0x00, 0xff, 0x70, 0x00, 0xfe, 0xf0, 0x00, 0xfd, +0xf0, 0x00, 0xfb, 0xf0, 0x00, 0xf7, 0xf0, 0x00, 0xef, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xbf, 0xff, +0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/rotate_90_vertical.txt b/tests/golden/rotate_90_vertical.txt new file mode 100644 index 0000000..e3f2e88 --- /dev/null +++ b/tests/golden/rotate_90_vertical.txt @@ -0,0 +1,7 @@ +// 'test_pattern', 24x32px +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x33, 0xcc, 0xcc, +0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, +0xff, 0xff, 0xff, 0xff, 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xfb, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/scale_fit_larger_canvas.txt b/tests/golden/scale_fit_larger_canvas.txt new file mode 100644 index 0000000..c5af95e --- /dev/null +++ b/tests/golden/scale_fit_larger_canvas.txt @@ -0,0 +1,16 @@ +// 'test_pattern', 48x40px +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, +0x38, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, +0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, +0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x1f, 0xff, 0x03, 0xc0, 0x3f, 0x3f, +0xff, 0xff, 0x03, 0xf0, 0x3f, 0xbf, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xdf, 0xff, 0xff, 0x03, 0xf0, +0x3f, 0xef, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xf7, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xfb, 0xff, 0xff, +0x03, 0xf0, 0x3f, 0xfd, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xfe, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xff, +0x7f, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xbf, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xdf, 0xff, 0x03, 0xf0, +0x3f, 0xff, 0xef, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xf7, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xfb, 0xff, +0x03, 0xf0, 0x3f, 0xff, 0xfd, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xfe, 0xff, 0x03, 0xf0, 0x3f, 0xff, +0xff, 0x7f, 0x03, 0xf0, 0x3f, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff \ No newline at end of file diff --git a/tests/golden/scale_stretch_h_larger_canvas.txt b/tests/golden/scale_stretch_h_larger_canvas.txt new file mode 100644 index 0000000..ee57f8f --- /dev/null +++ b/tests/golden/scale_stretch_h_larger_canvas.txt @@ -0,0 +1,10 @@ +// 'test_pattern', 48x24px +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, +0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0x03, 0xf0, 0x3f, 0x3f, 0xff, 0xff, 0x03, 0xf0, +0x3f, 0x9f, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xe7, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xf3, 0xff, 0xff, +0x03, 0xf0, 0x3f, 0xfc, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xfe, 0x7f, 0xff, 0x03, 0xf0, 0x3f, 0xff, +0x9f, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xcf, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xf3, 0xff, 0x03, 0xf0, +0x3f, 0xff, 0xf9, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xfe, 0x7f, 0x03, 0xf0, 0x3f, 0xff, 0xff, 0x3e \ No newline at end of file diff --git a/tests/golden/scale_stretch_larger_canvas.txt b/tests/golden/scale_stretch_larger_canvas.txt new file mode 100644 index 0000000..a85719f --- /dev/null +++ b/tests/golden/scale_stretch_larger_canvas.txt @@ -0,0 +1,16 @@ +// 'test_pattern', 48x40px +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, +0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0x1c, 0x71, +0xc6, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, +0x1c, 0x71, 0xc7, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, +0x0f, 0xff, 0xe3, 0x8e, 0x38, 0x00, 0x3f, 0xff, 0x03, 0x80, 0x3f, 0x3f, 0xff, 0xff, 0x03, 0xf0, +0x3f, 0x3f, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0x9f, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xef, 0xff, 0xff, +0x03, 0xf0, 0x3f, 0xe7, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xf3, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xfb, +0xff, 0xff, 0x03, 0xf0, 0x3f, 0xfc, 0xff, 0xff, 0x03, 0xf0, 0x3f, 0xfe, 0xff, 0xff, 0x03, 0xf0, +0x3f, 0xff, 0x7f, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xbf, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0x9f, 0xff, +0x03, 0xf0, 0x3f, 0xff, 0xcf, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xf7, 0xff, 0x03, 0xf0, 0x3f, 0xff, +0xf3, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xf9, 0xff, 0x03, 0xf0, 0x3f, 0xff, 0xfd, 0xff, 0x03, 0xf0, +0x3f, 0xff, 0xfe, 0x7f, 0x03, 0xf0, 0x3f, 0xff, 0xff, 0x7e, 0x03, 0xf0, 0x3f, 0xff, 0xff, 0x3e \ No newline at end of file diff --git a/tests/golden/scale_stretch_v_larger_canvas.txt b/tests/golden/scale_stretch_v_larger_canvas.txt new file mode 100644 index 0000000..93d9734 --- /dev/null +++ b/tests/golden/scale_stretch_v_larger_canvas.txt @@ -0,0 +1,11 @@ +// 'test_pattern', 32x40px +0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, +0xcc, 0xcc, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, 0x33, 0x33, 0x00, 0xff, +0x33, 0x33, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x00, 0xff, 0xcc, 0xcc, 0x03, 0xff, +0x0c, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0x7f, 0xff, 0x0f, 0x0f, 0xbf, 0xff, 0x0f, 0x0f, 0xdf, 0xff, +0x0f, 0x0f, 0xdf, 0xff, 0x0f, 0x0f, 0xef, 0xff, 0x0f, 0x0f, 0xef, 0xff, 0x0f, 0x0f, 0xf7, 0xff, +0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfb, 0xff, 0x0f, 0x0f, 0xfd, 0xff, 0x0f, 0x0f, 0xfd, 0xff, +0x0f, 0x0f, 0xfe, 0xff, 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0x7f, 0x0f, 0x0f, 0xff, 0xbf, +0x0f, 0x0f, 0xff, 0xbf, 0x0f, 0x0f, 0xff, 0xdf, 0x0f, 0x0f, 0xff, 0xee, 0x0f, 0x0f, 0xff, 0xee \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..d662229 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,2 @@ +playwright +pillow diff --git a/tests/test_conversions.py b/tests/test_conversions.py new file mode 100644 index 0000000..aed12b3 --- /dev/null +++ b/tests/test_conversions.py @@ -0,0 +1,444 @@ +#!/usr/bin/env python3 +"""Test suite for image2cpp's conversion output. + +Controls the real index.html in a headless browser (Playwright), feeds it the +deterministic test-pattern image, exercises every conversion option through +the actual UI, and compares the generated code output against saved golden +files. Because it runs the real app (not a reimplementation of the +conversion logic), any change to js/script.js or js/dithering.js that +changes output is caught. + +Usage: + python tests/test_conversions.py # run tests, compare to golden + python tests/test_conversions.py --diff # print diff on failing scenarios + python tests/test_conversions.py --update # (re)generate golden files +""" +import argparse +import difflib +import re +import sys +from pathlib import Path + +from playwright.sync_api import sync_playwright + +ROOT = Path(__file__).parent.parent +INDEX_HTML = ROOT / "index.html" +TEST_IMAGE = Path(__file__).parent / "fixtures" / "test_pattern.png" +GOLDEN_DIR = Path(__file__).parent / "golden" + +NATIVE_WIDTH, NATIVE_HEIGHT = 32, 24 + +# Full set of controllable options and their app defaults. +BASE_SETTINGS = { + "drawMode": "horizontal1bit", + "outputFormat": "plain", + "backgroundColor": "white", + "invertColors": False, + "ditheringMode": 0, + "ditheringThreshold": 128, + "scale": 1, + "centerHorizontally": False, + "centerVertically": False, + "rotation": 0, + "flipHorizontally": False, + "flipVertically": False, + "bitswap": False, + "prefix": "0x", + "separator": ", ", + "esp32Format": False, + "bytesPerRow": 16, + "showAsciiPreview": False, + "outputComments": True, + "fullExample": False, +} + +# (scenario name, overrides on top of BASE_SETTINGS, optional canvas resize) +SCENARIOS = [ + ("default", {}, None), + ("draw_mode_vertical1bit", {"drawMode": "vertical1bit"}, None), + ("draw_mode_horizontal565", {"drawMode": "horizontal565"}, None), + ("draw_mode_horizontal888", {"drawMode": "horizontal888"}, None), + ("draw_mode_horizontal_alpha", {"drawMode": "horizontalAlpha"}, None), + ("output_arduino", {"outputFormat": "arduino"}, None), + ("output_arduino_single", {"outputFormat": "arduino_single"}, None), + ("output_adafruit_gfx", {"outputFormat": "adafruit_gfx"}, None), + ("output_arduino_esp32", {"outputFormat": "arduino", "esp32Format": True}, None), + ( + "output_arduino_single_esp32", + {"outputFormat": "arduino_single", "esp32Format": True}, + None, + ), + ("output_adafruit_gfx_esp32", {"outputFormat": "adafruit_gfx", "esp32Format": True}, None), + ( + "output_arduino_esp32_565", + {"outputFormat": "arduino", "drawMode": "horizontal565", "esp32Format": True}, + None, + ), + ("invert_colors", {"invertColors": True}, None), + ("flip_horizontal", {"flipHorizontally": True}, None), + ("flip_vertical", {"flipVertically": True}, None), + ("flip_both", {"flipHorizontally": True, "flipVertically": True}, None), + ("rotate_90", {"rotation": 90}, None), + ("rotate_180", {"rotation": 180}, None), + ("rotate_270", {"rotation": 270}, None), + ("rotate_90_vertical", {"drawMode": "vertical1bit", "rotation": 90}, None), + ("rotate_270_vertical", {"drawMode": "vertical1bit", "rotation": 270}, None), + ("rotate_180_vertical", {"drawMode": "vertical1bit", "rotation": 180}, None), + ("rotate_90_horizontal565", {"drawMode": "horizontal565", "rotation": 90}, None), + ("rotate_90_horizontal888", {"drawMode": "horizontal888", "rotation": 90}, None), + ("rotate_90_horizontal_alpha", {"drawMode": "horizontalAlpha", "rotation": 90}, None), + ( + "rotate_90_flip_both", + {"rotation": 90, "flipHorizontally": True, "flipVertically": True}, + None, + ), + ("rotate_270_flip_horizontal", {"rotation": 270, "flipHorizontally": True}, None), + ("rotate_90_resized", {"rotation": 90}, (48, 24)), + ("bitswap_vertical", {"drawMode": "vertical1bit", "bitswap": True}, None), + ("dithering_bayer", {"ditheringMode": 1}, None), + ("dithering_floyd_steinberg", {"ditheringMode": 2}, None), + ("dithering_atkinson", {"ditheringMode": 3}, None), + ("dithering_threshold_low", {"ditheringThreshold": 64}, None), + ("dithering_threshold_high", {"ditheringThreshold": 200}, None), + ("bitswap", {"bitswap": True}, None), + ("ascii_preview", {"showAsciiPreview": True}, None), + ( + "ascii_preview_bytes_per_row_ignored", + {"showAsciiPreview": True, "bytesPerRow": 3}, + None, + ), + ( + "ascii_preview_horizontal565", + {"showAsciiPreview": True, "drawMode": "horizontal565"}, + None, + ), + ( + "ascii_preview_horizontal888", + {"showAsciiPreview": True, "drawMode": "horizontal888"}, + None, + ), + ( + "ascii_preview_arduino", + {"showAsciiPreview": True, "outputFormat": "arduino"}, + None, + ), + ("remove_zeroes_commas", {"prefix": "", "separator": ""}, None), + # scale=1 (original) on a canvas larger than the image so the + # background actually shows through in the margins. + ("background_white_larger_canvas", {"backgroundColor": "white"}, (48, 40)), + ("background_black", {"backgroundColor": "black"}, (48, 40)), + # RGB channels of a transparent background are zero-initialized, same as + # an explicit black background, so the two are indistinguishable under + # the 1-bit draw modes (which ignore alpha). Use the alpha draw mode + # here so transparency is actually used. + ( + "background_transparent", + {"backgroundColor": "transparent", "drawMode": "horizontalAlpha"}, + (48, 40), + ), + ("scale_fit_larger_canvas", {"scale": 2}, (48, 40)), + ("scale_stretch_larger_canvas", {"scale": 3}, (48, 40)), + ("scale_stretch_h_larger_canvas", {"scale": 4}, (48, NATIVE_HEIGHT)), + ("scale_stretch_v_larger_canvas", {"scale": 5}, (NATIVE_WIDTH, 40)), + ( + "center_both_larger_canvas", + {"centerHorizontally": True, "centerVertically": True}, + (48, 40), + ), + ( + "kitchen_sink", + { + "drawMode": "vertical1bit", + "invertColors": True, + "flipHorizontally": True, + "flipVertically": True, + "bitswap": True, + "removeZeroesCommas": True, + "ditheringMode": 2, + }, + None, + ), +] + +# Bytes per output value per drawMode, mirroring CONVERSION_BYTES_PER_VALUE in +# js/script.js. Used to verify downloadBinFile()'s byte stream (via the +# computeBinData() helper) matches the hex values shown in the text output, +# instead of the multi-byte values (565/888) getting truncated to one byte. +BYTES_PER_VALUE = { + "horizontal1bit": 1, + "vertical1bit": 1, + "horizontal565": 2, + "horizontal888": 4, + "horizontalAlpha": 1, +} + +# Scenario names to also verify against computeBinData(); restricted to ones +# using the default plain/comma-separated output (outputFormat and separator +# untouched), since that's the format downloadBinFile's parser expects. +BIN_CHECK_NAMES = { + "default", + "draw_mode_vertical1bit", + "draw_mode_horizontal565", + "draw_mode_horizontal888", + "draw_mode_horizontal_alpha", + "rotate_90_horizontal565", + "rotate_90_horizontal888", + "rotate_90_horizontal_alpha", +} + + +def expected_bin_bytes(output, draw_mode): + """Reconstruct the byte stream a correct downloadBinFile() should produce + from the plain-format hex text output, expanding each value back to its + full byte width (MSB first) instead of assuming one byte per value.""" + bytes_per_value = BYTES_PER_VALUE[draw_mode] + values = (int(tok, 16) for tok in re.findall(r"0x[0-9a-fA-F]+", output)) + result = [] + for value in values: + for shift in range((bytes_per_value - 1) * 8, -1, -8): + result.append((value >> shift) & 0xFF) + return result + + +def reset_canvas_size(page, width, height): + """Set canvas size through the first image's per-image width/height + inputs in the "Canvas size(s)" list (each image has its own size in the + current layout; there's no single global canvas size control anymore).""" + page.fill("#image-size-settings li:nth-child(1) input[name='width']", str(width)) + page.fill("#image-size-settings li:nth-child(1) input[name='height']", str(height)) + + +def apply_settings(page, settings): + page.select_option("#drawMode", settings["drawMode"]) + # Selecting an output format resets prefix/separator to their defaults + # (updateOutputFormat() in script.js), so this must run before those two + # fields are filled in below. + page.select_option("#outputFormat", settings["outputFormat"]) + page.check(f"#backgroundColor{settings['backgroundColor'].capitalize()}") + set_checkbox(page, "#invertColors", settings["invertColors"]) + page.select_option("#ditheringMode", str(settings["ditheringMode"])) + page.fill("#ditheringThreshold", str(settings["ditheringThreshold"])) + page.select_option("#scale", str(settings["scale"])) + set_checkbox(page, "#centerHorizontally", settings["centerHorizontally"]) + set_checkbox(page, "#centerVertically", settings["centerVertically"]) + page.select_option("#rotation", str(settings["rotation"])) + set_checkbox(page, "#flipHorizontally", settings["flipHorizontally"]) + set_checkbox(page, "#flipVertically", settings["flipVertically"]) + set_checkbox(page, "#bitswap", settings["bitswap"]) + page.fill("#prefix", settings["prefix"]) + page.fill("#separator", settings["separator"]) + page.fill("#bytesPerRow", str(settings["bytesPerRow"])) + set_checkbox(page, "#showAsciiPreview", settings["showAsciiPreview"]) + set_checkbox(page, "#outputComments", settings["outputComments"]) + # esp32Format/fullExample checkboxes only exist in the DOM (visible) for + # non-plain output formats; plain output has no type/PROGMEM/example code + # for them to affect. + if settings["outputFormat"] != "plain": + set_checkbox(page, "#esp32Format", settings["esp32Format"]) + set_checkbox(page, "#fullExample", settings["fullExample"]) + + +def set_checkbox(page, selector, checked): + if checked: + page.check(selector) + else: + page.uncheck(selector) + + +def run_scenario(page, name, overrides, resize): + settings = {**BASE_SETTINGS, **overrides} + reset_canvas_size(page, *(resize or (NATIVE_WIDTH, NATIVE_HEIGHT))) + apply_settings(page, settings) + # Force a redraw with the final settings state regardless of which + # controls' change events actually fired (some may be no-ops if the + # value didn't change from the previous scenario). + page.evaluate("updateAllImages()") + page.click("text=Generate code") + return page.input_value("#code-output") + + +def roundtrip_eligible(settings): + """Only plain-format, non-bitswapped 1-bit output is re-importable via the + "Paste byte array" box: other draw modes aren't supported by the parser, + bitswap mangles the byte stream with no importer to undo it, and the + parser splits bytes on commas, so a separator without one (e.g. the + empty string used to strip formatting) can't be read back. showAsciiPreview + and a non-default bytesPerRow are excluded too: run_roundtrip reloads a + fresh page and never restores those two, so the re-exported text would use + default formatting and not textually match the original even though the + underlying pixel data round-trips fine.""" + return ( + settings["drawMode"] in ("horizontal1bit", "vertical1bit") + and settings["outputFormat"] == "plain" + and not settings["bitswap"] + and "," in settings["separator"] + and not settings["showAsciiPreview"] + and settings["bytesPerRow"] == BASE_SETTINGS["bytesPerRow"] + ) + + +def run_roundtrip(page, output, draw_mode, width, height): + """Paste a generated byte array back in, import it, and re-export it, + same steps a user would take to sanity-check their array. Uses a fresh + page load, so the reimported canvas is the only pixel source, nothing + left over from a previous scenario.""" + page.goto(INDEX_HTML.as_uri()) + # window.onload defaults outputFormat to "arduino"; force it back to plain + # to match the format the scenario was exported in. + page.select_option("#outputFormat", "plain") + page.fill("#byte-input", output) + page.fill("#text-input-width", str(width)) + page.fill("#text-input-height", str(height)) + direction = "horizontal" if draw_mode == "horizontal1bit" else "vertical" + page.click(f"text=Read as {direction}") + # The imported canvas is only backed by a real once its data-URL + # finishes loading (async); switching draw mode before that swap + # completes triggers a redraw from the still-blank placeholder image and + # wipes the canvas. Wait for the swap so this matches how a person would + # naturally pause between clicking "Read as..." and changing the dropdown. + page.wait_for_function("images.first().img.src") + if direction == "vertical": + page.select_option("#drawMode", "vertical1bit") + page.click("text=Generate code") + return page.input_value("#code-output") + + +def run_multi_image_independent_sizes(page): + """Each image in a multi-image upload keeps its own canvas size; setting + one image's width/height must not resize any other image's canvas. + Regression test for a bug where every canvas was forced to the size of + the first uploaded image.""" + page.goto(INDEX_HTML.as_uri()) + page.set_input_files("#file-input", [str(TEST_IMAGE), str(TEST_IMAGE)]) + page.wait_for_function("document.querySelectorAll('#image-size-settings li').length === 2") + + page.fill("#image-size-settings li:nth-child(1) input[name='width']", "50") + page.fill("#image-size-settings li:nth-child(1) input[name='height']", "60") + page.fill("#image-size-settings li:nth-child(2) input[name='width']", "20") + page.fill("#image-size-settings li:nth-child(2) input[name='height']", "10") + + sizes = page.evaluate( + "[images.getByIndex(0).canvas.width, images.getByIndex(0).canvas.height," + " images.getByIndex(1).canvas.width, images.getByIndex(1).canvas.height]" + ) + expected = [50, 60, 20, 10] + if sizes != expected: + print("FAIL multi_image_independent_sizes") + return [f"multi_image_independent_sizes: expected canvas sizes {expected}, got {sizes}"] + print("ok multi_image_independent_sizes") + return [] + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--update", action="store_true", help="(re)generate golden files instead of comparing" + ) + parser.add_argument( + "--diff", action="store_true", help="print a diff against golden output on failure" + ) + args = parser.parse_args() + + if not TEST_IMAGE.exists(): + print(f"Test image missing at {TEST_IMAGE}; run generate_test_image.py first") + sys.exit(1) + + GOLDEN_DIR.mkdir(parents=True, exist_ok=True) + + failures = [] + with sync_playwright() as p: + browser = p.chromium.launch() + page = browser.new_page() + page.goto(INDEX_HTML.as_uri()) + page.set_input_files("#file-input", str(TEST_IMAGE)) + # Wait for the app to finish loading the image and create its canvas. + page.wait_for_selector("#image-size-settings li") + + for name, overrides, resize in SCENARIOS: + settings = {**BASE_SETTINGS, **overrides} + output = run_scenario(page, name, overrides, resize) + golden_path = GOLDEN_DIR / f"{name}.txt" + + if args.update: + golden_path.write_text(output) + print(f"wrote {name}") + continue + + if not golden_path.exists(): + failures.append(f"{name}: no golden file (run with --update first)") + print(f"MISSING {name}") + continue + + expected = golden_path.read_text() + if output != expected: + failures.append(name) + print(f"FAIL {name}") + if args.diff: + diff = difflib.unified_diff( + expected.splitlines(keepends=True), + output.splitlines(keepends=True), + fromfile=f"{name} (golden)", + tofile=f"{name} (actual)", + ) + sys.stdout.writelines(diff) + continue + + print(f"ok {name}") + + if name in BIN_CHECK_NAMES: + expected_bytes = expected_bin_bytes(output, settings["drawMode"]) + actual_bytes = page.evaluate("Array.from(computeBinData())") + if actual_bytes != expected_bytes: + failures.append(f"{name}: bin data mismatch") + print(f"FAIL {name} (bin)") + else: + print(f"ok {name} (bin)") + + if roundtrip_eligible(settings): + width, height = resize or (NATIVE_WIDTH, NATIVE_HEIGHT) + roundtripped = run_roundtrip(page, output, settings["drawMode"], width, height) + # The re-imported image has no filename to derive a glyph + # comment from, so plain output drops its leading "// name, + # WxHpx" comment line; strip it before comparing byte data. + comparable_output = re.sub(r"^//[^\n]*\n", "", output) + if roundtripped != comparable_output: + failures.append(f"{name}: round-trip mismatch") + print(f"FAIL {name} (round-trip)") + if args.diff: + diff = difflib.unified_diff( + comparable_output.splitlines(keepends=True), + roundtripped.splitlines(keepends=True), + fromfile=f"{name} (exported)", + tofile=f"{name} (re-imported+exported)", + ) + sys.stdout.writelines(diff) + else: + print(f"ok {name} (round-trip)") + + # The page was reloaded for the round-trip check; reload the + # test image so the next scenario has its canvas back. + page.goto(INDEX_HTML.as_uri()) + page.set_input_files("#file-input", str(TEST_IMAGE)) + page.wait_for_selector("#image-size-settings li") + + if not args.update: + failures.extend(run_multi_image_independent_sizes(page)) + + browser.close() + + if args.update: + print(f"\nWrote {len(SCENARIOS)} golden files to {GOLDEN_DIR}") + return + + total = len(SCENARIOS) + 1 + if failures: + print(f"\n{len(failures)} of {total} scenarios failed:") + for f in failures: + print(f" - {f}") + sys.exit(1) + + print(f"\nAll {total} scenarios match golden output.") + + +if __name__ == "__main__": + main()