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_RGBMASKPIXELFORMATS_HXX
25 #define INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX
26 
27 #include <basebmp/color.hxx>
28 #include <basebmp/colortraits.hxx>
29 #include <basebmp/accessor.hxx>
30 #include <basebmp/pixeliterator.hxx>
31 #include <basebmp/pixelformatadapters.hxx>
32 #include <basebmp/metafunctions.hxx>
33 #include <basebmp/endian.hxx>
34 
35 #include <vigra/numerictraits.hxx>
36 #include <vigra/metaprogramming.hxx>
37 
38 #include <functional>
39 
40 namespace basebmp
41 {
42 
43 /** Base class operating on RGB truecolor mask pixel
44 
45     Use this template, if you have an (integer) pixel type, and three
46     bitmasks denoting where the channel bits are.
47 
48     @tpl PixelType
49     Input pixel type to operate on
50 
51     @tpl ColorType
52     Underlying color type, to convert the pixel values into
53 
54     @tpl RedMask
55     Bitmask, to access the red bits in the data type
56 
57     @tpl GreenMask
58     Bitmask, to access the green bits in the data type
59 
60     @tpl BlueMask
61     Bitmask, to access the blue bits in the data type
62 
63     @tpl SwapBytes
64     When true, the final pixel values will be byte-swapped before
65     passed on.
66  */
67 template< typename     PixelType,
68           typename     ColorType,
69           unsigned int RedMask,
70           unsigned int GreenMask,
71           unsigned int BlueMask,
72           bool         SwapBytes > struct RGBMaskFunctorBase
73 {
74     typedef PixelType                                       pixel_type;
75     typedef ColorType                                       color_type;
76     typedef typename make_unsigned<pixel_type>::type        unsigned_pixel_type;
77     typedef typename ColorTraits<ColorType>::component_type component_type;
78 
79     // calc corrective shifts for all three channels in advance
80     enum {
81         red_shift   = numberOfTrailingZeros<RedMask>::value,
82         green_shift = numberOfTrailingZeros<GreenMask>::value,
83         blue_shift  = numberOfTrailingZeros<BlueMask>::value,
84 
85         red_bits    = bitcount<RedMask>::value,
86         green_bits  = bitcount<GreenMask>::value,
87         blue_bits   = bitcount<BlueMask>::value
88     };
89 };
90 
91 template< typename     PixelType,
92           typename     ColorType,
93           unsigned int RedMask,
94           unsigned int GreenMask,
95           unsigned int BlueMask,
96           bool         SwapBytes > struct RGBMaskGetter :
97         public RGBMaskFunctorBase<PixelType,
98                                   ColorType,
99                                   RedMask,
100                                   GreenMask,
101                                   BlueMask,
102                                   SwapBytes>,
103         public std::unary_function<PixelType, ColorType>
104 {
105     typedef RGBMaskFunctorBase<PixelType,
106                                ColorType,
107                                RedMask,
108                                GreenMask,
109                                BlueMask,
110                                SwapBytes> base_type;
111 
operator ()basebmp::RGBMaskGetter112     ColorType operator()( PixelType v ) const
113     {
114         v = SwapBytes ? byteSwap(v) : v;
115 
116         const typename base_type::unsigned_pixel_type red  (v & RedMask);
117         const typename base_type::unsigned_pixel_type green(v & GreenMask);
118         const typename base_type::unsigned_pixel_type blue (v & BlueMask);
119 
120         // shift color nibbles to right-aligend position. ORing it
121         // channel value shifted twice the number of channel bits, to
122         // spread the value into the component_type range
123         ColorType res( (shiftRight(red,
124                                    base_type::red_shift-8*
125                                    (signed)sizeof(typename base_type::component_type)+
126                                    base_type::red_bits)) |
127                        (shiftRight(red,
128                                    base_type::red_shift-8*
129                                    (signed)sizeof(typename base_type::component_type)+
130                                    2*base_type::red_bits)),
131 
132                        (shiftRight(green,
133                                    base_type::green_shift-8*
134                                    (signed)sizeof(typename base_type::component_type)+
135                                    base_type::green_bits)) |
136                        (shiftRight(green,
137                                    base_type::green_shift-8*
138                                    (signed)sizeof(typename base_type::component_type)+
139                                    2*base_type::green_bits)),
140 
141                        (shiftRight(blue,
142                                    base_type::blue_shift-8*
143                                    (signed)sizeof(typename base_type::component_type)+
144                                    base_type::blue_bits)) |
145                        (shiftRight(blue,
146                                    base_type::blue_shift-8*
147                                    (signed)sizeof(typename base_type::component_type)+
148                                    2*base_type::blue_bits)) );
149         return res;
150     }
151 };
152 
153 template< typename     PixelType,
154           typename     ColorType,
155           unsigned int RedMask,
156           unsigned int GreenMask,
157           unsigned int BlueMask,
158           bool         SwapBytes > struct RGBMaskSetter :
159         public RGBMaskFunctorBase<PixelType,
160                                   ColorType,
161                                   RedMask,
162                                   GreenMask,
163                                   BlueMask,
164                                   SwapBytes>,
165         public std::unary_function<ColorType, PixelType>
166 {
167     typedef RGBMaskFunctorBase<PixelType,
168                                ColorType,
169                                RedMask,
170                                GreenMask,
171                                BlueMask,
172                                SwapBytes> base_type;
173 
operator ()basebmp::RGBMaskSetter174     PixelType operator()( ColorType const& c ) const
175     {
176         const typename base_type::unsigned_pixel_type red  (c.getRed());
177         const typename base_type::unsigned_pixel_type green(c.getGreen());
178         const typename base_type::unsigned_pixel_type blue (c.getBlue());
179 
180         typename base_type::unsigned_pixel_type res(
181             (shiftLeft(red,
182                        base_type::red_shift-8*
183                        (signed)sizeof(typename base_type::component_type)+
184                        base_type::red_bits) & RedMask) |
185             (shiftLeft(green,
186                        base_type::green_shift-8*
187                        (signed)sizeof(typename base_type::component_type)+
188                        base_type::green_bits) & GreenMask) |
189             (shiftLeft(blue,
190                        base_type::blue_shift-8*
191                        (signed)sizeof(typename base_type::component_type)+
192                        base_type::blue_bits) & BlueMask) );
193 
194         return SwapBytes ? byteSwap(res) : res;
195     }
196 };
197 
198 //-----------------------------------------------------------------------------
199 
200 template< typename     PixelType,
201           unsigned int RedMask,
202           unsigned int GreenMask,
203           unsigned int BlueMask,
204           bool         SwapBytes > struct PixelFormatTraitsTemplate_RGBMask
205 {
206     typedef PixelType                           pixel_type;
207 
208     typedef RGBMaskGetter<pixel_type,
209                           Color,
210                           RedMask,
211                           GreenMask,
212                           BlueMask,
213                           SwapBytes>            getter_type;
214     typedef RGBMaskSetter<pixel_type,
215                           Color,
216                           RedMask,
217                           GreenMask,
218                           BlueMask,
219                           SwapBytes>            setter_type;
220 
221     typedef PixelIterator<pixel_type>           iterator_type;
222     typedef StandardAccessor<pixel_type>        raw_accessor_type;
223     typedef AccessorSelector<
224         getter_type, setter_type>               accessor_selector;
225 };
226 
227 //-----------------------------------------------------------------------------
228 
229 #ifdef OSL_LITENDIAN
230 # define BASEBMP_TRUECOLORMASK_LSB_SWAP false
231 # define BASEBMP_TRUECOLORMASK_MSB_SWAP true
232 #else
233 # ifdef OSL_BIGENDIAN
234 #  define BASEBMP_TRUECOLORMASK_LSB_SWAP true
235 #  define BASEBMP_TRUECOLORMASK_MSB_SWAP false
236 # else
237 #  error Undetermined endianness!
238 # endif
239 #endif
240 
241 //-----------------------------------------------------------------------------
242 
243 // 16bpp MSB RGB
244 typedef PixelFormatTraitsTemplate_RGBMask<
245     sal_uInt16,
246     0xF800,
247     0x07E0,
248     0x001F,
249     BASEBMP_TRUECOLORMASK_MSB_SWAP >            PixelFormatTraits_RGB16_565_MSB;
250 BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB16_565_MSB::getter_type,
251                                   PixelFormatTraits_RGB16_565_MSB::setter_type);
252 
253 // 16bpp LSB RGB
254 typedef PixelFormatTraitsTemplate_RGBMask<
255     sal_uInt16,
256     0xF800,
257     0x07E0,
258     0x001F,
259     BASEBMP_TRUECOLORMASK_LSB_SWAP >            PixelFormatTraits_RGB16_565_LSB;
260 BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB16_565_LSB::getter_type,
261                                   PixelFormatTraits_RGB16_565_LSB::setter_type);
262 
263 // 32bpp endian-sensitive RGB
264 typedef PixelFormatTraitsTemplate_RGBMask<
265     sal_uInt32,
266     0xFF0000,
267     0x00FF00,
268     0x0000FF,
269     BASEBMP_TRUECOLORMASK_LSB_SWAP >            PixelFormatTraits_RGB32_888;
270 BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB32_888::getter_type,
271                                   PixelFormatTraits_RGB32_888::setter_type);
272 
273 // 32bpp endian-sensitive BGR
274 typedef PixelFormatTraitsTemplate_RGBMask<
275     sal_uInt32,
276     0xFF0000,
277     0x00FF00,
278     0x0000FF,
279     BASEBMP_TRUECOLORMASK_MSB_SWAP >            PixelFormatTraits_BGR32_888;
280 BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_BGR32_888::getter_type,
281                                   PixelFormatTraits_BGR32_888::setter_type);
282 
283 } // namespace basebmp
284 
285 #endif /* INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX */
286