update layout and error checks

This commit is contained in:
javl
2026-08-14 18:43:24 +02:00
parent cf74b95ae9
commit f2ef5e5f1c
4 changed files with 143 additions and 63 deletions
+1 -1
View File
@@ -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 convert 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.
+32 -3
View File
@@ -438,6 +438,11 @@ code {
max-width: 320px;
}
#continue-note {
display: none;
margin-top: 30px;
}
.msg {
font-size: 16px;
color: var(--text-muted);
@@ -495,6 +500,12 @@ input[type="radio"] {
line-height: 22px;
resize: vertical;
}
#text-input-error {
color: var(--error);
font-size: 14px;
margin-top: 8px;
display: none;
}
.text-input-size {
margin: 8px 0;
@@ -506,6 +517,21 @@ input[type="radio"] {
width: 72px;
}
.sub-field {
display: flex;
align-items: center;
gap: 8px;
margin-top: 8px;
}
.sub-field:first-child {
margin-top: 0;
}
.sub-field-label {
min-width: 160px;
}
.glyph-input {
width: 80px;
margin-left: 10px;
@@ -542,7 +568,7 @@ button:active {
input[type="file"] {
background: var(--surface-container);
color: var(--on-surface-variant);
border: 2px dashed var(--outline-variant);
/* border: 2px dashed var(--outline-variant); */
border-radius: var(--radius-lg);
font-size: 14px;
padding: 16px 20px;
@@ -589,6 +615,9 @@ input[type="file"]::file-selector-button {
color: var(--on-surface-variant);
}
#no-images-error {
margin-bottom: 10px;
}
/* ---- File info / size list ---- */
.file-input-entry {
@@ -652,9 +681,9 @@ input[type="file"]::file-selector-button {
.code-output {
height: 400px;
width: 100%;
margin-top: 16px;
/* margin-top: 16px; */
background: var(--editor-bg);
color: #dcdcaa;
color: #000000;
border: 1px solid var(--on-surface-variant);
border-radius: var(--radius-xl);
font-family: var(--font-mono);
+53 -42
View File
File diff suppressed because one or more lines are too long
+57 -17
View File
@@ -639,6 +639,21 @@ function listToImageVertical(list, canvas) {
img.src = canvas.toDataURL('image/png');
}
// 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 hasImages = images.length() > 0;
error.style.display = hasImages ? 'none' : 'block';
return hasImages;
}
// Handle inserting an image by pasting code
// eslint-disable-next-line no-unused-vars
function handleTextInput(drawMode) {
@@ -678,6 +693,13 @@ function handleTextInput(drawMode) {
// Split into list
const list = input.split(',');
if (list.length === 1 && list[0] === '') {
// eslint-disable-next-line no-alert
const errorEl = document.getElementById('text-input-error');
errorEl.style.display = 'block';
return;
}
if (drawMode === 'horizontal') {
listToImageHorizontal(list, canvas);
} else {
@@ -726,6 +748,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.*')) {
@@ -751,7 +779,7 @@ function handleImageSelection(evt) {
const fileInputColumnEntryRemoveButton = document.createElement('button');
fileInputColumnEntryRemoveButton.className = 'remove-button';
fileInputColumnEntryRemoveButton.innerHTML = 'remove';
fileInputColumnEntryRemoveButton.innerHTML = 'remove image';
const canvas = document.createElement('canvas');
@@ -799,15 +827,7 @@ function handleImageSelection(evt) {
image.glyph = gi.value;
};
const fn = document.createElement('span');
fn.className = 'file-info file-name';
fn.innerHTML = `${file.name} (file resolution: ${img.width} x ${img.height})`;
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');
@@ -822,6 +842,7 @@ 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';
@@ -830,7 +851,18 @@ function handleImageSelection(evt) {
updateAllImages();
};
const rb = document.createElement('button');
rb.className = 'remove-button';
rb.innerHTML = 'remove image';
rb.onclick = removeButtonOnClick;
const fn = document.createElement('span');
fn.className = 'file-info file-name';
fn.innerHTML = `${file.name} (file resolution: ${img.width} x ${img.height})`;
fn.appendChild(rb);
fileInputColumnEntryRemoveButton.onclick = removeButtonOnClick;
fileInputColumnEntry.appendChild(fileInputColumnEntryLabel);
@@ -843,7 +875,6 @@ function handleImageSelection(evt) {
imageEntry.appendChild(h);
imageEntry.appendChild(gil);
imageEntry.appendChild(gi);
imageEntry.appendChild(rb);
imageSizeSettings.appendChild(imageEntry);
@@ -856,6 +887,7 @@ function handleImageSelection(evt) {
document.getElementById('all-same-size').style.display = 'block';
}
placeImage(images.last());
checkImagesAvailable();
};
img.src = file.target.result;
};
@@ -883,6 +915,8 @@ function getIdentifier() {
// Output the image string to the textfield
// eslint-disable-next-line no-unused-vars
function generateOutputString() {
if (!checkImagesAvailable()) return;
let outputString = '';
let code = '';
@@ -1018,17 +1052,24 @@ function generateOutputString() {
}
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);
}
// eslint-disable-next-line no-unused-vars
function downloadBinFile() {
if (!checkImagesAvailable()) return;
let raw = [];
images.each((image) => {
const data = imageToString(image)
@@ -1102,12 +1143,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 outputFormatArduino = document.getElementById('outputFormatArduino');
outputFormatArduino.checked = true;
outputFormatArduino.onchange();
};