image-classifier-ts
Version:
Command line tool to auto-classify images, renaming them with appropriate labels. Uses Node and Google Vision API.
146 lines • 5.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExifUtils = exports.ExifTagSet = exports.ExifTag = void 0;
var fs = require("fs");
var path = require("path");
var Verbosity_1 = require("./output/Verbosity");
var SimpleDate_1 = require("./SimpleDate");
// To solve warning from exifreader
global.DOMParser = require("xmldom").DOMParser;
var exifReader = require("exifreader");
// Interesting subset of exif tags
var ExifTag;
(function (ExifTag) {
ExifTag["ApertureValue"] = "ApertureValue";
ExifTag["ColorSpace"] = "ColorSpace";
ExifTag["DateTime"] = "DateTime";
ExifTag["FocalLength"] = "FocalLength";
ExifTag["GPSAltitude"] = "GPSAltitude";
ExifTag["GPSAltitudeRef"] = "GPSAltitudeRef";
ExifTag["GPSDateStamp"] = "GPSDateStamp";
ExifTag["GPSLatitude"] = "GPSLatitude";
ExifTag["GPSLatitudeRef"] = "GPSLatitudeRef";
ExifTag["GPSLongitude"] = "GPSLongitude";
ExifTag["GPSLongitudeRef"] = "GPSLongitudeRef";
ExifTag["ISOSpeedRatings"] = "ISOSpeedRatings";
ExifTag["Orientation"] = "Orientation";
ExifTag["ShutterSpeedValue"] = "ShutterSpeedValue";
})(ExifTag = exports.ExifTag || (exports.ExifTag = {}));
var KNOWN_LATITUDE_FORMAT = "North latitude";
var KNOWN_LONGITUDE_FORMAT = "East longitude";
var DUMP_INDENT = " ";
var ExifTagSet = /** @class */ (function () {
function ExifTagSet() {
this.map = new Map();
}
ExifTagSet.fromTags = function (tags, outputter) {
var interestingTags = Object.keys(ExifTag);
var tagSet = new ExifTagSet();
interestingTags.forEach(function (tag) {
var value = tags[tag] ? tags[tag].description : null;
if (value) {
tagSet.map.set(tag, value);
}
});
if (outputter.verbosity === Verbosity_1.Verbosity.High) {
tagSet.dump(outputter);
}
return tagSet;
};
ExifTagSet.prototype.dump = function (outputter) {
var _this = this;
this.map.forEach(function (value, key) {
_this.dumpTag(key, value, outputter);
});
outputter.infoMediumVerbose("".concat(DUMP_INDENT, "lat/longs"), this.isLatLongOk() ? "[ok]" : "[unknown format]");
};
ExifTagSet.prototype.dumpTag = function (tag, value, outputter) {
outputter.infoMediumVerbose("".concat(DUMP_INDENT).concat(tag, " = ").concat(value));
};
ExifTagSet.prototype.get = function (tag) {
if (!this.map.has(tag)) {
return null;
}
return this.map.get(tag);
};
ExifTagSet.prototype.getDateStamp = function () {
// issue: some images have valid DateTime, but GPSDateStamp is in the future!
// so, parse both and try to pick the best one:
var dates = this.getAvailableDateStamps();
var now = new Date();
var nowSimple = SimpleDate_1.SimpleDate.fromDate(now);
var validDates = dates.filter(function (d) { return d.year <= nowSimple.year && d.year > 1970; });
return validDates[0] || null;
};
ExifTagSet.prototype.getAvailableDateStamps = function () {
return [
this.tryGetExifDateStamp(ExifTag.GPSDateStamp),
this.tryGetExifDateStamp(ExifTag.DateTime),
].filter(function (d) { return !!d; });
};
ExifTagSet.prototype.tryGetExifDateStamp = function (tag) {
var dateValueYMD = this.tryGet(tag);
if (!dateValueYMD) {
return null;
}
// 'Y:M:D' OR 'Y:M:D H:M:S'
return SimpleDate_1.SimpleDate.parseFromExifDate(dateValueYMD);
};
ExifTagSet.prototype.tryGet = function (tag) {
if (this.map.has(tag)) {
return this.get(tag);
}
return null;
};
ExifTagSet.prototype.isLatLongOk = function () {
var lat = this.get(ExifTag.GPSLatitude);
var long = this.get(ExifTag.GPSLongitude);
return (lat !== null &&
long !== null &&
this.get(ExifTag.GPSLatitudeRef) === KNOWN_LATITUDE_FORMAT &&
this.get(ExifTag.GPSLongitudeRef) === KNOWN_LONGITUDE_FORMAT);
};
return ExifTagSet;
}());
exports.ExifTagSet = ExifTagSet;
var ExifUtils;
(function (ExifUtils) {
function readFile(filepath, outputter) {
if (!hasFileExif(filepath)) {
return null;
}
var buffer = fs.readFileSync(filepath);
try {
var tags = exifReader.load(buffer.buffer);
deleteUnusedTags(tags);
return ExifTagSet.fromTags(tags, outputter);
}
catch (error) {
if (error.name === "MetadataMissingError") {
return null;
}
outputter.error("exif error", filepath, error);
throw error;
}
}
ExifUtils.readFile = readFile;
var DELETED = {};
function deleteUnusedTags(tags) {
// The MakerNote tag can be really large. Remove it to lower memory
// usage if you're parsing a lot of files and saving the tags.
tags["MakerNote"] = DELETED;
// also delete any props that start with 'undefined-
Object.keys(tags)
.filter(function (t) { return t.startsWith("undefined"); })
.forEach(function (t) {
tags[t] = DELETED;
});
}
function hasFileExif(filepath) {
var extension = path.extname(filepath).toLowerCase();
// ExifReader supports JPEG.
// note: some PNG files can have some EXIF data but it's not yet standard.
return [".jpg", ".jpeg"].includes(extension);
}
})(ExifUtils = exports.ExifUtils || (exports.ExifUtils = {}));
//# sourceMappingURL=ExifUtils.js.map