1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
35 /// Get bitmask for data at given intra-word position, for given bit depth
36 template< typename value_type
,
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
) :
62 template< typename Valuetype
,
64 bool MsbFirst
> class PackedPixelColumnIterator
: public NonStandardIterator
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
;
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
)
88 difference_type shift_
;
100 bool equal( PackedPixelColumnIterator
const & rhs
) const
105 bool less( PackedPixelColumnIterator
const & rhs
) const
111 PackedPixelColumnIterator() :
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
) :
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
)
129 PackedPixelColumnIterator
& operator-=( difference_type d
)
135 PackedPixelColumnIterator
operator+( difference_type d
)
137 PackedPixelColumnIterator
res(*this);
142 PackedPixelColumnIterator
operator-( difference_type d
)
144 PackedPixelColumnIterator
res(*this);
149 PackedPixelColumnIterator
& operator++()
155 PackedPixelColumnIterator
& operator--()
161 PackedPixelColumnIterator
operator++(int)
163 PackedPixelColumnIterator
res(*this);
168 PackedPixelColumnIterator
operator--(int)
170 PackedPixelColumnIterator
res(*this);
175 bool operator==(PackedPixelColumnIterator
const & rhs
) const
180 bool operator!=(PackedPixelColumnIterator
const & rhs
) const
182 return !equal( rhs
);
185 bool operator<(PackedPixelColumnIterator
const & rhs
) const
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
205 difference_type
operator-(PackedPixelColumnIterator
const & rhs
) const
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
,
235 bool MsbFirst
> class PackedPixelRowIterator
: public NonStandardIterator
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
;
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
)
258 difference_type remainder_
;
262 mask_
= get_mask
<value_type
, bits_per_pixel
, MsbFirst
>(remainder_
);
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(
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) :
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(
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
?
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_
) :
325 PackedPixelRowIterator() :
327 mask_( get_mask
<value_type
, bits_per_pixel
, MsbFirst
, difference_type
>(0) ),
331 explicit PackedPixelRowIterator( pointer base
, int x
) :
334 remainder_(x
% num_intraword_positions
)
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
;
359 PackedPixelRowIterator
& operator-=( difference_type d
)
361 // forward to operator+= - which has to cope with negative
366 PackedPixelRowIterator
operator+( difference_type d
)
368 PackedPixelRowIterator
res(*this);
373 PackedPixelRowIterator
operator-( difference_type d
)
375 PackedPixelRowIterator
res(*this);
380 PackedPixelRowIterator
& operator++()
386 PackedPixelRowIterator
& operator--()
392 PackedPixelRowIterator
operator++(int)
394 PackedPixelRowIterator
res(*this);
399 PackedPixelRowIterator
operator--(int)
401 PackedPixelRowIterator
res(*this);
406 bool operator==(PackedPixelRowIterator
const & rhs
) const
411 bool operator!=(PackedPixelRowIterator
const & rhs
) const
413 return !equal( rhs
);
416 bool operator<(PackedPixelRowIterator
const & rhs
) const
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
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
,
446 MsbFirst
>(remainder_
);
449 value_type
get(difference_type d
) const
451 PackedPixelRowIterator
tmp(*this);
456 void set( value_type v
) const
458 const value_type
pixel_value(
460 get_shift
<num_intraword_positions
, bits_per_pixel
, MsbFirst
>(remainder_
))
462 *data_
= (*data_
& ~mask_
) | pixel_value
;
465 void set( value_type v
, difference_type d
) const
467 PackedPixelRowIterator
tmp(*this);
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
,
481 bool MsbFirst
> class PackedPixelIterator
: public NonStandardIterator
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
,
490 MsbFirst
> row_iterator
;
491 typedef PackedPixelColumnIterator
<value_type
,
493 MsbFirst
> column_iterator
;
495 typedef value_type
* pointer
;
497 typedef StridedArrayIterator
< value_type
> MoveY
;
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
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
);
528 PackedPixelIterator() :
533 PackedPixelIterator(pointer base
, int ystride
) :
538 bool operator==(PackedPixelIterator
const & rhs
) const
543 bool operator!=(PackedPixelIterator
const & rhs
) const
548 difference_type
operator-(PackedPixelIterator
const & rhs
) const
550 return difference_type(x
- rhs
.x
, y
- rhs
.y
);
556 PackedPixelIterator
& operator+=(difference_type
const & s
)
563 PackedPixelIterator
& operator-=(difference_type
const & s
)
570 PackedPixelIterator
operator+(difference_type
const & s
) const
572 PackedPixelIterator
ret(*this);
577 PackedPixelIterator
operator-(difference_type
const & s
) const
579 PackedPixelIterator
ret(*this);
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(
620 get_shift
<num_intraword_positions
, bits_per_pixel
, MsbFirst
>(remainder
))
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(
632 get_shift
<num_intraword_positions
, bits_per_pixel
, MsbFirst
>(remainder
))
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
644 template< class Accessor
,
648 bool MsbFirst
> struct maskedAccessorSelector
< Accessor
,
651 PackedPixelIterator
< typename
MaskAccessor::value_type
,
656 typedef TernarySetterFunctionAccessorAdapter
<
659 typename outputMaskFunctorSelector
<
660 typename
Accessor::value_type
,
661 typename
MaskAccessor::value_type
,
667 } // namespace basebmp
669 #endif /* INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX */
671 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */