Writing GPS exif data into image in Node - node.js

Good evening, community.
I have a question regarding changing exif meta data on jpegs using node.js. I have a set of coordinates which I need to attach to the image file, but for some reason, I cannot find the right library on npm for that. There are plenty of extracting libraries, like exif, exif-js, no-exif and so on, but all of the are retrieving data from images. I'm going the opposite direction, and extracting coordinates/gps data from the kml file and based on that updating the images, which do not have geo-location metadata.
What is the best approach for doing this?

I have written a library to modify exif on client-side. It would help you even on Node.js.
https://github.com/hMatoba/piexifjs
I tried to run the library on Node.js. No error occurred and got a new jpeg modified exif.
var piexif = require("piexif.js");
var fs = required("fs");
var jpeg = fs.readFileSync(filename1);
var data = jpeg.toString("binary");
var exifObj = piexif.load(data);
exifObj["GPS"][piexif.GPSIFD.GPSVersionID] = [7, 7, 7, 7];
exifObj["GPS"][piexif.GPSIFD.GPSDateStamp] = "1999:99:99 99:99:99";
var exifbytes = piexif.dump(exifObj);
var newData = piexif.insert(exifbytes, data);
var newJpeg = new Buffer(newData, "binary");
fs.writeFileSync(filename2, newJpeg);

This worked best for me. eg. to write a coordinate of 23.2342 N, 2.343 W
const piexifjs = require("piexifjs");
var filename1 = "image.jpg";
var filename2 = "out.jpg";
var jpeg = fs.readFileSync(filename1);
var data = jpeg.toString("binary");
var exifObj = piexif.load(data);
exifObj.GPS[piexif.GPSIFD.GPSLatitude] = degToDmsRational(23.2342);
exifObj.GPS[piexif.GPSIFD.GPSLatitudeRef] = "N";
exifObj.GPS[piexif.GPSIFD.GPSLongitude] = degToDmsRational(2.343);
exifObj.GPS[piexif.GPSIFD.GPSLongitudeRef] = "W";
var exifbytes = piexif.dump(exifObj);
var newData = piexif.insert(exifbytes, data);
var newJpeg = Buffer.from(newData, "binary");
fs.writeFileSync(filename2, newJpeg);
function degToDmsRational(degFloat) {
var minFloat = degFloat % 1 * 60
var secFloat = minFloat % 1 * 60
var deg = Math.floor(degFloat)
var min = Math.floor(minFloat)
var sec = Math.round(secFloat * 100)
deg = Math.abs(deg) * 1
min = Math.abs(min) * 1
sec = Math.abs(sec) * 1
return [[deg, 1], [min, 1], [sec, 100]]
}

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!!

Modify one specific field of Exif information of image file using piexifjs in Node.js

