1 //
2 // Copyright 2007-2008 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_IO_SCANLINE_READ_ITERATOR_HPP
9 #define BOOST_GIL_IO_SCANLINE_READ_ITERATOR_HPP
10 
11 #include <boost/gil/io/error.hpp>
12 #include <boost/gil/io/typedefs.hpp>
13 
14 #include <boost/iterator/iterator_facade.hpp>
15 
16 #include <iterator>
17 #include <memory>
18 #include <vector>
19 
20 namespace boost { namespace gil {
21 
22 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
23 #pragma warning(push)
24 #pragma warning(disable:4512) //assignment operator could not be generated
25 #endif
26 
27 /// Input iterator to read images.
28 template <typename Reader>
29 class scanline_read_iterator
30     : public boost::iterator_facade<scanline_read_iterator<Reader>, byte_t*, std::input_iterator_tag>
31 {
32 private:
33     using base_t = boost::iterator_facade
34         <
35             scanline_read_iterator<Reader>,
36             byte_t*,
37             std::input_iterator_tag
38         >;
39 public:
scanline_read_iterator(Reader & reader,int pos=0)40     scanline_read_iterator(Reader& reader, int pos = 0)
41         : reader_(reader), pos_(pos)
42     {
43         buffer_       = std::make_shared<buffer_t>(buffer_t(reader_._scanline_length));
44         buffer_start_ = &buffer_->front();
45     }
46 
47 private:
48     friend class boost::iterator_core_access;
49 
increment()50     void increment()
51     {
52         if (skip_scanline_)
53         {
54             reader_.skip(buffer_start_, pos_);
55         }
56 
57         ++pos_;
58 
59         skip_scanline_ = true;
60         read_scanline_ = true;
61     }
62 
equal(scanline_read_iterator const & rhs) const63     bool equal(scanline_read_iterator const& rhs) const
64     {
65         return pos_ == rhs.pos_;
66     }
67 
dereference() const68     typename base_t::reference dereference() const
69     {
70         if (read_scanline_)
71         {
72             reader_.read(buffer_start_, pos_);
73         }
74         skip_scanline_ = false;
75         read_scanline_ = false;
76 
77         return buffer_start_;
78     }
79 
80 private:
81     Reader& reader_;
82 
83     mutable int pos_            = 0;
84     mutable bool read_scanline_ = true;
85     mutable bool skip_scanline_ = true;
86 
87     using buffer_t     = std::vector<byte_t>;
88     using buffer_ptr_t = std::shared_ptr<buffer_t>;
89     buffer_ptr_t buffer_;
90     mutable byte_t* buffer_start_ = nullptr;
91 };
92 
93 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
94 #pragma warning(pop)
95 #endif
96 
97 } // namespace gil
98 } // namespace boost
99 
100 #endif
101