Recursive AI

Read EXIF data in C#

All oneimage recipes

Call Image.Identify(path).Metadata.ReadExif(). It reads only the file headers and returns the common EXIF fields (camera, capture time, orientation, GPS position in decimal degrees), or null when the file has no EXIF block. The program below reads a Nikon photo with GPS from the public exif-samples collection.

Terminal
dotnet new console -o ReadExif && cd ReadExif
dotnet add package RecursiveAI.OneImage --version 1.10.4
repo=https://raw.githubusercontent.com/ianare/exif-samples/master
curl -L -o gps.jpg $repo/jpg/gps/DSCN0010.jpg

OneImage needs the .NET 10 SDK. Put this in Program.cs and run dotnet run:

C#
using OneImage;
 
ExifData? exif = Image.Identify("gps.jpg").Metadata.ReadExif();
if (exif is null)
{
    Console.WriteLine("No EXIF block.");
    return;
}
 
Console.WriteLine($"Camera:      {exif.Make} {exif.Model}");
Console.WriteLine($"Software:    {exif.Software}");
Console.WriteLine($"Taken:       {exif.CaptureTime:yyyy-MM-dd HH:mm:ss}");
Console.WriteLine($"Orientation: {exif.Orientation}");
Console.WriteLine($"Pixels:      {exif.PixelWidth}x{exif.PixelHeight}");
 
if (exif.Gps is GpsPosition gps)
{
    Console.WriteLine($"GPS:         {gps.Latitude:F5}, {gps.Longitude:F5}");
}
Text
Camera:      NIKON COOLPIX P6000
Software:    Nikon Transfer 1.1 W
Taken:       2008-10-22 16:28:39
Orientation: 1
Pixels:      640x480
GPS:         43.46745, 11.88513

Latitude and longitude are signed decimal degrees: south and west are negative. CaptureTime is DateTimeOriginal, falling back to the digitized and file times; it is returned as recorded, which is usually the camera’s local clock, with no time zone applied. Gps.Altitude is set when the file has one.

Other tags

ReadExif parses the common fields only. The raw EXIF, XMP and IPTC blocks and the ICC profile are on Metadata, for a dedicated parser:

C#
using OneImage;
 
ImageMetadata metadata = Image.Identify("gps.jpg").Metadata;
Console.WriteLine($"EXIF {metadata.Exif.Length} bytes, "
                + $"XMP {metadata.Xmp.Length} bytes");
Console.WriteLine($"IPTC {metadata.Iptc.Length} bytes, "
                + $"ICC {metadata.IccProfile.Length} bytes");
Text
EXIF 11250 bytes, XMP 4000 bytes
IPTC 0 bytes, ICC 0 bytes

Limits

  • Common fields only. Exposure, ISO, lens, maker notes and the like aren’t parsed; read them from the raw Exif bytes.
  • Damaged blocks: reading is bounds-checked, so a malformed block throws ImageFormatException from ReadExif; TryReadExif returns false instead.
  • Read-only. OneImage keeps, updates (orientation, pixel size) or removes EXIF; it doesn’t edit other tags.

GPS positions are private data: before publishing photos, remove the metadata. Metadata handling is in the guide.