I am developing web application using Node.js that involves some image processing. In my application, I need to modify the Exif information of an image (Orientation), only one field. And then I want all the other information remains the same. I am using this library.
I am using this code
var filename1 = "test.jpg";
var filename2 = "out1.jpg";
var jpeg = fs.readFileSync(filename1);
var data = jpeg.toString("binary");
var zeroth = {}; //exifData.image;//{};//exifData.image//{};
var exif = {};
var gps = {};
zeroth[piexif.ImageIFD.Make] = "Make";
zeroth[piexif.ImageIFD.XResolution] = [777, 1];
zeroth[piexif.ImageIFD.YResolution] = [777, 1];
zeroth[piexif.ImageIFD.Software] = "Piexifjs";
exif[piexif.ExifIFD.DateTimeOriginal] = "2010:10:10 10:10:10";
exif[piexif.ExifIFD.LensMake] = "LensMake";
exif[piexif.ExifIFD.Sharpness] = 777;
exif[piexif.ExifIFD.LensSpecification] = [[1, 1], [1, 1], [1, 1], [1, 1]];
gps[piexif.GPSIFD.GPSVersionID] = [7, 7, 7, 7];
gps[piexif.GPSIFD.GPSDateStamp] = "1999:99:99 99:99:99";
var exifObj = {"0th":zeroth, "Exif":exif, "GPS":gps};
var exifbytes = piexif.dump(exifObj);
var newData = piexif.insert(exifbytes, data);
var newJpeg = new Buffer(newData, "binary");
fs.writeFileSync(filename2, newJpeg)
What above code doing is creating the new file and Exif information. Then insert that new Exif information into the new image file, but I do not want it, because I am modifying only one field. I only want to change orientation only and maintain the other fields. So, I tried doing something like this:
var filename1 = "test.jpg";
var filename2 = "out1.jpg";
var jpeg = fs.readFileSync(filename1);
var data = jpeg.toString("binary");
var zeroth = {}; //exifData.image;//{};//exifData.image//{};
var exif = {};
var gps = {};
zeroth[piexif.ImageIFD.Orientation] = 1;
var exifObj = {"0th":zeroth, "Exif":exif, "GPS":gps};
var exifbytes = piexif.dump(exifObj);
var newData = piexif.insert(exifbytes, data);
fs.writeFileSync(filename2, newJpeg)
But the attempt was not working. So, how can I modify only one specific field (Orientation) and maintain other fields of Exif data of an image file using piexifjs?

base64 encode, nodejs c++ python's result is diffrent

nodejs:
var test = 'VdEU+Q2J5qfwsn9xshAcEImDSnxTR8RkRLlLmyNaeos=';
var result = new Buffer(test, 'base64').toString()
//var buf = Buffer.from(test, 'base64');
//var result = new Buffer(test, 'base64').toString("utf8");
var fs = require('fs');
fs.writeFile("test.txt",result,function(e){//会先清空原先的内容
if(e) throw e;
})
python:
import base64
result = base64.b64decode('VdEU+Q2J5qfwsn9xshAcEImDSnxTR8RkRLlLmyNaeos=')
file_object = open('thefile.txt', 'w')
file_object.write(result)
file_object.close( )
c++: (I use libcef's base library's base64):
const std::string kText = "VdEU+Q2J5qfwsn9xshAcEImDSnxTR8RkRLlLmyNaeos=";
std::string encoded;
base::Base64Decode(kText, &encoded);
FILE *pFile = fopen("1.txt", "wb+");
fwrite(encoded.c_str(), encoded.length(), 1, pFile);
fclose(pFile);
the result is python c++ is the same, but nodejs is different
You simply need to not call toString():
var result = new Buffer(test, 'base64');
Then the Node code does the same as the others.

Image found but not visible Nodejs and Express

