Implementation:NVIDIA DALI EXIF Parser
| Knowledge Sources | |
|---|---|
| Domains | Image_Processing, Metadata_Parsing |
| Last Updated | 2026-02-08 16:00 GMT |
Overview
C++ EXIF metadata parser derived from OpenCV that reads and interprets EXIF tags from JPEG image data within the DALI image processing pipeline.
Description
This file (third_party/opencv/exif/exif.cc) implements an EXIF (Exchangeable Image File Format) metadata reader within the dali::cv namespace. It is based on the OpenCV EXIF parsing code (originally from the Open Source Computer Vision Library) and adapted for use within DALI's image decoding pipeline. The parser handles the binary structure of EXIF data embedded in JPEG files, supporting both Intel (little-endian) and Motorola (big-endian) byte orderings.
The core class ExifReader provides the public interface through parseExif(unsigned char* data, size_t size) which accepts raw EXIF data and populates an internal map of EXIF entries, and getTag(ExifTagName tag) which retrieves parsed entries by tag name. Internally, the parser validates the TIFF header tag mark (0x002A), determines the IFD0 offset, iterates through directory entries, and dispatches parsing to tag-specific methods.
The parser supports the following EXIF tags: IMAGE_DESCRIPTION, MAKE, MODEL, ORIENTATION, XRESOLUTION, YRESOLUTION, RESOLUTION_UNIT, SOFTWARE, DATE_TIME, WHITE_POINT, PRIMARY_CHROMATICIES, Y_CB_CR_COEFFICIENTS, Y_CB_CR_POSITIONING, REFERENCE_BLACK_WHITE, COPYRIGHT, and EXIF_OFFSET. Each tag is parsed into the appropriate data type within the ExifEntry_t structure, which holds fields for strings, unsigned/signed integers (8/16/32-bit), floats, doubles, and rational number vectors. Low-level byte reading methods (getU16, getU32, getURational) handle endianness-aware extraction with bounds checking that throws ExifParsingError on out-of-bounds access.
Usage
This parser is used internally by DALI's image decoding pipeline to extract orientation and other metadata from JPEG images. The orientation tag is particularly important for correctly rotating images during decode. This code is not intended to be used as a standalone utility.
Code Reference
Source Location
- Repository: NVIDIA_DALI
- File: third_party/opencv/exif/exif.cc
- Lines: 1-538
Signature
namespace dali {
namespace cv {
struct ExifEntry_t {
// Holds parsed EXIF field data
std::string field_str;
float field_float;
double field_double;
uint32_t field_u32;
int32_t field_s32;
uint16_t tag;
uint16_t field_u16;
int16_t field_s16;
uint8_t field_u8;
int8_t field_s8;
std::vector<u_rational_t> field_u_rational;
};
class ExifReader {
public:
ExifReader();
~ExifReader();
ExifEntry_t getTag(const ExifTagName tag) const;
bool parseExif(unsigned char* data, const size_t size);
private:
void parseExif();
Endianess_t getFormat() const;
bool checkTagMark() const;
uint32_t getStartOffset() const;
size_t getNumDirEntry(const size_t offsetNumDir) const;
ExifEntry_t parseExifEntry(const size_t offset);
uint16_t getExifTag(const size_t offset) const;
std::string getString(const size_t offset) const;
uint16_t getU16(const size_t offset) const;
uint32_t getU32(const size_t offset) const;
u_rational_t getURational(const size_t offset) const;
uint16_t getOrientation(const size_t offset) const;
std::vector<u_rational_t> getResolution(const size_t offset) const;
uint16_t getResolutionUnit(const size_t offset) const;
std::vector<u_rational_t> getWhitePoint(const size_t offset) const;
std::vector<u_rational_t> getPrimaryChromaticies(const size_t offset) const;
std::vector<u_rational_t> getYCbCrCoeffs(const size_t offset) const;
uint16_t getYCbCrPos(const size_t offset) const;
std::vector<u_rational_t> getRefBW(const size_t offset) const;
};
} // namespace cv
} // namespace dali
Import
#include "exif.h"
// Usage within DALI's C++ codebase
dali::cv::ExifReader reader;
bool success = reader.parseExif(raw_data, data_size);
if (success) {
dali::cv::ExifEntry_t orientation = reader.getTag(dali::cv::ORIENTATION);
}
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| data | unsigned char* | Yes | Pointer to raw EXIF data buffer starting with endianness marker bytes |
| size | size_t | Yes | Size of the EXIF data buffer in bytes |
Outputs
| Name | Type | Description |
|---|---|---|
| return value | bool | true if EXIF parsing succeeded and at least one tag was found; false otherwise |
| ExifEntry_t | struct | Parsed EXIF entry retrieved via getTag(), containing the tag value in the appropriate typed field |
Usage Examples
Parse EXIF and read orientation
#include "exif.h"
// Assume jpeg_exif_data points to EXIF segment of a JPEG
dali::cv::ExifReader reader;
if (reader.parseExif(jpeg_exif_data, exif_size)) {
dali::cv::ExifEntry_t entry = reader.getTag(dali::cv::ORIENTATION);
uint16_t orientation = entry.field_u16;
// orientation values 1-8 per EXIF spec
// 1 = normal, 6 = rotated 90 CW, 3 = rotated 180, 8 = rotated 90 CCW
}
Read camera make and model
dali::cv::ExifReader reader;
if (reader.parseExif(data, size)) {
dali::cv::ExifEntry_t make = reader.getTag(dali::cv::MAKE);
dali::cv::ExifEntry_t model = reader.getTag(dali::cv::MODEL);
std::string camera = make.field_str + " " + model.field_str;
}