Exemplo n.º 1
0
/**
 * @brief Get unsigned short data from raw exif data
 *          This is internal function and is not exposed to client
 * @param [in] offset Offset to entry in bytes inside raw exif data
 * @return Unsigned short data
 */
uint16_t ExifReader::getU16(const size_t offset) const
{
    if (offset + 1 >= m_data.size())
        throw ExifParsingError();

    if( m_format == INTEL )
    {
        return m_data[offset] + ( m_data[offset + 1] << 8 );
    }
    return ( m_data[offset] << 8 ) + m_data[offset + 1];
}
Exemplo n.º 2
0
/**
 * @brief Get string information from raw exif data
 *          This is internal function and is not exposed to client
 * @param [in] offset Offset to entry in bytes inside raw exif data
 * @return string value
 */
std::string ExifReader::getString(const size_t offset) const
{
    size_t size = getU32( offset + 4 );
    size_t dataOffset = 8; // position of data in the field
    if( size > maxDataSize )
    {
        dataOffset = getU32( offset + 8 );
    }
    if (dataOffset > m_data.size() || dataOffset + size > m_data.size()) {
        throw ExifParsingError();
    }
    std::vector<uint8_t>::const_iterator it = m_data.begin() + dataOffset;
    std::string result( it, it + size ); //copy vector content into result

    return result;
}
Exemplo n.º 3
0
/**
 * @brief Get unsigned 32-bit data from raw exif data
 *          This is internal function and is not exposed to client
 * @param [in] offset Offset to entry in bytes inside raw exif data
 * @return Unsigned 32-bit data
 */
uint32_t ExifReader::getU32(const size_t offset) const
{
    if (offset + 3 >= m_data.size())
        throw ExifParsingError();

    if( m_format == INTEL )
    {
        return m_data[offset] +
                ( m_data[offset + 1] << 8 ) +
                ( m_data[offset + 2] << 16 ) +
                ( m_data[offset + 3] << 24 );
    }

    return ( m_data[offset] << 24 ) +
            ( m_data[offset + 1] << 16 ) +
            ( m_data[offset + 2] << 8 ) +
            m_data[offset + 3];
}
Exemplo n.º 4
0
/**
 * @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;
}
Exemplo n.º 5
0
/**
 * @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);
                if (exifSize <= offsetToTiffHeader) {
                    throw ExifParsingError();
                }
                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;
}