UNPKG

image-classifier-ts

Version:

Command line tool to auto-classify images, renaming them with appropriate labels. Uses Node and Google Vision API.

174 lines 7.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MapDateToLocation = exports.AUTO_DATE_MAP_CSV_FILENAME = void 0; var fs = require("fs"); var path = require("path"); var ImageLocation_1 = require("../model/ImageLocation"); var CsvWriter_1 = require("./CsvWriter"); var FileUtils_1 = require("./FileUtils"); var SimpleDate_1 = require("./SimpleDate"); var DATE_MAP_CSV_FILENAME = "mapDateToLocation.csv"; exports.AUTO_DATE_MAP_CSV_FILENAME = "mapDateToLocation.auto.csv"; var MapDateToLocation = /** @class */ (function () { function MapDateToLocation() { this.mapDateToLocations = new Map(); this.mapExactDateToLocation = new Map(); } MapDateToLocation.parseFromCsvAtDirectory = function (pathToDirectory, options) { var filepath = path.join(pathToDirectory, DATE_MAP_CSV_FILENAME); return this.parseFromCsvAtPath(filepath, options); }; MapDateToLocation.parseFromCsvAtPath = function (filepath, options) { var map = new MapDateToLocation(); if (!fs.existsSync(filepath)) { return map; } // expected format: // // # Dates are US format // # Start Date, End Date, Location description // 10/07/2018,20/07/2018,Rotterdam var allText = fs.readFileSync(filepath, "utf8"); allText .split("\n") .map(function (l) { return l.trim(); }) .map(function (l, zeroBasedLineNo) { return { line: l, zeroBasedLineNo: zeroBasedLineNo }; }) .filter(function (l) { return !MapDateToLocation.isComment(l.line) && l.line.length > 0; }) .forEach(function (line) { var columns = line.line.split(",").map(function (c) { return c.trim(); }); var expectedColumns = 3; if (columns.length !== expectedColumns) { throw new Error("line ".concat(line.zeroBasedLineNo + 1, ": expected ").concat(expectedColumns, " columns but got ").concat(columns.length)); } var column = 0; var simpleStartDate = SimpleDate_1.SimpleDate.parseFromMDY(columns[column++]); var simpleEndDate = SimpleDate_1.SimpleDate.parseFromMDY(columns[column++]); var date = simpleStartDate; var location = columns[column++]; while (date.isLessThanOrEqualTo(simpleEndDate)) { map.addLocationForDate(date, ImageLocation_1.ImageLocation.fromGivenLocation(location, options)); date = date.nextDay(); } }); return map; }; MapDateToLocation.isComment = function (line) { return line.startsWith("#"); }; MapDateToLocation.prototype.writeToCsvAtPath = function (filePath) { var writer = new CsvWriter_1.CsvWriter(filePath); this.mapDateToLocations.forEach(function (value, key) { value.forEach(function (dateAndLocation) { writer.writeRow([ // File has a 'from' and 'to' date - simplest to just write out 1 row for each date: dateAndLocation.date.toString(), dateAndLocation.date.toString(), dateAndLocation.location.toString() ]); }); }); }; MapDateToLocation.prototype.removeFromDisk = function (filePath) { if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } }; MapDateToLocation.prototype.addLocationForDate = function (date, location, allowOverwrite) { if (allowOverwrite === void 0) { allowOverwrite = false; } // Dates should not be *exactly* identical if (this.mapExactDateToLocation.has(date.toString()) && !allowOverwrite) { throw new Error("Already have an entry for date ".concat(date.toString())); } if (!location || location.completionScore === 0) { throw new Error("No location set for date ".concat(date.toString())); } this.mapExactDateToLocation.set(date.toString(), location); var dateOnlyAsText = date.toStringDateOnly(); if (!this.mapDateToLocations.has(dateOnlyAsText)) { this.mapDateToLocations.set(dateOnlyAsText, []); } var dateAndLocationsThisDate = this.mapDateToLocations.get(dateOnlyAsText); dateAndLocationsThisDate.push({ date: date, location: location }); // sort for simpler searching: dateAndLocationsThisDate.sort(function (a, b) { return a.date.compareTo(b.date); }); }; MapDateToLocation.prototype.addLocationForDateAllowOverwrite = function (date, location) { this.addLocationForDate(date, location, true); }; MapDateToLocation.prototype.getLocationForDate = function (date) { if (this.mapExactDateToLocation.has(date.toString())) { return this.mapExactDateToLocation.get(date.toString()); } if (this.mapDateToLocations.has(date.toStringDateOnly())) { // Use case: mobile photos with locations are mixed in with non-mobile photos, // and we want to match the non-mobile photos to the closest mobile ones, to use the location. // // Use exact match OR else the closest match (before or after!) // // Assumptions: // - photos not taken around midnight // - processing timezone close to the timezone of the photos // alt solution: use a b-tree? var sameDates = this.mapDateToLocations.get(date.toStringDateOnly()); if (sameDates.length === 0) { return null; } var preceding = null; var following = null; // assumption: sameDates are sorted by time for (var _i = 0, sameDates_1 = sameDates; _i < sameDates_1.length; _i++) { var sameDate = sameDates_1[_i]; if (date.isGreaterThan(sameDate.date)) { preceding = sameDate; } if (!following && date.isLessThan(sameDate.date)) { following = sameDate; } // unlikely, but could happen if (sameDate.date.isEqualTo(date)) { return sameDate.location; } if (following) { break; } } if (preceding && !following) { return preceding.location; } if (!preceding && following) { return following.location; } if (preceding && following) { // Pick the closest: var timeAfterPreceding = Math.abs(date.compareTo(preceding.date)); var timeBeforeFollowing = Math.abs(following.date.compareTo(date)); if (timeAfterPreceding < timeBeforeFollowing) { return preceding.location; } return following.location; } return null; } return null; }; MapDateToLocation.prototype.getLocationForFile = function (filepath, outputter) { var modified = FileUtils_1.FileUtils.getModificationDateOfFile(filepath, outputter); var location = this.getLocationForDate(modified); outputter.infoVerbose(" location for file - date ".concat(modified.toString(), " = '").concat(location, "'")); return location; }; return MapDateToLocation; }()); exports.MapDateToLocation = MapDateToLocation; //# sourceMappingURL=MapDateToLocation.js.map