-
Notifications
You must be signed in to change notification settings - Fork 593
/
Copy path94-exif.js
141 lines (136 loc) · 6.67 KB
/
94-exif.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
module.exports = function(RED) {
"use strict";
function convertDegreesMinutesSecondsToDecimals(degrees, minutes, seconds) {
var result;
result = degrees + (minutes / 60) + (seconds / 3600);
return result;
}
function ExifNode(n) {
RED.nodes.createNode(this,n);
this.mode = n.mode || "normal";
if (this.mode === "worldmap") { this.property = "payload.content"; }
else if (this.mode === "tak") { this.property = "payload.event.detail.image['#text']"; }
else { this.property = n.property || "payload"; }
var node = this;
var ExifReader = require('exifreader');
/***
* Extracts GPS location information from Exif data. If enough information is
* provided, convert the Exif data into a pair of single floating point number
* latitude/longitude data pairs. Populates msg.location with these.
* Assumes that the msg object will always have exifData available as msg.exif.
* Assume that the GPS data saved into Exif provides a valid value
*/
function addMsgLocationDataFromExifGPSData(msg,val) {
if (msg.exif.GPSAltitude) {
/* istanbul ignore else */
if (!msg.location) { msg.location = {}; }
msg.location.alt = parseFloat(msg.exif.GPSAltitude);
}
if (msg.exif.GPSLatitudeRef && msg.exif.GPSLatitude && msg.exif.GPSLongitudeRef && msg.exif.GPSLongitude) { // location can be determined, OK
if (!msg.location) { msg.location = {}; }
msg.location.lat = msg.exif.GPSLatitude;
msg.location.lon = msg.exif.GPSLongitude;
if (msg.exif.GPSLatitudeRef == "South latitude") {
msg.location.lat *= -1;
}
if (msg.exif.GPSLongitudeRef == "West longitude") {
msg.location.lon *= -1;
}
}
else {
node.log("The location of this image cannot be determined safely so no location information has been added to the message.");
}
if (msg.location) {
msg.location.arc = {
ranges: [100,300,500],
pan: msg.exif.GPSImgDirection ?? msg.exif.GimbalYawDegree,
fov: (2 * Math.atan(36 / (2 * msg.exif.FocalLengthIn35mmFilm)) * 180 / Math.PI),
color: '#aaaa00'
}
msg.location.icon = "fa-camera fa-lg";
if (msg.exif.Make === "DJI") { msg.location.icon = "quad"; }
if (msg.exif.Make === "Potensic") { msg.location.icon = "quad"; }
if (msg.exif.Make === "Parrot") { msg.location.icon = "quad"; }
msg.location.iconColor = "orange";
var na;
var pop = "";
if (val.hasOwnProperty("name")) { na = val.name; }
else if (msg.hasOwnProperty("filename")) {
na = msg.filename.split('/').pop();
pop = "Timestamp: "+msg.exif.DateTimeOriginal+"<br/>";
}
else { na = msg.exif.Make+"_"+msg.exif.DateTimeOriginal; }
msg.location.name = na;
msg.location.layer = "Images";
if (msg.exif.ImageDescription) {
pop = "Caption: "+msg.exif.ImageDescription+"<br/>"+pop;
}
pop += '<img width="280" src="data:image/jpeg;base64,'+val.toString("base64")+'"/>'
if (msg.location.lat && msg.location.lon) {
pop += "<br/>Lat, Lon: "+msg.location.lat+", "+msg.location.lon;
}
msg.location.popup = pop;
}
}
this.on("input", function(msg) {
if (node.mode === "worldmap" && Buffer.isBuffer(msg.payload)) { node.property = "payload"; }
else if (node.mode === "worldmap" && (msg.payload.action !== "file" || msg.payload.type.indexOf("image") === -1)) { return; } // in case worldmap-in not filtered.
try {
var value = RED.util.getMessageProperty(msg,node.property);
if (value !== undefined) {
if (typeof value === "string") { // it must be a base64 encoded inline image type
if (value.indexOf('data:image') !== -1) {
value = new Buffer.from(value.replace(/^data:image\/[a-z]+;base64,/, ""), 'base64');
}
else {
value = new Buffer.from(value, 'base64');
}
}
if (Buffer.isBuffer(value)) { // or a proper image buffer
msg.exif = ExifReader.load(value);
for (const p in msg.exif) {
if (msg.exif.hasOwnProperty(p)) {
msg.exif[p] = msg.exif[p].description
if (!isNaN(Number(msg.exif[p]))) {
msg.exif[p] = Number(msg.exif[p])
}
}
}
if (msg.exif && msg.exif.hasOwnProperty("GPSLatitude") && msg.exif.hasOwnProperty("GPSLongitude")) {
addMsgLocationDataFromExifGPSData(msg,value);
}
if (node.mode === "worldmap") {
msg.payload = msg.location || {};
delete msg.location;
}
if (node.mode === "tak") {
msg.payload.exif = msg.exif || {};
delete msg.exif;
}
node.send(msg);
}
else {
node.error("Invalid payload received, the Exif node cannot proceed, no messages sent.",msg);
return;
}
}
else {
node.warn("No input received, the Exif node cannot proceed, no messages sent.",msg);
return;
}
}
catch (error) {
if (node.mode === "tak") {
node.send(msg);
return;
}
else {
node.error("An error occurred while extracting Exif information. Please check the log for details.",msg);
node.log('Error: '+error.message);
return;
}
}
});
}
RED.nodes.registerType("exif",ExifNode);
}