xref: /trunk/main/basebmp/inc/basebmp/scaleimage.hxx (revision 48cdb363)
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_SCALEIMAGE_HXX
25 #define INCLUDED_BASEBMP_SCALEIMAGE_HXX
26 
27 #include <osl/diagnose.h>
28 
29 #include <vigra/tuple.hxx>
30 #include <vigra/copyimage.hxx>
31 #include <vigra/basicimage.hxx>
32 #include <vigra/iteratortraits.hxx>
33 
34 namespace basebmp
35 {
36 
37 template< class SourceIter, class SourceAcc,
38           class DestIter, class DestAcc >
scaleLine(SourceIter s_begin,SourceIter s_end,SourceAcc s_acc,DestIter d_begin,DestIter d_end,DestAcc d_acc)39 void scaleLine( SourceIter      s_begin,
40                 SourceIter      s_end,
41                 SourceAcc       s_acc,
42                 DestIter        d_begin,
43                 DestIter        d_end,
44                 DestAcc         d_acc )
45 {
46     const int src_width  = s_end - s_begin;
47     const int dest_width = d_end - d_begin;
48 
49     OSL_ASSERT( src_width > 0 && dest_width > 0 );
50 
51     if( src_width >= dest_width )
52     {
53         // shrink
54         int rem = 0;
55         while( s_begin != s_end )
56         {
57             if( rem >= 0 )
58             {
59                 d_acc.set( s_acc(s_begin), d_begin );
60 
61                 rem -= src_width;
62                 ++d_begin;
63             }
64 
65             rem += dest_width;
66             ++s_begin;
67         }
68     }
69     else
70     {
71         // enlarge
72         int rem = -dest_width;
73         while( d_begin != d_end )
74         {
75             if( rem >= 0 )
76             {
77                 rem -= dest_width;
78                 ++s_begin;
79             }
80 
81             d_acc.set( s_acc(s_begin), d_begin );
82 
83             rem += src_width;
84             ++d_begin;
85         }
86     }
87 }
88 
89 /** Scale an image using zero order interpolation (pixel replication)
90 
91     Source and destination range must be at least one pixel wide and
92     high.
93 
94     @param s_begin
95     Start iterator for source image
96 
97     @param s_end
98     End iterator for source image
99 
100     @param s_acc
101     Source accessor
102 
103     @param d_begin
104     Start iterator for destination image
105 
106     @param d_end
107     End iterator for destination image
108 
109     @param d_acc
110     Destination accessor
111 
112     @param bMustCopy
113     When true, scaleImage always copies source, even when doing 1:1
114     copy
115  */
116 template< class SourceIter, class SourceAcc,
117           class DestIter, class DestAcc >
scaleImage(SourceIter s_begin,SourceIter s_end,SourceAcc s_acc,DestIter d_begin,DestIter d_end,DestAcc d_acc,bool bMustCopy=false)118 void scaleImage( SourceIter      s_begin,
119                  SourceIter      s_end,
120                  SourceAcc       s_acc,
121                  DestIter        d_begin,
122                  DestIter        d_end,
123                  DestAcc         d_acc,
124                  bool            bMustCopy=false )
125 {
126     const int src_width ( s_end.x - s_begin.x );
127     const int src_height( s_end.y - s_begin.y );
128 
129     const int dest_width ( d_end.x - d_begin.x );
130     const int dest_height( d_end.y - d_begin.y );
131 
132     if( !bMustCopy &&
133         src_width == dest_width &&
134         src_height == dest_height )
135     {
136         // no scaling involved, can simply copy
137         vigra::copyImage( s_begin, s_end, s_acc,
138                           d_begin, d_acc );
139         return;
140     }
141 
142     typedef vigra::BasicImage<typename SourceAcc::value_type> TmpImage;
143     typedef typename TmpImage::traverser TmpImageIter;
144 
145     TmpImage     tmp_image(src_width,
146                            dest_height);
147     TmpImageIter t_begin = tmp_image.upperLeft();
148 
149     // scale in y direction
150     for( int x=0; x<src_width; ++x, ++s_begin.x, ++t_begin.x )
151     {
152         typename SourceIter::column_iterator   s_cbegin = s_begin.columnIterator();
153         typename TmpImageIter::column_iterator t_cbegin = t_begin.columnIterator();
154 
155         scaleLine(s_cbegin, s_cbegin+src_height, s_acc,
156                   t_cbegin, t_cbegin+dest_height, tmp_image.accessor());
157     }
158 
159     t_begin = tmp_image.upperLeft();
160 
161     // scale in x direction
162     for( int y=0; y<dest_height; ++y, ++d_begin.y, ++t_begin.y )
163     {
164         typename DestIter::row_iterator     d_rbegin = d_begin.rowIterator();
165         typename TmpImageIter::row_iterator t_rbegin = t_begin.rowIterator();
166 
167         scaleLine(t_rbegin, t_rbegin+src_width, tmp_image.accessor(),
168                   d_rbegin, d_rbegin+dest_width, d_acc);
169     }
170 }
171 
172 /** Scale an image, range tuple version
173 
174     @param bMustCopy
175     When true, scaleImage always copies source, even when doing 1:1
176     copy
177  */
178 template< class SourceIter, class SourceAcc,
179           class DestIter, class DestAcc >
scaleImage(vigra::triple<SourceIter,SourceIter,SourceAcc> const & src,vigra::triple<DestIter,DestIter,DestAcc> const & dst,bool bMustCopy=false)180 inline void scaleImage( vigra::triple<SourceIter,SourceIter,SourceAcc> const& src,
181                         vigra::triple<DestIter,DestIter,DestAcc> const&       dst,
182                         bool                                                  bMustCopy=false )
183 {
184     scaleImage(src.first,src.second,src.third,
185                dst.first,dst.second,dst.third,
186                bMustCopy);
187 }
188 
189 }
190 
191 #endif /* INCLUDED_BASEBMP_SCALEIMAGE_HXX */
192