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