Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef INCLUDED_BASEBMP_SCALEIMAGE_HXX
21 : #define INCLUDED_BASEBMP_SCALEIMAGE_HXX
22 :
23 : #include <osl/diagnose.h>
24 :
25 : #include <vigra/tuple.hxx>
26 : #include <vigra/copyimage.hxx>
27 : #include <vigra/basicimage.hxx>
28 : #include <vigra/iteratortraits.hxx>
29 :
30 : namespace basebmp
31 : {
32 :
33 : template< class SourceIter, class SourceAcc,
34 : class DestIter, class DestAcc >
35 32056 : void scaleLine( SourceIter s_begin,
36 : SourceIter s_end,
37 : SourceAcc s_acc,
38 : DestIter d_begin,
39 : DestIter d_end,
40 : DestAcc d_acc )
41 : {
42 32056 : const int src_width = s_end - s_begin;
43 32056 : const int dest_width = d_end - d_begin;
44 :
45 : OSL_ASSERT( src_width > 0 && dest_width > 0 );
46 :
47 32056 : if( src_width >= dest_width )
48 : {
49 : // shrink
50 2020 : int rem = 0;
51 30844 : while( s_begin != s_end )
52 : {
53 26804 : if( rem >= 0 )
54 : {
55 15384 : d_acc.set( s_acc(s_begin), d_begin );
56 :
57 15384 : rem -= src_width;
58 15384 : ++d_begin;
59 : }
60 :
61 26804 : rem += dest_width;
62 26804 : ++s_begin;
63 : }
64 : }
65 : else
66 : {
67 : // enlarge
68 30036 : int rem = -dest_width;
69 5454579 : while( d_begin != d_end )
70 : {
71 5394507 : if( rem >= 0 )
72 : {
73 2066514 : rem -= dest_width;
74 2066514 : ++s_begin;
75 : }
76 :
77 5394507 : d_acc.set( s_acc(s_begin), d_begin );
78 :
79 5394507 : rem += src_width;
80 5394507 : ++d_begin;
81 : }
82 : }
83 32056 : }
84 :
85 : /** Scale an image using zero order interpolation (pixel replication)
86 :
87 : Source and destination range must be at least one pixel wide and
88 : high.
89 :
90 : @param s_begin
91 : Start iterator for source image
92 :
93 : @param s_end
94 : End iterator for source image
95 :
96 : @param s_acc
97 : Source accessor
98 :
99 : @param d_begin
100 : Start iterator for destination image
101 :
102 : @param d_end
103 : End iterator for destination image
104 :
105 : @param d_acc
106 : Destination accessor
107 :
108 : @param bMustCopy
109 : When true, scaleImage always copies source, even when doing 1:1
110 : copy
111 : */
112 : template< class SourceIter, class SourceAcc,
113 : class DestIter, class DestAcc >
114 36159 : void scaleImage( SourceIter s_begin,
115 : SourceIter s_end,
116 : SourceAcc s_acc,
117 : DestIter d_begin,
118 : DestIter d_end,
119 : DestAcc d_acc,
120 : bool bMustCopy=false )
121 : {
122 36159 : const int src_width ( s_end.x - s_begin.x );
123 36159 : const int src_height( s_end.y - s_begin.y );
124 :
125 36159 : const int dest_width ( d_end.x - d_begin.x );
126 36159 : const int dest_height( d_end.y - d_begin.y );
127 :
128 36159 : if( !bMustCopy &&
129 : src_width == dest_width &&
130 : src_height == dest_height )
131 : {
132 : // no scaling involved, can simply copy
133 35379 : vigra::copyImage( s_begin, s_end, s_acc,
134 48956 : d_begin, d_acc );
135 71538 : return;
136 : }
137 :
138 : typedef vigra::BasicImage<typename SourceAcc::value_type> TmpImage;
139 : typedef typename TmpImage::traverser TmpImageIter;
140 :
141 : TmpImage tmp_image(src_width,
142 780 : dest_height);
143 780 : TmpImageIter t_begin = tmp_image.upperLeft();
144 :
145 : // scale in y direction
146 10973 : for( int x=0; x<src_width; ++x, ++s_begin.x, ++t_begin.x )
147 : {
148 10193 : typename SourceIter::column_iterator s_cbegin = s_begin.columnIterator();
149 10193 : typename TmpImageIter::column_iterator t_cbegin = t_begin.columnIterator();
150 :
151 10193 : scaleLine(s_cbegin, s_cbegin+src_height, s_acc,
152 20386 : t_cbegin, t_cbegin+dest_height, tmp_image.accessor());
153 : }
154 :
155 780 : t_begin = tmp_image.upperLeft();
156 :
157 : // scale in x direction
158 22643 : for( int y=0; y<dest_height; ++y, ++d_begin.y, ++t_begin.y )
159 : {
160 21863 : typename DestIter::row_iterator d_rbegin = d_begin.rowIterator();
161 21863 : typename TmpImageIter::row_iterator t_rbegin = t_begin.rowIterator();
162 :
163 21863 : scaleLine(t_rbegin, t_rbegin+src_width, tmp_image.accessor(),
164 43726 : d_rbegin, d_rbegin+dest_width, d_acc);
165 780 : }
166 : }
167 :
168 : /** Scale an image, range tuple version
169 :
170 : @param bMustCopy
171 : When true, scaleImage always copies source, even when doing 1:1
172 : copy
173 : */
174 : template< class SourceIter, class SourceAcc,
175 : class DestIter, class DestAcc >
176 36159 : inline void scaleImage( vigra::triple<SourceIter,SourceIter,SourceAcc> const& src,
177 : vigra::triple<DestIter,DestIter,DestAcc> const& dst,
178 : bool bMustCopy=false )
179 : {
180 36159 : scaleImage(src.first,src.second,src.third,
181 : dst.first,dst.second,dst.third,
182 61355 : bMustCopy);
183 36159 : }
184 :
185 : }
186 :
187 : #endif /* INCLUDED_BASEBMP_SCALEIMAGE_HXX */
188 :
189 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|