Code.gs
--
/*
Uses Library: 1T03nYHRho6XMWYcaumClcWr6ble65mAT8OLJqRFJ5lukPVogAN2NDl-y
From: https://github.com/tanaikech/ImgApp
to resize images
*/
var img_leader = "data:image/jpeg;base64," //I'm assuming a JPEG here, tsk, tsk...
var imageFolderId = "148kImTGptbKdckcrV3sL3xUCMqXRRdWu" //WHERE WE WANT THE IMAGES TO BE SAVED//CHANGE ME
var folder = DriveApp.getFolderById(imageFolderId)
//Used to display the last three images
function doGet(e) {
var action = e.parameter.action
var scriptUrl = ScriptApp.getService().getUrl()
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName("Images")
var values = sheet.getDataRange().getValues()
var headers = values.shift()
if (action == "list" | action == null){
values = values.slice(Math.max(values.length - 3, 1))//Get the last three items
values.reverse()
try{
var lastRow = sheet.getLastRow()
var data = sheet.getRange(lastRow, 10).getValue()
Logger.log(data.length + " chars")
var template = HtmlService.createTemplateFromFile('index.html')
template.scriptUrl = scriptUrl
template.values = values
var homepage = template.evaluate().setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
return homepage;
}catch(e){
return ContentService.createTextOutput(e)
}
}else if (action == "view"){//View just one image
var timestamp = Number(e.parameter.timestamp)
for (v in values){//looping slow but...
var row = values[v]
try{
if (row[0].getTime() == timestamp){
var template = HtmlService.createTemplateFromFile('view.html')
template.data = row[3] // the full size image data
var homepage = template.evaluate().setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
return homepage;
}
}catch(e){
return ContentService.createTextOutput(e)
}
}
}
}
//Called by App Inventor App to upload a picture and data
function doPost(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName("Images")
var now = new Date()
try{
var image = e.parameter.image
var imageFileUrl = ''
try{ // to make an image
var name = "App_Inventor_" + now.getTime() + ".jpg"
var decoded = Utilities.base64Decode( image.toString() )//Utilities.Charset.UTF_8
var blob = Utilities.newBlob(decoded, MimeType.JPEG, name);
var imageFile = folder.createFile(blob)
var thumbnailData = getThumbnail( imageFile.getId())
imageFileUrl = imageFile.getUrl()
}catch(e){
log(e + " " + e.stack)
}
var asimuth = e.parameter.asimuth
var pitch = e.parameter.pitch
var roll = e.parameter.roll
var angle = e.parameter.angle
var text = e.parameter.text
var latlng = e.parameter.latlng
var address = e.parameter.address
//timestamp text latlng image image URL asimuth pitch roll angle
var data = [now, text, latlng, image, imageFileUrl, asimuth, pitch, roll, angle, thumbnailData, address]
sheet.appendRow(data)
SpreadsheetApp.flush()//Do I need this?
return ContentService.createTextOutput("IMAGE UPLOADED OK");
}catch(e){
return ContentService.createTextOutput(e + " " + e.stack )
}
}
var thumbnailWidth = 32
function getThumbnail(id){
//https://github.com/tanaikech/ImgApp
//"16y9kDWjCmSjx_YbF3ZSN_UvRL74I_5dE"
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName("Images")
var imageFile = DriveApp.getFileById(id)
var tempImageFile = imageFile.makeCopy(folder)
var thumbnailBlob = tempImageFile.getBlob() //
log( ImgApp.getSize(thumbnailBlob) )
var res = ImgApp.doResize(tempImageFile.getId(), 48)
var width = res.resizedwidth;
var height = res.resizedheight;
var newName = tempImageFile.getName().replace(".jpg", "_thumb.jpg")
var newNewFile = DriveApp.createFile(res.blob.setName( newName ));
folder.addFile(newNewFile)
log( ImgApp.getSize( newNewFile.getBlob() ))
var thumbnailData = Utilities.base64Encode( newNewFile.getBlob().getBytes())
var thumbnailDataLength = thumbnailData.length
//sheet.getRange(2, 10).setValue(thumbnailData)
tempImageFile.setTrashed( true )
DriveApp.removeFile(tempImageFile) //remove the copy that got resized.
return thumbnailData
}
Utils.gs
--
var logSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Log")
function log(s){
logSheet.appendRow([s])
}
function prettyprint(object){
var text = JSON.stringify(object, null, 4); //you can specify a number instead of '\t' and that many spaces will be used for indentation...
return text
}
function setRowHeights(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName("Images")
var lastRow = sheet.getLastRow()
sheet.setRowHeights(1, lastRow, 20)
//Logger.log( "There are " + lastRow + " rows, including the header")
}
function howManyRows(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName("Images")
var lastRow = sheet.getLastRow()
Logger.log( "There are " + lastRow + " rows, including the header")
}
function test(){ //So some Extensions encode the path, and not the image
var s = "/storage/emulated/0/DCIM/Camera/pic.jpg"
Logger.log( Utilities.base64Encode(s))
}
function testCreateImage(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName("Images")
var lastRow = sheet.getLastRow()
var image = sheet.getRange(lastRow, 4).getValue()
try{ // to make an image
var decoded = Utilities.base64Decode( image ) //Utilities.Charset.UTF_8
var blob = Utilities.newBlob(decoded, MimeType.JPEG, "App Inventor.jpg");
//var imageFile = DriveApp.createFile(blob)
var imageFile = folder.createFile(blob)
imageFileUrl = imageFile.getUrl()
log(imageFileUrl)
}catch(e){
log(e + " " + e.stack)
}
}
function include_drive_file(id){
var file = DriveApp.getFileById(id)
var source = file.getAs('text/plain').getDataAsString()
return source
}
/* CACHE-ING CALLS - USEFUL FOR SPEEDING UP ACCESS ON DATA THAT DOESN'T CHANGE MUCH */
function include_drive_file_cache(id){
try{
var cache = CacheService.getPublicCache();
var items_data = cache.get(id);
if (items_data == null) {
items_data = include_drive_file(id);
cache.put(id, Utilities.jsonStringify(items_data), 3600);
} else {
items_data = Utilities.jsonParse(items_data);
}
return items_data;
}catch(e){
Logger.log( e ) //Sometimes if the data is too big, it can't be cached it seems, so it just bails and reads it.
var data = include_drive_file(id)
Logger.log( data.length)
return data
}
}
index.html
--
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script>
<base target="_top">
<style>
#warning{
visibility:hidden;
}
#container{
text-align: center;
display: block;
}
img{
margin:10px;
}
</style>
<script>
var timer
function hider(){
//var ele = $("#warning");
const el = $("#warning")
if (el) {
el.css('display','none')
} else {
//console.log("argh!")
}
clearInterval(timer);
}
$(function() {
timer = setInterval(function(){ hider(); }, 3000);
});
</script>
</head>
<body>
<div id="container">
<p>Displays the last 3 images uploaded.</p>
<?
for (v in values){
var row = values[v]
var data = row[9]
var timestamp = row[0].getTime()
?>
<a href="<?=scriptUrl?>?action=view×tamp=<?=timestamp?>"><img src="data:image/jpeg;base64,<?!=data?>" width="96"></a>
<?}?>
</div>
</body>
</html>
view.html
--
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
#warning{
visibility:hidden;
}
#container{
text-align: center;
display: block;
}
img{
margin:10px;
}
</style>
</head>
<body>
<div id="container">
<img src="data:image/jpeg;base64,<?!=data?>" width="100%">
</div>
</body>
</html>