image icon indicating copy to clipboard operation
image copied to clipboard

How to set GPS related exif tags?

Open Flajt opened this issue 1 year ago • 4 comments

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 avatar Aug 25 '24 16:08 Flajt

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 avatar Aug 26 '24 17:08 Flajt

See #677 for the PR

Flajt avatar Sep 01 '24 11:09 Flajt

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 avatar Oct 03 '24 01:10 spin7ion

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

spin7ion avatar Oct 03 '24 02:10 spin7ion

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!

Joshua-RF avatar Nov 11 '24 16:11 Joshua-RF

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 avatar Nov 12 '24 17:11 Flajt

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 avatar Nov 22 '24 18:11 Flajt

PR has been merged, I'll close this

Flajt avatar Nov 24 '24 09:11 Flajt