I'm using the awesome MetadataExtractor NuGet package to extract some data from my png and jpg. It works like a charm.
Some of my pictures have missing date data, so I also developped a piece of code to add those. MetadataExtractor is not providing a EXIF Tag writing feature, so after some research, I came up with the ExifLibNet NuGet package.
Although it works perfectly with jpg files, this does not png files.
Here's my full (simple) code. If you want to try it out, just create a new MAUI .NET 7 Project, add the NuGet packages and the following use :
using ExifLibrary;
using MetadataExtractor;
using MetadataExtractor.Formats.Exif;
And the button clicked method :
private void OnCounterClicked(object sender, EventArgs e)
{
//string aFile = @"C:\Users\Beb\Google Drive\Python\EXIF Cleanup\NEW\2019_10_05_173730_JCS.JPG";
string aFile = @"C:\Users\Beb\Google Drive\Python\EXIF Cleanup\NEW\IMG-20230420-WA0001_TAGGED 15 04 2023 13 00 ANDROID.png";
// =====================================================================
// USING METADATAEXTRACTOR 2.7.2
// PART I : Extract all tags found with their values => WORKS
IEnumerable<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(aFile);
foreach (var directory in directories)
foreach (var tag in directory.Tags)
Debug.WriteLine($"{directory.Name} - {tag.Name} = {tag.Description}");
// PART II : Read specific DateTimeOriginal Tag => WORKS
IEnumerable<Directory> dir = ImageMetadataReader.ReadMetadata(aFile);
var subIfDir = dir.OfType<ExifSubIfdDirectory>().FirstOrDefault();
// DatetimeOriginal Tag = Exif SubIFD -Date / Time Original - 36867
var dtOriginal = subIfDir?.GetDescription(ExifDirectoryBase.TagDateTimeOriginal);
Debug.WriteLine($"Using MetadataExtractor, Date Time Original is : {dtOriginal.ToString()}"); // => In my test file 2023:04:15 13:00:00
// =====================================================================
// USING EXIFLIBNET 2.1.4
var img = ImageFile.FromFile(aFile);
// PART I : Extract all tags found with their values => WORKS for jpg, BUT for png, nothing found with a date time of 2023:04:15 13:00:00
foreach (ExifTag aTag in (ExifTag[])Enum.GetValues(typeof(ExifTag)))
{
ExifProperty exifTag = img.Properties.Get(aTag);
if (exifTag != null)
Debug.WriteLine($"{aTag.ToString()} ==> {exifTag.Value.ToString()}");
}
// PART II : Read specific DateTimeOriginal Tags to check if 2023:04:15 is found => WORKS for jpg, null for png
ExifProperty tagDT = img.Properties.Get(ExifTag.DateTime);
ExifProperty tagDTO = img.Properties.Get(ExifTag.DateTimeOriginal);
ExifProperty tagDTD = img.Properties.Get(ExifTag.DateTimeDigitized);
ExifProperty tagPNGCT = img.Properties.Get(ExifTag.PNGCreationTime);
Debug.WriteLine($"DateTime ==> {(tagDT == null ? "null" : tagDT.Value.ToString())}"); // => ok for jpg, null for png
Debug.WriteLine($"DateTime Original ==> {(tagDTO == null ? "null" : tagDTO.Value.ToString())}"); // => ok for jpg, null for png
Debug.WriteLine($"DateTime Digitzed ==> {(tagDTD == null ? "null" : tagDTD.Value.ToString())}"); // => ok for jpg, null for png
Debug.WriteLine($"DateTime PNG Creation Time ==> {(tagPNGCT == null ? "null" : tagPNGCT.Value.ToString())}"); // => ok for jpg, null for png
// PART III : Using ExifLibNet 2.1.4 : try to Write the tag with a new Date for possible ExifTag candidates :
DateTime newDate = new DateTime(2023, 04, 10, 13,37, 00);
img.Properties.Set(ExifTag.DateTime, newDate);
img.Properties.Set(ExifTag.DateTimeDigitized, newDate);
img.Properties.Set(ExifTag.DateTimeOriginal, newDate); // 236867
img.Properties.Set(ExifTag.PNGCreationTime, newDate);
img.Save(aFile);
// PART IV : Once saved, browse the tags again. Correct values shown for jpg, still nothing for png
img = ImageFile.FromFile(aFile);
foreach (ExifTag aTag in (ExifTag[])Enum.GetValues(typeof(ExifTag)))
{
ExifProperty exifTag = img.Properties.Get(aTag);
if (exifTag != null)
Debug.WriteLine($"{aTag.ToString()} ==> {exifTag.Value.ToString()}");
}
}
I thought it seemed that the tags ID for PNG files in ExifLibNet and MetadataExtract where different for DateTimeOriginal. From the https://exiv2.org/tags.html site, I found : 0x9003 36867 Image Exif.Image.DateTimeOriginal Ascii The date and time when the original image data was generated.
And when browsing the source code of ExifLibNet and MetadataExtract, I found : For ExifLibNet: DateTimeOriginal = 236867, For MetadataExtractor : TagDateTimeOriginal = 0x9003;
The '236867' has an additionnal '2' in front but still, the tags in ExifLibNet has additionnal ints before the real values, and I don't understand why it works with jpg but not with png...
I'm puzzled... Any ideas ?
I was able to change the PNG Create Time successfully but it wasn't the DateTime Original. It seems it's an issue with ExifLibNet. So I switched to the ImageSharp NuGet. It is very slow on Android, but it works.
Here's my code, if it can help anyone :
bool useExifLibNet = false;
// ExifLibNet version : works for windows, but do not with Android Gallery
if (useExifLibNet)
{
var filePng = ImageFile.FromFile(aDriveFile.FullPath);
filePng.Properties.Set(new PNGText(ExifTag.PNGCreationTime, "Creation Time", newDate.Value.ToString("yyyy:MM:dd HH:mm:ss"), false));
filePng.Save(aDriveFile.FullPath);
}
else
{
// ImageSharp version : works but VERY, VERY slow
using (var img = SixLabors.ImageSharp.Image.Load(aDriveFile.FullPath))
{
img.Metadata.ExifProfile.SetValue(SixLabors.ImageSharp.Metadata.Profiles.Exif.ExifTag.DateTimeOriginal, newDate.Value.ToString("yyyy:MM:dd HH:mm:ss"));
img.Save(aDriveFile.FullPath);
}
}