You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.2 KiB
C++

//
// Copyright 2012 Christian Henning
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP
#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP
#include <boost/gil/extension/io/targa/tags.hpp>
namespace boost { namespace gil {
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
///
/// Targa Backend
///
template< typename Device >
struct reader_backend< Device
, targa_tag
>
{
public:
using format_tag_t = targa_tag;
public:
reader_backend( const Device& io_dev
, const image_read_settings< targa_tag >& settings
)
: _io_dev ( io_dev )
, _scanline_length(0)
, _settings( settings )
, _info()
{
read_header();
if( _settings._dim.x == 0 )
{
_settings._dim.x = _info._width;
}
if( _settings._dim.y == 0 )
{
_settings._dim.y = _info._height;
}
}
void read_header()
{
_info._header_size = targa_header_size::_size;
_info._offset = _io_dev.read_uint8() + _info._header_size;
_info._color_map_type = _io_dev.read_uint8();
_info._image_type = _io_dev.read_uint8();
_info._color_map_start = _io_dev.read_uint16();
_info._color_map_length = _io_dev.read_uint16();
_info._color_map_depth = _io_dev.read_uint8();
_info._x_origin = _io_dev.read_uint16();
_info._y_origin = _io_dev.read_uint16();
_info._width = _io_dev.read_uint16();
_info._height = _io_dev.read_uint16();
if( _info._width < 1 || _info._height < 1 )
{
io_error( "Invalid dimension for targa file" );
}
_info._bits_per_pixel = _io_dev.read_uint8();
if( _info._bits_per_pixel != 24 && _info._bits_per_pixel != 32 )
{
io_error( "Unsupported bit depth for targa file" );
}
_info._descriptor = _io_dev.read_uint8();
// According to TGA specs, http://www.gamers.org/dEngine/quake3/TGA.txt,
// the image descriptor byte is:
//
// For Data Type 1, This entire byte should be set to 0.
if (_info._image_type == 1 && _info._descriptor != 0)
{
io_error("Unsupported descriptor for targa file");
}
else if (_info._bits_per_pixel == 24)
{
// Bits 3-0 - For the Targa 24, it should be 0.
if ((_info._descriptor & 0x0FU) != 0)
{
io_error("Unsupported descriptor for targa file");
}
}
else if (_info._bits_per_pixel == 32)
{
// Bits 3-0 - For Targa 32, it should be 8.
if (_info._descriptor != 8 && _info._descriptor != 40)
{
io_error("Unsupported descriptor for targa file");
}
}
else
{
io_error("Unsupported descriptor for targa file");
}
if (_info._descriptor & 32)
{
_info._screen_origin_bit = true;
}
_info._valid = true;
}
/// Check if image is large enough.
void check_image_size( const point_t& img_dim )
{
if( _settings._dim.x > 0 )
{
if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
}
else
{
if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
}
if( _settings._dim.y > 0 )
{
if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
}
else
{
if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
}
}
public:
Device _io_dev;
std::size_t _scanline_length;
image_read_settings< targa_tag > _settings;
image_read_info< targa_tag > _info;
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
} // namespace gil
} // namespace boost
#endif