/* TinyEXIF.h -- A simple ISO C++ library to parse basic EXIF and XMP information from a JPEG file. Copyright (c) 2015-2025 Seacave cdc.seacave@gmail.com MIT License */ #ifndef __TINYEXIF_H__ #define __TINYEXIF_H__ #include #include #include #define TINYEXIF_MAJOR_VERSION 1 #define TINYEXIF_MINOR_VERSION 0 #define TINYEXIF_PATCH_VERSION 3 #ifdef _MSC_VER # ifdef TINYEXIF_EXPORT # define TINYEXIF_LIB __declspec(dllexport) # elif defined(TINYEXIF_IMPORT) # define TINYEXIF_LIB __declspec(dllimport) # else # define TINYEXIF_LIB # endif #elif __GNUC__ >= 4 # define TINYEXIF_LIB __attribute__((visibility("default"))) #else # define TINYEXIF_LIB #endif namespace TinyEXIF { enum ErrorCode { PARSE_SUCCESS = 0, // Parse EXIF and/or XMP was successful PARSE_INVALID_JPEG = 1, // No JPEG markers found in buffer, possibly invalid JPEG file PARSE_UNKNOWN_BYTEALIGN = 2, // Byte alignment specified in EXIF file was unknown (neither Motorola nor Intel) PARSE_ABSENT_DATA = 3, // No EXIF and/or XMP data found in JPEG file PARSE_CORRUPT_DATA = 4, // EXIF and/or XMP header was found, but data was corrupted }; enum FieldCode { FIELD_NA = 0, // No EXIF or XMP data FIELD_EXIF = (1 << 0), // EXIF data available FIELD_XMP = (1 << 1), // XMP data available FIELD_ALL = FIELD_EXIF|FIELD_XMP }; class EntryParser; // // Interface class responsible for fetching stream data to be parsed // class TINYEXIF_LIB EXIFStream { public: virtual ~EXIFStream() {} // Check the state of the stream. virtual bool IsValid() const = 0; // Return the pointer to the beginning of the desired size buffer // following current buffer position. virtual const uint8_t* GetBuffer(unsigned desiredLength) = 0; // Advance current buffer position with the desired size; // return false if stream ends in less than the desired size. virtual bool SkipBuffer(unsigned desiredLength) = 0; }; // // Class responsible for storing and parsing EXIF & XMP metadata from a JPEG stream // class TINYEXIF_LIB EXIFInfo { public: EXIFInfo(); EXIFInfo(EXIFStream& stream); EXIFInfo(std::istream& stream); // NB: the stream must have been opened in binary mode EXIFInfo(const uint8_t* data, unsigned length); // Parsing function for an entire JPEG image stream. // // PARAM 'stream': Interface to fetch JPEG image stream. // PARAM 'data': A pointer to a JPEG image. // PARAM 'length': The length of the JPEG image. // RETURN: PARSE_SUCCESS (0) on success with 'result' filled out // error code otherwise, as defined by the PARSE_* macros int parseFrom(EXIFStream& stream); int parseFrom(std::istream& stream); // NB: the stream must have been opened in binary mode int parseFrom(const uint8_t* data, unsigned length); // Parsing function for an EXIF segment. This is used internally by parseFrom() // but can be called for special cases where only the EXIF section is // available (i.e., a blob starting with the bytes "Exif\0\0"). int parseFromEXIFSegment(const uint8_t* buf, unsigned len); #ifndef TINYEXIF_NO_XMP_SUPPORT // Parsing function for an XMP segment. This is used internally by parseFrom() // but can be called for special cases where only the XMP section is // available (i.e., a blob starting with the bytes "http://ns.adobe.com/xap/1.0/\0"). int parseFromXMPSegment(const uint8_t* buf, unsigned len); int parseFromXMPSegmentXML(const char* szXML, unsigned len); #endif // TINYEXIF_NO_XMP_SUPPORT // Set all data members to default values. // Should be called before parsing a new stream. void clear(); private: // Parse tag as Image IFD. void parseIFDImage(EntryParser&, unsigned&, unsigned&); // Parse tag as Exif IFD. void parseIFDExif(EntryParser&); // Parse tag as GPS IFD. void parseIFDGPS(EntryParser&); // Parse tag as MakerNote IFD. void parseIFDMakerNote(EntryParser&); public: // Data fields uint32_t Fields; // Store if EXIF and/or XMP data fields are available uint32_t ImageWidth; // Image width reported in EXIF data uint32_t ImageHeight; // Image height reported in EXIF data uint32_t RelatedImageWidth; // Original image width reported in EXIF data uint32_t RelatedImageHeight; // Original image height reported in EXIF data std::string ImageDescription; // Image description std::string Make; // Camera manufacturer's name std::string Model; // Camera model std::string SerialNumber; // Serial number of the body of the camera uint16_t Orientation; // Image orientation, start of data corresponds to // 0: unspecified in EXIF data // 1: upper left of image // 3: lower right of image // 6: upper right of image // 8: lower left of image // 9: undefined double XResolution; // Number of pixels per ResolutionUnit in the ImageWidth direction double YResolution; // Number of pixels per ResolutionUnit in the ImageLength direction uint16_t ResolutionUnit; // Unit of measurement for XResolution and YResolution // 1: no absolute unit of measurement. Used for images that may have a non-square aspect ratio, but no meaningful absolute dimensions // 2: inch // 3: centimeter uint16_t BitsPerSample; // Number of bits per component std::string Software; // Software used std::string DateTime; // File change date and time std::string DateTimeOriginal; // Original file date and time (may not exist) std::string DateTimeDigitized; // Digitization date and time (may not exist) std::string SubSecTimeOriginal; // Sub-second time that original picture was taken std::string Copyright; // File copyright information double ExposureTime; // Exposure time in seconds double FNumber; // F/stop uint16_t ExposureProgram; // Exposure program // 0: not defined // 1: manual // 2: normal program // 3: aperture priority // 4: shutter priority // 5: creative program // 6: action program // 7: portrait mode // 8: landscape mode uint16_t ISOSpeedRatings; // ISO speed double ShutterSpeedValue; // Shutter speed (reciprocal of exposure time) double ApertureValue; // The lens aperture double BrightnessValue; // The value of brightness double ExposureBiasValue; // Exposure bias value in EV double SubjectDistance; // Distance to focus point in meters double FocalLength; // Focal length of lens in millimeters uint16_t Flash; // Flash info // Flash used (Flash&1) // 0: no flash, >0: flash used // Flash returned light status ((Flash & 6) >> 1) // 0: no strobe return detection function // 1: reserved // 2: strobe return light not detected // 3: strobe return light detected // Flash mode ((Flash & 24) >> 3) // 0: unknown // 1: compulsory flash firing // 2: compulsory flash suppression // 3: auto mode // Flash function ((Flash & 32) >> 5) // 0: flash function present, >0: no flash function // Flash red-eye ((Flash & 64) >> 6) // 0: no red-eye reduction mode or unknown, >0: red-eye reduction supported uint16_t MeteringMode; // Metering mode // 0: unknown // 1: average // 2: center weighted average // 3: spot // 4: multi-spot // 5: pattern // 6: partial uint16_t LightSource; // Kind of light source // 0: unknown // 1: daylight // 2: fluorescent // 3: tungsten (incandescent light) // 4: flash // 9: fine weather // 10: cloudy weather // 11: shade // 12: daylight fluorescent (D 5700 - 7100K) // 13: day white fluorescent (N 4600 - 5400K) // 14: cool white fluorescent (W 3900 - 4500K) // 15: white fluorescent (WW 3200 - 3700K) // 17: standard light A // 18: standard light B // 19: standard light C // 20: D55 // 21: D65 // 22: D75 // 23: D50 // 24: ISO studio tungsten uint16_t ProjectionType; // Projection type // 0: unknown projection // 1: perspective projection // 2: equirectangular/spherical projection std::vector SubjectArea; // Location and area of the main subject in the overall scene expressed in relation to the upper left as origin, prior to rotation // 0: unknown // 2: location of the main subject as coordinates (first value is the X coordinate and second is the Y coordinate) // 3: area of the main subject as a circle (first value is the center X coordinate, second is the center Y coordinate, and third is the diameter) // 4: area of the main subject as a rectangle (first value is the center X coordinate, second is the center Y coordinate, third is the width of the area, and fourth is the height of the area) struct TINYEXIF_LIB Calibration_t { // Camera calibration information double FocalLength; // Focal length (pixels) double OpticalCenterX; // Principal point X (pixels) double OpticalCenterY; // Principal point Y (pixels) bool hasCalibration() const; // Return true if FocalLength, OpticalCenterX, OpticalCenterY are available (nonzero) } Calibration; struct TINYEXIF_LIB Distortion_t { // Lens distortion information uint32_t DewarpFlag; // Dewarp flag - indicates whether undistortion has been applied to the image // UINT32_MAX: flag missing from EXIF data // 0: no dewarp (raw image) - the image is distorted, should also have coefficients // 1: dewarp applied (undistorted image) double K1; double K2; double P1; double P2; double K3; bool hasDewarpFlag() const; // Return true if DewarpFlag is available bool hasDistortion() const; // Return true if any of K1, K2, P1, P2, K3 are available } Distortion; struct TINYEXIF_LIB LensInfo_t { // Lens information double FStopMin; // Min aperture (f-stop) double FStopMax; // Max aperture (f-stop) double FocalLengthMin; // Min focal length (mm) double FocalLengthMax; // Max focal length (mm) double DigitalZoomRatio; // Digital zoom ratio when the image was shot double FocalLengthIn35mm; // Focal length in 35mm film double FocalPlaneXResolution; // Number of pixels in the image width (X) direction per FocalPlaneResolutionUnit on the camera focal plane (may not exist) double FocalPlaneYResolution; // Number of pixels in the image width (Y) direction per FocalPlaneResolutionUnit on the camera focal plane (may not exist) uint16_t FocalPlaneResolutionUnit;// Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution (may not exist) // 0: unspecified in EXIF data // 1: no absolute unit of measurement // 2: inch // 3: centimeter std::string Make; // Lens manufacturer std::string Model; // Lens model } LensInfo; struct TINYEXIF_LIB Geolocation_t { // GPS information embedded in file double Latitude; // Image latitude expressed as decimal double Longitude; // Image longitude expressed as decimal double Altitude; // Altitude in meters, relative to sea level int8_t AltitudeRef; // 0: above sea level, -1: below sea level double RelativeAltitude; // Relative altitude in meters double RollDegree; // Flight roll in degrees double PitchDegree; // Flight pitch in degrees double YawDegree; // Flight yaw in degrees double SpeedX; // Flight speed on X in meters/second double SpeedY; // Flight speed on Y in meters/second double SpeedZ; // Flight speed on Z in meters/second double AccuracyXY; // GPS accuracy on XY in meters double AccuracyZ; // GPS accuracy on Z in meters double GPSDOP; // GPS DOP (data degree of precision) uint16_t GPSDifferential; // Differential correction applied to the GPS receiver (may not exist) // 0: measurement without differential correction // 1: differential correction applied std::string GPSMapDatum; // Geodetic survey data (may not exist) std::string GPSTimeStamp; // Time as UTC (Coordinated Universal Time) (may not exist) std::string GPSDateStamp; // A character string recording date and time information relative to UTC (Coordinated Universal Time) YYYY:MM:DD (may not exist) struct Coord_t { double degrees; double minutes; double seconds; uint8_t direction; } LatComponents, LonComponents; // Latitude/Longitude expressed in deg/min/sec void parseCoords(); // Convert Latitude/Longitude from deg/min/sec to decimal bool hasLatLon() const; // Return true if (lat,lon) is available bool hasAltitude() const; // Return true if (alt) is available bool hasRelativeAltitude()const;// Return true if (rel_alt) is available bool hasOrientation() const; // Return true if (roll,yaw,pitch) is available bool hasSpeed() const; // Return true if (speedX,speedY,speedZ) is available bool hasAccuracy() const; // Return true if (accuracyXY,accuracyZ) is available } GeoLocation; struct TINYEXIF_LIB GPano_t { // Spherical metadata. https://developers.google.com/streetview/spherical-metadata double PosePitchDegrees; // Pitch, measured in degrees above the horizon, for the center in the image. Value must be >= -90 and <= 90. double PoseRollDegrees; // Roll, measured in degrees, of the image where level with the horizon is 0. As roll increases, the horizon rotates counterclockwise in the image. Value must be > -180 and <= 180. bool hasPosePitchDegrees() const; // Return true if PosePitchDegrees is available bool hasPoseRollDegrees() const; // Return true if PoseRollDegrees is available } GPano; struct TINYEXIF_LIB MicroVideo_t { // Google camera video file in metadata uint32_t HasMicroVideo; // not zero if exists uint32_t MicroVideoVersion; // just regularinfo uint32_t MicroVideoOffset; // offset from end of file } MicroVideo; }; } // namespace TinyEXIF #endif // __TINYEXIF_H__