1*48cdb363SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*48cdb363SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*48cdb363SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*48cdb363SAndrew Rist  * distributed with this work for additional information
6*48cdb363SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*48cdb363SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*48cdb363SAndrew Rist  * "License"); you may not use this file except in compliance
9*48cdb363SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*48cdb363SAndrew Rist  *
11*48cdb363SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*48cdb363SAndrew Rist  *
13*48cdb363SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*48cdb363SAndrew Rist  * software distributed under the License is distributed on an
15*48cdb363SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*48cdb363SAndrew Rist  * KIND, either express or implied.  See the License for the
17*48cdb363SAndrew Rist  * specific language governing permissions and limitations
18*48cdb363SAndrew Rist  * under the License.
19*48cdb363SAndrew Rist  *
20*48cdb363SAndrew Rist  *************************************************************/
21*48cdb363SAndrew Rist 
22*48cdb363SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #ifndef INCLUDED_BASEBMP_TRUECOLORMASKACCESSOR_HXX
25cdf0e10cSrcweir #define INCLUDED_BASEBMP_TRUECOLORMASKACCESSOR_HXX
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <basebmp/colortraits.hxx>
28cdf0e10cSrcweir #include <basebmp/accessortraits.hxx>
29cdf0e10cSrcweir #include <basebmp/metafunctions.hxx>
30cdf0e10cSrcweir #include <basebmp/endian.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <vigra/numerictraits.hxx>
33cdf0e10cSrcweir #include <vigra/metaprogramming.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir namespace basebmp
36cdf0e10cSrcweir {
37cdf0e10cSrcweir 
38cdf0e10cSrcweir namespace
39cdf0e10cSrcweir {
40cdf0e10cSrcweir     /// Shift left for positive shift value, and right otherwise
shiftLeft(T v,int shift)41cdf0e10cSrcweir     template< typename T > inline T shiftLeft( T v, int shift )
42cdf0e10cSrcweir     {
43cdf0e10cSrcweir         return shift > 0 ? v << shift : v >> (-shift);
44cdf0e10cSrcweir     }
45cdf0e10cSrcweir 
46cdf0e10cSrcweir     /// Shift right for positive shift value, and left otherwise
shiftRight(T v,int shift)47cdf0e10cSrcweir     template< typename T > inline T shiftRight( T v, int shift )
48cdf0e10cSrcweir     {
49cdf0e10cSrcweir         return shift > 0 ? v >> shift : v << (-shift);
50cdf0e10cSrcweir     }
51cdf0e10cSrcweir }
52cdf0e10cSrcweir 
53cdf0e10cSrcweir /** Access true color data, which is pixel-packed into a POD.
54cdf0e10cSrcweir 
55cdf0e10cSrcweir     @tpl Accessor
56cdf0e10cSrcweir     Wrapped accessor, used to access the actual pixel values
57cdf0e10cSrcweir 
58cdf0e10cSrcweir     @tpl ColorType
59cdf0e10cSrcweir     Underlying color type, to convert the pixel values into
60cdf0e10cSrcweir 
61cdf0e10cSrcweir     @tpl RedMask
62cdf0e10cSrcweir     Bitmask, to access the red bits in the data type
63cdf0e10cSrcweir 
64cdf0e10cSrcweir     @tpl GreenMask
65cdf0e10cSrcweir     Bitmask, to access the green bits in the data type
66cdf0e10cSrcweir 
67cdf0e10cSrcweir     @tpl BlueMask
68cdf0e10cSrcweir     Bitmask, to access the blue bits in the data type
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     @tpl SwapBytes
71cdf0e10cSrcweir     When true, the final pixel values will be byte-swapped before
72cdf0e10cSrcweir     passed to/from the iterator.
73cdf0e10cSrcweir  */
74cdf0e10cSrcweir template< class    Accessor,
75cdf0e10cSrcweir           typename ColorType,
76cdf0e10cSrcweir           int      RedMask,
77cdf0e10cSrcweir           int      GreenMask,
78cdf0e10cSrcweir           int      BlueMask,
79cdf0e10cSrcweir           bool     SwapBytes > class TrueColorMaskAccessor
80cdf0e10cSrcweir {
81cdf0e10cSrcweir public:
82cdf0e10cSrcweir     typedef typename Accessor::value_type                   data_type;
83cdf0e10cSrcweir     typedef ColorType                                       value_type;
84cdf0e10cSrcweir     typedef typename make_unsigned<data_type>::type         unsigned_data_type;
85cdf0e10cSrcweir     typedef typename ColorTraits<ColorType>::component_type component_type;
86cdf0e10cSrcweir 
87cdf0e10cSrcweir #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
88cdf0e10cSrcweir // making all members public, if no member template friends
89cdf0e10cSrcweir private:
90cdf0e10cSrcweir     template<class A, typename C, int R, int G, int B, bool S> friend class TrueColorMaskAccessor;
91cdf0e10cSrcweir #endif
92cdf0e10cSrcweir 
93cdf0e10cSrcweir     Accessor     maAccessor;
94cdf0e10cSrcweir 
95cdf0e10cSrcweir public:
96cdf0e10cSrcweir     // calc corrective shifts for all three channels in advance
97cdf0e10cSrcweir     enum {
98cdf0e10cSrcweir         red_shift   = numberOfTrailingZeros<RedMask>::value,
99cdf0e10cSrcweir         green_shift = numberOfTrailingZeros<GreenMask>::value,
100cdf0e10cSrcweir         blue_shift  = numberOfTrailingZeros<BlueMask>::value,
101cdf0e10cSrcweir 
102cdf0e10cSrcweir         red_bits    = bitcount<RedMask>::value,
103cdf0e10cSrcweir         green_bits  = bitcount<GreenMask>::value,
104cdf0e10cSrcweir         blue_bits   = bitcount<BlueMask>::value
105cdf0e10cSrcweir     };
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     // -------------------------------------------------------
108cdf0e10cSrcweir 
TrueColorMaskAccessor()109cdf0e10cSrcweir     TrueColorMaskAccessor() :
110cdf0e10cSrcweir         maAccessor()
111cdf0e10cSrcweir     {}
112cdf0e10cSrcweir 
113cdf0e10cSrcweir     template< class A > explicit
TrueColorMaskAccessor(TrueColorMaskAccessor<A,ColorType,RedMask,GreenMask,BlueMask,SwapBytes> const & rSrc)114cdf0e10cSrcweir     TrueColorMaskAccessor( TrueColorMaskAccessor< A,
115cdf0e10cSrcweir                                                   ColorType,
116cdf0e10cSrcweir                                                   RedMask,
117cdf0e10cSrcweir                                                   GreenMask,
118cdf0e10cSrcweir                                                   BlueMask,
119cdf0e10cSrcweir                                                   SwapBytes > const& rSrc ) :
120cdf0e10cSrcweir         maAccessor( rSrc.maAccessor )
121cdf0e10cSrcweir     {}
122cdf0e10cSrcweir 
TrueColorMaskAccessor(T accessor)123cdf0e10cSrcweir     template< class T > explicit TrueColorMaskAccessor( T accessor ) :
124cdf0e10cSrcweir         maAccessor(accessor)
125cdf0e10cSrcweir     {}
126cdf0e10cSrcweir 
127cdf0e10cSrcweir     // -------------------------------------------------------
128cdf0e10cSrcweir 
getWrappedAccessor() const129cdf0e10cSrcweir     Accessor const& getWrappedAccessor() const { return maAccessor; }
getWrappedAccessor()130cdf0e10cSrcweir     Accessor&       getWrappedAccessor() { return maAccessor; }
131cdf0e10cSrcweir 
132cdf0e10cSrcweir     // -------------------------------------------------------
133cdf0e10cSrcweir 
toValue(unsigned_data_type v) const134cdf0e10cSrcweir     value_type toValue( unsigned_data_type v ) const
135cdf0e10cSrcweir     {
136cdf0e10cSrcweir         v = SwapBytes ? byteSwap(v) : v;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         const unsigned_data_type red  (v & RedMask);
139cdf0e10cSrcweir         const unsigned_data_type green(v & GreenMask);
140cdf0e10cSrcweir         const unsigned_data_type blue (v & BlueMask);
141cdf0e10cSrcweir 
142cdf0e10cSrcweir         value_type res( (shiftRight(red,
143cdf0e10cSrcweir                                     red_shift-8*sizeof(component_type)+red_bits)) |
144cdf0e10cSrcweir                         (shiftRight(red,
145cdf0e10cSrcweir                                     red_shift-8*sizeof(component_type)+2*red_bits)),
146cdf0e10cSrcweir 
147cdf0e10cSrcweir                         (shiftRight(green,
148cdf0e10cSrcweir                                     green_shift-8*sizeof(component_type)+green_bits)) |
149cdf0e10cSrcweir                         (shiftRight(green,
150cdf0e10cSrcweir                                     green_shift-8*sizeof(component_type)+2*green_bits)),
151cdf0e10cSrcweir 
152cdf0e10cSrcweir                         (shiftRight(blue,
153cdf0e10cSrcweir                                     blue_shift-8*sizeof(component_type)+blue_bits)) |
154cdf0e10cSrcweir                         (shiftRight(blue,
155cdf0e10cSrcweir                                     blue_shift-8*sizeof(component_type)+2*blue_bits)) );
156cdf0e10cSrcweir         return res;
157cdf0e10cSrcweir     }
158cdf0e10cSrcweir 
toPacked(value_type v) const159cdf0e10cSrcweir     data_type toPacked( value_type v ) const
160cdf0e10cSrcweir     {
161cdf0e10cSrcweir         const unsigned_data_type red  (v.getRed());
162cdf0e10cSrcweir         const unsigned_data_type green(v.getGreen());
163cdf0e10cSrcweir         const unsigned_data_type blue (v.getBlue());
164cdf0e10cSrcweir 
165cdf0e10cSrcweir         unsigned_data_type res(
166cdf0e10cSrcweir             (shiftLeft(red,
167cdf0e10cSrcweir                        red_shift-8*sizeof(component_type)+red_bits) & RedMask) |
168cdf0e10cSrcweir             (shiftLeft(green,
169cdf0e10cSrcweir                        green_shift-8*sizeof(component_type)+green_bits) & GreenMask) |
170cdf0e10cSrcweir             (shiftLeft(blue,
171cdf0e10cSrcweir                        blue_shift-8*sizeof(component_type)+blue_bits) & BlueMask) );
172cdf0e10cSrcweir 
173cdf0e10cSrcweir         return SwapBytes ? byteSwap(res) : res;
174cdf0e10cSrcweir     }
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     // -------------------------------------------------------
177cdf0e10cSrcweir 
178cdf0e10cSrcweir     template< class Iterator >
operator ()(Iterator const & i) const179cdf0e10cSrcweir     value_type operator()(Iterator const& i) const
180cdf0e10cSrcweir     {
181cdf0e10cSrcweir         return toValue(
182cdf0e10cSrcweir             unsigned_cast<data_type>( maAccessor(i)) );
183cdf0e10cSrcweir     }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir     template< class Iterator, class Difference >
operator ()(Iterator const & i,Difference const & diff) const186cdf0e10cSrcweir     value_type operator()(Iterator const& i, Difference const& diff) const
187cdf0e10cSrcweir     {
188cdf0e10cSrcweir         return toValue(
189cdf0e10cSrcweir             unsigned_cast<data_type>( maAccessor(i,diff)) );
190cdf0e10cSrcweir     }
191cdf0e10cSrcweir 
192cdf0e10cSrcweir     // -------------------------------------------------------
193cdf0e10cSrcweir 
194cdf0e10cSrcweir     template< typename V, class Iterator >
set(V const & value,Iterator const & i) const195cdf0e10cSrcweir     void set(V const& value, Iterator const& i) const
196cdf0e10cSrcweir     {
197cdf0e10cSrcweir         maAccessor.set(
198cdf0e10cSrcweir             toPacked(
199cdf0e10cSrcweir                 vigra::detail::RequiresExplicitCast<value_type>::cast(
200cdf0e10cSrcweir                     value) ),
201cdf0e10cSrcweir             i);
202cdf0e10cSrcweir     }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     template< typename V, class Iterator, class Difference >
set(V const & value,Iterator const & i,Difference const & diff) const205cdf0e10cSrcweir     void set(V const& value, Iterator const& i, Difference const& diff) const
206cdf0e10cSrcweir     {
207cdf0e10cSrcweir         maAccessor.set(
208cdf0e10cSrcweir             toPacked(
209cdf0e10cSrcweir                 vigra::detail::RequiresExplicitCast<value_type>::cast(
210cdf0e10cSrcweir                     value)),
211cdf0e10cSrcweir             i,
212cdf0e10cSrcweir             diff );
213cdf0e10cSrcweir     }
214cdf0e10cSrcweir };
215cdf0e10cSrcweir 
216cdf0e10cSrcweir //-----------------------------------------------------------------------------
217cdf0e10cSrcweir 
218cdf0e10cSrcweir /** Convert Color to packed true color value for TrueColorMaskAccessor
219cdf0e10cSrcweir  */
220cdf0e10cSrcweir template< class Accessor > struct ColorConvert
221cdf0e10cSrcweir {
operator ()basebmp::ColorConvert222cdf0e10cSrcweir     typename Accessor::data_type operator()( const Accessor&               acc,
223cdf0e10cSrcweir                                              typename Accessor::value_type v )
224cdf0e10cSrcweir     {
225cdf0e10cSrcweir         return acc.toPacked(v);
226cdf0e10cSrcweir     }
227cdf0e10cSrcweir };
228cdf0e10cSrcweir 
229cdf0e10cSrcweir //-----------------------------------------------------------------------------
230cdf0e10cSrcweir 
231cdf0e10cSrcweir // partial specialization for TrueColorMaskAccessor
232cdf0e10cSrcweir template< class    Accessor,
233cdf0e10cSrcweir           typename ColorType,
234cdf0e10cSrcweir           int      RedMask,
235cdf0e10cSrcweir           int      GreenMask,
236cdf0e10cSrcweir           int      BlueMask,
237cdf0e10cSrcweir           bool     SwapBytes > struct AccessorTraits<
238cdf0e10cSrcweir     TrueColorMaskAccessor< Accessor,
239cdf0e10cSrcweir                            ColorType,
240cdf0e10cSrcweir                            RedMask,
241cdf0e10cSrcweir                            GreenMask,
242cdf0e10cSrcweir                            BlueMask,
243cdf0e10cSrcweir                            SwapBytes > >
244cdf0e10cSrcweir {
245cdf0e10cSrcweir     /// value type of described accessor
246cdf0e10cSrcweir     typedef typename TrueColorMaskAccessor< Accessor,
247cdf0e10cSrcweir                                             ColorType,
248cdf0e10cSrcweir                                             RedMask,
249cdf0e10cSrcweir                                             GreenMask,
250cdf0e10cSrcweir                                             BlueMask,
251cdf0e10cSrcweir                                             SwapBytes >::value_type  value_type;
252cdf0e10cSrcweir 
253cdf0e10cSrcweir     /// Retrieve stand-alone color lookup function for given Accessor type
254cdf0e10cSrcweir     typedef ColorConvert< TrueColorMaskAccessor< Accessor,
255cdf0e10cSrcweir                                                  ColorType,
256cdf0e10cSrcweir                                                  RedMask,
257cdf0e10cSrcweir                                                  GreenMask,
258cdf0e10cSrcweir                                                  BlueMask,
259cdf0e10cSrcweir                                                  SwapBytes > >        color_lookup;
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     /// Retrieve raw pixel data accessor for given Accessor type
262cdf0e10cSrcweir     typedef Accessor                                                 raw_accessor;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     /** accessor for XOR setter access is disabled, since the results
265cdf0e10cSrcweir      *  are usually completely unintended - you'll usually want to
266cdf0e10cSrcweir      *  wrap an xor_accessor with a TrueColorMaskAccessor, not the
267cdf0e10cSrcweir      *  other way around.
268cdf0e10cSrcweir      */
269cdf0e10cSrcweir     typedef vigra::VigraFalseType                                    xor_accessor;
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     /** accessor for masked setter access is disabled, since the
272cdf0e10cSrcweir      *  results are usually completely unintended - you'll usually
273cdf0e10cSrcweir      *  want to wrap a masked_accessor with a TrueColorMaskAccessor,
274cdf0e10cSrcweir      *  not the other way around.
275cdf0e10cSrcweir      */
276cdf0e10cSrcweir     template< class MaskAccessor,
277cdf0e10cSrcweir               class Iterator,
278cdf0e10cSrcweir               class MaskIterator > struct                            masked_accessor
279cdf0e10cSrcweir     {
280cdf0e10cSrcweir         typedef vigra::VigraFalseType type;
281cdf0e10cSrcweir     };
282cdf0e10cSrcweir };
283cdf0e10cSrcweir 
284cdf0e10cSrcweir } // namespace basebmp
285cdf0e10cSrcweir 
286cdf0e10cSrcweir #endif /* INCLUDED_BASEBMP_TRUECOLORMASKACCESSOR_HXX */
287