UNPKG

exiftool-vendored

Version:
188 lines 8.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const node_child_process_1 = require("node:child_process"); const node_path_1 = require("node:path"); const node_util_1 = require("node:util"); const _chai_spec_1 = require("./_chai.spec"); const ExifTool_1 = require("./ExifTool"); const ExiftoolPath_1 = require("./ExiftoolPath"); const GeolocationTags_1 = require("./GeolocationTags"); const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile); async function getGeolocationTags(lat, lon) { const exiftool = await (0, ExiftoolPath_1.exiftoolPath)(); const { stdout } = await execFileAsync(exiftool, [ "-api", `geolocation=${lat},${lon}`, "-json", ]); const results = JSON.parse(stdout); return results[0]; } // Tags that are always returned by ExifTool for valid coordinates const alwaysReturnedTags = new Set([ "GeolocationBearing", "GeolocationCity", "GeolocationCountry", "GeolocationCountryCode", "GeolocationDistance", "GeolocationFeatureCode", "GeolocationFeatureType", "GeolocationPopulation", "GeolocationPosition", "GeolocationRegion", "GeolocationSubregion", "GeolocationTimeZone", ]); // Tags that may not be returned in normal results const optionalTags = new Set(["GeolocationWarning"]); describe("GeolocationTags", function () { this.timeout(10000); this.slow(2000); // Expected values from ExifTool - this validates tag name casing const sfExploratorium = { GeolocationBearing: 227, GeolocationCity: "Chinatown", GeolocationCountry: "United States", GeolocationCountryCode: "US", GeolocationDistance: "0.80 km", GeolocationFeatureCode: "PPLX", GeolocationFeatureType: "Section of Populated Place", GeolocationPopulation: 100000, GeolocationPosition: "37.7966, -122.4086", GeolocationRegion: "California", GeolocationSubregion: "City and County of San Francisco", GeolocationTimeZone: "America/Los_Angeles", GeolocationWarning: undefined, // Not returned for valid coordinates }; const eiffelTower = { GeolocationBearing: 319, GeolocationCity: "Neuilly-sur-Seine", GeolocationCountry: "France", GeolocationCountryCode: "FR", GeolocationDistance: "3.33 km", GeolocationFeatureCode: "PPL", GeolocationFeatureType: "Populated Place", GeolocationPopulation: 61000, GeolocationPosition: "48.8845, 2.2697", GeolocationRegion: "Île-de-France", GeolocationSubregion: "Hauts-de-Seine", GeolocationTimeZone: "Europe/Paris", GeolocationWarning: undefined, }; // Southern hemisphere test case const sydneyOperaHouse = { GeolocationBearing: 251, GeolocationCity: "The Rocks", GeolocationCountry: "Australia", GeolocationCountryCode: "AU", GeolocationDistance: "0.69 km", GeolocationFeatureCode: "PPLL", GeolocationFeatureType: "Populated Locality", GeolocationPopulation: 2100, GeolocationPosition: "-33.8592, 151.2083", GeolocationRegion: "New South Wales", GeolocationSubregion: "City of Sydney", GeolocationTimeZone: "Australia/Sydney", GeolocationWarning: undefined, }; const testLocations = [ { name: "SF Exploratorium", lat: 37.802078, lon: -122.4026305, expected: sfExploratorium, }, { name: "Eiffel Tower", lat: 48.8583736, lon: 2.2919064, expected: eiffelTower, }, { name: "Sydney Opera House", lat: -33.856784, lon: 151.215297, expected: sydneyOperaHouse, }, ]; for (const loc of testLocations) { describe(loc.name, () => { let result; before(async () => { result = await getGeolocationTags(loc.lat, loc.lon); }); it("returns expected tag values", () => { for (const tagName of GeolocationTags_1.GeolocationTagNames.values) { if (optionalTags.has(tagName)) continue; (0, _chai_spec_1.expect)(result[tagName]).to.eql(loc.expected[tagName], `Tag ${tagName} mismatch`); } }); it("all returned tag names match GeolocationTagNames casing", () => { const returnedKeys = Object.keys(result).filter((k) => k !== "SourceFile"); const unknownTags = []; const knownTagsSet = new Set(GeolocationTags_1.GeolocationTagNames.values); for (const key of returnedKeys) { if (!knownTagsSet.has(key)) { unknownTags.push(key); } } (0, _chai_spec_1.expect)(unknownTags).to.eql([], `ExifTool returned geolocation tags not in GeolocationTagNames: ${unknownTags.join(", ")}. ` + `This may indicate a casing mismatch or missing tags.`); }); it("all expected tags are returned by ExifTool", () => { const returnedKeys = new Set(Object.keys(result)); for (const tagName of alwaysReturnedTags) { (0, _chai_spec_1.expect)(returnedKeys.has(tagName)).to.eql(true, `Expected tag "${tagName}" not returned by ExifTool`); } }); }); } describe("reading from image file", () => { let et; before(() => { et = new ExifTool_1.ExifTool({ geolocation: true }); }); after(() => (0, _chai_spec_1.end)(et)); // Expected values when reading pixel.jpg with geolocation enabled // Note: GeolocationPosition format differs from raw exiftool output because // numericTags includes GeolocationPosition, so ExifTool uses -Tag# which // returns "lat lon" instead of "lat, lon" const pixelJpgExpected = { GeolocationBearing: 318, GeolocationCity: "El Granada", GeolocationCountry: "United States", GeolocationCountryCode: "US", GeolocationDistance: "2.60 km", GeolocationFeatureCode: "PPL", GeolocationFeatureType: "Populated Place", GeolocationPopulation: 5500, GeolocationPosition: "37.5027 -122.4694", GeolocationRegion: "California", GeolocationSubregion: "San Mateo County", GeolocationTimeZone: "America/Los_Angeles", GeolocationWarning: undefined, }; it("returns geolocation tags when reading pixel.jpg", async () => { const tags = await et.read((0, node_path_1.join)(_chai_spec_1.testDir, "pixel.jpg")); for (const tagName of GeolocationTags_1.GeolocationTagNames.values) { if (optionalTags.has(tagName)) continue; (0, _chai_spec_1.expect)(tags[tagName]).to.eql(pixelJpgExpected[tagName], `Tag ${tagName} mismatch`); } }); it("all returned geolocation tag names match GeolocationTagNames casing", async () => { const tags = await et.read((0, node_path_1.join)(_chai_spec_1.testDir, "pixel.jpg")); const returnedKeys = Object.keys(tags).filter((k) => k.startsWith("Geolocation")); const unknownTags = []; const knownTagsSet = new Set(GeolocationTags_1.GeolocationTagNames.values); for (const key of returnedKeys) { if (!knownTagsSet.has(key)) { unknownTags.push(key); } } (0, _chai_spec_1.expect)(unknownTags).to.eql([], `ExifTool returned geolocation tags not in GeolocationTagNames: ${unknownTags.join(", ")}`); }); }); }); //# sourceMappingURL=GeolocationTags.spec.js.map