reader_backend.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // Copyright 2012 Christian Henning
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. #ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP
  9. #define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP
  10. #include <boost/gil/extension/io/targa/tags.hpp>
  11. namespace boost { namespace gil {
  12. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  13. #pragma warning(push)
  14. #pragma warning(disable:4512) //assignment operator could not be generated
  15. #endif
  16. ///
  17. /// Targa Backend
  18. ///
  19. template< typename Device >
  20. struct reader_backend< Device
  21. , targa_tag
  22. >
  23. {
  24. public:
  25. using format_tag_t = targa_tag;
  26. public:
  27. reader_backend( const Device& io_dev
  28. , const image_read_settings< targa_tag >& settings
  29. )
  30. : _io_dev ( io_dev )
  31. , _scanline_length(0)
  32. , _settings( settings )
  33. , _info()
  34. {
  35. read_header();
  36. if( _settings._dim.x == 0 )
  37. {
  38. _settings._dim.x = _info._width;
  39. }
  40. if( _settings._dim.y == 0 )
  41. {
  42. _settings._dim.y = _info._height;
  43. }
  44. }
  45. void read_header()
  46. {
  47. _info._header_size = targa_header_size::_size;
  48. _info._offset = _io_dev.read_uint8() + _info._header_size;
  49. _info._color_map_type = _io_dev.read_uint8();
  50. _info._image_type = _io_dev.read_uint8();
  51. _info._color_map_start = _io_dev.read_uint16();
  52. _info._color_map_length = _io_dev.read_uint16();
  53. _info._color_map_depth = _io_dev.read_uint8();
  54. _info._x_origin = _io_dev.read_uint16();
  55. _info._y_origin = _io_dev.read_uint16();
  56. _info._width = _io_dev.read_uint16();
  57. _info._height = _io_dev.read_uint16();
  58. if( _info._width < 1 || _info._height < 1 )
  59. {
  60. io_error( "Invalid dimension for targa file" );
  61. }
  62. _info._bits_per_pixel = _io_dev.read_uint8();
  63. if( _info._bits_per_pixel != 24 && _info._bits_per_pixel != 32 )
  64. {
  65. io_error( "Unsupported bit depth for targa file" );
  66. }
  67. _info._descriptor = _io_dev.read_uint8();
  68. // According to TGA specs, http://www.gamers.org/dEngine/quake3/TGA.txt,
  69. // the image descriptor byte is:
  70. //
  71. // For Data Type 1, This entire byte should be set to 0.
  72. if (_info._image_type == 1 && _info._descriptor != 0)
  73. {
  74. io_error("Unsupported descriptor for targa file");
  75. }
  76. else if (_info._bits_per_pixel == 24)
  77. {
  78. // Bits 3-0 - For the Targa 24, it should be 0.
  79. if ((_info._descriptor & 0x0FU) != 0)
  80. {
  81. io_error("Unsupported descriptor for targa file");
  82. }
  83. }
  84. else if (_info._bits_per_pixel == 32)
  85. {
  86. // Bits 3-0 - For Targa 32, it should be 8.
  87. if (_info._descriptor != 8 && _info._descriptor != 40)
  88. {
  89. io_error("Unsupported descriptor for targa file");
  90. }
  91. }
  92. else
  93. {
  94. io_error("Unsupported descriptor for targa file");
  95. }
  96. if (_info._descriptor & 32)
  97. {
  98. _info._screen_origin_bit = true;
  99. }
  100. _info._valid = true;
  101. }
  102. /// Check if image is large enough.
  103. void check_image_size( const point_t& img_dim )
  104. {
  105. if( _settings._dim.x > 0 )
  106. {
  107. if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
  108. }
  109. else
  110. {
  111. if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
  112. }
  113. if( _settings._dim.y > 0 )
  114. {
  115. if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
  116. }
  117. else
  118. {
  119. if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
  120. }
  121. }
  122. public:
  123. Device _io_dev;
  124. std::size_t _scanline_length;
  125. image_read_settings< targa_tag > _settings;
  126. image_read_info< targa_tag > _info;
  127. };
  128. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  129. #pragma warning(pop)
  130. #endif
  131. } // namespace gil
  132. } // namespace boost
  133. #endif