update credits
[LibreOffice.git] / include / basebmp / packedpixeliterator.hxx
blob89a88506bbcdafcfbe920bed096da7c89d01e687
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX
21 #define INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX
23 #include <basebmp/metafunctions.hxx>
24 #include <basebmp/stridedarrayiterator.hxx>
25 #include <basebmp/nonstandarditerator.hxx>
26 #include <basebmp/accessortraits.hxx>
28 #include <boost/static_assert.hpp>
29 #include <vigra/metaprogramming.hxx>
30 #include <vigra/diff2d.hxx>
32 namespace basebmp
35 /// Get bitmask for data at given intra-word position, for given bit depth
36 template< typename value_type,
37 int bits_per_pixel,
38 bool MsbFirst,
39 typename difference_type >
40 inline value_type get_mask( difference_type d )
42 BOOST_STATIC_ASSERT(bits_per_pixel > 0);
43 BOOST_STATIC_ASSERT(sizeof(value_type)*8 % bits_per_pixel == 0);
44 BOOST_STATIC_ASSERT(sizeof(value_type)*8 / bits_per_pixel > 1);
45 BOOST_STATIC_ASSERT(vigra::TypeTraits<value_type>::isPOD::asBool);
47 const unsigned int nIntraWordPositions( sizeof(value_type)*8 / bits_per_pixel );
49 // create bits_per_pixel 1s shift to intra-word position
50 return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ?
51 (nIntraWordPositions-1 - (d % nIntraWordPositions)) :
52 (d % nIntraWordPositions)));
55 template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder )
57 return bits_per_pixel*(MsbFirst ?
58 (num_intraword_positions - 1 - remainder) :
59 remainder);
62 template< typename Valuetype,
63 int bits_per_pixel,
64 bool MsbFirst > class PackedPixelColumnIterator : public NonStandardIterator
66 public:
67 // no reference, no index_reference type here
68 typedef Valuetype value_type;
69 typedef int difference_type;
70 typedef image_traverser_tag iterator_category;
72 typedef typename remove_const<value_type>::type mask_type;
73 typedef value_type* pointer;
74 typedef StridedArrayIterator< value_type > MoveY;
76 enum {
77 /** The number of pixel within a single value_type value
79 num_intraword_positions=sizeof(value_type)*8/bits_per_pixel,
80 /** Bit mask for one pixel (least significant bits)
82 bit_mask=~(~0 << bits_per_pixel)
85 private:
86 MoveY y;
87 mask_type mask_;
88 difference_type shift_;
90 void inc()
92 ++y;
95 void dec()
97 --y;
100 bool equal( PackedPixelColumnIterator const & rhs ) const
102 return rhs.y == y;
105 bool less( PackedPixelColumnIterator const & rhs ) const
107 return y < rhs.y;
110 public:
111 PackedPixelColumnIterator() :
112 y(0),
113 mask_( get_mask<value_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
114 shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) )
117 PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) :
118 y(base),
119 mask_( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) ),
120 shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) )
123 PackedPixelColumnIterator& operator+=( difference_type d )
125 y += d;
126 return *this;
129 PackedPixelColumnIterator& operator-=( difference_type d )
131 y -= d;
132 return *this;
135 PackedPixelColumnIterator operator+( difference_type d )
137 PackedPixelColumnIterator res(*this);
138 res += d;
139 return res;
142 PackedPixelColumnIterator operator-( difference_type d )
144 PackedPixelColumnIterator res(*this);
145 res -= d;
146 return res;
149 PackedPixelColumnIterator& operator++()
151 inc();
152 return *this;
155 PackedPixelColumnIterator& operator--()
157 dec();
158 return *this;
161 PackedPixelColumnIterator operator++(int)
163 PackedPixelColumnIterator res(*this);
164 inc();
165 return res;
168 PackedPixelColumnIterator operator--(int)
170 PackedPixelColumnIterator res(*this);
171 dec();
172 return res;
175 bool operator==(PackedPixelColumnIterator const & rhs) const
177 return equal( rhs );
180 bool operator!=(PackedPixelColumnIterator const & rhs) const
182 return !equal( rhs );
185 bool operator<(PackedPixelColumnIterator const & rhs) const
187 return less(rhs);
190 bool operator<=(PackedPixelColumnIterator const & rhs) const
192 return !rhs.less(*this);
195 bool operator>(PackedPixelColumnIterator const & rhs) const
197 return rhs.less(*this);
200 bool operator>=(PackedPixelColumnIterator const & rhs) const
202 return !less(rhs);
205 difference_type operator-(PackedPixelColumnIterator const & rhs) const
207 return y - rhs.y;
210 value_type get() const
212 return unsigned_cast<value_type>(*y() & mask_) >> shift_;
215 value_type get(difference_type d) const
217 return unsigned_cast<value_type>(*y(d) & mask_) >> shift_;
220 void set( value_type v ) const
222 const value_type pixel_value( (v << shift_) & mask_ );
223 *y() = (*y() & ~mask_) | pixel_value;
226 void set( value_type v, difference_type d ) const
228 const value_type pixel_value( (v << shift_) & mask_ );
229 *y(d) = (*y(d) & ~mask_) | pixel_value;
233 template< typename Valuetype,
234 int bits_per_pixel,
235 bool MsbFirst > class PackedPixelRowIterator : public NonStandardIterator
237 public:
238 // no reference, no index_reference type here
239 typedef Valuetype value_type;
240 typedef int difference_type;
241 typedef image_traverser_tag iterator_category;
243 typedef typename remove_const<value_type>::type mask_type;
244 typedef value_type* pointer;
246 enum {
247 /** The number of pixel within a single value_type value
249 num_intraword_positions=sizeof(value_type)*8/bits_per_pixel,
250 /** Bit mask for one pixel (least significant bits)
252 bit_mask=~(~0 << bits_per_pixel)
255 private:
256 pointer data_;
257 mask_type mask_;
258 difference_type remainder_;
260 void update_mask()
262 mask_ = get_mask<value_type, bits_per_pixel, MsbFirst>(remainder_);
265 void inc()
267 const difference_type newValue( remainder_ + 1 );
268 const difference_type data_offset( newValue / num_intraword_positions );
270 data_ += data_offset;
271 remainder_ = newValue % num_intraword_positions;
273 const mask_type shifted_mask(
274 MsbFirst ?
275 unsigned_cast<mask_type>(mask_) >> bits_per_pixel :
276 mask_ << bits_per_pixel );
278 // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
279 mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
280 bit_mask << bits_per_pixel*(num_intraword_positions-1) :
281 bit_mask);
284 void dec()
286 const difference_type newValue( remainder_ - 1 );
287 const bool isNegative( is_negative(newValue) );
288 const difference_type newRemainder( newValue % num_intraword_positions );
290 // calc data_ += newValue / num_intraword_positions;
291 // remainder_ = newRemainder;
292 // for newValue >= 0, and
293 // data_ += newValue / num_intraword_positions - 1;
294 // remainder_ = num_intraword_positions - newRemainder;
295 // (to force remainder_ to be positive).
296 // This is branch-free, if is_negative() is branch-free
297 const difference_type data_offset( newValue / num_intraword_positions - isNegative );
298 data_ += data_offset;
299 remainder_ = newRemainder + isNegative*num_intraword_positions;
301 const mask_type shifted_mask(
302 MsbFirst ?
303 mask_ << bits_per_pixel :
304 unsigned_cast<mask_type>(mask_) >> bits_per_pixel );
306 // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
307 mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
308 bit_mask :
309 bit_mask << bits_per_pixel*(num_intraword_positions-1));
312 bool equal( PackedPixelRowIterator const & rhs ) const
314 return rhs.data_ == data_ && rhs.remainder_ == remainder_;
317 bool less( PackedPixelRowIterator const & rhs ) const
319 return data_ == rhs.data_ ?
320 (remainder_ < rhs.remainder_) :
321 (data_ < rhs.data_);
324 public:
325 PackedPixelRowIterator() :
326 data_(0),
327 mask_( get_mask<value_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
328 remainder_(0)
331 explicit PackedPixelRowIterator( pointer base, int x ) :
332 data_(base),
333 mask_(0),
334 remainder_(x % num_intraword_positions)
336 update_mask();
339 PackedPixelRowIterator& operator+=( difference_type d )
341 const difference_type newValue( remainder_ + d );
342 const bool isNegative( is_negative(newValue) );
343 const difference_type newRemainder( newValue % num_intraword_positions );
345 // calc data_ += newValue / num_intraword_positions;
346 // remainder_ = newRemainder;
347 // for newValue >= 0, and
348 // data_ += newValue / num_intraword_positions - 1;
349 // remainder_ = newRemainder + num_intraword_positions;
350 // (to force remainder_ to be positive).
351 // This is branch-free, if is_negative() is branch-free
352 data_ += newValue / num_intraword_positions - isNegative;
353 remainder_ = newRemainder + isNegative*num_intraword_positions;
354 update_mask();
356 return *this;
359 PackedPixelRowIterator& operator-=( difference_type d )
361 // forward to operator+= - which has to cope with negative
362 // values, anyway.
363 return *this += -d;
366 PackedPixelRowIterator operator+( difference_type d )
368 PackedPixelRowIterator res(*this);
369 res += d;
370 return res;
373 PackedPixelRowIterator operator-( difference_type d )
375 PackedPixelRowIterator res(*this);
376 res -= d;
377 return res;
380 PackedPixelRowIterator& operator++()
382 inc();
383 return *this;
386 PackedPixelRowIterator& operator--()
388 dec();
389 return *this;
392 PackedPixelRowIterator operator++(int)
394 PackedPixelRowIterator res(*this);
395 inc();
396 return res;
399 PackedPixelRowIterator operator--(int)
401 PackedPixelRowIterator res(*this);
402 dec();
403 return res;
406 bool operator==(PackedPixelRowIterator const & rhs) const
408 return equal( rhs );
411 bool operator!=(PackedPixelRowIterator const & rhs) const
413 return !equal( rhs );
416 bool operator<(PackedPixelRowIterator const & rhs) const
418 return less(rhs);
421 bool operator<=(PackedPixelRowIterator const & rhs) const
423 return !rhs.less(*this);
426 bool operator>(PackedPixelRowIterator const & rhs) const
428 return rhs.less(*this);
431 bool operator>=(PackedPixelRowIterator const & rhs) const
433 return !less(rhs);
436 difference_type operator-(PackedPixelRowIterator const & rhs) const
438 return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_);
441 value_type get() const
443 return unsigned_cast<value_type>(*data_ & mask_) >>
444 get_shift<num_intraword_positions,
445 bits_per_pixel,
446 MsbFirst>(remainder_);
449 value_type get(difference_type d) const
451 PackedPixelRowIterator tmp(*this);
452 tmp += d;
453 return tmp.get();
456 void set( value_type v ) const
458 const value_type pixel_value(
459 (v <<
460 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_))
461 & mask_ );
462 *data_ = (*data_ & ~mask_) | pixel_value;
465 void set( value_type v, difference_type d ) const
467 PackedPixelRowIterator tmp(*this);
468 tmp += d;
469 tmp.set(v);
473 /** 2D image iterator for packed pixel formats
475 This iterator can be used for image formats that pack more than
476 one pixel into an machine data type (like one bit per pixel, eight
477 of which packed into one char)
479 template< typename Valuetype,
480 int bits_per_pixel,
481 bool MsbFirst > class PackedPixelIterator : public NonStandardIterator
483 public:
484 // no reference, no index_reference type here
485 typedef Valuetype value_type;
486 typedef vigra::Diff2D difference_type;
487 typedef image_traverser_tag iterator_category;
488 typedef PackedPixelRowIterator<value_type,
489 bits_per_pixel,
490 MsbFirst> row_iterator;
491 typedef PackedPixelColumnIterator<value_type,
492 bits_per_pixel,
493 MsbFirst> column_iterator;
495 typedef value_type* pointer;
496 typedef int MoveX;
497 typedef StridedArrayIterator< value_type > MoveY;
499 enum {
500 /** The number of pixel within a single value_type value
502 num_intraword_positions=sizeof(value_type)*8/bits_per_pixel,
503 /** Bit mask for one pixel (least significant bits)
505 bit_mask=~(~0 << bits_per_pixel)
508 // TODO(F2): direction of iteration (ImageIterator can be made to
509 // run backwards)
511 private:
512 pointer current() const
514 return y() + (x / num_intraword_positions);
517 pointer current(int dx, int dy) const
519 return y(dy) + ((x+dx)/num_intraword_positions);
522 bool equal(PackedPixelIterator const & rhs) const
524 return (x == rhs.x) && (y == rhs.y);
527 public:
528 PackedPixelIterator() :
529 x(0),
530 y(0)
533 PackedPixelIterator(pointer base, int ystride) :
534 x(0),
535 y(ystride,base)
538 bool operator==(PackedPixelIterator const & rhs) const
540 return equal(rhs);
543 bool operator!=(PackedPixelIterator const & rhs) const
545 return !equal(rhs);
548 difference_type operator-(PackedPixelIterator const & rhs) const
550 return difference_type(x - rhs.x, y - rhs.y);
553 MoveX x;
554 MoveY y;
556 PackedPixelIterator & operator+=(difference_type const & s)
558 x += s.x;
559 y += s.y;
560 return *this;
563 PackedPixelIterator & operator-=(difference_type const & s)
565 x -= s.x;
566 y -= s.y;
567 return *this;
570 PackedPixelIterator operator+(difference_type const & s) const
572 PackedPixelIterator ret(*this);
573 ret += s;
574 return ret;
577 PackedPixelIterator operator-(difference_type const & s) const
579 PackedPixelIterator ret(*this);
580 ret -= s;
581 return ret;
584 row_iterator rowIterator() const
586 return row_iterator(current(),x);
589 column_iterator columnIterator() const
591 return column_iterator(MoveY(y,
592 x / num_intraword_positions),
593 x % num_intraword_positions);
596 value_type get() const
598 const int remainder( x % num_intraword_positions );
600 return (unsigned_cast<value_type>(*current() &
601 get_mask<value_type, bits_per_pixel, MsbFirst>(remainder))
602 >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder));
605 value_type get(difference_type const & d) const
607 const int remainder( x(d.x) % num_intraword_positions );
609 return (unsigned_cast<value_type>(*current(d.x,d.y) &
610 get_mask<value_type, bits_per_pixel, MsbFirst>(remainder))
611 >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder));
614 void set( value_type v ) const
616 const int remainder( x % num_intraword_positions );
617 const int mask( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) );
618 const value_type pixel_value(
619 (v <<
620 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
621 & mask );
622 pointer p = current();
623 *p = (*p & ~mask) | pixel_value;
626 void set( value_type v, difference_type const & d ) const
628 const int remainder( (x + d.x) % num_intraword_positions );
629 const int mask( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) );
630 const value_type pixel_value(
631 (v <<
632 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
633 & mask );
634 pointer p = current(d.x,d.y);
635 *p = (*p & ~mask) | pixel_value;
639 //-----------------------------------------------------------------------------
641 // partial specialization for the accessor traits masked_accessor
642 // selector metafunction - can employ fast mask functor for the 1bpp
643 // case.
644 template< class Accessor,
645 class MaskAccessor,
646 class Iterator,
647 bool polarity,
648 bool MsbFirst > struct maskedAccessorSelector< Accessor,
649 MaskAccessor,
650 Iterator,
651 PackedPixelIterator< typename MaskAccessor::value_type,
653 MsbFirst >,
654 polarity >
656 typedef TernarySetterFunctionAccessorAdapter<
657 Accessor,
658 MaskAccessor,
659 typename outputMaskFunctorSelector<
660 typename Accessor::value_type,
661 typename MaskAccessor::value_type,
662 polarity,
663 FastMask>::type >
664 type;
667 } // namespace basebmp
669 #endif /* INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX */
671 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */