148cdb363SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
348cdb363SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
448cdb363SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
548cdb363SAndrew Rist  * distributed with this work for additional information
648cdb363SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
748cdb363SAndrew Rist  * to you under the Apache License, Version 2.0 (the
848cdb363SAndrew Rist  * "License"); you may not use this file except in compliance
948cdb363SAndrew Rist  * with the License.  You may obtain a copy of the License at
1048cdb363SAndrew Rist  *
1148cdb363SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1248cdb363SAndrew Rist  *
1348cdb363SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1448cdb363SAndrew Rist  * software distributed under the License is distributed on an
1548cdb363SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1648cdb363SAndrew Rist  * KIND, either express or implied.  See the License for the
1748cdb363SAndrew Rist  * specific language governing permissions and limitations
1848cdb363SAndrew Rist  * under the License.
1948cdb363SAndrew Rist  *
2048cdb363SAndrew Rist  *************************************************************/
2148cdb363SAndrew Rist 
2248cdb363SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #ifndef INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX
25cdf0e10cSrcweir #define INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <basebmp/metafunctions.hxx>
28cdf0e10cSrcweir #include <basebmp/stridedarrayiterator.hxx>
29cdf0e10cSrcweir #include <basebmp/nonstandarditerator.hxx>
30cdf0e10cSrcweir #include <basebmp/accessortraits.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <boost/static_assert.hpp>
33cdf0e10cSrcweir #include <vigra/metaprogramming.hxx>
34cdf0e10cSrcweir #include <vigra/diff2d.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir namespace basebmp
37cdf0e10cSrcweir {
38cdf0e10cSrcweir 
39cdf0e10cSrcweir /// Get bitmask for data at given intra-word position, for given bit depth
40cdf0e10cSrcweir template< typename value_type,
41cdf0e10cSrcweir           int      bits_per_pixel,
42cdf0e10cSrcweir           bool     MsbFirst,
43cdf0e10cSrcweir           typename difference_type >
get_mask(difference_type d)44cdf0e10cSrcweir inline value_type get_mask( difference_type d )
45cdf0e10cSrcweir {
46cdf0e10cSrcweir     BOOST_STATIC_ASSERT(bits_per_pixel > 0);
47cdf0e10cSrcweir     BOOST_STATIC_ASSERT(sizeof(value_type)*8 % bits_per_pixel == 0);
48cdf0e10cSrcweir     BOOST_STATIC_ASSERT(sizeof(value_type)*8 / bits_per_pixel > 1);
49cdf0e10cSrcweir     BOOST_STATIC_ASSERT(vigra::TypeTraits<value_type>::isPOD::asBool);
50cdf0e10cSrcweir 
51cdf0e10cSrcweir     const unsigned int nIntraWordPositions( sizeof(value_type)*8 / bits_per_pixel );
52cdf0e10cSrcweir 
53cdf0e10cSrcweir     //      create bits_per_pixel 1s      shift to intra-word position
54a529b01cStruckman     return ((~(~0u << bits_per_pixel)) << bits_per_pixel*(MsbFirst ?
55cdf0e10cSrcweir                                                          (nIntraWordPositions-1 - (d % nIntraWordPositions)) :
56cdf0e10cSrcweir                                                          (d % nIntraWordPositions)));
57cdf0e10cSrcweir }
58cdf0e10cSrcweir 
get_shift(difference_type remainder)59cdf0e10cSrcweir template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder )
60cdf0e10cSrcweir {
61cdf0e10cSrcweir     return bits_per_pixel*(MsbFirst ?
62cdf0e10cSrcweir                            (num_intraword_positions - 1 - remainder) :
63cdf0e10cSrcweir                            remainder);
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
66cdf0e10cSrcweir template< typename Valuetype,
67cdf0e10cSrcweir           int      bits_per_pixel,
68cdf0e10cSrcweir           bool     MsbFirst > class PackedPixelColumnIterator : public NonStandardIterator
69cdf0e10cSrcweir {
70cdf0e10cSrcweir public:
71cdf0e10cSrcweir     // no reference, no index_reference type here
72cdf0e10cSrcweir     typedef Valuetype                                   value_type;
73cdf0e10cSrcweir     typedef int                                         difference_type;
74cdf0e10cSrcweir     typedef image_traverser_tag                         iterator_category;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir     typedef typename remove_const<value_type>::type     mask_type;
77cdf0e10cSrcweir     typedef value_type*                                 pointer;
78cdf0e10cSrcweir     typedef StridedArrayIterator< value_type >          MoveY;
79cdf0e10cSrcweir 
80cdf0e10cSrcweir     enum {
81cdf0e10cSrcweir         /** The number of pixel within a single value_type value
82cdf0e10cSrcweir          */
83cdf0e10cSrcweir         num_intraword_positions=sizeof(value_type)*8/bits_per_pixel,
84cdf0e10cSrcweir         /** Bit mask for one pixel (least significant bits)
85cdf0e10cSrcweir          */
86bc5cd333SMechtilde Stehmann         bit_mask=~(~0u << bits_per_pixel)
87cdf0e10cSrcweir     };
88cdf0e10cSrcweir 
89cdf0e10cSrcweir private:
90cdf0e10cSrcweir     MoveY           y;
91cdf0e10cSrcweir     mask_type       mask_;
92cdf0e10cSrcweir     difference_type shift_;
93cdf0e10cSrcweir 
inc()94cdf0e10cSrcweir     void inc()
95cdf0e10cSrcweir     {
96cdf0e10cSrcweir         ++y;
97cdf0e10cSrcweir     }
98cdf0e10cSrcweir 
dec()99cdf0e10cSrcweir     void dec()
100cdf0e10cSrcweir     {
101cdf0e10cSrcweir         --y;
102cdf0e10cSrcweir     }
103cdf0e10cSrcweir 
equal(PackedPixelColumnIterator const & rhs) const104cdf0e10cSrcweir     bool equal( PackedPixelColumnIterator const & rhs ) const
105cdf0e10cSrcweir     {
106cdf0e10cSrcweir         return rhs.y == y;
107cdf0e10cSrcweir     }
108cdf0e10cSrcweir 
less(PackedPixelColumnIterator const & rhs) const109cdf0e10cSrcweir     bool less( PackedPixelColumnIterator const & rhs ) const
110cdf0e10cSrcweir     {
111cdf0e10cSrcweir         return y < rhs.y;
112cdf0e10cSrcweir     }
113cdf0e10cSrcweir 
114cdf0e10cSrcweir public:
PackedPixelColumnIterator()115cdf0e10cSrcweir     PackedPixelColumnIterator() :
116cdf0e10cSrcweir         y(0),
117cdf0e10cSrcweir         mask_( get_mask<value_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
118cdf0e10cSrcweir         shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) )
119cdf0e10cSrcweir     {}
120cdf0e10cSrcweir 
PackedPixelColumnIterator(const MoveY & base,difference_type remainder)121cdf0e10cSrcweir     PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) :
122cdf0e10cSrcweir         y(base),
123cdf0e10cSrcweir         mask_( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) ),
124cdf0e10cSrcweir         shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) )
125cdf0e10cSrcweir     {}
126cdf0e10cSrcweir 
operator +=(difference_type d)127cdf0e10cSrcweir     PackedPixelColumnIterator& operator+=( difference_type d )
128cdf0e10cSrcweir     {
129cdf0e10cSrcweir         y += d;
130cdf0e10cSrcweir         return *this;
131cdf0e10cSrcweir     }
132cdf0e10cSrcweir 
operator -=(difference_type d)133cdf0e10cSrcweir     PackedPixelColumnIterator& operator-=( difference_type d )
134cdf0e10cSrcweir     {
135cdf0e10cSrcweir         y -= d;
136cdf0e10cSrcweir         return *this;
137cdf0e10cSrcweir     }
138cdf0e10cSrcweir 
operator +(difference_type d)139cdf0e10cSrcweir     PackedPixelColumnIterator operator+( difference_type d )
140cdf0e10cSrcweir     {
141cdf0e10cSrcweir         PackedPixelColumnIterator res(*this);
142cdf0e10cSrcweir         res += d;
143cdf0e10cSrcweir         return res;
144cdf0e10cSrcweir     }
145cdf0e10cSrcweir 
operator -(difference_type d)146cdf0e10cSrcweir     PackedPixelColumnIterator operator-( difference_type d )
147cdf0e10cSrcweir     {
148cdf0e10cSrcweir         PackedPixelColumnIterator res(*this);
149cdf0e10cSrcweir         res -= d;
150cdf0e10cSrcweir         return res;
151cdf0e10cSrcweir     }
152cdf0e10cSrcweir 
operator ++()153cdf0e10cSrcweir     PackedPixelColumnIterator& operator++()
154cdf0e10cSrcweir     {
155cdf0e10cSrcweir         inc();
156cdf0e10cSrcweir         return *this;
157cdf0e10cSrcweir     }
158cdf0e10cSrcweir 
operator --()159cdf0e10cSrcweir     PackedPixelColumnIterator& operator--()
160cdf0e10cSrcweir     {
161cdf0e10cSrcweir         dec();
162cdf0e10cSrcweir         return *this;
163cdf0e10cSrcweir     }
164cdf0e10cSrcweir 
operator ++(int)165cdf0e10cSrcweir     PackedPixelColumnIterator operator++(int)
166cdf0e10cSrcweir     {
167cdf0e10cSrcweir         PackedPixelColumnIterator res(*this);
168cdf0e10cSrcweir         inc();
169cdf0e10cSrcweir         return res;
170cdf0e10cSrcweir     }
171cdf0e10cSrcweir 
operator --(int)172cdf0e10cSrcweir     PackedPixelColumnIterator operator--(int)
173cdf0e10cSrcweir     {
174cdf0e10cSrcweir         PackedPixelColumnIterator res(*this);
175cdf0e10cSrcweir         dec();
176cdf0e10cSrcweir         return res;
177cdf0e10cSrcweir     }
178cdf0e10cSrcweir 
operator ==(PackedPixelColumnIterator const & rhs) const179cdf0e10cSrcweir     bool operator==(PackedPixelColumnIterator const & rhs) const
180cdf0e10cSrcweir     {
181cdf0e10cSrcweir         return equal( rhs );
182cdf0e10cSrcweir     }
183cdf0e10cSrcweir 
operator !=(PackedPixelColumnIterator const & rhs) const184cdf0e10cSrcweir     bool operator!=(PackedPixelColumnIterator const & rhs) const
185cdf0e10cSrcweir     {
186cdf0e10cSrcweir         return !equal( rhs );
187cdf0e10cSrcweir     }
188cdf0e10cSrcweir 
operator <(PackedPixelColumnIterator const & rhs) const189cdf0e10cSrcweir     bool operator<(PackedPixelColumnIterator const & rhs) const
190cdf0e10cSrcweir     {
191cdf0e10cSrcweir         return less(rhs);
192cdf0e10cSrcweir     }
193cdf0e10cSrcweir 
operator <=(PackedPixelColumnIterator const & rhs) const194cdf0e10cSrcweir     bool operator<=(PackedPixelColumnIterator const & rhs) const
195cdf0e10cSrcweir     {
196cdf0e10cSrcweir         return !rhs.less(*this);
197cdf0e10cSrcweir     }
198cdf0e10cSrcweir 
operator >(PackedPixelColumnIterator const & rhs) const199cdf0e10cSrcweir     bool operator>(PackedPixelColumnIterator const & rhs) const
200cdf0e10cSrcweir     {
201cdf0e10cSrcweir         return rhs.less(*this);
202cdf0e10cSrcweir     }
203cdf0e10cSrcweir 
operator >=(PackedPixelColumnIterator const & rhs) const204cdf0e10cSrcweir     bool operator>=(PackedPixelColumnIterator const & rhs) const
205cdf0e10cSrcweir     {
206cdf0e10cSrcweir         return !less(rhs);
207cdf0e10cSrcweir     }
208cdf0e10cSrcweir 
operator -(PackedPixelColumnIterator const & rhs) const209cdf0e10cSrcweir     difference_type operator-(PackedPixelColumnIterator const & rhs) const
210cdf0e10cSrcweir     {
211cdf0e10cSrcweir         return y - rhs.y;
212cdf0e10cSrcweir     }
213cdf0e10cSrcweir 
get() const214cdf0e10cSrcweir     value_type get() const
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         return unsigned_cast<value_type>(*y() & mask_) >> shift_;
217cdf0e10cSrcweir     }
218cdf0e10cSrcweir 
get(difference_type d) const219cdf0e10cSrcweir     value_type get(difference_type d) const
220cdf0e10cSrcweir     {
221cdf0e10cSrcweir         return unsigned_cast<value_type>(*y(d) & mask_) >> shift_;
222cdf0e10cSrcweir     }
223cdf0e10cSrcweir 
set(value_type v) const224cdf0e10cSrcweir     void set( value_type v ) const
225cdf0e10cSrcweir     {
226cdf0e10cSrcweir         const value_type pixel_value( (v << shift_) & mask_ );
227cdf0e10cSrcweir         *y() = (*y() & ~mask_) | pixel_value;
228cdf0e10cSrcweir     }
229cdf0e10cSrcweir 
set(value_type v,difference_type d) const230cdf0e10cSrcweir     void set( value_type v, difference_type d ) const
231cdf0e10cSrcweir     {
232cdf0e10cSrcweir         const value_type pixel_value( (v << shift_) & mask_ );
233cdf0e10cSrcweir         *y(d) = (*y(d) & ~mask_) | pixel_value;
234cdf0e10cSrcweir     }
235cdf0e10cSrcweir };
236cdf0e10cSrcweir 
237cdf0e10cSrcweir template< typename Valuetype,
238cdf0e10cSrcweir           int      bits_per_pixel,
239cdf0e10cSrcweir           bool     MsbFirst > class PackedPixelRowIterator : public NonStandardIterator
240cdf0e10cSrcweir {
241cdf0e10cSrcweir public:
242cdf0e10cSrcweir     // no reference, no index_reference type here
243cdf0e10cSrcweir     typedef Valuetype                                   value_type;
244cdf0e10cSrcweir     typedef int                                         difference_type;
245cdf0e10cSrcweir     typedef image_traverser_tag                         iterator_category;
246cdf0e10cSrcweir 
247cdf0e10cSrcweir     typedef typename remove_const<value_type>::type     mask_type;
248cdf0e10cSrcweir     typedef value_type*                                 pointer;
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     enum {
251cdf0e10cSrcweir         /** The number of pixel within a single value_type value
252cdf0e10cSrcweir          */
253cdf0e10cSrcweir         num_intraword_positions=sizeof(value_type)*8/bits_per_pixel,
254cdf0e10cSrcweir         /** Bit mask for one pixel (least significant bits)
255cdf0e10cSrcweir          */
256bc5cd333SMechtilde Stehmann         bit_mask=~(~0u << bits_per_pixel)
257cdf0e10cSrcweir     };
258cdf0e10cSrcweir 
259cdf0e10cSrcweir private:
260cdf0e10cSrcweir     pointer         data_;
261cdf0e10cSrcweir     mask_type       mask_;
262cdf0e10cSrcweir     difference_type remainder_;
263cdf0e10cSrcweir 
update_mask()264cdf0e10cSrcweir     void update_mask()
265cdf0e10cSrcweir     {
266cdf0e10cSrcweir         mask_ = get_mask<value_type, bits_per_pixel, MsbFirst>(remainder_);
267cdf0e10cSrcweir     }
268cdf0e10cSrcweir 
inc()269cdf0e10cSrcweir     void inc()
270cdf0e10cSrcweir     {
271cdf0e10cSrcweir         const difference_type newValue( remainder_ + 1 );
272cdf0e10cSrcweir         const difference_type data_offset( newValue / num_intraword_positions );
273cdf0e10cSrcweir 
274cdf0e10cSrcweir         data_ += data_offset;
275cdf0e10cSrcweir         remainder_ = newValue % num_intraword_positions;
276cdf0e10cSrcweir 
277cdf0e10cSrcweir         const mask_type shifted_mask(
278cdf0e10cSrcweir             MsbFirst ?
279cdf0e10cSrcweir             unsigned_cast<mask_type>(mask_) >> bits_per_pixel :
280cdf0e10cSrcweir             mask_ << bits_per_pixel );
281cdf0e10cSrcweir 
282cdf0e10cSrcweir         // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
283cdf0e10cSrcweir         mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
284cdf0e10cSrcweir                                                             bit_mask << bits_per_pixel*(num_intraword_positions-1) :
285cdf0e10cSrcweir                                                             bit_mask);
286cdf0e10cSrcweir     }
287cdf0e10cSrcweir 
dec()288cdf0e10cSrcweir     void dec()
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         const difference_type newValue( remainder_ - 1 );
291cdf0e10cSrcweir         const bool            isNegative( is_negative(newValue) );
292cdf0e10cSrcweir         const difference_type newRemainder( newValue % num_intraword_positions );
293cdf0e10cSrcweir 
294cdf0e10cSrcweir         // calc  data_ += newValue / num_intraword_positions;
295cdf0e10cSrcweir         //       remainder_ = newRemainder;
296cdf0e10cSrcweir         // for newValue >= 0, and
297cdf0e10cSrcweir         //       data_ += newValue / num_intraword_positions - 1;
298cdf0e10cSrcweir         //       remainder_ = num_intraword_positions - newRemainder;
299cdf0e10cSrcweir         // (to force remainder_ to be positive).
300cdf0e10cSrcweir         // This is branch-free, if is_negative() is branch-free
301cdf0e10cSrcweir         const difference_type data_offset( newValue / num_intraword_positions - isNegative );
302cdf0e10cSrcweir         data_     += data_offset;
303cdf0e10cSrcweir         remainder_ = newRemainder + isNegative*num_intraword_positions;
304cdf0e10cSrcweir 
305cdf0e10cSrcweir         const mask_type shifted_mask(
306cdf0e10cSrcweir             MsbFirst ?
307cdf0e10cSrcweir             mask_ << bits_per_pixel :
308cdf0e10cSrcweir             unsigned_cast<mask_type>(mask_) >> bits_per_pixel );
309cdf0e10cSrcweir 
310cdf0e10cSrcweir         // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
311cdf0e10cSrcweir         mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
312cdf0e10cSrcweir                                                             bit_mask :
313cdf0e10cSrcweir                                                             bit_mask << bits_per_pixel*(num_intraword_positions-1));
314cdf0e10cSrcweir     }
315cdf0e10cSrcweir 
equal(PackedPixelRowIterator const & rhs) const316cdf0e10cSrcweir     bool equal( PackedPixelRowIterator const & rhs ) const
317cdf0e10cSrcweir     {
318cdf0e10cSrcweir         return rhs.data_ == data_ && rhs.remainder_ == remainder_;
319cdf0e10cSrcweir     }
320cdf0e10cSrcweir 
less(PackedPixelRowIterator const & rhs) const321cdf0e10cSrcweir     bool less( PackedPixelRowIterator const & rhs ) const
322cdf0e10cSrcweir     {
323cdf0e10cSrcweir         return data_ == rhs.data_ ?
324cdf0e10cSrcweir             (remainder_ < rhs.remainder_) :
325cdf0e10cSrcweir             (data_ < rhs.data_);
326cdf0e10cSrcweir     }
327cdf0e10cSrcweir 
328cdf0e10cSrcweir public:
PackedPixelRowIterator()329cdf0e10cSrcweir     PackedPixelRowIterator() :
330cdf0e10cSrcweir         data_(0),
331cdf0e10cSrcweir         mask_( get_mask<value_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
332cdf0e10cSrcweir         remainder_(0)
333cdf0e10cSrcweir     {}
334cdf0e10cSrcweir 
PackedPixelRowIterator(pointer base,int x)335cdf0e10cSrcweir     explicit PackedPixelRowIterator( pointer base, int x ) :
336cdf0e10cSrcweir         data_(base),
337cdf0e10cSrcweir         mask_(0),
338cdf0e10cSrcweir         remainder_(x % num_intraword_positions)
339cdf0e10cSrcweir     {
340cdf0e10cSrcweir         update_mask();
341cdf0e10cSrcweir     }
342cdf0e10cSrcweir 
operator +=(difference_type d)343cdf0e10cSrcweir     PackedPixelRowIterator& operator+=( difference_type d )
344cdf0e10cSrcweir     {
345cdf0e10cSrcweir         const difference_type newValue( remainder_ + d );
346cdf0e10cSrcweir         const bool            isNegative( is_negative(newValue) );
347cdf0e10cSrcweir         const difference_type newRemainder( newValue % num_intraword_positions );
348cdf0e10cSrcweir 
349cdf0e10cSrcweir         // calc  data_ += newValue / num_intraword_positions;
350cdf0e10cSrcweir         //       remainder_ = newRemainder;
351cdf0e10cSrcweir         // for newValue >= 0, and
352cdf0e10cSrcweir         //       data_ += newValue / num_intraword_positions - 1;
353cdf0e10cSrcweir         //       remainder_ = newRemainder + num_intraword_positions;
354cdf0e10cSrcweir         // (to force remainder_ to be positive).
355cdf0e10cSrcweir         // This is branch-free, if is_negative() is branch-free
356cdf0e10cSrcweir         data_     += newValue / num_intraword_positions - isNegative;
357cdf0e10cSrcweir         remainder_ = newRemainder + isNegative*num_intraword_positions;
358cdf0e10cSrcweir         update_mask();
359cdf0e10cSrcweir 
360cdf0e10cSrcweir         return *this;
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
operator -=(difference_type d)363cdf0e10cSrcweir     PackedPixelRowIterator& operator-=( difference_type d )
364cdf0e10cSrcweir     {
365cdf0e10cSrcweir         // forward to operator+= - which has to cope with negative
366cdf0e10cSrcweir         // values, anyway.
367cdf0e10cSrcweir         return *this += -d;
368cdf0e10cSrcweir     }
369cdf0e10cSrcweir 
operator +(difference_type d)370cdf0e10cSrcweir     PackedPixelRowIterator operator+( difference_type d )
371cdf0e10cSrcweir     {
372cdf0e10cSrcweir         PackedPixelRowIterator res(*this);
373cdf0e10cSrcweir         res += d;
374cdf0e10cSrcweir         return res;
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
operator -(difference_type d)377cdf0e10cSrcweir     PackedPixelRowIterator operator-( difference_type d )
378cdf0e10cSrcweir     {
379cdf0e10cSrcweir         PackedPixelRowIterator res(*this);
380cdf0e10cSrcweir         res -= d;
381cdf0e10cSrcweir         return res;
382cdf0e10cSrcweir     }
383cdf0e10cSrcweir 
operator ++()384cdf0e10cSrcweir     PackedPixelRowIterator& operator++()
385cdf0e10cSrcweir     {
386cdf0e10cSrcweir         inc();
387cdf0e10cSrcweir         return *this;
388cdf0e10cSrcweir     }
389cdf0e10cSrcweir 
operator --()390cdf0e10cSrcweir     PackedPixelRowIterator& operator--()
391cdf0e10cSrcweir     {
392cdf0e10cSrcweir         dec();
393cdf0e10cSrcweir         return *this;
394cdf0e10cSrcweir     }
395cdf0e10cSrcweir 
operator ++(int)396cdf0e10cSrcweir     PackedPixelRowIterator operator++(int)
397cdf0e10cSrcweir     {
398cdf0e10cSrcweir         PackedPixelRowIterator res(*this);
399cdf0e10cSrcweir         inc();
400cdf0e10cSrcweir         return res;
401cdf0e10cSrcweir     }
402cdf0e10cSrcweir 
operator --(int)403cdf0e10cSrcweir     PackedPixelRowIterator operator--(int)
404cdf0e10cSrcweir     {
405cdf0e10cSrcweir         PackedPixelRowIterator res(*this);
406cdf0e10cSrcweir         dec();
407cdf0e10cSrcweir         return res;
408cdf0e10cSrcweir     }
409cdf0e10cSrcweir 
operator ==(PackedPixelRowIterator const & rhs) const410cdf0e10cSrcweir     bool operator==(PackedPixelRowIterator const & rhs) const
411cdf0e10cSrcweir     {
412cdf0e10cSrcweir         return equal( rhs );
413cdf0e10cSrcweir     }
414cdf0e10cSrcweir 
operator !=(PackedPixelRowIterator const & rhs) const415cdf0e10cSrcweir     bool operator!=(PackedPixelRowIterator const & rhs) const
416cdf0e10cSrcweir     {
417cdf0e10cSrcweir         return !equal( rhs );
418cdf0e10cSrcweir     }
419cdf0e10cSrcweir 
operator <(PackedPixelRowIterator const & rhs) const420cdf0e10cSrcweir     bool operator<(PackedPixelRowIterator const & rhs) const
421cdf0e10cSrcweir     {
422cdf0e10cSrcweir         return less(rhs);
423cdf0e10cSrcweir     }
424cdf0e10cSrcweir 
operator <=(PackedPixelRowIterator const & rhs) const425cdf0e10cSrcweir     bool operator<=(PackedPixelRowIterator const & rhs) const
426cdf0e10cSrcweir     {
427cdf0e10cSrcweir         return !rhs.less(*this);
428cdf0e10cSrcweir     }
429cdf0e10cSrcweir 
operator >(PackedPixelRowIterator const & rhs) const430cdf0e10cSrcweir     bool operator>(PackedPixelRowIterator const & rhs) const
431cdf0e10cSrcweir     {
432cdf0e10cSrcweir         return rhs.less(*this);
433cdf0e10cSrcweir     }
434cdf0e10cSrcweir 
operator >=(PackedPixelRowIterator const & rhs) const435cdf0e10cSrcweir     bool operator>=(PackedPixelRowIterator const & rhs) const
436cdf0e10cSrcweir     {
437cdf0e10cSrcweir         return !less(rhs);
438cdf0e10cSrcweir     }
439cdf0e10cSrcweir 
operator -(PackedPixelRowIterator const & rhs) const440cdf0e10cSrcweir     difference_type operator-(PackedPixelRowIterator const & rhs) const
441cdf0e10cSrcweir     {
442cdf0e10cSrcweir         return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_);
443cdf0e10cSrcweir     }
444cdf0e10cSrcweir 
get() const445cdf0e10cSrcweir     value_type get() const
446cdf0e10cSrcweir     {
447cdf0e10cSrcweir         return unsigned_cast<value_type>(*data_ & mask_) >>
448cdf0e10cSrcweir             get_shift<num_intraword_positions,
449cdf0e10cSrcweir                       bits_per_pixel,
450cdf0e10cSrcweir                       MsbFirst>(remainder_);
451cdf0e10cSrcweir     }
452cdf0e10cSrcweir 
get(difference_type d) const453cdf0e10cSrcweir     value_type get(difference_type d) const
454cdf0e10cSrcweir     {
455cdf0e10cSrcweir         PackedPixelRowIterator tmp(*this);
456cdf0e10cSrcweir         tmp += d;
457cdf0e10cSrcweir         return tmp.get();
458cdf0e10cSrcweir     }
459cdf0e10cSrcweir 
set(value_type v) const460cdf0e10cSrcweir     void set( value_type v ) const
461cdf0e10cSrcweir     {
462cdf0e10cSrcweir         const value_type pixel_value(
463cdf0e10cSrcweir             (v <<
464cdf0e10cSrcweir              get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_))
465cdf0e10cSrcweir             & mask_ );
466cdf0e10cSrcweir         *data_ = (*data_ & ~mask_) | pixel_value;
467cdf0e10cSrcweir     }
468cdf0e10cSrcweir 
set(value_type v,difference_type d) const469cdf0e10cSrcweir     void set( value_type v, difference_type d ) const
470cdf0e10cSrcweir     {
471cdf0e10cSrcweir         PackedPixelRowIterator tmp(*this);
472cdf0e10cSrcweir         tmp += d;
473cdf0e10cSrcweir         tmp.set(v);
474cdf0e10cSrcweir     }
475cdf0e10cSrcweir };
476cdf0e10cSrcweir 
477cdf0e10cSrcweir /** 2D image iterator for packed pixel formats
478cdf0e10cSrcweir 
479cdf0e10cSrcweir     This iterator can be used for image formats that pack more than
480cdf0e10cSrcweir     one pixel into an machine data type (like one bit per pixel, eight
481cdf0e10cSrcweir     of which packed into one char)
482cdf0e10cSrcweir  */
483cdf0e10cSrcweir template< typename Valuetype,
484cdf0e10cSrcweir           int      bits_per_pixel,
485cdf0e10cSrcweir           bool     MsbFirst > class PackedPixelIterator : public NonStandardIterator
486cdf0e10cSrcweir {
487cdf0e10cSrcweir public:
488cdf0e10cSrcweir     // no reference, no index_reference type here
489cdf0e10cSrcweir     typedef Valuetype                                   value_type;
490cdf0e10cSrcweir     typedef vigra::Diff2D                               difference_type;
491cdf0e10cSrcweir     typedef image_traverser_tag                         iterator_category;
492cdf0e10cSrcweir     typedef PackedPixelRowIterator<value_type,
493cdf0e10cSrcweir                                    bits_per_pixel,
494cdf0e10cSrcweir                                    MsbFirst>            row_iterator;
495cdf0e10cSrcweir     typedef PackedPixelColumnIterator<value_type,
496cdf0e10cSrcweir                                       bits_per_pixel,
497cdf0e10cSrcweir                                       MsbFirst>         column_iterator;
498cdf0e10cSrcweir 
499cdf0e10cSrcweir     typedef value_type*                                 pointer;
500cdf0e10cSrcweir     typedef int                                         MoveX;
501cdf0e10cSrcweir     typedef StridedArrayIterator< value_type >          MoveY;
502cdf0e10cSrcweir 
503cdf0e10cSrcweir     enum {
504cdf0e10cSrcweir         /** The number of pixel within a single value_type value
505cdf0e10cSrcweir          */
506cdf0e10cSrcweir         num_intraword_positions=sizeof(value_type)*8/bits_per_pixel,
507cdf0e10cSrcweir         /** Bit mask for one pixel (least significant bits)
508cdf0e10cSrcweir          */
509bc5cd333SMechtilde Stehmann         bit_mask=~(~0u << bits_per_pixel)
510cdf0e10cSrcweir     };
511cdf0e10cSrcweir 
512cdf0e10cSrcweir     // TODO(F2): direction of iteration (ImageIterator can be made to
513cdf0e10cSrcweir     // run backwards)
514cdf0e10cSrcweir 
515cdf0e10cSrcweir private:
current() const516cdf0e10cSrcweir     pointer current() const
517cdf0e10cSrcweir     {
518cdf0e10cSrcweir         return y() + (x / num_intraword_positions);
519cdf0e10cSrcweir     }
520cdf0e10cSrcweir 
current(int dx,int dy) const521cdf0e10cSrcweir     pointer current(int dx, int dy) const
522cdf0e10cSrcweir     {
523cdf0e10cSrcweir         return y(dy) + ((x+dx)/num_intraword_positions);
524cdf0e10cSrcweir     }
525cdf0e10cSrcweir 
equal(PackedPixelIterator const & rhs) const526cdf0e10cSrcweir     bool equal(PackedPixelIterator const & rhs) const
527cdf0e10cSrcweir     {
528cdf0e10cSrcweir         return (x == rhs.x) && (y == rhs.y);
529cdf0e10cSrcweir     }
530cdf0e10cSrcweir 
531cdf0e10cSrcweir public:
PackedPixelIterator()532cdf0e10cSrcweir     PackedPixelIterator() :
533cdf0e10cSrcweir         x(0),
534cdf0e10cSrcweir         y(0)
535cdf0e10cSrcweir     {}
536cdf0e10cSrcweir 
PackedPixelIterator(pointer base,int ystride)537cdf0e10cSrcweir     PackedPixelIterator(pointer base, int ystride) :
538cdf0e10cSrcweir         x(0),
539cdf0e10cSrcweir         y(ystride,base)
540cdf0e10cSrcweir     {}
541cdf0e10cSrcweir 
operator ==(PackedPixelIterator const & rhs) const542cdf0e10cSrcweir     bool operator==(PackedPixelIterator const & rhs) const
543cdf0e10cSrcweir     {
544cdf0e10cSrcweir         return equal(rhs);
545cdf0e10cSrcweir     }
546cdf0e10cSrcweir 
operator !=(PackedPixelIterator const & rhs) const547cdf0e10cSrcweir     bool operator!=(PackedPixelIterator const & rhs) const
548cdf0e10cSrcweir     {
549cdf0e10cSrcweir         return !equal(rhs);
550cdf0e10cSrcweir     }
551cdf0e10cSrcweir 
operator -(PackedPixelIterator const & rhs) const552cdf0e10cSrcweir     difference_type operator-(PackedPixelIterator const & rhs) const
553cdf0e10cSrcweir     {
554cdf0e10cSrcweir         return difference_type(x - rhs.x, y - rhs.y);
555cdf0e10cSrcweir     }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir     MoveX x;
558cdf0e10cSrcweir     MoveY y;
559cdf0e10cSrcweir 
operator +=(difference_type const & s)560cdf0e10cSrcweir     PackedPixelIterator & operator+=(difference_type const & s)
561cdf0e10cSrcweir     {
562cdf0e10cSrcweir         x += s.x;
563cdf0e10cSrcweir         y += s.y;
564cdf0e10cSrcweir         return *this;
565cdf0e10cSrcweir     }
566cdf0e10cSrcweir 
operator -=(difference_type const & s)567cdf0e10cSrcweir     PackedPixelIterator & operator-=(difference_type const & s)
568cdf0e10cSrcweir     {
569cdf0e10cSrcweir         x -= s.x;
570cdf0e10cSrcweir         y -= s.y;
571cdf0e10cSrcweir         return *this;
572cdf0e10cSrcweir     }
573cdf0e10cSrcweir 
operator +(difference_type const & s) const574cdf0e10cSrcweir     PackedPixelIterator operator+(difference_type const & s) const
575cdf0e10cSrcweir     {
576cdf0e10cSrcweir         PackedPixelIterator ret(*this);
577cdf0e10cSrcweir         ret += s;
578cdf0e10cSrcweir         return ret;
579cdf0e10cSrcweir     }
580cdf0e10cSrcweir 
operator -(difference_type const & s) const581cdf0e10cSrcweir     PackedPixelIterator operator-(difference_type const & s) const
582cdf0e10cSrcweir     {
583cdf0e10cSrcweir         PackedPixelIterator ret(*this);
584cdf0e10cSrcweir         ret -= s;
585cdf0e10cSrcweir         return ret;
586cdf0e10cSrcweir     }
587cdf0e10cSrcweir 
rowIterator() const588cdf0e10cSrcweir     row_iterator rowIterator() const
589cdf0e10cSrcweir     {
590cdf0e10cSrcweir         return row_iterator(current(),x);
591cdf0e10cSrcweir     }
592cdf0e10cSrcweir 
columnIterator() const593cdf0e10cSrcweir     column_iterator columnIterator() const
594cdf0e10cSrcweir     {
595cdf0e10cSrcweir         return column_iterator(MoveY(y,
596cdf0e10cSrcweir                                      x / num_intraword_positions),
597cdf0e10cSrcweir                                x % num_intraword_positions);
598cdf0e10cSrcweir     }
599cdf0e10cSrcweir 
get() const600cdf0e10cSrcweir     value_type get() const
601cdf0e10cSrcweir     {
602cdf0e10cSrcweir         const int remainder( x % num_intraword_positions );
603cdf0e10cSrcweir 
604cdf0e10cSrcweir         return (unsigned_cast<value_type>(*current() &
605cdf0e10cSrcweir                                           get_mask<value_type, bits_per_pixel, MsbFirst>(remainder))
606cdf0e10cSrcweir                 >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder));
607cdf0e10cSrcweir     }
608cdf0e10cSrcweir 
609*8ff30341SDon Lewis /***** XXX - This appears to be unused and fails to compile with gcc9
610cdf0e10cSrcweir     value_type get(difference_type const & d) const
611cdf0e10cSrcweir     {
612*8ff30341SDon Lewis //      XXX - should x(d.x) be (x + d.x)?
613cdf0e10cSrcweir         const int remainder( x(d.x) % num_intraword_positions );
614cdf0e10cSrcweir 
615cdf0e10cSrcweir         return (unsigned_cast<value_type>(*current(d.x,d.y) &
616cdf0e10cSrcweir                                           get_mask<value_type, bits_per_pixel, MsbFirst>(remainder))
617cdf0e10cSrcweir                 >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder));
618cdf0e10cSrcweir     }
619*8ff30341SDon Lewis ******/
620cdf0e10cSrcweir 
set(value_type v) const621cdf0e10cSrcweir     void set( value_type v ) const
622cdf0e10cSrcweir     {
623cdf0e10cSrcweir         const int remainder( x % num_intraword_positions );
624cdf0e10cSrcweir         const int mask( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) );
625cdf0e10cSrcweir         const value_type pixel_value(
626cdf0e10cSrcweir             (v <<
627cdf0e10cSrcweir              get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
628cdf0e10cSrcweir             & mask );
629cdf0e10cSrcweir         pointer p = current();
630cdf0e10cSrcweir         *p = (*p & ~mask) | pixel_value;
631cdf0e10cSrcweir     }
632cdf0e10cSrcweir 
set(value_type v,difference_type const & d) const633cdf0e10cSrcweir     void set( value_type v, difference_type const & d ) const
634cdf0e10cSrcweir     {
635cdf0e10cSrcweir         const int remainder( (x + d.x) % num_intraword_positions );
636cdf0e10cSrcweir         const int mask( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) );
637cdf0e10cSrcweir         const value_type pixel_value(
638cdf0e10cSrcweir             (v <<
639cdf0e10cSrcweir              get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
640cdf0e10cSrcweir              & mask );
641cdf0e10cSrcweir         pointer p = current(d.x,d.y);
642cdf0e10cSrcweir         *p = (*p & ~mask) | pixel_value;
643cdf0e10cSrcweir     }
644cdf0e10cSrcweir };
645cdf0e10cSrcweir 
646cdf0e10cSrcweir //-----------------------------------------------------------------------------
647cdf0e10cSrcweir 
648cdf0e10cSrcweir // partial specialization for the accessor traits masked_accessor
649cdf0e10cSrcweir // selector metafunction - can employ fast mask functor for the 1bpp
650cdf0e10cSrcweir // case.
651cdf0e10cSrcweir template< class Accessor,
652cdf0e10cSrcweir           class MaskAccessor,
653cdf0e10cSrcweir           class Iterator,
654cdf0e10cSrcweir           bool  polarity,
655cdf0e10cSrcweir           bool  MsbFirst > struct maskedAccessorSelector< Accessor,
656cdf0e10cSrcweir                                                           MaskAccessor,
657cdf0e10cSrcweir                                                           Iterator,
658cdf0e10cSrcweir                                                           PackedPixelIterator< typename MaskAccessor::value_type,
659cdf0e10cSrcweir                                                                                1,
660cdf0e10cSrcweir                                                                                MsbFirst >,
661cdf0e10cSrcweir                                                           polarity >
662cdf0e10cSrcweir {
663cdf0e10cSrcweir     typedef TernarySetterFunctionAccessorAdapter<
664cdf0e10cSrcweir         Accessor,
665cdf0e10cSrcweir         MaskAccessor,
666cdf0e10cSrcweir         typename outputMaskFunctorSelector<
667cdf0e10cSrcweir             typename Accessor::value_type,
668cdf0e10cSrcweir             typename MaskAccessor::value_type,
669cdf0e10cSrcweir             polarity,
670cdf0e10cSrcweir             FastMask>::type >
671cdf0e10cSrcweir         type;
672cdf0e10cSrcweir };
673cdf0e10cSrcweir 
674cdf0e10cSrcweir } // namespace basebmp
675cdf0e10cSrcweir 
676cdf0e10cSrcweir #endif /* INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX */
677