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_PALETTEIMAGEACCESSOR_HXX
25 #define INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX
26 
27 #include <basebmp/colortraits.hxx>
28 #include <basebmp/accessortraits.hxx>
29 
30 #include <vigra/numerictraits.hxx>
31 #include <vigra/metaprogramming.hxx>
32 
33 #include <algorithm>
34 #include <functional>
35 
36 namespace basebmp
37 {
38 
39 /** Access pixel data via palette indirection
40 
41     @tpl Accessor
42     Raw accessor, to be used to actually access the pixel values
43 
44     @tpl ColorType
45     The color value type to use - e.g. the palette is an array of that
46     type
47  */
48 template< class Accessor, typename ColorType > class PaletteImageAccessor
49 {
50 public:
51     typedef typename Accessor::value_type  data_type;
52     typedef ColorType                      value_type;
53 
54 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
55 // making all members public, if no member template friends
56 private:
57     template<class A, typename C> friend class PaletteImageAccessor;
58 #endif
59 
60     Accessor          maAccessor;
61     const value_type* mpPalette;
62     std::size_t       mnNumEntries;
63 
64 public:
PaletteImageAccessor()65     PaletteImageAccessor() :
66         maAccessor(),
67         mpPalette(0),
68         mnNumEntries(0)
69     {}
70 
71     template< class A > explicit
PaletteImageAccessor(PaletteImageAccessor<A,ColorType> const & rSrc)72     PaletteImageAccessor( PaletteImageAccessor<A,ColorType> const& rSrc ) :
73         maAccessor( rSrc.maAccessor ),
74         mpPalette( rSrc.mpPalette ),
75         mnNumEntries( rSrc.mnNumEntries )
76     {}
77 
PaletteImageAccessor(const value_type * pPalette,std::size_t numEntries)78     PaletteImageAccessor( const value_type* pPalette,
79                           std::size_t       numEntries ) :
80         maAccessor(),
81         mpPalette(pPalette),
82         mnNumEntries(numEntries)
83     {}
84 
PaletteImageAccessor(T accessor,const value_type * pPalette,std::size_t numEntries)85     template< class T > PaletteImageAccessor( T                 accessor,
86                                               const value_type* pPalette,
87                                               std::size_t       numEntries ) :
88         maAccessor(accessor),
89         mpPalette(pPalette),
90         mnNumEntries(numEntries)
91     {}
92 
93     // -------------------------------------------------------
94 
getWrappedAccessor() const95     Accessor const& getWrappedAccessor() const { return maAccessor; }
getWrappedAccessor()96     Accessor&       getWrappedAccessor() { return maAccessor; }
97 
98     // -------------------------------------------------------
99 
lookup(value_type const & v) const100     data_type lookup(value_type const& v) const
101     {
102         // TODO(P3): use table-based/octree approach here!
103         const value_type* best_entry;
104         const value_type* palette_end( mpPalette+mnNumEntries );
105         if( (best_entry=std::find( mpPalette, palette_end, v)) != palette_end )
106             return best_entry-mpPalette;
107 
108         const value_type* curr_entry( mpPalette );
109         best_entry = curr_entry;
110         while( curr_entry != palette_end )
111         {
112             if( ColorTraits<value_type>::distance(*curr_entry,
113                                                   *best_entry)
114                 > ColorTraits<value_type>::distance(*curr_entry,
115                                                     v) )
116             {
117                 best_entry = curr_entry;
118             }
119 
120             ++curr_entry;
121         }
122 
123         return best_entry-mpPalette;
124     }
125 
126     // -------------------------------------------------------
127 
128     template< class Iterator >
operator ()(Iterator const & i) const129     value_type operator()(Iterator const& i) const
130     {
131         return mpPalette[ maAccessor(i) ];
132     }
133 
134     template< class Iterator, class Difference >
operator ()(Iterator const & i,Difference const & diff) const135     value_type operator()(Iterator const& i, Difference const& diff) const
136     {
137         return mpPalette[ maAccessor(i,diff) ];
138     }
139 
140     // -------------------------------------------------------
141 
142     template< typename V, class Iterator >
set(V const & value,Iterator const & i) const143     void set(V const& value, Iterator const& i) const
144     {
145         maAccessor.set(
146             lookup(
147                 vigra::detail::RequiresExplicitCast<value_type>::cast(value) ),
148             i );
149     }
150 
151     template< typename V, class Iterator, class Difference >
set(V const & value,Iterator const & i,Difference const & diff) const152     void set(V const& value, Iterator const& i, Difference const& diff) const
153     {
154         maAccessor.set(
155             lookup(
156                 vigra::detail::RequiresExplicitCast<value_type>::cast(value) ),
157             i,
158             diff );
159     }
160 };
161 
162 } // namespace basebmp
163 
164 #endif /* INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX */
165