2022-02-19 01:34:37 +00:00
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<link rel="stylesheet" href="../../css/spectre.min.css">
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
|
|
|
|
<script src="../../core/lib/heatshrink.js"></script>
|
|
|
|
<script src="../../core/lib/imageconverter.js"></script>
|
|
|
|
<script src="../../core/lib/customize.js"></script>
|
2022-02-20 00:52:28 +00:00
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.js"></script>
|
2022-02-19 01:34:37 +00:00
|
|
|
|
2022-02-20 01:00:27 +00:00
|
|
|
<h4>Upload watchface:</h4>
|
2022-02-19 01:34:37 +00:00
|
|
|
|
|
|
|
|
2022-02-20 01:00:27 +00:00
|
|
|
<p>Select watchface folder:</br><input type="file" id="fileLoader" name="files[]" multiple directory="" webkitdirectory="" moxdirectory="" /></p>
|
|
|
|
<p><b>or</b></p>
|
|
|
|
<p>Select watchface zip file: </br><input type="file" id="zipLoader" name="zip"/></p><br/>
|
|
|
|
<button id="btnUpload" class="btn btn-primary">Upload to watch</button>
|
|
|
|
<button id="btnSave" class="btn btn-secondary">Save resources file</button></br>
|
2022-02-19 01:34:37 +00:00
|
|
|
<canvas id="canvas" style="display:none;"></canvas></br>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
var result = "";
|
|
|
|
var resultJson = {};
|
2022-02-20 00:52:28 +00:00
|
|
|
var infoJson;
|
|
|
|
var faceJson;
|
2022-02-20 17:59:42 +00:00
|
|
|
var handledFiles = 0;
|
|
|
|
var expectedFiles = 0;
|
2022-02-19 01:34:37 +00:00
|
|
|
|
|
|
|
function imageLoaded() {
|
|
|
|
var options = {};
|
|
|
|
|
|
|
|
options.diffusion = infoJson.diffusion ? infoJson.diffusion : "none";
|
2022-02-20 20:15:34 +00:00
|
|
|
options.compression = infoJson.compression ? infoJson.compression : false;
|
2022-02-19 01:34:37 +00:00
|
|
|
options.alphaToColor = false;
|
2022-02-20 13:59:49 +00:00
|
|
|
options.transparent = false;
|
2022-02-19 01:34:37 +00:00
|
|
|
options.inverted = false;
|
|
|
|
options.autoCrop = false;
|
|
|
|
options.brightness = 0;
|
|
|
|
options.contrast = 0;
|
2022-02-20 00:52:28 +00:00
|
|
|
options.mode = infoJson.color ? infoJson.color : "1bit";
|
2022-02-19 01:34:37 +00:00
|
|
|
options.output = "jsonobject";
|
2022-02-20 13:59:49 +00:00
|
|
|
|
|
|
|
var faceJson;
|
|
|
|
console.log("Loaded image has path", this.path);
|
|
|
|
var jsonPath = this.path.split("/");
|
|
|
|
|
|
|
|
var forcedTransparentColorMatch = jsonPath[jsonPath.length-1].match(/.*\.t([^.]+)\..*/)
|
|
|
|
|
|
|
|
var forcedTransparentColor;
|
|
|
|
if (jsonPath[jsonPath.length-1].includes(".t.")){
|
|
|
|
options.transparent = true;
|
|
|
|
} else if (forcedTransparentColorMatch){
|
|
|
|
options.transparent = false;
|
|
|
|
forcedTransparentColor = forcedTransparentColorMatch[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log("image has transparency", options.transparent);
|
|
|
|
console.log("image has forced transparent color", forcedTransparentColor);
|
|
|
|
jsonPath[jsonPath.length-1] = jsonPath[jsonPath.length-1].replace(/([^.]*)\..*/, "$1");
|
|
|
|
console.log("Loaded image has json path", jsonPath);
|
2022-02-19 01:34:37 +00:00
|
|
|
|
|
|
|
var canvas = document.getElementById("canvas")
|
|
|
|
canvas.width = this.width*2;
|
|
|
|
canvas.height = this.height;
|
|
|
|
var ctx = canvas.getContext("2d");
|
|
|
|
ctx.drawImage(this,0,0);
|
|
|
|
|
|
|
|
var imgstr = "";
|
|
|
|
|
|
|
|
|
|
|
|
var imageData = ctx.getImageData(0, 0, this.width, this.height);
|
|
|
|
ctx.fillStyle = 'white';
|
|
|
|
ctx.fillRect(options.width, 0, this.width, this.height);
|
|
|
|
var rgba = imageData.data;
|
|
|
|
options.rgbaOut = rgba;
|
|
|
|
options.width = this.width;
|
|
|
|
options.height = this.height;
|
2022-02-20 00:52:28 +00:00
|
|
|
console.log("options", options);
|
2022-02-19 01:34:37 +00:00
|
|
|
imgstr = imageconverter.RGBAtoString(rgba, options);
|
|
|
|
var outputImageData = new ImageData(options.rgbaOut, options.width, options.height);
|
|
|
|
ctx.putImageData(outputImageData,this.width,0);
|
|
|
|
|
|
|
|
|
|
|
|
// checkerboard for transparency on original image
|
|
|
|
var imageData = ctx.getImageData(0, 0, this.width, this.height);
|
|
|
|
imageconverter.RGBAtoCheckerboard(imageData.data, {width:this.width,height:this.height});
|
|
|
|
ctx.putImageData(imageData,0,0);
|
|
|
|
|
|
|
|
|
|
|
|
var currentElement = resultJson;
|
|
|
|
|
|
|
|
for (var i = 0; i < jsonPath.length; i++){
|
|
|
|
if (i == jsonPath.length - 1){
|
2022-02-20 13:59:49 +00:00
|
|
|
var resultingObject = JSON.parse(imgstr);
|
|
|
|
if (forcedTransparentColor !== undefined) resultingObject.transparent = forcedTransparentColor;
|
|
|
|
currentElement[jsonPath[i]] = resultingObject;
|
|
|
|
console.log("result is ", resultingObject);
|
2022-02-19 01:34:37 +00:00
|
|
|
} else {
|
|
|
|
if (!currentElement[jsonPath[i]]) currentElement[jsonPath[i]] = {};
|
|
|
|
currentElement = currentElement[jsonPath[i]];
|
|
|
|
}
|
|
|
|
}
|
2022-02-20 17:59:42 +00:00
|
|
|
|
|
|
|
handledFiles++;
|
|
|
|
console.log("Expected:", expectedFiles, " handled:", handledFiles);
|
|
|
|
|
|
|
|
if (handledFiles == expectedFiles){
|
|
|
|
document.getElementById('btnSave').disabled = false;
|
|
|
|
document.getElementById('btnUpload').disabled = false;
|
|
|
|
}
|
2022-02-19 01:34:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function handleWatchFace(infoFile, faceFile, resourceFiles){
|
|
|
|
var reader = new FileReader();
|
|
|
|
reader.path = infoFile.webkitRelativePath;
|
|
|
|
reader.onload = function(event) {
|
|
|
|
infoJson = JSON.parse(reader.result);
|
|
|
|
handleFaceJson(faceFile, resourceFiles);
|
|
|
|
};
|
|
|
|
reader.readAsText(infoFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleFaceJson(faceFile, resourceFiles){
|
|
|
|
var reader = new FileReader();
|
|
|
|
reader.path = faceFile.webkitRelativePath;
|
|
|
|
reader.onload = function(event) {
|
|
|
|
faceJson = JSON.parse(reader.result);
|
|
|
|
handleResourceFiles(resourceFiles);
|
|
|
|
};
|
|
|
|
reader.readAsText(faceFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleResourceFiles(files){
|
|
|
|
for (var current of files){
|
|
|
|
console.log('Handle resource file ', current);
|
|
|
|
var reader = new FileReader();
|
2022-02-20 00:52:28 +00:00
|
|
|
console.log("Handling ", current.name, " with path ", current.webkitRelativePath);
|
2022-02-20 01:00:27 +00:00
|
|
|
var filteredPath = current.webkitRelativePath.replace(/.*\/resources\//,"")
|
2022-02-20 00:52:28 +00:00
|
|
|
reader.path = filteredPath;
|
2022-02-19 01:34:37 +00:00
|
|
|
reader.onload = function(event) {
|
|
|
|
var img = new Image();
|
2022-02-20 01:00:27 +00:00
|
|
|
img.path = this.path;
|
2022-02-19 01:34:37 +00:00
|
|
|
img.onload = imageLoaded;
|
|
|
|
img.src = event.target.result;
|
|
|
|
};
|
|
|
|
reader.readAsDataURL(current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleFileSelect(event) {
|
2022-02-20 17:59:42 +00:00
|
|
|
handledFiles = 0;
|
|
|
|
expectedFiles = undefined;
|
|
|
|
|
|
|
|
document.getElementById('btnSave').disabled = true;
|
|
|
|
document.getElementById('btnUpload').disabled = true;
|
|
|
|
|
2022-02-19 01:34:37 +00:00
|
|
|
console.log("File select event", event);
|
|
|
|
if (event.target.files.length == 0) return;
|
|
|
|
result = "";
|
|
|
|
resultJson= {};
|
|
|
|
|
|
|
|
var resourceFiles = [];
|
|
|
|
var faceFile;
|
|
|
|
var infoFile;
|
|
|
|
|
|
|
|
for (var current of event.target.files){
|
|
|
|
console.log('Handle file ', current);
|
|
|
|
if (current.webkitRelativePath.split("/")[1].startsWith("resources")){
|
|
|
|
console.log('Found resource file', current.name);
|
|
|
|
resourceFiles.push(current);
|
2022-02-20 17:59:42 +00:00
|
|
|
expectedFiles = resourceFiles.length;
|
2022-02-19 01:34:37 +00:00
|
|
|
} else if (current.name == "face.json"){
|
|
|
|
console.log('Found face file', current.name);
|
|
|
|
faceFile = current;
|
|
|
|
} else if (current.name == "info.json"){
|
|
|
|
console.log('Found info file', current.name);
|
|
|
|
infoFile = current;
|
|
|
|
} else {
|
|
|
|
console.log('Found unsupported file', current.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
handleWatchFace(infoFile, faceFile, resourceFiles);
|
|
|
|
|
|
|
|
};
|
|
|
|
document.getElementById('fileLoader').addEventListener('change', handleFileSelect, false);
|
|
|
|
|
|
|
|
document.getElementById("btnSave").addEventListener("click", function() {
|
|
|
|
var h = document.createElement('a');
|
|
|
|
h.href = 'data:text/json;charset=utf-8,' + encodeURI(JSON.stringify(resultJson));
|
|
|
|
h.target = '_blank';
|
|
|
|
h.download = "imageclock.resources.json";
|
|
|
|
h.click();
|
|
|
|
});
|
|
|
|
document.getElementById("btnUpload").addEventListener("click", function() {
|
|
|
|
var appDef = {
|
|
|
|
id : "imageclock",
|
|
|
|
storage:[
|
|
|
|
{name:"imageclock.app.js", url:"app.js"},
|
|
|
|
{name:"imageclock.face.json", content: JSON.stringify(faceJson)},
|
|
|
|
{name:"imageclock.resources.json", content: JSON.stringify(resultJson)},
|
|
|
|
{name:"imageclock.img", url:"app-icon.js", evaluate:true},
|
|
|
|
]
|
|
|
|
};
|
|
|
|
sendCustomizedApp(appDef);
|
|
|
|
});
|
2022-02-20 00:52:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
function handleZipSelect(evt) {
|
|
|
|
|
|
|
|
function handleFile(f) {
|
2022-02-20 17:59:42 +00:00
|
|
|
expectedFiles = 0;
|
|
|
|
handledFiles = 0;
|
|
|
|
document.getElementById('btnSave').disabled = true;
|
|
|
|
document.getElementById('btnUpload').disabled = true;
|
2022-02-20 00:52:28 +00:00
|
|
|
JSZip.loadAsync(f).then(function(zip) {
|
|
|
|
|
|
|
|
console.log("Zip loaded", zip);
|
|
|
|
result = "";
|
|
|
|
resultJson= {};
|
|
|
|
|
|
|
|
var resourceFiles = [];
|
|
|
|
|
|
|
|
var promise = zip.file("face.json").async("string").then((data)=>{
|
|
|
|
console.log("face.json data", data);
|
|
|
|
faceJson = JSON.parse(data);
|
|
|
|
});
|
|
|
|
|
|
|
|
promise = promise.then(zip.file("info.json").async("string").then((data)=>{
|
|
|
|
console.log("info.json data", data);
|
|
|
|
infoJson = JSON.parse(data);
|
|
|
|
}));
|
|
|
|
|
|
|
|
zip.folder("resources").forEach(function (relativePath, file){
|
|
|
|
console.log("iterating over", relativePath);
|
|
|
|
|
|
|
|
if (!file.dir){
|
2022-02-20 17:59:42 +00:00
|
|
|
expectedFiles++;
|
2022-02-20 00:52:28 +00:00
|
|
|
promise = promise.then(file.async("blob").then(function (blob) {
|
|
|
|
var reader = new FileReader();
|
|
|
|
console.log("Handling ", file.name, " with path ", relativePath);
|
|
|
|
reader.path = relativePath;
|
|
|
|
reader.onload = function(event) {
|
|
|
|
var img = new Image();
|
|
|
|
img.path = this.path;
|
|
|
|
img.onload = imageLoaded;
|
|
|
|
img.src = event.target.result;
|
|
|
|
};
|
|
|
|
reader.readAsDataURL(blob);
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}, function (e) {
|
|
|
|
console.log("Error reading " + f.name + ": " + e.message);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log("Zip select event", evt);
|
|
|
|
var files = evt.target.files;
|
|
|
|
|
|
|
|
if (files.length > 1){
|
|
|
|
alert("Only one file allowed");
|
|
|
|
}
|
|
|
|
|
|
|
|
handleFile(files[0]);
|
2022-02-20 17:59:42 +00:00
|
|
|
}
|
2022-02-20 00:52:28 +00:00
|
|
|
|
|
|
|
|
2022-02-19 01:34:37 +00:00
|
|
|
|
2022-02-20 17:59:42 +00:00
|
|
|
document.getElementById('zipLoader').addEventListener('change', handleZipSelect, false);
|
|
|
|
document.getElementById('btnSave').disabled = true;
|
|
|
|
document.getElementById('btnUpload').disabled = true;
|
2022-02-19 01:34:37 +00:00
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|