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