/** * @brief Get exif directory structure contained in file (if any) * This is internal function and is not exposed to client * * @return Map where key is tag number and value is ExifEntry_t structure */ std::map<int, ExifEntry_t > ExifReader::getExif() { const std::streamsize markerSize = 2; const std::streamsize offsetToTiffHeader = 6; //bytes from Exif size field to the first TIFF header unsigned char appMarker[markerSize]; m_exif.erase( m_exif.begin(), m_exif.end() ); std::streamsize count; bool exifFound = false, stopSearch = false; while( ( !m_stream.eof() ) && !exifFound && !stopSearch ) { m_stream.read( reinterpret_cast<char*>(appMarker), markerSize ); count = m_stream.gcount(); if( count < markerSize ) { break; } unsigned char marker = appMarker[1]; size_t bytesToSkip; size_t exifSize; switch( marker ) { //For all the markers just skip bytes in file pointed by followed two bytes (field size) case SOF0: case SOF2: case DHT: case DQT: case DRI: case SOS: case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7: case APP0: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8: case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15: case COM: bytesToSkip = getFieldSize(); if (bytesToSkip < markerSize) { throw ExifParsingError(); } m_stream.seekg( static_cast<long>( bytesToSkip - markerSize ), m_stream.cur ); if ( m_stream.fail() ) { throw ExifParsingError(); } break; //SOI and EOI don't have the size field after the marker case SOI: case EOI: break; case APP1: //actual Exif Marker exifSize = getFieldSize(); if (exifSize <= offsetToTiffHeader) { throw ExifParsingError(); } m_data.resize( exifSize - offsetToTiffHeader ); m_stream.seekg( static_cast<long>( offsetToTiffHeader ), m_stream.cur ); if ( m_stream.fail() ) { throw ExifParsingError(); } m_stream.read( reinterpret_cast<char*>(&m_data[0]), exifSize - offsetToTiffHeader ); count = m_stream.gcount(); exifFound = true; break; default: //No other markers are expected according to standard. May be a signal of error stopSearch = true; break; } } if( !exifFound ) { return m_exif; } parseExif(); return m_exif; }
/** * @brief Get exif directory structure contained in jpeg file (if any) * This is internal function and is not exposed to client * * @return Map where key is tag number and value is ExifEntry_t structure */ std::map<int, ExifEntry_t > ExifReader::getExif() { const size_t markerSize = 2; const size_t offsetToTiffHeader = 6; //bytes from Exif size field to the first TIFF header unsigned char appMarker[markerSize]; m_exif.erase( m_exif.begin(), m_exif.end() ); size_t count; FILE* f = fopen( m_filename.c_str(), "rb" ); if( !f ) { return m_exif; //Until this moment the map is empty } bool exifFound = false; while( ( !feof( f ) ) && !exifFound ) { count = fread( appMarker, sizeof(unsigned char), markerSize, f ); if( count < markerSize ) { break; } unsigned char marker = appMarker[1]; size_t bytesToSkip; size_t exifSize; switch( marker ) { //For all the markers just skip bytes in file pointed by followed two bytes (field size) case SOF0: case SOF2: case DHT: case DQT: case DRI: case SOS: case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7: case APP0: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8: case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15: case COM: bytesToSkip = getFieldSize( f ); fseek( f, static_cast<long>( bytesToSkip - markerSize ), SEEK_CUR ); break; //SOI and EOI don't have the size field after the marker case SOI: case EOI: break; case APP1: //actual Exif Marker exifSize = getFieldSize(f); m_data.resize( exifSize - offsetToTiffHeader ); fseek(f, static_cast<long>( offsetToTiffHeader ), SEEK_CUR); count = fread( &m_data[0], sizeof( unsigned char ), exifSize - offsetToTiffHeader, f ); exifFound = true; break; default: //No other markers are expected according to standard. May be a signal of error break; } } fclose(f); if( !exifFound ) { return m_exif; } parseExif(); return m_exif; }