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