Writing png after capturing from webcam in node-webkit not working - node.js

I am taking snapshot in html5 using the following code.
window.takeSnapshot = function(){
$("body").append("<canvas id='dummyCanvas' class='canvas' style='display: none'></canvas>");
var canvas = document.getElementById("dummyCanvas");
canvas.width = videoWidth;
canvas.height = videoHeight;
var context = canvas.getContext("2d");
var type = mediaType;
var tp = tupple;
context.drawImage(videoElement, 0, 0, videoWidth, videoHeight);
var contents = canvas.toDataURL('image/png');
var dt = new Date();
Message.showProgress();
var time = dt.getHours() + "_" + dt.getMinutes() + "_" + dt.getSeconds();
var file = {name: "Snapshot_" + time + ".png", contents: contents, recorded: true};
var id = "attachment_" + window.Guid();
var icon = (type==ContentTypes.Video)?("video.png"):((type==ContentTypes.Audio)?"audio.png":"image.png");
$("#attachments").append("<tr id='"+id+"'><td align='right'><img src='assets/images/progress.gif' style='width:16px'/></td><td><img src='assets/images/" + icon + "' style='width: 14px;' /></td><td style='font-size: 8pt; font-family: Arial; font-weight: bold;' style='text-decoration:none; color: #000000'>"+file.name+"</td></tr>");
Logger.log("Uploading " + file.name + " ...", LogTypes.INFO);
$("#mediaPanel").remove();
$("#attachmentPopup").show();
window.stream.stop();
var callback = function(){
Logger.log("Upload completed for " + file.name + " !", LogTypes.INFO);
CWDocumentWriter.addAttachment(tp, file.name, type);
$("#"+id).find('td').eq(0).html("<a href='javascript:void(0)' title='Delete attachment' onclick='window.deleteAttachment(["+tp[0]+","+tp[1]+","+tp[2]+","+tp[3]+"],\""+file.name+"\", event)'><img src='assets/images/delete.png' style='width:16px'/></a>");
$("#"+id).find('td').eq(2).html("<a href='javascript:void(0)' title='"+file.name+"' onclick='window.showContent(\"" + file.name + "\", " + type + ")'>"+file.name+"</a>");
Message.hideProgress();
};
if(Cloud.isLive())
Cloud.writeFile(file, contents, callback);
else{
var canvasImage = canvas.toDataURL("image/png").split(',')[1];
var decodedImg = window.atob(canvasImage);
var img = new Buffer(decodedImg, encoding='base64');
file.contents = img;
StorageManager.writeImageFile(file, contents, callback);
}
};
The image is uploaded to the cloud or saved on the local storage (using nodejs functions) depending upon the live or dead internet. It works fine in uploading the image data to the cloud and I can save and see the image back. But in the case of local hard drive it is not working. The image seems to be corrupted. Here is how I am saving it.
StorageManager.writeImageFile = function(file, data, callback){
if(!UserManager.isLoggedIn()){
UserManager.login();
return;
}
var key = ProjectManager.projectName;
var dir = Settings.USER_FOLDER + "/" + key + "/" + "media";
data = window.encode64(file.contents);
fs.writeFile(dir + "/" + file.name, data, "base64", function(err){});
callback();
};
I have tried several approaches but it seems to be not working correctly. The image file is written in the hard drive but it is corrupted. Please help me to resolve this problem.

I believe this will solve your problem:
var imgData = canvas.toDataURL('image/png');
var data = imgData.replace(/^data:image\/\w+;base64,/, "");
var buf = new Buffer(data, 'base64');
var whereToSave = "C:\pathToSave"; // edit this
fs.writeFile(whereToSave, buf);

Related

error by using in PDFTron:' NetworkError(`Unsupported protocol ${this._url.protocol}`'

I trying to convert pdf file to pdfa3 file by using PDFTron.
I added current url_path.
the my code below:
var input_url = './utils/';
var input_filename = 'test.pdf';
var output_filename = 'test_pdfa.pdf';
var convert = true;
var pwd = '';
var exceptions;
var max_ref_objs = 10;
var url_input = input_url + input_filename;
console.log('Converting input document: ' + input_filename);
var pdfa = await PDFNet.PDFACompliance.createFromUrl(true, url_input, '', PDFNet.PDFACompliance.Conformance.e_Level2B, exceptions, max_ref_objs);
get error:
'NetworkError(Unsupported protocol ${this._url.protocol})',
Does anyone know what the problem is,
And why doesn't it recognize the location?
I changed the code to :
here.
Now it's working!!

Google Script - convert sheet to XLSX

I have this code that search new doc in drive folder, and send files via email
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var email = "xxx#gmail.com";
var timezone = ss.getSpreadsheetTimeZone();
var today = new Date();
var oneDayAgo = new Date(today.getTime() - 1 * 24 * 60 * 60 * 1000);
var startTime = oneDayAgo.toISOString();
var search = '(trashed = false or trashed = false) and (modifiedDate > "' + startTime + '")';
var folder1 = DriveApp.getFoldersByName('SaveToPDF').next();
var files1 = folder1.searchFiles(search);
var row = "", count=0;
while( files1.hasNext() ) {
var file1 = files1.next();
var fileName = file1.getName();
var fileURL = file1.getUrl();
var lastUpdated = Utilities.formatDate(file1.getLastUpdated(), timezone, "yyyy-MM-dd HH:mm");
var dateCreated = Utilities.formatDate(file1.getDateCreated(), timezone, "yyyy-MM-dd HH:mm")
row += "<li>" + lastUpdated + " <a href='" + fileURL + "'>" + fileName + "</a></li>";
sheet.appendRow([dateCreated, lastUpdated, fileName, fileURL]);
count++;
}
if (row !== "") {
row = "<p>" + count + " file(s) have changed in your Google Drive in the past 24 hours. Here's the list:</p><ol>" + row + "</ol>";
row += "<br><small>To stop these notifications, please <a href='" + ss.getUrl() + "'>click here</a> and choose <em>Uninstall</em> from the Drive Activity menu.<br/></small>";
MailApp.sendEmail(email, "Google Drive - File Activity Report", "", {htmlBody: row, cc: "xxx#gmail.com"} );
}
I need to convert sheet files to XLSX format before send.
Can someone help me?
Thanks
You can follow this tutorial on how to convert the current Google Spreadsheet to Excel XLSX format and then emails the file as an attachment to the specified user using getGoogleSpreadsheetAsExcel() method.
function getGoogleSpreadsheetAsExcel(){
try {
var ss = SpreadsheetApp.getActive();
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + ss.getId() + "&exportFormat=xlsx";
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(ss.getName() + ".xlsx");
MailApp.sendEmail("amit#labnol.org", "Google Sheet to Excel", "The XLSX file is attached", {attachments: [blob]});
} catch (f) {
Logger.log(f.toString());
}
}
Here are some similar threads which might help:
Google apps script to email google spreadsheet excel version
Converting .xls to google spreadsheet in google apps script

const usage inside for loop, why this behaviour?

