How to set GPS related exif tags?
Hello, first of all, a nice package for the exif-related parts of images (I'm dying to try and save a small amount of data).
I want to save a GPSLongitude & GPSLatitude tag in my jpg file.
However, I can't get it to work:
I tried:
// with and without toString()
image.exif.gpsIfd[0x0002] = locationModel.latitude.toString();
image.exif.gpsIfd[0x0004] = locationModel.longitude.toString();
// Also for latitude ofc
image.exif.gpsIfd["GPSLongitude"] = locationModel.longitude.toString();
// With the imageIfd
image.exif.imgIfd["GPSLongitude"] = locationModel.longitude.toString();
// With the imageIfd and hex value
image.imageifd.gpsIfd[0x0004] = locationModel.longitude.toString();
The GPSOffset is being calculated an added, but not my Coordinates : /
Here a the map containg the data that is added (I anonymized some stuff):
{271: Apple, 272: iPhone ****, 282: 72/1, 283: 72/1, 296: 2, 305: Decentproof 1.0.0, 306: ****, 316: iPhone ****, 34665: 236, 37510: <data>, 34853: 2264}
The gpsIfd is just empty.
I've considered forking and extending the setters like userComment etc. but idk if that would resolve it. Since I'm not yet 100% understanding the codebase.
Found it, will open a fork and send a PR with the changes. (I'll keep the issue open until then)
For anyone in dire need see the methods below:
bool get hasGPSLatitude => data.containsKey(0x0002);
double? get gpsLatitude => data[0x0002]?.toDouble();
set gpsLatitude(double? value) {
if (value == null) {
data.remove(0x0002);
} else {
data[0x0002] = IfdValueDouble(value);
}
}
bool get hasGPSLongitude => data.containsKey(0x0004);
double? get gpsLongitude => data[0x0004]?.toDouble();
set gpsLongitude(double? value) {
if (value == null) {
data.remove(0x0004);
} else {
data[0x0004] = IfdValueDouble(value);
}
}
Just add them to the ifd_directory.dart and you should be good
See #677 for the PR
Found it, will open a fork and send a PR with the changes. (I'll keep the issue open until then)
For anyone in dire need see the methods below:
bool get hasGPSLatitude => data.containsKey(0x0002); double? get gpsLatitude => data[0x0002]?.toDouble(); set gpsLatitude(double? value) { if (value == null) { data.remove(0x0002); } else { data[0x0002] = IfdValueDouble(value); } } bool get hasGPSLongitude => data.containsKey(0x0004); double? get gpsLongitude => data[0x0004]?.toDouble(); set gpsLongitude(double? value) { if (value == null) { data.remove(0x0004); } else { data[0x0004] = IfdValueDouble(value); } }Just add them to the ifd_directory.dart and you should be good
For those of you who tries to change coords it is:
image.exif.gpsIfd.gpsLatitude=43.303083; image.exif.gpsIfd.gpsLongitude=5.378229;
If anyone need also to chage GPS times here is code like @Flajt made
bool get hasGPSDate => data.containsKey(0x001D);
String? get gpsDate => data[0x001D]?.toString();
set gpsDate(String? value) {
if (value == null) {
data.remove(0x001D);
} else {
data[0x001D] = IfdValueAscii(value);
}
}
Found it, will open a fork and send a PR with the changes. (I'll keep the issue open until then)
For anyone in dire need see the methods below:
bool get hasGPSLatitude => data.containsKey(0x0002); double? get gpsLatitude => data[0x0002]?.toDouble(); set gpsLatitude(double? value) { if (value == null) { data.remove(0x0002); } else { data[0x0002] = IfdValueDouble(value); } } bool get hasGPSLongitude => data.containsKey(0x0004); double? get gpsLongitude => data[0x0004]?.toDouble(); set gpsLongitude(double? value) { if (value == null) { data.remove(0x0004); } else { data[0x0004] = IfdValueDouble(value); } }Just add them to the ifd_directory.dart and you should be good
Hello, I have expanded upon your code as it wasn't fully complete, please consider updating your submitted PR.
import 'package:image/image.dart';
extension IfdDirectoryExtension on IfdDirectory {
bool get hasGPSLatitudeRef => data.containsKey(0x0001);
bool get hasGPSLatitude => data.containsKey(0x0002);
bool get hasGPSLongitudeRef => data.containsKey(0x0003);
bool get hasGPSLongitude => data.containsKey(0x0004);
String? get gpsLatitudeRef => data[0x0001]?.toString();
double? get gpsLatitude => data[0x0002]?.toDouble();
String? get gpsLongitudeRef => data[0x0003]?.toString();
double? get gpsLongitude => data[0x0004]?.toDouble();
bool get hasGPSDate => data.containsKey(0x001D);
set gpsLatitudeRef(String? value) {
if (value == null) {
data.remove(0x0001);
} else {
data[0x0001] = IfdValueAscii(value);
}
}
set gpsLatitude(double? value) {
if (value == null) {
data.remove(0x0002);
} else {
data[0x0002] = IfdValueDouble(value);
}
}
set gpsLongitudeRef(String? value) {
if (value == null) {
data.remove(0x0003);
} else {
data[0x0003] = IfdValueAscii(value);
}
}
set gpsLongitude(double? value) {
if (value == null) {
data.remove(0x0004);
} else {
data[0x0004] = IfdValueDouble(value);
}
}
// set both latitude and longitude at the same time
void setGpsLocation({
required double latitude,
required double longitude,
}) {
gpsLatitude = latitude.abs();
gpsLongitude = longitude.abs();
gpsLatitudeRef = latitude < 0.0 ? 'S' : 'N';
gpsLongitudeRef = longitude < 0.0 ? 'W' : 'E';
}
}
The longitude and latitude cannot be negative, and the refs must be included as these are responsible for the polar directions. I have encoded a jpeg image, and uploaded this and you can see the location is correct (previously it was incorrect taking me to a location in Belgium). For reference see exiftool to understand EXIF standards and EXIF information.
Hope this helps!
Thanks both of you, I'll update it this week. Will post here as soon as its done. EDIT: And thanks for the in depth explanation
So after nearly forgetting it, I've added the changes, just need to check if it works, bc I did it on the fly in the github editor. EDIT: I think it works as it should.
PR has been merged, I'll close this