/** conversion de données gpx conversion de données exif **/ // @ts-ignore import piexif from 'piexif'; import * as fs from 'node:fs'; // @ts-ignore import path from "node:path"; // @ts-ignore import minimist from 'minimist'; import * as Buffer from "buffer"; // @ts-ignore const moment = require( "moment"); // configs let sequence_name: string = '3596977' let folders_list_txt: any = [ "3596249", "3596253", "3596977", "3675557", "3675577", "3716345", "4456921", "4457241", "4457257", // "4457273", // à récupérer "4457289", "4457689", "4457705", "4539913", "4539929", "4539945", "4559529", "4559545", "4559561", "4559577", "4559593", "4559609", "4559625", "4559641", "4559657", "4559673", "4559689", "4559705", "4559721", "4559737", "4559753", "4559769", "4559785", "4559801", "4559817", "4559833", "4559849", "4559865", "4904153", "4904233", "4904249", "4904265", "4904281", "4904297", "4904313", "4904329", "4904345", "4904361", "4904377", "4904393", "5192937", "5193161", "5193177", "5193193", "5193209", "5193225", "5193321", "5193337", "5193417", "5193433", // "5193449", "5201385", "5213385", "5213481", "5213529", "5234665", "5234857", "5234889", "5235001", "5324265", "5775977", "5775993", // "5776009", "5776025", "6081417", "6081433", "6081449", "6081465", "6081689", "6081705", "6092281", "6092313", "6101305", "6102457", "6102473", "6102489", // "6102521", "6102537", "6102569", "6127433", "6133465", "6242729", "6329129", "6329177", "6329241", "6329305", "6329321", "6738633", "6738809", "6738953", "6752761", "6752889", "6752905", "6752921", "6752937", "6752953", "6760985", "6761049", "6761289", "6794633", "7325929", "7326457", "7328265", "7330009", "7330025", "7330041", "7330057" ] let enable_write_gpx_file = true; let just_one_photo_in_folder = false; let folder = "/home/poule/encrypted/stockage-syncable/photos/imagerie kartaview carto tel/kartaview_export_storage/share2tykayn/" let folder_photos = folder+"photo" let dossier_gpx: string = "./output_gpx" let file_gpx: string = "3596249_d875a_60a0f9bf38f99.txt" let mini_arguments: any = minimist(process.argv.slice(2)) console.log('mini_arguments', mini_arguments) if (mini_arguments['sequence']) { sequence_name = mini_arguments['sequence'] } if (mini_arguments['folder']) { folder = mini_arguments['folder'] } if (mini_arguments['gpx-output']) { dossier_gpx = mini_arguments['gpx-output'] } if (mini_arguments['gpx-input']) { file_gpx = mini_arguments['gpx-input'] } // let dossier_photo: string = folder + "test_photo_apply" let dossier_photo: string = folder_photos let dossier_gpx_input: string = folder + "metadata_file" let path_gpx_input: string = dossier_gpx_input + "/" + sequence_name + "/" + file_gpx if (mini_arguments['gpx-input-path']) { path_gpx_input = mini_arguments['gpx-input-path'] } let gpxData: any = {} let exif_commands:any = ['#!/bin/bash' ,'# apply exif data to photos'] function makeGpxFromKartaview(tableKartaviewTrace: any) { console.log('make gpx') let track_points: string = ''; tableKartaviewTrace.forEach((elem: any) => { // console.log('elem', elem) // console.log('elem', elem[6] *1000) let utc_time = new Date(elem[6] * 1000) // console.log('utc_time', utc_time.toISOString()) track_points = `${track_points} ${elem[2]} ` }) let content = ` trace_gpx_de_demo somebody 2023 https://creativecommons.org/licenses/by-sa/2.5 nada ${track_points} ` return content; } function reduceGpxPointsToInterval(sequence_name: any) { let photos_count_in_sequence = photo_folders_counter[sequence_name].length let interval = Math.round(gpxData[sequence_name].length / photos_count_in_sequence) let ii = 1; console.log('--------- sequence_name', sequence_name) console.log('--------- nombre de photos ', photos_count_in_sequence) console.log('--------- nombre de points gpx ', gpxData[sequence_name].length) console.log('--------- interval: prendre une donnée gps tous les ', interval, 'points de la trace de séquence') let jj = 0 let photo_counter = 0 gpxData[sequence_name].forEach((elem: any) => { // only work on an interval of files to assign gps coordinates jj++ ii-- if (ii <= 0) { // set the gps coordinates to the picture in sequence let timestamp = elem[6] * 1000 let lat = elem[0] let lon = elem[1] let date = new Date(timestamp) let date_simezone_indicator = ''; // +2:00 let iso = moment(date).format('YYYY:MM:DD HH:mm:ss')+date_simezone_indicator ii = interval * 1 let file_photo_name = photo_folders_counter[sequence_name][photo_counter] if (file_photo_name) { // set exif data // console.log('file_photo_name to apply exif data', photo_counter, file_photo_name) // -File:ModificationDateTime=="${iso}" \\ // -File:CreateDate="${iso}" \\ let exif_command= `\n exiftool -overwrite_original \\ -GPSDateTime="${iso}" \\ -AllDates="${iso}" \\ -MediaCreateDate="${iso}" \\ -MediaModifyDate="${iso}" \\ -TrackCreateDate=="${iso}" \\ -TrackModifyDate=="${iso}" \\ -GPSLongitude="${lon}" \\ -GPSLatitude="${lat}" \\ "${dossier_photo+'/'+sequence_name+'/'+file_photo_name}" ` // -GPSLongitudeRef="West" \ // -GPSLatitudeRef="North" \ // exiftool -overwrite_original '-AllDates { if (err) { throw err; } const gpx_content = data; let lines = gpx_content.split('\n') console.log('lines.length', lines.length) let tableKartaviewTrace: any = []; // loop on all lines, only take the lines that contain :g: lines.forEach((elem: any) => { if (elem.indexOf(":g:") > -1) { // do stuff on gpxData to enrich it let boom = elem.split(':') let timestamp = boom[0] let gpsmodel = boom[2] let gps = gpsmodel.split(';') gps.push(timestamp) tableKartaviewTrace.push(gps) // let date = new Date(boom[0] * 1000) // console.log('*', date, gps[0], gps[1]) } }) gpxData[sequence_name] = [...tableKartaviewTrace] // console.log('gpxData', gpxData) let content_gpx = makeGpxFromKartaview(tableKartaviewTrace) if (enable_write_gpx_file) { writeFile('' + fileName + '_trace.gpx', content_gpx) } if (Object.keys(gpxData).length === folders_list_txt.length) { gather() } // console.log('gpx_content', gpx_content) }) } let cwd = path.dirname(process.cwd()) + '/' + path.basename(process.cwd()) /** * get a list of all files in a path * @param folderPath */ async function getAllFilesInFolder(folderPath: string) { let filesList: any = [] console.log('------ reading folder ', folderPath) filesList = fs.readdirSync(folderPath); if (just_one_photo_in_folder) { filesList = [filesList.shift()] } return filesList; } function writeFile(fileName: string, fileContent: any) { console.log('write file', fileName) return fs.writeFile( `${dossier_gpx}/${fileName}`, fileContent, 'utf8', (err) => { if (err) { console.log(`Error writing file: ${err}`) } } ) } let photo_folders_counter: any = {} function listPhotos(sequence_number: string) { console.log('------- listPhotos dossier_photo', dossier_photo + '/' + sequence_number) let photo_folder = dossier_photo + '/' + sequence_number; getAllFilesInFolder(photo_folder) .then(listOfFiles => { photo_folders_counter[sequence_number] = listOfFiles }) } async function getGPXAndEnrichExifOfPhotosInFolder(sequence_number: string) { // get metadata txt file in metadata folder getAllFilesInFolder(dossier_gpx_input + '/' + sequence_number) .then(listOfFiles => { console.log('listOfFiles', listOfFiles.length) // console.log('listOfFiles', listOfFiles) listOfFiles.forEach((jpg_file: string) => { openKartaviewTxtGPX(dossier_gpx_input + '/' + sequence_number + '/' + jpg_file, sequence_number) }) }, err => { throw new Error(err) }) listPhotos(sequence_number) } /** * runs after all sequences have gotten their photo and gpx data */ function gather() { // console.log('gpxData', gpxData) console.log('sequences', folders_list_txt) folders_list_txt.forEach((sequence: string) => { reduceGpxPointsToInterval(sequence) }) } function main() { console.log('dossiers à traiter: ', folders_list_txt.length) folders_list_txt.forEach((elem: string) => { getGPXAndEnrichExifOfPhotosInFolder(elem).then(r => { console.log('r', r) } ) }) } // run it all main()