I have a canvas and in the canvas I want to load an image.
client.js
game.viewport = document.getElementById('viewport');
game.card1 = document.getElementById('card1');
//Adjust their size
game.viewport.width = game.world.width;
game.viewport.height = game.world.height;
game.card1.width = game.cards.width;
game.card1.height = game.cards.height;
//Fetch the rendering contexts
game.ctx = game.viewport.getContext('2d');
game.ctx2 = game.card1.getContext('2d');
game_core.js
game_core.prototype.client_cards = function(game_instance) {
this.instance = game_instance;
var img = new Image();
img.src = '/images/Chainlinks/AddBurn.png';
this.ctx2.drawImage(img,10,20);
this.ctx2.fillStyle = 'rgba(255,255,255,0.7)';
this.ctx2.fillText('Summoner: '+player1, 10 , 20);
The text Summnor2: is visible in the canvas but the image isn't drawed. If I look in de cmd of node.js he finds the image path. so I really don't know where it goes wrong.
Try something like this. Make sure image path is correct.
var self = this;
var img = new Image();
img.src = './images/Chainlinks/AddBurn.png';
img.onload = function() {
self.ctx2.drawImage(img,10,20);
self.ctx2.fillStyle = 'rgba(255,255,255,0.7)';
self.ctx2.fillText('Summoner: '+player1, 10 , 20);
};

Image not saving on a Palm device

Updated: webOS version 2.1...
This base64 encoded image data generates the correct data image when I append it to the source of an image, like this:
var img = new Image();
img.src= data
var data = "data:image/png;base64,iVBORw0KGgoAAAANSUh
EUgAAAJYAAACmCAIAAAC3GeEYAAEkgklEQVR4AQD9/wIAADt8Fj5/GUSA IESAIEN/GUd/H0V+IEaEIE
WFHUOEHEqJIE2KIk2KI1GQKFSQLFaQKlaOKVaQKlORLlaYLVaVKFWV KVWUKliWKFiXJlKVIliTJW2oP
m6jOW+kPGqkPmehPWWePWagOmmjP2ykQ2ulQmylRWykQmqmP2qr QGqnP26qSGyvRmquQWyyQGquP2yu
RHSzSHWwSXGxSGytRG+vSG6vSW2vRWquRGqtRGmsQnO1R3Gw SG+rSXavUXWwUnKqR3CuRWquP26zQ3C
yRXK0SHG0SWupR2qoR3CuS2qrQ3CsSG6vS22pR26qSGyq RWetO22uQ2yqP22wRGetP2yyP4TEWgElAB
UrBRYmAx05AidHBB9MCydRDylSGChWGCZUFyFLEyNK Ex5IDBtJBhc/Bx9FDBxDDh5HDyRGExs8DRs4D
B04DRw8Exo6DxMuBw8kAhEeABIYAQ4VABAUAA0S AAwVAg8bAw0bAgwaAxAYAAULAQgQAQcQBQsPAAwQ
AggMAwMLAQAIAAgOBAYOAAsWBg4bChMgDxUk DxcmERopEh8vFBwuExspEhcnDxUpDhcqERUnDhUnDRQ
rDxgsERgvEx8xGQA+fxk7gxU9hBc9ghg/ gR1CgBxBhBtChRxIhyFMiyNMiyNNjiZNiypRkCpSjydRkC
VVkSpTkihYmi9YlC9XlCxVlClYlixW lSpZlS1eli16skJnqDxppj1qpDxmpD9mpD1loj1opz9qqENvq
Udpp0FmqD9npkFtpUVvp0ZvrUVs q0NsrEFtrURsrkBrsT9vskFvrj5srz5ssUJsrkJsrkNtr0NusEVm
qjxrrz5ttkNquEFqtEFu"
I am trying to save the image using my custom service, but it does not save the correct image. Here is the Node.js code for saving the image:
var fs = IMPORTS.require('fs');
var path = IMPORTS.require('path');
var buff = new Buffer(img.substr('data:image/png;base64,'.length), 'base64');
path.exists('/media/internal/wallpapers/', function(exists){
if (exists) {
var id = fs.openSync('/media/internal/wallpapers/i.png', 'w', 666);
var written = fs.writeSync(id, buff,0, buff.length, 0);
fs.closeSync(id);
}
});
The saved version of the image has totally different pixel values.
EDIT
I came to find out that the image data above isn't correct. I am using a PNG library to generate base64 image data of a canvas pixel array. The link is http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/.
That is an alternative to canvas.toDataURL();. webOS does not support toDataURL, so I had to use a library.
Here is the code I have used with this library to manipulate my canvas image data as a pixel array:
EditorAssistant.prototype.getDataURL = function(width,height,pixelArray) {
var p = new PNGlib(height, width, 256); // Construcor takes height, weight and color-depth.
var background = p.color(0, 0, 0, 0);
var k = 0;
for (var j = 0; j<height; j++) {
for (var i =0; i<width; i++) {
var x =i;
var y =j;
p.buffer[p.index(x,y)] = p.color(pixelArray[k], pixelArray[k+1], pixelArray[k+2]);
k+=4;
}
}
return 'data:image/png;base64,'+p.getBase64() ;
}
Does this library work and where am I doing it wrong?
libpng.js only supports 256 color images, so that may be the problem. There are other base64 encoding utilities which may work as expected.

Resources