I have a for loop in my nodejs code
const saveDocument = co.wrap(function *(documentData, user, locale) {
var now = moment();
var creationDateLongString = now.format("YYYYMMDDHHmmss");
var creationDateShortString = now.format("YYYYMMDD");
var outputChildFolder = documentData.code + '_' + creationDateLongString + '_' + documentCounter;
var outputFolder = config.files.incomingDocumentsDir + '/' + outputChildFolder;
++documentCounter;
yield fs.mkdir(outputFolder)
var xmlFileName = documentData.code + "-" + creationDateLongString + ".xml";
var pdfFileName = documentData.code + "-" + creationDateLongString + ".pdf";
const pages = [];
for(var index=0;index < documentData.pages.length; ++index) {
const page = documentData.pages[index];
var data = new Buffer(page, "base64");
var dataEncoding = imageType(data).mime === "image/png" ? "png" : "jpg";
var fileName = "page" + index + "." + dataEncoding;
var targetFilePath = outputFolder + "/" + fileName
yield fs.writeFile(targetFilePath,data);
pages.push(fileName);
}
...
}
What I don't understand is why in the above code page only gets assigned once, on the first iteration, and holds that same value during the other iterations. So if I have 5 pages I end up 5 times with the data of the first page in that variable.
I am running node 4 without any special arguments or postprocessor. Simply npm run ... which maps to a node src/main/myApp.js in my package.json
I am probably missing something simple here but I've never seen this before when doing client side ES6 code. The big difference of course being that the client side code goes through Babel + Webpack and the server side code is ran directly through node.
Small addendum: if you are wondering why the "old school" for syntax and not something along the lines of pages.forEach(...., it's because this is existing code where I just did a few minor modifications.
This will work as you are expecting in strict mode. Try adding...
"use strict";
You will only see this behavior in environments (like Node) that actually respect and enforce the keyword. Babel simply converts all let and const to var right now to provide ES5 compatibility. To demonstrate, take a look at this Babel example. You can see in the output that const has been changed to var

how to pass image buffer data to gm in() GraphicsMagic

var buf = require('fs').readFileSync('test.jpg');
gm().in('-page', '+0+0').in(buf,'test.jpg').write('output.jpg', function (err) {
if (err) console.log(err);
})
in this case i want to pass buffer data as input to the gm.in() method.
Below is the link I'm referencing but in it, an image path is used as an input. I want to use buffer data as an input. How can I do this?
Tile four images together using Node.js and GraphicsMagick
Without modifying the source of GraphicsMagick itself, you can't. The gm module interacts with the GraphicsMagick program through the command line. The arguments you're passing through the .in() method are being converted into command-line arguments. The GraphicsMagick program only accepts filenames for this argument and will not attempt to process any direct form of data.
If you really needed to make this work without the filesystem, you could always download the GraphicsMagick source code and change the CLI to accept some form of data blob instead of a URL for this argument.
Actually I was creating a poster with two different image one is template image "background" and 2nd is top image with some text. I tried with gm but i loose image quality. Someone guide me to use Buffer data as input to improve the image quality. I tried but don't know how to pass Buffer data as an input.
So finally i decided to use node child process with command string. Here is the sample code i am sharing with you.
var fs = require('fs');
var gm = require("gm");
var exec = require('child_process').exec;
var IMAGEFILEPATH = "/images";
var gmcreateImage = function() {
var imageConfig = {"topimage":{"density":"300x300","startx":925,"starty":650,"width":575,"height":825},
"offers": [
{"startx": 75, "starty": 850, "msg": "SAVE 5$", "textcolor": "#4f61ac", "font": "Arial Bold", "fontsize":34,"stroke":{"color":"#4f61ac","width":4}},
{"startx": 75, "starty": 970, "msg": "per gallon", "textcolor": "#4f61ac", "font": "Arial Bold", "fontsize":34,"stroke":{"color":"#4f61ac","width":4}},
{"startx": 75, "starty": 1150, "msg": "With the purchase of", "textcolor": "black", "font": "Arial", "fontsize":18,"stroke":{"color":"black","width":1}},
{"startx": 75, "starty": 1260, "msg": "any Pepsi Z0 S2", "textcolor": "black", "font": "Arial", "fontsize":16,"stroke":{"color":"black","width":1}},
{"startx": 75, "starty": 1370, "msg": "on all flavours", "textcolor": "black", "font": "Arial", "fontsize":16,"stroke":{"color":"black","width":1}},
{"startx": 75, "starty": 1480, "msg": "Ask for details.", "textcolor": "black", "font": "Arial", "fontsize":18,"stroke":{"color":"black","width":1}}
]};
var addLast=imageConfig.topimage.last;
var commandStr = "gm convert '-page' '+0+0' '-units' 'PixelsPerInch' '-density' '" + imageConfig.topimage.density + "' '" + IMAGEFILEPATH+ "/template.jpg' ";
var imageActualPosition={};
imageActualPosition["x"] = imageConfig.topimage.startx;
imageActualPosition["y"] = imageConfig.topimage.starty;
if (!addLast) {
commandStr += " '-page' '+" + imageActualPosition["x"] + "+" + imageActualPosition["y"] + "' '" + IMAGEFILEPATH + "/top.jpg' ";
}
var offers = imageConfig.offers;
for (var i in offers) {
var color = offers[i].textcolor;
var startX = offers[i].startx;
var startY = offers[i].starty;
var font = offers[i].font;
var fontSize = offers[i].fontsize;
var msg = offers[i].msg;
var offerStr = "";
if (offers[i].stroke) {
offerStr += " '-stroke' '" + offers[i].stroke.color + "' '-strokewidth' '" + offers[i].stroke.width + "'";
}
offerStr += " '-fill' '" + color + "' '-pointsize' '" + fontSize + "' '-draw' 'text " + startX + " " + startY + " \"" + msg + "\"'";
commandStr += offerStr;
}
if (addLast) {
commandStr += " '-page' '+" + imageActualPosition["x"] + "+" + imageActualPosition["y"] + "' '" + IMAGEFILEPATH + "/top.jpg' ";
}
var finalImage="done.jpg";
commandStr += " '-mosaic' '-quality' '100' '" + IMAGEFILEPATH + finalImage + "'";
exec(commandStr, function(err, stdout, stderr) {
if (err) {
console.log("Error while executing gm commands" + err);
return;
} else {
console.log("Done See your image");
}
})
};
gmcreateImage();
As noted in another response, graphicsmagick doesn't allow a buffer as an input. However, interestingly, it does allow an HTTP URL as an input. If you are determined to get this to work without modifying graphicsmagick's source code, try something like this:
setup
Add the uuid module:
npm install uuid
Create a global object to hold the buffers:
const magickbuffers = {}
Create an http server in your script:
const uuid = require('uuid')
const http = require('http')
const magickserver = new http.Server()
const magickport = 9555
magickserver.on('request', (req, res) => {
res.writeHead(200, { 'Content-Type': 'image/png' })
if (magickbuffers[req.url]) {
res.end(magickbuffers[req.url])
}
else {
res.end("\n")
}
})
magickserver.listen(magickport, () => {})
Create a prototype to supply a usable local url so graphicsmagick can find the buffer on the local server and hand it off as an image, and also to handle the storage of the buffer:
Object.prototype.openBuffer = function() {
this.id = uuid()
magickbuffers[`/${this.id}`] = this
return `http://localhost:${magickport}/${this.id}`
}
Create another prototype to handle the cleanup of the buffer once you're completely done with it:
Object.prototype.closeBuffer = function() {
delete magickbuffers[`/${this.id}`]
return true
}
usage
Old example that is desired but doesn't work:
gm()
.in('-page', '+0+0')
.in(bufferone) // gm cant use a buffer here, this won't work
.in('-page', '+50+20')
.in(buffertwo) // or here
.mosaic()
.stream('png', function (err, stdout, stderr) {
stdout.pipe(writestream)
})
New method that works:
let one = bufferone.openBuffer()
let two = buffertwo.openBuffer()
gm()
.in('-page', '+0+0')
.in(one) // gm recognizes this because 'one' is a url pointing to the buffer
.in('-page', '+50+20')
.in(two)
.mosaic()
.stream('png', function (err, stdout, stderr) {
stdout.pipe(writestream)
bufferone.closeBuffer() // do this once gm has completely finished using these buffers
buffertwo.closeBuffer() // don't forget to do this for each buffer manipulated with .openBuffer()
})
I haven't figured out how to do it with both an image and the watermark as buffers, but I have figured out how to keep the image as a buffer:
gm(imageBuffer)
.composite('./logo_path.png')
.geometry(geometry)
.gravity('SouthEast')
.dissolve(this.options.opacity)
.toBuffer(function (err, buffer) {
next(err, buffer, 'image/jpeg');
});
};
Check out the code in this great library for more info.

gruntjs 0.4 registerHelper deprecated, syntax fix?

I've been running the following task for grunt 0.3 and moved to 0.4 and registerHelper has been deprecated. What is the correct method of implementing this with the new API.
module.exports = function(grunt) {
'use strict';
var fs = require('fs');
var path = require('path');
var crypto = require('crypto');
grunt.registerTask('wpversion', 'Set the versions in scripts.php for CSS/JS', function() {
var scriptsPhp = 'src/lib/include_functions/scripts.php';
// Hash the CSS
var hashCss = grunt.helper('md5', 'dist/assets/css/main.min.css');
// Hash the JS
var hashJs = grunt.helper('md5', 'dist/assets/scripts/scripts.min.js');
// Update scripts.php to reference the new versions
var regexCss = /(wp_enqueue_style\('main_css',(\s*[^,]+,){2})\s*[^\)]+\);/;
var regexJs = /(wp_register_script\('main_js',(\s*[^,]+,){2})\s*[^,]+,\s*([^\)]+)\);/;
var content = grunt.file.read(scriptsPhp);
content = content.replace(regexCss, "\$1 '" + hashCss + "');");
content = content.replace(regexJs, "\$1 '" + hashJs + "', " + "\$3);");
grunt.file.write(scriptsPhp, content);
grunt.log.writeln('"' + scriptsPhp + '" updated with new CSS/JS versions.');
});
/**
* The 'md5' helper is a basic wrapper around crypto.createHash
*/
grunt.registerHelper('md5', function(filepath) {
var hash = crypto.createHash('md5');
hash.update(fs.readFileSync(filepath));
grunt.log.write('Versioning ' + filepath + '...').ok();
return hash.digest('hex');
});
};
Just make it a normal function. If it's large put it in an separate file and require it. If it's reusable for other tasks, publish it as a node module so that other tasks can make use of it.
The grunt-helpers are deprecated in favor of node's require.
There is a project to help use the legacy helpers:
https://github.com/gruntjs/grunt-lib-legacyhelpers

Resources