|
| 1 | +# Exif Tools |
| 2 | + |
| 3 | +This repository is a collection of the Exif Tools I wrote to manage my photo libraries a bit better. |
| 4 | + |
| 5 | +## Before running any of this, create backups of your photos |
| 6 | + |
| 7 | +I tested these tools on my personal files and all went well, but always be careful when it comes to your precious memories. |
| 8 | + |
| 9 | +## Prerequisites |
| 10 | + |
| 11 | +You need to use Node 20 (best installed using nvm). |
| 12 | +Then clone this repository and the install the dependencies with the command: |
| 13 | + |
| 14 | +``` |
| 15 | +npm ci |
| 16 | +``` |
| 17 | + |
| 18 | +After that you are ready to get started. |
| 19 | + |
| 20 | +## Current Tools |
| 21 | + |
| 22 | +### Google Maps -> Exif GPS Data |
| 23 | + |
| 24 | +If you took Photos in the past but did not enable Location Data in your Camera app but want it, this might help you. |
| 25 | +It analyzes your Google Maps Timeline and if it finds your location for Photos that do not have Exif GPS data yet, it will add it. |
| 26 | + |
| 27 | +The setup for this is a bit more involved due to the sheer amount of data you could get from the Google Maps Takeout. |
| 28 | + |
| 29 | +First get your Google Maps Location History takeout: |
| 30 | +https://takeout.google.com/ |
| 31 | + |
| 32 | +Location History (Timelime) is what you want. |
| 33 | +Deselect all the other options to avoid getting giant export. |
| 34 | + |
| 35 | +After you have received your export, download and extract it. |
| 36 | + |
| 37 | +The data we are interested in is the semantic location history and the raw records. |
| 38 | + |
| 39 | +First you probably have to split up your Records.json file. |
| 40 | +Due to limitations in nodejs, each file should not be bigger than 200MBs. |
| 41 | +I'd suggest to use a good text editor and just copying/pasting the values in the array into different files. |
| 42 | +The outcome files should have the array on a top level. eg. like this |
| 43 | + |
| 44 | +``` |
| 45 | +[{ |
| 46 | + latitudeE7: ..., |
| 47 | + longitudeE7: ..., |
| 48 | + ... |
| 49 | +}, {...}, {...}] |
| 50 | +``` |
| 51 | + |
| 52 | +After that we have to seed this data into an SQLite database, since the JSON format is just too inefficient to use it in the application. |
| 53 | + |
| 54 | +Go to seedDatabase.js and modify the paths provided as parameters in loadRecordFile([...]) to point to all recordsX.json files you have created previously. |
| 55 | + |
| 56 | +Then provide the semantic location history folder path to the findLocationFiles(...) function. |
| 57 | + |
| 58 | +After that we are ready to seed the database! |
| 59 | +Run the following commands |
| 60 | + |
| 61 | +``` |
| 62 | +# Create the Empty SQLite database |
| 63 | +npm run migrate-db |
| 64 | +# Add the JSON data to the database |
| 65 | +npm run seed-migration |
| 66 | +``` |
| 67 | + |
| 68 | +This should take a while depending on the amount of location data available. (I tested it with 14k Place Visits and 1.5 Million raw location records) |
| 69 | + |
| 70 | +When this script is done, the SQLite database is seeded properly with all your location data and we are ready to infuse your photos from that juicy GPS data. |
| 71 | + |
| 72 | +The steps before you now never need to do again, hurray! |
| 73 | + |
| 74 | +To now process your photos and add the GPS data, open up the index.js file. |
| 75 | +At the top of the file, add the paths to your photos to the photoLibs array. |
| 76 | +The script will check every image in that folder and add GPS data to it if: |
| 77 | + |
| 78 | +- it's a valid image file |
| 79 | +- it already has Exif data with the date the photo was taken |
| 80 | +- it does not already have GPS data (unless the GPS data comes from this script for reruns) |
| 81 | + |
| 82 | +Now run the script: |
| 83 | + |
| 84 | +``` |
| 85 | +node index.js |
| 86 | +``` |
| 87 | + |
| 88 | +Depending on the amount of images, this might take quite a bit of time. |
| 89 | +The script will output current status into your terminal. |
| 90 | + |
| 91 | +After it's done, it will also output a summary of the actions it took. |
| 92 | +Please check that to make sure nothing went horribly wrong. |
| 93 | + |
| 94 | +Your photos now have GPS Exif tags in them. |
| 95 | + |
| 96 | +### WhatsApp Images Date Taken |
| 97 | + |
| 98 | +By default WhatsApp strips any Exif Tags from Images that you receive/send. |
| 99 | +This might be a good thing for privacy, but if you also backup your WhatsApp images it can lead to the photo showing up at random days (depending on createdAt/modifiedAt timestamps). |
| 100 | + |
| 101 | +So this script will find all the WhatsApp Images (based on naming pattern) in the specified folders. |
| 102 | +Then for each it will parse the filename and set the Exif.Photo.DateTime tags to the day you have received/sent this image. |
| 103 | +It also looks at the modified date of the file and if it matches the date it will take over the time too. |
| 104 | +If the modifie date does not match up with the date parsed from the filename, it will default to 12:00. |
| 105 | + |
| 106 | +Right now it also simply hardcodes +02:00 timezone, so if you use this, be sure to change this to something sensible where you live. |
| 107 | + |
| 108 | +Additionally it adds "WhatsApp" as Exif.Image.Make tag, which usually contains the camera/phone model. To easier identify WhatsApp images in your photo library. |
| 109 | + |
| 110 | +Please Note: The original modified date of the file will not be changed, it will add the Exif Tags and then change the modified date to what it was before. |
| 111 | + |
| 112 | +Examples: |
| 113 | + |
| 114 | +- IMG-20170704-WA0000.jpg |
| 115 | + modified date 01.01.2019 17:45 |
| 116 | + => Exif Date: 04.07.2017 12:00 |
| 117 | + |
| 118 | +- IMG-20170704-WA0000.jpg |
| 119 | + modified date 04.07.2017 17:45 |
| 120 | + => Exif Date: 04.07.2017 17:45 |
| 121 | + |
| 122 | +To run the WhatsApp Image tool simply write: |
| 123 | + |
| 124 | +``` |
| 125 | +node whatsapp.js /PATH/TO/MY/WHATSAPP/FOLDER |
| 126 | +``` |
| 127 | + |
| 128 | +It should parse all the files in the folder which match the WhatsApp naming pattern and then get going. |
0 commit comments