diff --git a/hugin-gopro-fusion/img/2015_01_02T10_10_53_GB120430_centre_de_briis_gopro_gopro_back - 2015_01_02T10_10_53_GF120430_centre_de_briis_gopro_gopro_front.jpg b/hugin-gopro-fusion/img/2015_01_02T10_10_53_GB120430_centre_de_briis_gopro_gopro_back - 2015_01_02T10_10_53_GF120430_centre_de_briis_gopro_gopro_front.jpg
deleted file mode 100644
index 81787bf7..00000000
Binary files a/hugin-gopro-fusion/img/2015_01_02T10_10_53_GB120430_centre_de_briis_gopro_gopro_back - 2015_01_02T10_10_53_GF120430_centre_de_briis_gopro_gopro_front.jpg and /dev/null differ
diff --git a/hugin-gopro-fusion/img/essai/GB080096.JPG b/hugin-gopro-fusion/img/essai/GB080096.JPG
new file mode 100644
index 00000000..a18fdf88
Binary files /dev/null and b/hugin-gopro-fusion/img/essai/GB080096.JPG differ
diff --git a/hugin-gopro-fusion/img/essai/GF080096.JPG b/hugin-gopro-fusion/img/essai/GF080096.JPG
new file mode 100644
index 00000000..854515c7
Binary files /dev/null and b/hugin-gopro-fusion/img/essai/GF080096.JPG differ
diff --git a/hugin-gopro-fusion/main.ts b/hugin-gopro-fusion/main.ts
new file mode 100644
index 00000000..9c4ab3aa
--- /dev/null
+++ b/hugin-gopro-fusion/main.ts
@@ -0,0 +1,342 @@
+/**
+ conversion de données gpx
+ conversion de données exif
+ **/
+
+// @ts-ignore
+import * as fs from 'node:fs';
+// @ts-ignore
+import path from "node:path";
+// @ts-ignore
+import minimist from 'minimist';
+// @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)
+ if (elem.length && elem[6]) {
+ let utc_time = new Date(elem[6] * 1000)
+
+ // console.log('utc_time', utc_time.toISOString())
+ track_points = `${track_points}
+ ${elem[2]}
+
+
+`
+ }else{
+ console.log('!!!!!! makeGpxFromKartaview no good element in gpx', elem)
+ }
+ })
+
+ 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(' makeGpxFromKartaview for sequence ', sequence_name)
+ 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()
+