Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set GPS related exif tags? #674

Closed
Flajt opened this issue Aug 25, 2024 · 8 comments
Closed

How to set GPS related exif tags? #674

Flajt opened this issue Aug 25, 2024 · 8 comments

Comments

@Flajt
Copy link
Contributor

Flajt commented Aug 25, 2024

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.

@Flajt Flajt changed the title How to GPS related exif tags? How to set GPS related exif tags? Aug 26, 2024
@Flajt
Copy link
Contributor Author

Flajt commented Aug 26, 2024

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

@Flajt
Copy link
Contributor Author

Flajt commented Sep 1, 2024

See #677 for the PR

@spin7ion
Copy link
Contributor

spin7ion commented Oct 3, 2024

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;

@spin7ion
Copy link
Contributor

spin7ion commented Oct 3, 2024

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);
    }
  }

@Joshua-RF
Copy link

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!

@Flajt
Copy link
Contributor Author

Flajt commented Nov 12, 2024

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

@Flajt
Copy link
Contributor Author

Flajt commented Nov 22, 2024

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.

@Flajt
Copy link
Contributor Author

Flajt commented Nov 24, 2024

PR has been merged, I'll close this

@Flajt Flajt closed this as completed Nov 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants