-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathphotos.js
188 lines (180 loc) · 6.88 KB
/
photos.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
const ExifImage = require('exif').ExifImage;
const imagenet = require("./imagenet.js")
const geoc = require('./reverse-geocode.js')
const natural = require('natural')
const {ipcMain} = require('electron');
const fs = require('fs')
class PhotoData {
constructor(path) {
this.path = path;
this.metadata = null;
this.imagenet = null;
this.location = null;
this.date = fs.statSync(path).ctime;
}
match(queries) {
if(queries === null) {
return 1;
}
var match_count = 0
for(let i in this.imagenet) {
let keyword = this.imagenet[i];
var hasTerms = false;
for(let j in queries){
let query = queries[j];
if(query.includes(":")){
// This is a special one.
let parts = query.split(/\s*:\s*/, 2)
let type = parts[0]
let value = parts[1]
if(type == "date") {
let date_search = new Date(value);
if(this.date !== null && !sameDay(date_search, this.date)) {
return 0;
}
}
if(type == "before") {
let date_search = new Date(value);
if(this.date !== null && date_search.getTime() < this.date.getTime()) {
return 0;
}
}
if(type == "after") {
let date_search = new Date(value);
if(this.date !== null && date_search.getTime() > this.date.getTime()) {
return 0;
}
}
}
else {
hasTerms = true;
if(natural.PorterStemmer.stem(query) == natural.PorterStemmer.stem(keyword)) {
match_count += 1
}
}
}
}
if(hasTerms) {
return match_count;
}
else {
return 1;
}
}
}
module.exports.Photos = class {
constructor(target) {
this.photos = new Map();
this.target = target;
this.query = null;
}
addPhoto(path) {
var photos = this.photos;
var target = this.target;
photos.set(path, new PhotoData(path));
var photo = photos.get(path);
photo.imagenet = null
target.send("update-images", [photo])
try {
new ExifImage({ image : path }, function (error, exifData) {
if (error)
console.log('Error: '+error.message);
else {
photo.metadata = exifData;
var gps_meta = exifData["gps"]
if("GPSLatitudeRef" in gps_meta && "GPSLatitude" in gps_meta && "GPSLongitudeRef" in gps_meta && "GPSLongitude" in gps_meta) {
var dms_lat = gps_meta["GPSLatitude"]
var dms_long = gps_meta["GPSLongitude"]
var latitude = Number(dms_lat[0]) + Number(dms_lat[1])/60 + Number(dms_lat[2])/3600
var longitude = Number(dms_long[0]) + Number(dms_long[1])/60 + Number(dms_long[2])/3600
if(gps_meta["GPSLatitudeRef"] == "S") {
latitude *= -1
}
if(gps_meta["GPSLongitudeRef"] == "W") {
longitude *= -1
}
photo.latitude = latitude;
photo.longitude = longitude
geoc.getLocation(latitude, longitude).then((e) => {
photo.location = e[0];
target.send("update-images", [photo])
})
}
if ("exif" in exifData && "DateTimeOriginal" in exifData.exif) {
let [year, month, day, hour, minute, second] = exifData.exif.DateTimeOriginal.split(/[ :]/);
photos.get(path).date = new Date(year, month-1, day, hour, minute, second)
}
target.send("update-images", [photo])
}
});
} catch (error) {
console.log('Error: ' + error.message);
}
imagenet.classify(path).then((e)=>{
let identified = [];
for(let i = 0; i<e.length; i++) { // Do we want to filter away low-probability identifications?
identified = identified.concat(e[i].class.split(", "));
}
photo.imagenet = identified;
if(identified.length == 0) {
console.log("aaa") // for some reason it doesn't work unless u log smth
photos.get(path).imagenet = ["no keyword matches :/"]
} else {
console.log("bb") // same thing
photos.get(path).imagenet = identified;
}
target.send("update-images", [photo])
}).catch((err)=>{
photo.imagenet = ["information unavailable :("]
target.send("update-images", [photo])
});
}
addPhotos(paths) {
for (path in paths) {
this.addImage(path);
}
}
// filter(query) {
// this.query = query;
// let results = [];
// for(const [path, photo] of this.photos.entries()){
// if(photo.match(natural.PorterStemmer.stem(query))){
// results.push(photo);
// }
// }
// this.target.send("replace-images", results);
// }
filter(query) {
// queries is an array of search terms, photopaths is an array of paths
// assuming photos.get(path).imagenet returns an array of keywords associated with photo
// returns a sorted array of paths
if(query == "") {
this.resetFilter();
return;
}
var queries = query.split(", ")
var matches = []
for(var [path, photo] of this.photos) {
let match_count = photo.match(queries);
if(match_count > 0) {
matches.push([match_count, photo])
}
}
matches = matches.sort(function(a, b) {
return b[0]-a[0]
})
for(var i=0; i<matches.length; i++) {
matches[i] = matches[i][1]
}
this.target.send("replace-images", matches);
}
resetFilter() {
this.target.send("replace-images", Array.from(this.photos.values()));
}
}
// Lifted from https://stackoverflow.com/questions/43855166/how-to-tell-if-two-dates-are-in-the-same-day
function sameDay(d1, d2) {
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
}