<!--<img id="sourceImage" src="https://placekitten.com/200/300" crossOrigin="Anonymous"  class="sourceImage" />-->
<h1 style="text-align: center;">Chrome - Arduino PROGMEM file<br />
  converter / creator V.1.0</h1>

<br />

<div id="step1" class="hide"> 
  <div id="step1DropArea" class="drop-area">
    <h1>Step 1 - drag the data file here.</h1>
    <p>Select your data file with the file dialog or by dragging and dropping the file into the dashed region. Use files less than 100Kb if possible!<br />
      <br />
      The file is NOT uploaded anywhere.</p>
    <input id="input1" type="file" onchange="step1HandleDrop([this.files])" />
    <label class="button" for="fileElem">&lt;&lt;&lt; Select a file</label>
  </div>
</div>


<br />
<div id="step2" class="hide" style="text-align: center;">

  <h1>Click <a href = "#" onclick="processFileAndDownload()">HERE</a> to download the header file:</h1>
  <br/>
  <span class="check aAcc" onClick="toggleCheck(this)">
    <input type="checkbox" id="swapBytes" value="swapBytes"/>
    <label for="swapBytes"> Tick to swap byte order H > L to L > H (not implemented yet)</label>
  </span>
  <br />

</div>
<br />
<br />
<br />
<pre>
<div id="out"></div>
</pre>
body{
  padding: 20px;
  margin: 0px;
  background: #2e2e2e;
  color: #f0f0f0;
  font: 14px arial, sans-serif;
}

a:link {
  color: lightGreen;
}

a:hover {
  color: white;
}

a:active {
  color: white;
}

a:visited {
  color: lightGreen;
}

.drop-area {
  border: 2px dashed #ccc;
  border-radius: 20px;
  width: 480px;
  font-family: arial;
  margin: 20px auto;
  padding: 20px;
  padding-top: 0px;
  background: rgba(90,90,90,.3);
}

.hide {
  display: none;
}

.drop-area.highlight {
  border-color: purple;
  filter: drop-shadow(0 0 30px purple);
}

h1 {
  margin-bottom: 0px;
}

.highlightText {
  color: lightGreen;
}

.check {
  cursor: pointer;
  font-size: 18px;
  margin-top: 10px;
  margin-bottom: 10px;
  padding: 10px;
  display: inline-block;
  background: #553555;
}

label {
  cursor: pointer;
}

input[type="checkbox"] {
  display: none;
  cursor: pointer;
}

input[type="checkbox"] + label:before {
  content:"☐ ";
  cursor: pointer;
}

input:checked + label:before {
  content:"☑ ";
  cursor: pointer;
}

let step1DropArea = document.getElementById("step1DropArea");
let step1 = document.getElementById("step1");
let step2 = document.getElementById("step2");
let input1 = document.getElementById("input1");

let out = document.getElementById("out");

let fileName = null;
let hexFile = null;
let headerFile = null;

step1.style.display = "block";

;["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
  step1DropArea.addEventListener(eventName, preventDefaults, false);
});

function preventDefaults (e) {
  e.preventDefault()
  e.stopPropagation()
}

["dragenter", "dragover"].forEach(eventName => {
  step1DropArea.addEventListener(eventName, highlight, false);
});

["dragleave", "drop"].forEach(eventName => {
  step1DropArea.addEventListener(eventName, unhighlight, false);
});

function highlight(e) {
  step1DropArea.classList.add("highlight");
}

function unhighlight(e) {
  step1DropArea.classList.remove("highlight");
}

function toggleCheck(o) {
  if(event.currentTarget == event.target) o = o.children[0]; 
  o.checked = !o.checked;
}

step1DropArea.addEventListener("drop", step1HandleDrop, false);

function step1HandleDrop(e) {
  let file = null;
  if(e[0])
     file = e[0][0];
  else
    file = e.dataTransfer.files[0];
  let reader = new FileReader();
  fileName = file.name;
  reader.onload = function(e) {
    let arrayBuffer = reader.result;
    hexFile = new Uint8Array(arrayBuffer);
    step1.style.display = "none";
    step2.style.display = "block";
    fileName = fileName.split('.')[0];
  }
  reader.readAsArrayBuffer(file);
}

function processFileAndDownload() {
  let swapBytesCheck = document.getElementById("swapBytes");
  swapOn = swapBytesCheck.checked;
  headerFile = addHeader(toText(hexFile), hexFile.length, fileName);
  //out.innerHTML = headerFile;
  downloadHeaderFile();
}

function downloadHeaderFile(){
  saveBlob(headerFile, fileName + ".h");
  fileName = null;
  hexFile = null;
  headerFile = null;
  input1.value = "";
  step2.style.display = "none";
  step1.style.display = "block";
}

function addHeader(data, length, theName){
  return `// We need this header file to use the flash memory as storage with the PROGMEM directive:
#include <pgmspace.h>
// Byte length: ${length}
constexpr uint8_t ${theName}[] PROGMEM = {
${data}};`
}

let saveBlob = (function () {
  var a = document.createElement("a");
  document.body.appendChild(a);
  a.style = "display: none";
  return function (data, fileName) {
    let blob = new Blob([data], {type: "octet/stream"});
    let url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = fileName;
    a.click();
    window.URL.revokeObjectURL(url);
  };
})();

function toText(hex){
  let text = "";
  let block = [];
  let itemCount = 0;
  for(i = 0; i < hex.length; i++){
    let c = hex[i];
    block.push( ((c < 100) ? " " : "") + ((c < 10) ? " " : "") + c );
    if((itemCount != 0) && !((i+1) % 640)){
      block.push("");
      text += "   " + block.join(", ") + "\r\n";
      itemCount = 0;
      block = []
    }
    ++itemCount;
  }
  if(block.length > 0) text += "   " + block.join(", ") + "\r\n";
  return text;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.