1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef INCLUDED_BASEBMP_SCALEIMAGE_HXX 29 #define INCLUDED_BASEBMP_SCALEIMAGE_HXX 30 31 #include <osl/diagnose.h> 32 33 #include <vigra/tuple.hxx> 34 #include <vigra/copyimage.hxx> 35 #include <vigra/basicimage.hxx> 36 #include <vigra/iteratortraits.hxx> 37 38 namespace basebmp 39 { 40 41 template< class SourceIter, class SourceAcc, 42 class DestIter, class DestAcc > 43 void scaleLine( SourceIter s_begin, 44 SourceIter s_end, 45 SourceAcc s_acc, 46 DestIter d_begin, 47 DestIter d_end, 48 DestAcc d_acc ) 49 { 50 const int src_width = s_end - s_begin; 51 const int dest_width = d_end - d_begin; 52 53 OSL_ASSERT( src_width > 0 && dest_width > 0 ); 54 55 if( src_width >= dest_width ) 56 { 57 // shrink 58 int rem = 0; 59 while( s_begin != s_end ) 60 { 61 if( rem >= 0 ) 62 { 63 d_acc.set( s_acc(s_begin), d_begin ); 64 65 rem -= src_width; 66 ++d_begin; 67 } 68 69 rem += dest_width; 70 ++s_begin; 71 } 72 } 73 else 74 { 75 // enlarge 76 int rem = -dest_width; 77 while( d_begin != d_end ) 78 { 79 if( rem >= 0 ) 80 { 81 rem -= dest_width; 82 ++s_begin; 83 } 84 85 d_acc.set( s_acc(s_begin), d_begin ); 86 87 rem += src_width; 88 ++d_begin; 89 } 90 } 91 } 92 93 /** Scale an image using zero order interpolation (pixel replication) 94 95 Source and destination range must be at least one pixel wide and 96 high. 97 98 @param s_begin 99 Start iterator for source image 100 101 @param s_end 102 End iterator for source image 103 104 @param s_acc 105 Source accessor 106 107 @param d_begin 108 Start iterator for destination image 109 110 @param d_end 111 End iterator for destination image 112 113 @param d_acc 114 Destination accessor 115 116 @param bMustCopy 117 When true, scaleImage always copies source, even when doing 1:1 118 copy 119 */ 120 template< class SourceIter, class SourceAcc, 121 class DestIter, class DestAcc > 122 void scaleImage( SourceIter s_begin, 123 SourceIter s_end, 124 SourceAcc s_acc, 125 DestIter d_begin, 126 DestIter d_end, 127 DestAcc d_acc, 128 bool bMustCopy=false ) 129 { 130 const int src_width ( s_end.x - s_begin.x ); 131 const int src_height( s_end.y - s_begin.y ); 132 133 const int dest_width ( d_end.x - d_begin.x ); 134 const int dest_height( d_end.y - d_begin.y ); 135 136 if( !bMustCopy && 137 src_width == dest_width && 138 src_height == dest_height ) 139 { 140 // no scaling involved, can simply copy 141 vigra::copyImage( s_begin, s_end, s_acc, 142 d_begin, d_acc ); 143 return; 144 } 145 146 typedef vigra::BasicImage<typename SourceAcc::value_type> TmpImage; 147 typedef typename TmpImage::traverser TmpImageIter; 148 149 TmpImage tmp_image(src_width, 150 dest_height); 151 TmpImageIter t_begin = tmp_image.upperLeft(); 152 153 // scale in y direction 154 for( int x=0; x<src_width; ++x, ++s_begin.x, ++t_begin.x ) 155 { 156 typename SourceIter::column_iterator s_cbegin = s_begin.columnIterator(); 157 typename TmpImageIter::column_iterator t_cbegin = t_begin.columnIterator(); 158 159 scaleLine(s_cbegin, s_cbegin+src_height, s_acc, 160 t_cbegin, t_cbegin+dest_height, tmp_image.accessor()); 161 } 162 163 t_begin = tmp_image.upperLeft(); 164 165 // scale in x direction 166 for( int y=0; y<dest_height; ++y, ++d_begin.y, ++t_begin.y ) 167 { 168 typename DestIter::row_iterator d_rbegin = d_begin.rowIterator(); 169 typename TmpImageIter::row_iterator t_rbegin = t_begin.rowIterator(); 170 171 scaleLine(t_rbegin, t_rbegin+src_width, tmp_image.accessor(), 172 d_rbegin, d_rbegin+dest_width, d_acc); 173 } 174 } 175 176 /** Scale an image, range tuple version 177 178 @param bMustCopy 179 When true, scaleImage always copies source, even when doing 1:1 180 copy 181 */ 182 template< class SourceIter, class SourceAcc, 183 class DestIter, class DestAcc > 184 inline void scaleImage( vigra::triple<SourceIter,SourceIter,SourceAcc> const& src, 185 vigra::triple<DestIter,DestIter,DestAcc> const& dst, 186 bool bMustCopy=false ) 187 { 188 scaleImage(src.first,src.second,src.third, 189 dst.first,dst.second,dst.third, 190 bMustCopy); 191 } 192 193 } 194 195 #endif /* INCLUDED_BASEBMP_SCALEIMAGE_HXX */ 196