Copy link to clipboard
Copied
I am very new to working with metadata. I have a microsoft excel file with the IPTC Core fields I need for each image file.
(Creator, Headline, Description, Keywords, Title, Job Identifier, Credit Line, Source, Rights Usage Terms, Copyright Status and Copyright Notice)
Is there a way to get the metadata into the files without having to copy from a cell into each metadata field individually?
I am hoping some for sort of script, possibly...
Also, if only ONE of these fields needed updating in all of the files (i.e. Rights Usage Terms) can that be done?
I have Bridge 5.1 (and earlier versions CS3/CS4)
Perhaps try tab delimited format instead of comma separated value format.
Edit – Paul Riggott originally wrote the following instructions:
...
N.B. The first field in the input file MUST be the filename only IE:- CRW_0001.jpg
This script will allow you to choose the fields and order they are in within either your CSV or TEXT file so that you can input your metadata.
Fields available are:-
Keywords 1 - These are Keywords that are in ONE field seperated by semicolons
Keywords 2 - These are Key
Copy link to clipboard
Copied
SuperMerlin, quick question. The Latitude and Longitude are exact duplicates. But the formatting on the Altitude is different between the 2 columns. One has a preceding "+" and the other has a trailing " m"
+140.951
140.951 m
Will this change the script?
Copy link to clipboard
Copied
That is not shown in you example csv file, as they are both the same:-
DJI_0002.JPG,50,0.008,0.007,0.017,34.95187873,-89.93024736,+148.931,34.95187873,-89.930247 36,+148.931
The one starting with a plus would be the correct format.
So this is what it would require:-
DJI_0002.JPG,50,0.008,0.007,0.017,34.95187873,-89.93024736,+148.931
Hope this helps.
Copy link to clipboard
Copied
Hey SuperMerlin,
Sorry for the confusion. If a CSV file is opened in Excel and has a leading + it is not shown . I have copied the code you provided in post 105 exactly into my Bridge script. The first 10 records from my csv file is as follows (pasting from Notepad++):
DJI_0002.JPG,50,0.008,0.007,0.017,34.95187873,-89.93024736,+148.931
DJI_0003.JPG,50,0.008,0.007,0.017,34.95181193,-89.93017817,+149.19
DJI_0004.JPG,50,0.008,0.011,0.015,34.95176096,-89.93012334,+149.67
DJI_0005.JPG,50,0.008,0.006,0.015,34.95170888,-89.93005634,+149.769
DJI_0006.JPG,50,0.008,0.006,0.015,34.95165501,-89.92998616,+149.653
DJI_0007.JPG,50,0.008,0.007,0.016,34.95154082,-89.92984514,+149.955
DJI_0008.JPG,50,0.012,0.019,0.016,34.95148343,-89.92977355,+150.012
DJI_0009.JPG,50,0.008,0.007,0.016,34.95142627,-89.92969896,+149.788
DJI_0010.JPG,50,0.008,0.007,0.016,34.95136721,-89.92962243,+149.572
DJI_0011.JPG,50,0.008,0.006,0.015,34.95130963,-89.92954778,+149.635
When I open Bridge>Tools>Drone Metadata V3
Then select the CSV file, it sits there for 2-3 seconds and then Bridge closes.
Here is the link to 10 images that go with above data and the script I have in Bridge. Hoping you can see what might be wrong.
https://drive.google.com/open?id=1FyhO81Q6opxmj9fbPCzx8y4Gy1LzguAO
I am running this on Windows 10
Thank you for helping me on this!
Copy link to clipboard
Copied
SuperMerlin,
Just looking through the code (cross eyed!). On Line 40 Longitude is referenced in the JS as [Lng] where down below for the tags it is referenced as [Lon] . I could not tell if they should be the same or not.
tim
Copy link to clipboard
Copied
That variable is ok as it is in a function, so it makes it local to that function only.
I am also using Windows 10 and Bridge 9.0.2.219 X64 (Latest Bridge Version)
It took less than a second to process all ten files without any errors, also I was using your script.
What version of Bridge are you using?
Edit: I have just tested the script with Bridge CS3,CS5,CS6,CC2018 & CC2019 all took less than a second to process.
Copy link to clipboard
Copied
SuperMerlin,
The problem is related to the number of entries in the CSV file. It runs fine with 10 or 50 records in the CSV. But when I bump it up to 200 records it crashes. I did not work down to find the cutoff point but there is something in the processing that is crashing above a certain record count in the CSV file.
So not sure if the crash would be due to exceeding a length of time (processing time) or a number of records?
Copy link to clipboard
Copied
Interesting, I wonder if its a memory problem as It's loading all the details into memory?
Could you please try this version as it loads one line at a time and not the whole csv file.
Edit: Jive is messing the code up, you could try to get it from here:
https://drive.google.com/drive/folders/1TltVKMElWcahfDYDnNkaX8bjR1Qckrjt
#target bridge | ||
if( BridgeTalk.appName == "bridge" ) { | ||
var drone = new MenuElement( "command", "Drone Metadata V4", "at the end of Tools" ); | ||
} | ||
drone.onSelect = function () { | ||
var csvFile = File.openDialog("Open Comma-delimited File","comma-delimited(*.csv):*.csv;"); | ||
if (!csvFile.exists) return; | ||
var folder = Folder(app.document.thumbnail.path); | ||
if(!folder.exists){ | ||
log("You are not in a valid folder. Is this a collection?"); | ||
return; | ||
} | ||
csvFile.open('r'); | ||
while(!csvFile.eof){ |
strInputLine = csvFile.readln();
if(strInputLine.length < 5) continue;
var p = strInputLine.split(','); | ||
droneMetadata(trim(p[0]),trim(p[1]),trim(p[2]),trim(p[3]),trim(p[4]),trim(p[5]),trim(p[6]),trim(p[7])); |
}
csvFile.close();
alert("Batch complete\nDrone Error Log on Desktop\n If any errors occured"); | |
function trim(s){ | |
return s.replace(/^\s+|\s+$/g,''); | |
} | |
function log(message){ | |
var errorLog = File(Folder.desktop + "/Drone Error Log.txt"); | |
errorLog.open("a"); | |
errorLog.writeln(message); | |
errorLog.close(); | |
} |
function ddToDms(lat, lng) {
var lat = lat;
var lng = lng;
var latResult, lngResult, dmsResult;
lat = parseFloat(lat);
lng = parseFloat(lng);
latResult = getDms(lat);
latResult += (lat >= 0)? 'N' : 'S';
lngResult = getDms(lng);
lngResult += (lng >= 0)? 'E' : 'W';
dmsResult = [latResult, lngResult];
return dmsResult;
};
function getDms(val) {
var valDeg, valMin, valSec, result;
val = Math.abs(val);
valDeg = Math.floor(val);
result = valDeg + ",";
valMin = Math.floor((val - valDeg) * 60);
result += valMin + ".";
valSec = Math.round((val - valDeg - valMin / 60) * 3600 * 1000);
result += valSec.toString().match(/^\d{4}/);
return result;
};
function droneHeight(H){ | |
return Math.floor(H*1000).toString() + "/1000"; | |
} | |
function droneMetadata(th,Flag,StdLon,StdLat,StdHgt,Lat,Lon,Hgt){ | |
var file = new File(new Folder(folder)+ '/' + trim(th)); | |
if(!file.exists){ | |
log("File does not exist! " + trim(th)); | |
return; | |
} | |
var thumb = new Thumbnail(file); | |
md = thumb.synchronousMetadata; | |
if(thumb.hasMetadata){ | |
md.namespace = "http://www.dji.com/drone-dji/1.0/"; |
md.RtkFlag = '';
md.RtkFlag = Flag;
md.RtkStdLon = '';
md.RtkStdLon = StdLon;
md.RtkStdLat = '';
md.RtkStdLat = StdLat;
md.RtkStdHgt = '';
md.RtkStdHgt = StdHgt;
md.GpsLatitude = '';
md.GpsLatitude = Lat;
md.GpsLongitude = '';
md.GpsLongitude = Lon;
md.AbsoluteAltitude = '';
md.AbsoluteAltitude = Hgt;
var LatLon = ddToDms(Lon,Lat);
md.namespace = "http://ns.adobe.com/exif/1.0/";
md.GPSLatitude = '';
md.GPSLatitude = LatLon[0];
md.GPSLongitude = '';
md.GPSLongitude = LatLon[1];
md.GPSAltitude = '';
md.GPSAltitude = droneHeight(Hgt);
}else{ | ||
log("Cannot write metadata to " + decodeURI(thumb.spec)); | ||
} | ||
}; | ||
}; |
Copy link to clipboard
Copied
SuperMerlin,
The new script does not run either (with all records). I have been running this on my office PC. So I went and tried it on my new PC build for drone mapping and it did the same there. Nothing can slow that one down
This is my office PC. Should not have any memory issues. I am sure it is something simple. Just figuring out what that is may be a challenge.
Copy link to clipboard
Copied
I will try to generate a couple of hundred files to test and get back to you.
I am only useing a laptop ( I7 with 16Gb of memory) so it will be interesting
Copy link to clipboard
Copied
Here are all the images if you want to use them:
Copy link to clipboard
Copied
I have generated 300 files and can reproduce the problem, it seems the script is running too fast for Bridge to process the files and is just eating memory, so far I have managed to get it to update 300 files but then Bridge closes, so still working on it.
Copy link to clipboard
Copied
Please try this version, it works for me with 300 files.
#target bridge | ||
if( BridgeTalk.appName == "bridge" ) { | ||
var drone = new MenuElement( "command", "Drone Metadata V6", "at the end of Tools" ); | ||
} | ||
drone.onSelect = function () { |
try{
var csvFile = File.openDialog("Open Comma-delimited File","comma-delimited(*.csv):*.csv;"); | |
if (!csvFile.exists) return; | |
var folder = Folder(app.document.thumbnail.path); | |
if(!folder.exists){ | |
log("You are not in a valid folder. Is this a collection?"); | |
return; | |
} | |
csvFile.open('r'); | |
var csv = csvFile.read().split("\n"); |
var csvCount = csv.length;
var value = 0;
csv=null;
csvFile.close();
csvFile.open('r');
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
win = new Window("palette{text:'Please be patient...',bounds:[100,100,580,140]," +
"progress:Progressbar{bounds:[20,10,460,30] , minvalue:0,value:" + value + "}};" ); |
var d = win.graphics;
d.backgroundColor = d.newBrush(d.BrushType.SOLID_COLOR, [0.00, 0.00, 0.00, 1]);
win.progress.maxvalue =csvCount-2;
while(!csvFile.eof){
win.center(); | |
win.show(); |
strInputLine = csvFile.readln();
if(strInputLine.length < 5) continue;
var p = strInputLine.split(','); | |
droneMetadata(trim(p[0]),trim(p[1]),trim(p[2]),trim(p[3]),trim(p[4]),trim(p[5]),trim(p[6]),trim(p[7])); | |
win.progress.value++; | |
win.layout.layout(true); |
}
function trim(s){ | |
return s.replace(/^\s+|\s+$/g,''); | |
} | |
function log(message){ | |
var errorLog = File(Folder.desktop + "/Drone Error Log.txt"); | |
errorLog.open("a"); | |
errorLog.writeln(message); | |
errorLog.close(); | |
} |
function ddToDms(lat, lng) {
var lat = lat;
var lng = lng;
var latResult, lngResult, dmsResult;
lat = parseFloat(lat);
lng = parseFloat(lng);
latResult = getDms(lat);
latResult += (lat >= 0)? 'N' : 'S';
lngResult = getDms(lng);
lngResult += (lng >= 0)? 'E' : 'W';
dmsResult = [latResult, lngResult];
return dmsResult;
};
function getDms(val) {
var valDeg, valMin, valSec, result;
val = Math.abs(val);
valDeg = Math.floor(val);
result = valDeg + ",";
valMin = Math.floor((val - valDeg) * 60);
result += valMin + ".";
valSec = Math.round((val - valDeg - valMin / 60) * 3600 * 1000);
result += valSec.toString().match(/^\d{4}/);
return result;
};
function droneHeight(H){ | |
return Math.floor(H*1000).toString() + "/1000"; | |
} |
function droneMetadata(th,Flag,StdLon,StdLat,StdHgt,Lat,Lon,Hgt){
var file = new File(new Folder(folder)+ '/' + trim(th));
if(!file.exists){
log(decodeURI(file) + " does not exist"); | |
return; | |
} |
var selectedFile = new Thumbnail(new File(new Folder(folder)+ '/' + trim(th)));
app.synchronousMode = true;
var xmp = new XMPMeta(selectedFile.synchronousMetadata.serialize());
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","RtkFlag"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","RtkFlag",Flag); | ||
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","RtkStdLon"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","RtkStdLon",StdLon); | ||
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","RtkStdLat"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","RtkStdLat",StdLat); | ||
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","RtkStdHgt"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","RtkStdHgt",StdHgt); | ||
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","GpsLatitude"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","GpsLatitude",Lat); | ||
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","GpsLongitude"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","GpsLongitude",Lon); | ||
xmp.deleteProperty("http://www.dji.com/drone-dji/1.0/","AbsoluteAltitude"); | ||
xmp.setProperty("http://www.dji.com/drone-dji/1.0/","AbsoluteAltitude",Hgt); | ||
var LatLon = ddToDms(Lon,Lat); | ||
xmp.deleteProperty(XMPConst.NS_EXIF, "GPSLatitude"); | ||
xmp.setProperty(XMPConst.NS_EXIF, "GPSLatitude", LatLon[0]); | ||
xmp.deleteProperty(XMPConst.NS_EXIF, "GPSLongitude"); | ||
xmp.setProperty(XMPConst.NS_EXIF, "GPSLongitude", LatLon[1]); | ||
xmp.deleteProperty(XMPConst.NS_EXIF, "GPSAltitude"); | ||
xmp.setProperty(XMPConst.NS_EXIF, "GPSAltitude", droneHeight(Hgt)); |
var newPacket = xmp.serialize(XMPConst.SERIALIZE_USE_COMPACT_FORMAT);
selectedFile.metadata = new Metadata(newPacket);
}
}catch(e){log(e + "\n" + e.line);}
finally{
win.close(); | |
csvFile.close(); | |
alert("Batch complete\nDrone Error Log on Desktop\n If any errors occured"); | |
} |
};
Copy link to clipboard
Copied
Jive is playing up again. You can download the file from:
Copy link to clipboard
Copied
Houston, we have Lift-off!!
SuperMerlin, That worked perfectly and it was SMOKING fast! It was so fast that I thought it had failed to write the images. But I checked the first and last images and they are updated. So thank you SuperMerlin and also thank you Stephen for your help! This will help alot of drone mappers
I had 360 images. So soon I will try this on a larger data set of 500-600 images and then up to around 1500 images.
Copy link to clipboard
Copied
Great to hear that it works! I also fixed the problem that Lumigraphics pointed out using presentationPath.
Copy link to clipboard
Copied
yep, I failed to thank Lumigraphics as well. Ya'lls team effort got the problem solved.
Copy link to clipboard
Copied
Stephen,
I thought it was writing the GpsLongitude and GpsLatitude in DJI:XMP section but this morning that is not the case .
This is my modified script. Is GpsLongitude considered 'rational' or should it be something else?
%Image::ExifTool::UserDefined = (
'Image::ExifTool::DJI::XMP' => {
RtkFlag => { Writable => 'rational', },
RtkStdLon => { Writable => 'rational', },
RtkStdLat => { Writable => 'rational', },
RtkStdHgt => { Writable => 'rational', },
GpsLongitude => { Writable => 'rational', },
GpsLatitude => { Writable => 'rational', },
AbsoluteAltitude => { Writable => 'rational', },
},
);
SourceFile | RtkFlag | RtkStdHgt | RtkStdLat | RtkStdLon | GpsLongitude | GpsLatitude | AbsoluteAltitude |
M:\Midsouth360\Missions\PPK Test Missions\2018-12-22 Snowden PPK\P4P\DJI_0002.JPG | 16 | 0.008 | 0.007 | 0.017 | -89.93024736 | 34.95187873 | 148.931 |
When I export the meta data out using ExifToolGUI it is showing that the GpsLatitude and GpsLongitude are being updated in the EXIF section and not the DJI:DRONE XMP block. How do I force it to write this to the XMP block? Below I am showing output from 2 images. The First one is where I ran ExifTool to update. The SECOND one is from an original image that contains the data originally (from drone camera). I tried using Bridge to copy and paste the exif data but it does not contain seperate it by block type like the ExifTool-GUI does.
EDITED IMAGE DATA
---- ExifTool ----
ExifTool Version Number : 11.26
---- File ----
File Name : DJI_0002.JPG
Directory : .
File Size : 7.0 MB
File Modification Date/Time : 2019:02:08 08:48:12-06:00
File Access Date/Time : 2019:02:08 08:48:12-06:00
File Creation Date/Time : 2019:02:08 08:44:04-06:00
File Permissions : rw-rw-rw-
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Little-endian (Intel, II)
Image Width : 4864
Image Height : 3648
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Colour Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:2 (2 1)
---- EXIF ----
Image Description : DCIM\100MEDIA\DJI_0002.JPG
Make : DJI
Camera Model Name : FC6310
Orientation : Horizontal (normal)
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Software : v01.07.1641
Modify Date : 2018:12:22 13:00:29
Y Cb Cr Positioning : Centered
Exposure Time : 1/320
F Number : 5.6
Exposure Program : Program AE
ISO : 100
Exif Version : 0230
Date/Time Original : 2018:12:22 13:00:29
Create Date : 2018:12:22 13:00:29
Components Configuration : -, Cr, Cb, Y
Compressed Bits Per Pixel : 3.185197909
Shutter Speed Value : 1/320
Aperture Value : 5.6
Exposure Compensation : 0
Max Aperture Value : 2.8
Subject Distance : 0 m
Metering Mode : Center-weighted average
Light Source : Daylight
Flash : No flash function
Focal Length : 8.8 mm
Flashpix Version : 0010
Colour Space : sRGB
Exif Image Width : 4864
Exif Image Height : 3648
Interoperability Index : R98 - DCF basic file (sRGB)
Interoperability Version : 0100
Exposure Index : undef
File Source : Digital Camera
Scene Type : Directly photographed
Custom Rendered : Normal
Exposure Mode : Auto
White Balance : Auto
Digital Zoom Ratio : undef
Focal Length In 35mm Format : 24 mm
Scene Capture Type : Standard
Gain Control : None
Contrast : Normal
Saturation : Normal
Sharpness : Hard
Subject Distance Range : Unknown
Serial Number : d3ea87f35e1f17805c95a554bba186a4
GPS Version ID : 2.3.0.0
GPS Latitude Ref : North
GPS Latitude : 34.951879°
GPS Longitude Ref : West
GPS Longitude : 89.930247°
GPS Altitude Ref : Above Sea Level
GPS Altitude : 140.242 m
XP Comment : Type=N, Mode=P, DE=None
XP Keywords : v01.07.1641;1.2.0;v1.0.0
Compression : JPEG (old-style)
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Thumbnail Offset : 2336
Thumbnail Length : 10203
Thumbnail Image : (Binary data 10203 bytes, use -b option to extract)
---- MakerNotes ----
Make : DJI
Speed X : -1.90
Speed Y : +2.00
Speed Z : +0.00
Pitch : -21.20
Yaw : +137.20
Roll : +5.30
Camera Pitch : -90.00
Camera Yaw : +158.70
Camera Roll : +0.00
---- XMP ----
XMP Toolkit : Image::ExifTool 11.14
About : DJI Meta Data
Format : image/jpg
Absolute Altitude : 148931/1000
Calibrated Focal Length : 3666.666504
Calibrated Optical Center X : 2432.000000
Calibrated Optical Center Y : 1824.000000
Cam Reverse : 0
Flight Pitch Degree : -21.20
Flight Roll Degree : +5.30
Flight Yaw Degree : +137.20
Gimbal Pitch Degree : -90.00
Gimbal Reverse : 0
Gimbal Roll Degree : +0.00
Gimbal Yaw Degree : +158.70
Relative Altitude : +60.70
Rtk Flag : 16
Rtk Std Hgt : 0.008
Rtk Std Lat : 0.007
Rtk Std Lon : 0.017
Self Data : 5c1e897315c82b30b8b201c12.86.0
Make : DJI
Camera Model Name : FC6310
Create Date : 2018:12:22
Modify Date : 2018:12:22
Already Applied : False
Has Crop : False
Has Settings : False
Version : 7.0
---- MPF ----
MPF Version : 0010
Number Of Images : 2
MP Image Flags : Representative image, Dependent parent image
MP Image Format : JPEG
MP Image Type : Baseline MP Primary Image
MP Image Length : 7093497
MP Image Start : 0
Dependent Image 1 Entry Number : 0
Dependent Image 2 Entry Number : 2
MP Image Flags : Dependent child image
MP Image Format : JPEG
MP Image Type : Large Thumbnail (VGA equivalent)
MP Image Length : 248341
MP Image Start : 7082186
Dependent Image 1 Entry Number : 0
Dependent Image 2 Entry Number : 0
Image UID List : (Binary data 66 bytes, use -b option to extract)
Total Frames : 1
Preview Image : (Binary data 248341 bytes, use -b option to extract)
---- Composite ----
Aperture : 5.6
GPS Altitude : 140.2 m Above Sea Level
GPS Latitude : 34.951879° N
GPS Longitude : 89.930247° W
GPS Position : 34.951879° N, 89.930247° W
Image Size : 4864x3648
Megapixels : 17.7
Scale Factor To 35 mm Equivalent: 2.7
Shutter Speed : 1/320
Circle Of Confusion : 0.011 mm
Field Of View : 73.7 deg
Focal Length : 8.8 mm (35 mm equivalent: 24.0 mm)
Hyperfocal Distance : 1.26 m
Light Value : 13.3
-----------------------------------------------
IMAGE THAT CONTAINS PROPER TAGS FROM CAMERA SOURCE - note the Exif section has GPS all caps. In the Dji:Drone XMP block it is listed as Gps. Not sure if that is noteworthy or not.
---- ExifTool ----
ExifTool Version Number : 11.26
Warning : [minor] Possibly incorrect maker notes offsets (fix by 1783?)
---- File ----
File Name : Run2-1.JPG
Directory : .
File Size : 8.2 MB
File Modification Date/Time : 2019:01:23 10:03:58-06:00
File Access Date/Time : 2019:01:27 06:09:27-06:00
File Creation Date/Time : 2019:01:27 06:09:27-06:00
File Permissions : rw-rw-rw-
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Little-endian (Intel, II)
Image Width : 5472
Image Height : 3648
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Colour Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:2 (2 1)
---- EXIF ----
Image Description : DCIM\SURVEY\100_0003\DJI_0
Make : DJI
Camera Model Name : FC6310R
Orientation : Horizontal (normal)
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Software : v01.09.1672
Modify Date : 2019:01:18 12:52:17
Y Cb Cr Positioning : Centered
Exposure Time : 1/200
F Number : 4.5
Exposure Program : Program AE
ISO : 100
Exif Version : 0230
Date/Time Original : 2019:01:18 12:52:17
Create Date : 2019:01:18 12:52:17
Components Configuration : -, Cr, Cb, Y
Compressed Bits Per Pixel : 3.349885702
Shutter Speed Value : 1/200
Aperture Value : 4.5
Exposure Compensation : 0
Max Aperture Value : 2.8
Subject Distance : 0 m
Metering Mode : Center-weighted average
Light Source : Daylight
Flash : No flash function
Focal Length : 8.8 mm
Flashpix Version : 0010
Colour Space : sRGB
Exif Image Width : 5472
Exif Image Height : 3648
Interoperability Index : R98 - DCF basic file (sRGB)
Interoperability Version : 0100
Exposure Index : undef
File Source : Digital Camera
Scene Type : Directly photographed
Custom Rendered : Normal
Exposure Mode : Auto
White Balance : Manual
Digital Zoom Ratio : undef
Focal Length In 35mm Format : 24 mm
Scene Capture Type : Standard
Gain Control : None
Contrast : Normal
Saturation : Normal
Sharpness : Normal
Subject Distance Range : Unknown
Serial Number : e22046fd317a945a296c908cc97882fd
GPS Version ID : 2.3.0.0
GPS Latitude Ref : North
GPS Latitude : 52.393140°
GPS Longitude Ref : East
GPS Longitude : 12.605566°
GPS Altitude Ref : Above Sea Level
GPS Altitude : 165.779 m
XP Comment : Type=N, Mode=P, DE=None
XP Keywords : v01.09.1672;1.2.0;v1.0.0
Compression : JPEG (old-style)
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Thumbnail Offset : 10240
Thumbnail Length : 10303
Thumbnail Image : (Binary data 10303 bytes, use -b option to extract)
---- MakerNotes ----
Make : DJI
Speed X : +0.10
Speed Y : -0.40
Speed Z : +0.20
Pitch : -24.70
Yaw : -66.60
Roll : -5.00
Camera Pitch : -90.00
Camera Yaw : -73.10
Camera Roll : +0.00
---- XMP ----
About : DJI Meta Data
Modify Date : 2019:01:18
Create Date : 2019:01:18
Make : DJI
Camera Model Name : FC6310R
Format : image/jpg
Absolute Altitude : +165.78
Relative Altitude : +100.20
Gps Latitude : 52.39314042
Gps Longtitude : 12.60556568
Gimbal Roll Degree : +0.00
Gimbal Yaw Degree : -73.10
Gimbal Pitch Degree : -90.00
Flight Roll Degree : -5.00
Flight Yaw Degree : -66.60
Flight Pitch Degree : -24.70
Flight X Speed : +0.10
Flight Y Speed : -0.40
Flight Z Speed : +0.20
Cam Reverse : 0
Gimbal Reverse : 0
Self Data : Undefined
Calibrated Focal Length : 3666.666504
Calibrated Optical Center X : 2736.000000
Calibrated Optical Center Y : 1824.000000
Rtk Flag : 16
Rtk Std Lon : 1.85592
Rtk Std Lat : 1.25373
Rtk Std Hgt : 3.37184
Dewarp Data : 2018-09-08;3667.610000000000,3661.110000000000,-15.600000000000,5.370000000000,-0.268462000000,0.113513000000,-0.000452653000,-0.000422281000,-0.034791700000
Dewarp Flag : 0
Version : 7.0
Has Settings : False
Has Crop : False
Already Applied : False
---- MPF ----
MPF Version : 0010
Number Of Images : 2
MP Image Flags : Representative image, Dependent parent image
MP Image Format : JPEG
MP Image Type : Baseline MP Primary Image
MP Image Length : 8387621
MP Image Start : 0
Dependent Image 1 Entry Number : 0
Dependent Image 2 Entry Number : 2
MP Image Flags : Dependent child image
MP Image Format : JPEG
MP Image Type : Large Thumbnail (VGA equivalent)
MP Image Length : 256885
MP Image Start : 8387621
Dependent Image 1 Entry Number : 0
Dependent Image 2 Entry Number : 0
Image UID List : (Binary data 66 bytes, use -b option to extract)
Total Frames : 1
Preview Image : (Binary data 256885 bytes, use -b option to extract)
---- Composite ----
Aperture : 4.5
GPS Altitude : 165.7 m Above Sea Level
GPS Latitude : 52.393140° N
GPS Longitude : 12.605566° E
GPS Position : 52.393140° N, 12.605566° E
Image Size : 5472x3648
Megapixels : 20.0
Scale Factor To 35 mm Equivalent: 2.7
Shutter Speed : 1/200
Circle Of Confusion : 0.011 mm
Field Of View : 73.7 deg
Focal Length : 8.8 mm (35 mm equivalent: 24.0 mm)
Hyperfocal Distance : 1.56 m
Light Value : 12.0
Copy link to clipboard
Copied
I thought it was writing the GpsLongitude and GpsLatitude in DJI:XMP section but this morning that is not the case.
For the GPS group tags, try using ‘rational64s' in the .config file, while keeping 'rational' for the DJI group tags.
Copy link to clipboard
Copied
Will do
Copy link to clipboard
Copied
Stephen,
I misread your comment. The problem is that ExifTook is updating the existing GPS data in the EXIF block instead of adding new tags in the XMP block.
So for my example it should be adding this to the DJI:DRONE XMP block.
Gps Latitude : 34.951879°
Gps Longitude : 89.930247°
But instead it is updating the GPS tags that already exist in the EXIF block. If the solution is to update the one AND add the second I could . But Pix4D mapping software will be looking at the DJI:DRONE XMP tags to get the data it needs to map processing. So that is why I need to add it there.
When I look at the EXIF data (all blocks) for an image that was taken with a different model drone (the one I am trying to emulate), the GPS data is duplicated. It is in the EXIF block and it is also in the XMP block. Hope this helps clarify.
Copy link to clipboard
Copied
Edit: Your csv is using tag shortcuts, try using the explicit full group:tag instead.
Copy link to clipboard
Copied
Would I enter the tag in the CSV like this?
<drone-dji:GpsLongtitude>
Or do I leave the < > off?
drone-dji:GpsLongtitude
And would I also change this in the config file?
Copy link to clipboard
Copied
Here is the revised code, also added a bit of error checking this time.
Could you please test this now.
#target bridge
if( BridgeTalk.appName == "bridge" ) {
var drone = new MenuElement( "command", "Drone Metadata", "at the end of Tools" );
}
drone.onSelect = function () {
var csvFile = File.openDialog("Open Comma-delimited File","comma-delimited(*.csv):*.csv;");
if (!csvFile.exists) return;
csvFile.open('r');
var data = csvFile.read().split("\n");
csvFile.close();
var line = new Array();
for(var a in data){
var Q = data.toString();
if(Q.length > 2) line.push(Q);
}
for(var z in line){
var p=line
.split(','); droneMetadata(trim(p[0]),trim(p[1]),trim(p[2]),trim(p[3]),trim(p[4]));
}
alert("Batch complete\nDrone Error Log on Desktop\n If any errors occured");
function trim(s){
return s.replace(/^\s+|\s+$/g,'');
}
function log(message){
var errorLog = File(Folder.desktop + "/Drone Error Log.txt");
errorLog.open("a");
errorLog.writeln(message);
errorLog.close();
}
function droneMetadata(th,Flag,Lon,Lat,Hgt){
var file = new File(new Folder(app.document.presentationPath)+ '/' + trim(th));
if(!file.exists){
log("File does not exist! " + trim(th));
return;
}
var thumb = new Thumbnail(file);
md = thumb.synchronousMetadata;
if(thumb.hasMetadata){
md.namespace = "http://www.dji.com/drone-dji/1.0/";
md.RtkFlag = '';
md.RtkFlag = Flag;
md.RtkStdLon = '';
md.RtkStdLon = Lon;
md.RtkStdLat = '';
md.RtkStdLat = Lat;
md.RtkStdHgt = '';
md.RtkStdHgt = Hgt;
}else{
log("Cannot write metadata to " + decodeURI(thumb.spec));
}
};
};
Copy link to clipboard
Copied
Be careful with presentationPath. There are bugs that prevent it from working on certain folders such as the desktop, the script will crash if you reference one of them.
Copy link to clipboard
Copied
Hey SuperMerlin!
That worked, no lockup. However I updated the code to account for all fields but I ended up with GPS data in the XMP section instead of the EXIF section. Here is the modified code. Can you tell me where I made the booboo? Thanks for the updated code!
Rtk Flag : 16
Rtk Std Lon : 0.008
Rtk Std Lat : 0.007
Rtk Std Hgt : 0.017
GPS Latitude : 34.95187873
GPS Longitude : -89.93024736
GPS Altitude : 148.931
Version : 7.0
Has Settings : False
-------------------------------------------------------
SPECIAL NOTE: the Lat, Lon, Hgt now refer to the GPS coordinates, and StdLat, StdLon, StdHgt refer to the standard deviation (error accuracy value).
Also when looking at the modified EXIF data there is an error message at the top:
---- ExifTool ----
ExifTool Version Number : 11.26
Warning : [minor] Possibly incorrect maker notes offsets (fix by 1783?)
---- File ----
File Name : DJI_0002.JPG
--------------------------------------------------------
This is the CSV file that I used with script below. It contains all the data
Dropbox - Batch_Update_Bridge_7_fields.csv
#target bridge
if( BridgeTalk.appName == "bridge" ) {
var drone = new MenuElement( "command", "Drone Metadata", "at the end of Tools" );
}
drone.onSelect = function () {
var csvFile = File.openDialog("Open Comma-delimited File","comma-delimited(*.csv):*.csv;");
if (!csvFile.exists) return;
csvFile.open('r');
var data = csvFile.read().split("\n");
csvFile.close();
var line = new Array();
for(var a in data){
var Q = data.toString();
if(Q.length > 2) line.push(Q);
}
for(var z in line){
var p=line
.split(','); droneMetadata(trim(p[0]),trim(p[1]),trim(p[2]),trim(p[3]),trim(p[4]),trim(p[5]),trim(p[6]),trim(p[7]));
}
alert("Batch complete\nDrone Error Log on Desktop\n If any errors occured");
function trim(s){
return s.replace(/^\s+|\s+$/,'');
}
function log(message){
var errorLog = File(Folder.desktop + "/Drone Error Log.txt");
errorLog.open("a");
errorLog.writeln(message);
errorLog.close();
}
function droneMetadata(th,Flag,StdLon,StdLat,StdHgt,Lat,Lon,Hgt){
var file = new File(new Folder(app.document.presentationPath)+ '/' + trim(th));
if(!file.exists){
log("File does not exist! " + trim(th));
return;
}
var thumb = new Thumbnail(file);
md = thumb.synchronousMetadata;
if(thumb.hasMetadata){
md.namespace = "http://www.dji.com/drone-dji/1.0/";
md.RtkFlag = '';
md.RtkFlag = Flag;
md.RtkStdLon = '';
md.RtkStdLon = StdLon;
md.RtkStdLat = '';
md.RtkStdLat = StdLat;
md.RtkStdHgt = '';
md.RtkStdHgt = StdHgt;
md.GPSLatitude = '';
md.GPSLatitude = Lat;
md.GPSLongitude = '';
md.GPSLongitude = Lon;
md.GPSAltitude = '';
md.GPSAltitude = Hgt;
}else{
log("Cannot write metadata to " + decodeURI(thumb.spec));
}
};
};