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 : #include <vcl/bmpacc.hxx>
21 : #include <vcl/bitmapscalesuper.hxx>
22 :
23 : #include <boost/scoped_array.hpp>
24 :
25 : namespace {
26 :
27 : #define MAP( cVal0, cVal1, nFrac ) ((sal_uInt8)((((long)(cVal0)<<7L)+nFrac*((long)(cVal1)-(cVal0)))>>7L))
28 :
29 2710 : void generateMap(long nW, long nDstW, bool bHMirr, long* pMapIX, long* pMapFX)
30 : {
31 2710 : const double fRevScaleX = (nDstW > 1L) ? (double) (nW - 1) / (nDstW - 1) : 0.0;
32 :
33 2710 : long nTemp = nW - 2L;
34 2710 : long nTempX = nW - 1L;
35 181376 : for (long nX = 0L; nX < nDstW; nX++)
36 : {
37 178666 : double fTemp = nX * fRevScaleX;
38 178666 : if (bHMirr)
39 0 : fTemp = nTempX - fTemp;
40 178666 : pMapIX[nX] = MinMax((long) fTemp, 0, nTemp);
41 178666 : pMapFX[nX] = (long) (fTemp - pMapIX[nX]) * 128.0;
42 : }
43 2710 : }
44 :
45 1355 : struct ScaleContext {
46 : BitmapReadAccess *mpSrc;
47 : BitmapWriteAccess *mpDest;
48 : long mnSrcW, mnDestW;
49 : long mnSrcH, mnDestH;
50 : bool mbHMirr, mbVMirr;
51 : boost::scoped_array<long> mpMapIX;
52 : boost::scoped_array<long> mpMapIY;
53 : boost::scoped_array<long> mpMapFX;
54 : boost::scoped_array<long> mpMapFY;
55 1355 : ScaleContext( BitmapReadAccess *pSrc,
56 : BitmapWriteAccess *pDest,
57 : long nSrcW, long nDestW,
58 : long nSrcH, long nDestH,
59 : bool bHMirr, bool bVMirr)
60 : : mpSrc( pSrc ), mpDest( pDest )
61 : , mnSrcW( nSrcW ), mnDestW( nDestW )
62 : , mnSrcH( nSrcH ), mnDestH( nDestH )
63 : , mbHMirr( bHMirr ), mbVMirr( bVMirr )
64 1355 : , mpMapIX( new long[ nDestW ] )
65 1355 : , mpMapIY( new long[ nDestH ] )
66 1355 : , mpMapFX( new long[ nDestW ] )
67 5420 : , mpMapFY( new long[ nDestH ] )
68 : {
69 1355 : generateMap(nSrcW, nDestW, bHMirr, mpMapIX.get(), mpMapFX.get());
70 1355 : generateMap(nSrcH, nDestH, bVMirr, mpMapIY.get(), mpMapFY.get());
71 1355 : }
72 : };
73 :
74 6 : void scalePallete8bit(ScaleContext &rCtx, long nStartY, long nEndY)
75 : {
76 6 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
77 :
78 420 : for( long nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
79 : {
80 414 : long nTempY = rCtx.mpMapIY[ nY ];
81 414 : long nTempFY = rCtx.mpMapFY[ nY ];
82 414 : Scanline pLine0 = rCtx.mpSrc->GetScanline( nTempY );
83 414 : Scanline pLine1 = rCtx.mpSrc->GetScanline( ++nTempY );
84 :
85 108622 : for(long nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
86 : {
87 108208 : long nTempX = rCtx.mpMapIX[ nX ];
88 108208 : long nTempFX = rCtx.mpMapFX[ nX ];
89 :
90 108208 : const BitmapColor& rCol0 = rCtx.mpSrc->GetPaletteColor( pLine0[ nTempX ] );
91 108208 : const BitmapColor& rCol2 = rCtx.mpSrc->GetPaletteColor( pLine1[ nTempX ] );
92 108208 : const BitmapColor& rCol1 = rCtx.mpSrc->GetPaletteColor( pLine0[ ++nTempX ] );
93 108208 : const BitmapColor& rCol3 = rCtx.mpSrc->GetPaletteColor( pLine1[ nTempX ] );
94 :
95 108208 : sal_uInt8 cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
96 108208 : sal_uInt8 cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
97 108208 : sal_uInt8 cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
98 :
99 108208 : sal_uInt8 cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
100 108208 : sal_uInt8 cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
101 108208 : sal_uInt8 cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
102 :
103 108208 : BitmapColor aColRes( MAP( cR0, cR1, nTempFY ),
104 108208 : MAP( cG0, cG1, nTempFY ),
105 324624 : MAP( cB0, cB1, nTempFY ) );
106 108208 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
107 108208 : }
108 : }
109 6 : }
110 :
111 0 : void scalePalleteGeneral(ScaleContext &rCtx, long nStartY, long nEndY)
112 : {
113 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
114 :
115 0 : for( long nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
116 : {
117 0 : long nTempY = rCtx.mpMapIY[ nY ];
118 0 : long nTempFY = rCtx.mpMapFY[ nY ];
119 :
120 0 : for( long nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
121 : {
122 0 : long nTempX = rCtx.mpMapIX[ nX ];
123 0 : long nTempFX = rCtx.mpMapFX[ nX ];
124 :
125 0 : BitmapColor aCol0 = rCtx.mpSrc->GetPaletteColor( rCtx.mpSrc->GetPixelIndex( nTempY, nTempX ) );
126 0 : BitmapColor aCol1 = rCtx.mpSrc->GetPaletteColor( rCtx.mpSrc->GetPixelIndex( nTempY, ++nTempX ) );
127 0 : sal_uInt8 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
128 0 : sal_uInt8 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
129 0 : sal_uInt8 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
130 :
131 0 : aCol1 = rCtx.mpSrc->GetPaletteColor( rCtx.mpSrc->GetPixelIndex( ++nTempY, nTempX ) );
132 0 : aCol0 = rCtx.mpSrc->GetPaletteColor( rCtx.mpSrc->GetPixelIndex( nTempY--, --nTempX ) );
133 0 : sal_uInt8 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
134 0 : sal_uInt8 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
135 0 : sal_uInt8 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
136 :
137 0 : BitmapColor aColRes( MAP( cR0, cR1, nTempFY ),
138 0 : MAP( cG0, cG1, nTempFY ),
139 0 : MAP( cB0, cB1, nTempFY ) );
140 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
141 0 : }
142 : }
143 0 : }
144 :
145 52 : void scale24bitBGR(ScaleContext &rCtx, long nStartY, long nEndY)
146 : {
147 52 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
148 :
149 11872 : for( long nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
150 : {
151 11820 : long nTempY = rCtx.mpMapIY[ nY ];
152 11820 : long nTempFY = rCtx.mpMapFY[ nY ];
153 11820 : Scanline pLine0 = rCtx.mpSrc->GetScanline( nTempY );
154 11820 : Scanline pLine1 = rCtx.mpSrc->GetScanline( ++nTempY );
155 :
156 4502710 : for( long nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
157 : {
158 4490890 : long nOff = 3L * rCtx.mpMapIX[ nX ];
159 4490890 : long nTempFX = rCtx.mpMapFX[ nX ];
160 :
161 4490890 : Scanline pTmp0 = pLine0 + nOff ;
162 4490890 : Scanline pTmp1 = pTmp0 + 3L;
163 4490890 : sal_uInt8 cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
164 4490890 : pTmp0++; pTmp1++;
165 4490890 : sal_uInt8 cG0 = MAP( *pTmp0, *pTmp1, nTempFX );
166 4490890 : pTmp0++; pTmp1++;
167 4490890 : sal_uInt8 cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
168 :
169 4490890 : pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
170 4490890 : sal_uInt8 cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
171 4490890 : pTmp0++; pTmp1++;
172 4490890 : sal_uInt8 cG1 = MAP( *pTmp0, *pTmp1, nTempFX );
173 4490890 : pTmp0++; pTmp1++;
174 4490890 : sal_uInt8 cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
175 :
176 4490890 : BitmapColor aColRes( MAP( cR0, cR1, nTempFY ),
177 4490890 : MAP( cG0, cG1, nTempFY ),
178 13472670 : MAP( cB0, cB1, nTempFY ) );
179 4490890 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
180 4490890 : }
181 : }
182 52 : }
183 :
184 0 : void scale24bitRGB(ScaleContext &rCtx, long nStartY, long nEndY)
185 : {
186 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
187 :
188 0 : for( long nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
189 : {
190 0 : long nTempY = rCtx.mpMapIY[ nY ];
191 0 : long nTempFY = rCtx.mpMapFY[ nY ];
192 0 : Scanline pLine0 = rCtx.mpSrc->GetScanline( nTempY );
193 0 : Scanline pLine1 = rCtx.mpSrc->GetScanline( ++nTempY );
194 :
195 0 : for( long nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
196 : {
197 0 : long nOff = 3L * rCtx.mpMapIX[ nX ];
198 0 : long nTempFX = rCtx.mpMapFX[ nX ];
199 :
200 0 : Scanline pTmp0 = pLine0 + nOff;
201 0 : Scanline pTmp1 = pTmp0 + 3L;
202 0 : sal_uInt8 cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
203 0 : pTmp0++; pTmp1++;
204 0 : sal_uInt8 cG0 = MAP( *pTmp0, *pTmp1, nTempFX );
205 0 : pTmp0++; pTmp1++;
206 0 : sal_uInt8 cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
207 :
208 0 : pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
209 0 : sal_uInt8 cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
210 0 : pTmp0++; pTmp1++;
211 0 : sal_uInt8 cG1 = MAP( *pTmp0, *pTmp1, nTempFX );
212 0 : pTmp0++; pTmp1++;
213 0 : sal_uInt8 cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
214 :
215 0 : BitmapColor aColRes( MAP( cR0, cR1, nTempFY ),
216 0 : MAP( cG0, cG1, nTempFY ),
217 0 : MAP( cB0, cB1, nTempFY ) );
218 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
219 0 : }
220 : }
221 0 : }
222 :
223 0 : void scaleNonPalleteGeneral(ScaleContext &rCtx, long nStartY, long nEndY)
224 : {
225 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
226 :
227 0 : for( long nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
228 : {
229 0 : long nTempY = rCtx.mpMapIY[ nY ];
230 0 : long nTempFY = rCtx.mpMapFY[ nY ];
231 :
232 0 : for( long nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
233 : {
234 0 : long nTempX = rCtx.mpMapIX[ nX ];
235 0 : long nTempFX = rCtx.mpMapFX[ nX ];
236 :
237 0 : BitmapColor aCol0 = rCtx.mpSrc->GetPixel( nTempY, nTempX );
238 0 : BitmapColor aCol1 = rCtx.mpSrc->GetPixel( nTempY, ++nTempX );
239 0 : sal_uInt8 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
240 0 : sal_uInt8 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
241 0 : sal_uInt8 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
242 :
243 0 : aCol1 = rCtx.mpSrc->GetPixel( ++nTempY, nTempX );
244 0 : aCol0 = rCtx.mpSrc->GetPixel( nTempY--, --nTempX );
245 0 : sal_uInt8 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
246 0 : sal_uInt8 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
247 0 : sal_uInt8 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
248 :
249 0 : BitmapColor aColRes( MAP( cR0, cR1, nTempFY ),
250 0 : MAP( cG0, cG1, nTempFY ),
251 0 : MAP( cB0, cB1, nTempFY ) );
252 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
253 0 : }
254 : }
255 0 : }
256 :
257 0 : void scalePallete8bit2(ScaleContext &rCtx, long nStartY, long nEndY)
258 : {
259 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
260 0 : const long nMax = 1 << 7L;
261 :
262 0 : for( long nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
263 : {
264 0 : long nTop = rCtx.mbVMirr ? ( nY + 1 ) : nY;
265 0 : long nBottom = rCtx.mbVMirr ? nY : ( nY + 1 ) ;
266 :
267 : long nLineStart, nLineRange;
268 0 : if( nY == nEndY )
269 : {
270 0 : nLineStart = rCtx.mpMapIY[ nY ];
271 0 : nLineRange = 0;
272 : }
273 : else
274 : {
275 0 : nLineStart = rCtx.mpMapIY[ nTop ] ;
276 0 : nLineRange = ( rCtx.mpMapIY[ nBottom ] == rCtx.mpMapIY[ nTop ] ) ? 1 :( rCtx.mpMapIY[ nBottom ] - rCtx.mpMapIY[ nTop ] );
277 : }
278 :
279 0 : for( long nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
280 : {
281 0 : long nLeft = rCtx.mbHMirr ? ( nX + 1 ) : nX;
282 0 : long nRight = rCtx.mbHMirr ? nX : ( nX + 1 ) ;
283 :
284 : long nRowStart;
285 : long nRowRange;
286 0 : if( nX == nEndX )
287 : {
288 0 : nRowStart = rCtx.mpMapIX[ nX ];
289 0 : nRowRange = 0;
290 : }
291 : else
292 : {
293 0 : nRowStart = rCtx.mpMapIX[ nLeft ];
294 0 : nRowRange = ( rCtx.mpMapIX[ nRight ] == rCtx.mpMapIX[ nLeft ] )? 1 : ( rCtx.mpMapIX[ nRight ] - rCtx.mpMapIX[ nLeft ] );
295 : }
296 :
297 0 : long nSumR = 0;
298 0 : long nSumG = 0;
299 0 : long nSumB = 0;
300 0 : long nTotalWeightY = 0;
301 :
302 0 : for(int i = 0; i<= nLineRange; i++)
303 : {
304 0 : Scanline pTmpY = rCtx.mpSrc->GetScanline( nLineStart + i );
305 0 : long nSumRowR = 0;
306 0 : long nSumRowG = 0;
307 0 : long nSumRowB = 0;
308 0 : long nTotalWeightX = 0;
309 :
310 0 : for(int j = 0; j <= nRowRange; j++)
311 : {
312 0 : const BitmapColor& rCol = rCtx.mpSrc->GetPaletteColor( pTmpY[ nRowStart + j ] );
313 :
314 0 : if(nX == nEndX )
315 : {
316 0 : nSumRowB += rCol.GetBlue() << 7L;
317 0 : nSumRowG += rCol.GetGreen() << 7L;
318 0 : nSumRowR += rCol.GetRed() << 7L;
319 0 : nTotalWeightX += 1 << 7L;
320 : }
321 0 : else if( j == 0 )
322 : {
323 0 : long nWeightX = (nMax- rCtx.mpMapFX[ nLeft ]) ;
324 0 : nSumRowB += ( nWeightX *rCol.GetBlue()) ;
325 0 : nSumRowG += ( nWeightX *rCol.GetGreen()) ;
326 0 : nSumRowR += ( nWeightX *rCol.GetRed()) ;
327 0 : nTotalWeightX += nWeightX;
328 : }
329 0 : else if ( nRowRange == j )
330 : {
331 0 : long nWeightX = rCtx.mpMapFX[ nRight ] ;
332 0 : nSumRowB += ( nWeightX *rCol.GetBlue() );
333 0 : nSumRowG += ( nWeightX *rCol.GetGreen() );
334 0 : nSumRowR += ( nWeightX *rCol.GetRed() );
335 0 : nTotalWeightX += nWeightX;
336 : }
337 : else
338 : {
339 0 : nSumRowB += rCol.GetBlue() << 7L;
340 0 : nSumRowG += rCol.GetGreen() << 7L;
341 0 : nSumRowR += rCol.GetRed() << 7L;
342 0 : nTotalWeightX += 1 << 7L;
343 : }
344 : }
345 :
346 0 : long nWeightY = nMax;
347 0 : if( nY == nEndY )
348 0 : nWeightY = nMax;
349 0 : else if( i == 0 )
350 0 : nWeightY = nMax - rCtx.mpMapFY[ nTop ];
351 0 : else if( nLineRange == 1 )
352 0 : nWeightY = rCtx.mpMapFY[ nTop ];
353 0 : else if ( nLineRange == i )
354 0 : nWeightY = rCtx.mpMapFY[ nBottom ];
355 :
356 0 : if (nTotalWeightX)
357 : {
358 0 : nSumRowB /= nTotalWeightX;
359 0 : nSumRowG /= nTotalWeightX;
360 0 : nSumRowR /= nTotalWeightX;
361 : }
362 :
363 0 : nSumB += nWeightY * nSumRowB;
364 0 : nSumG += nWeightY * nSumRowG;
365 0 : nSumR += nWeightY * nSumRowR;
366 0 : nTotalWeightY += nWeightY;
367 : }
368 :
369 0 : if (nTotalWeightY)
370 : {
371 0 : nSumR /= nTotalWeightY;
372 0 : nSumG /= nTotalWeightY;
373 0 : nSumB /= nTotalWeightY;
374 : }
375 :
376 0 : BitmapColor aColRes((sal_uInt8)nSumR, (sal_uInt8)nSumG, (sal_uInt8)nSumB);
377 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
378 0 : }
379 : }
380 0 : }
381 :
382 0 : void scalePalleteGeneral2(ScaleContext &rCtx, long nStartY, long nEndY)
383 : {
384 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
385 0 : const long nMax = 1 << 7L;
386 :
387 0 : for( long nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
388 : {
389 0 : long nTop = rCtx.mbVMirr ? ( nY + 1 ) : nY;
390 0 : long nBottom = rCtx.mbVMirr ? nY : ( nY + 1 ) ;
391 :
392 : long nLineStart, nLineRange;
393 0 : if( nY ==nEndY )
394 : {
395 0 : nLineStart = rCtx.mpMapIY[ nY ];
396 0 : nLineRange = 0;
397 : }
398 : else
399 : {
400 0 : nLineStart = rCtx.mpMapIY[ nTop ] ;
401 0 : nLineRange = ( rCtx.mpMapIY[ nBottom ] == rCtx.mpMapIY[ nTop ] ) ? 1 :( rCtx.mpMapIY[ nBottom ] - rCtx.mpMapIY[ nTop ] );
402 : }
403 :
404 0 : for( long nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
405 : {
406 0 : long nLeft = rCtx.mbHMirr ? ( nX + 1 ) : nX;
407 0 : long nRight = rCtx.mbHMirr ? nX : ( nX + 1 ) ;
408 :
409 : long nRowStart, nRowRange;
410 0 : if( nX == nEndX )
411 : {
412 0 : nRowStart = rCtx.mpMapIX[ nX ];
413 0 : nRowRange = 0;
414 : }
415 : else
416 : {
417 0 : nRowStart = rCtx.mpMapIX[ nLeft ];
418 0 : nRowRange = ( rCtx.mpMapIX[ nRight ] == rCtx.mpMapIX[ nLeft ] )? 1 : ( rCtx.mpMapIX[ nRight ] - rCtx.mpMapIX[ nLeft ] );
419 : }
420 :
421 0 : long nSumR = 0;
422 0 : long nSumG = 0;
423 0 : long nSumB = 0;
424 0 : long nTotalWeightY = 0;
425 :
426 0 : for(int i = 0; i<= nLineRange; i++)
427 : {
428 0 : long nSumRowR = 0;
429 0 : long nSumRowG = 0;
430 0 : long nSumRowB = 0;
431 0 : long nTotalWeightX = 0;
432 :
433 0 : for(int j = 0; j <= nRowRange; j++)
434 : {
435 0 : BitmapColor aCol0 = rCtx.mpSrc->GetPaletteColor ( rCtx.mpSrc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
436 :
437 0 : if(nX == nEndX )
438 : {
439 :
440 0 : nSumRowB += aCol0.GetBlue() << 7L;
441 0 : nSumRowG += aCol0.GetGreen() << 7L;
442 0 : nSumRowR += aCol0.GetRed() << 7L;
443 0 : nTotalWeightX += 1 << 7L;
444 : }
445 0 : else if( j == 0 )
446 : {
447 :
448 0 : long nWeightX = (nMax- rCtx.mpMapFX[ nLeft ]) ;
449 0 : nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
450 0 : nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
451 0 : nSumRowR += ( nWeightX *aCol0.GetRed()) ;
452 0 : nTotalWeightX += nWeightX;
453 : }
454 0 : else if ( nRowRange == j )
455 : {
456 :
457 0 : long nWeightX = rCtx.mpMapFX[ nRight ] ;
458 0 : nSumRowB += ( nWeightX *aCol0.GetBlue() );
459 0 : nSumRowG += ( nWeightX *aCol0.GetGreen() );
460 0 : nSumRowR += ( nWeightX *aCol0.GetRed() );
461 0 : nTotalWeightX += nWeightX;
462 : }
463 : else
464 : {
465 :
466 0 : nSumRowB += aCol0.GetBlue() << 7L;
467 0 : nSumRowG += aCol0.GetGreen() << 7L;
468 0 : nSumRowR += aCol0.GetRed() << 7L;
469 0 : nTotalWeightX += 1 << 7L;
470 : }
471 0 : }
472 :
473 0 : long nWeightY = nMax;
474 0 : if( nY == nEndY )
475 0 : nWeightY = nMax;
476 0 : else if( i == 0 )
477 0 : nWeightY = nMax - rCtx.mpMapFY[ nTop ];
478 0 : else if( nLineRange == 1 )
479 0 : nWeightY = rCtx.mpMapFY[ nTop ];
480 0 : else if ( nLineRange == i )
481 0 : nWeightY = rCtx.mpMapFY[ nBottom ];
482 :
483 0 : if (nTotalWeightX)
484 : {
485 0 : nSumRowB /= nTotalWeightX;
486 0 : nSumRowG /= nTotalWeightX;
487 0 : nSumRowR /= nTotalWeightX;
488 : }
489 :
490 0 : nSumB += nWeightY * nSumRowB;
491 0 : nSumG += nWeightY * nSumRowG;
492 0 : nSumR += nWeightY * nSumRowR;
493 0 : nTotalWeightY += nWeightY;
494 : }
495 :
496 0 : if (nTotalWeightY)
497 : {
498 0 : nSumR /= nTotalWeightY;
499 0 : nSumG /= nTotalWeightY;
500 0 : nSumB /= nTotalWeightY;
501 : }
502 :
503 0 : BitmapColor aColRes((sal_uInt8)nSumR, (sal_uInt8)nSumG, (sal_uInt8)nSumB);
504 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
505 0 : }
506 : }
507 0 : }
508 :
509 1297 : void scale24bitBGR2(ScaleContext &rCtx, long nStartY, long nEndY)
510 : {
511 1297 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
512 1297 : const long nMax = 1 << 7L;
513 :
514 39340 : for( long nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
515 : {
516 38043 : long nTop = rCtx.mbVMirr ? ( nY + 1 ) : nY;
517 38043 : long nBottom = rCtx.mbVMirr ? nY : ( nY + 1 ) ;
518 :
519 : long nLineStart;
520 : long nLineRange;
521 38043 : if( nY ==nEndY )
522 : {
523 1297 : nLineStart = rCtx.mpMapIY[ nY ];
524 1297 : nLineRange = 0;
525 : }
526 : else
527 : {
528 36746 : nLineStart = rCtx.mpMapIY[ nTop ] ;
529 36746 : nLineRange = ( rCtx.mpMapIY[ nBottom ] == rCtx.mpMapIY[ nTop ] ) ? 1 :( rCtx.mpMapIY[ nBottom ] - rCtx.mpMapIY[ nTop ] );
530 : }
531 :
532 5927110 : for( long nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
533 : {
534 5889067 : long nLeft = rCtx.mbHMirr ? ( nX + 1 ) : nX;
535 5889067 : long nRight = rCtx.mbHMirr ? nX : ( nX + 1 ) ;
536 :
537 : long nRowStart;
538 : long nRowRange;
539 5889067 : if( nX == nEndX )
540 : {
541 38043 : nRowStart = rCtx.mpMapIX[ nX ];
542 38043 : nRowRange = 0;
543 : }
544 : else
545 : {
546 5851024 : nRowStart = rCtx.mpMapIX[ nLeft ];
547 5851024 : nRowRange = ( rCtx.mpMapIX[ nRight ] == rCtx.mpMapIX[ nLeft ] )? 1 : ( rCtx.mpMapIX[ nRight ] - rCtx.mpMapIX[ nLeft ] );
548 : }
549 :
550 5889067 : long nSumR = 0;
551 5889067 : long nSumG = 0;
552 5889067 : long nSumB = 0;
553 5889067 : long nTotalWeightY = 0;
554 :
555 30652254 : for(int i = 0; i<= nLineRange; i++)
556 : {
557 24763187 : Scanline pTmpY = rCtx.mpSrc->GetScanline( nLineStart + i );
558 24763187 : Scanline pTmpX = pTmpY + 3L * nRowStart;
559 24763187 : long nSumRowR = 0;
560 24763187 : long nSumRowG = 0;
561 24763187 : long nSumRowB = 0;
562 24763187 : long nTotalWeightX = 0;
563 :
564 138613345 : for(int j = 0; j <= nRowRange; j++)
565 : {
566 113850158 : if(nX == nEndX )
567 : {
568 152145 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
569 152145 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
570 152145 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
571 152145 : nTotalWeightX += 1 << 7L;
572 : }
573 113698013 : else if( j == 0 )
574 : {
575 24611042 : long nWeightX = (nMax- rCtx.mpMapFX[ nLeft ]) ;
576 24611042 : nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
577 24611042 : nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
578 24611042 : nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
579 24611042 : nTotalWeightX += nWeightX;
580 : }
581 89086971 : else if ( nRowRange == j )
582 : {
583 24611042 : long nWeightX = rCtx.mpMapFX[ nRight ] ;
584 24611042 : nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
585 24611042 : nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
586 24611042 : nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
587 24611042 : nTotalWeightX += nWeightX;
588 : }
589 : else
590 : {
591 64475929 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
592 64475929 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
593 64475929 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
594 64475929 : nTotalWeightX += 1 << 7L;
595 : }
596 : }
597 :
598 24763187 : long nWeightY = nMax;
599 24763187 : if( nY == nEndY )
600 114883 : nWeightY = nMax;
601 24648304 : else if( i == 0 )
602 5774184 : nWeightY = nMax - rCtx.mpMapFY[ nTop ];
603 18874120 : else if( nLineRange == 1 )
604 64800 : nWeightY = rCtx.mpMapFY[ nTop ];
605 18809320 : else if ( nLineRange == i )
606 5709384 : nWeightY = rCtx.mpMapFY[ nBottom ];
607 :
608 24763187 : if (nTotalWeightX)
609 : {
610 24763187 : nSumRowB /= nTotalWeightX;
611 24763187 : nSumRowG /= nTotalWeightX;
612 24763187 : nSumRowR /= nTotalWeightX;
613 : }
614 24763187 : nSumB += nWeightY * nSumRowB;
615 24763187 : nSumG += nWeightY * nSumRowG;
616 24763187 : nSumR += nWeightY * nSumRowR;
617 24763187 : nTotalWeightY += nWeightY;
618 : }
619 :
620 5889067 : if (nTotalWeightY)
621 : {
622 5889067 : nSumR /= nTotalWeightY;
623 5889067 : nSumG /= nTotalWeightY;
624 5889067 : nSumB /= nTotalWeightY;
625 : }
626 5889067 : BitmapColor aColRes((sal_uInt8)nSumR, (sal_uInt8)nSumG, (sal_uInt8)nSumB);
627 5889067 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
628 5889067 : }
629 : }
630 1297 : }
631 :
632 0 : void scale24bitRGB2(ScaleContext &rCtx, long nStartY, long nEndY)
633 : {
634 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
635 0 : const long nMax = 1 << 7L;
636 :
637 0 : for( long nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
638 : {
639 0 : long nTop = rCtx.mbVMirr ? ( nY + 1 ) : nY;
640 0 : long nBottom = rCtx.mbVMirr ? nY : ( nY + 1 ) ;
641 :
642 : long nLineStart, nLineRange;
643 0 : if( nY ==nEndY )
644 : {
645 0 : nLineStart = rCtx.mpMapIY[ nY ];
646 0 : nLineRange = 0;
647 : }
648 : else
649 : {
650 0 : nLineStart = rCtx.mpMapIY[ nTop ] ;
651 0 : nLineRange = ( rCtx.mpMapIY[ nBottom ] == rCtx.mpMapIY[ nTop ] ) ? 1 :( rCtx.mpMapIY[ nBottom ] - rCtx.mpMapIY[ nTop ] );
652 : }
653 :
654 0 : for( long nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
655 : {
656 0 : long nLeft = rCtx.mbHMirr ? ( nX + 1 ) : nX;
657 0 : long nRight = rCtx.mbHMirr ? nX : ( nX + 1 ) ;
658 :
659 : long nRowStart, nRowRange;
660 0 : if( nX == nEndX )
661 : {
662 0 : nRowStart = rCtx.mpMapIX[ nX ];
663 0 : nRowRange = 0;
664 : }
665 : else
666 : {
667 0 : nRowStart = rCtx.mpMapIX[ nLeft ];
668 0 : nRowRange = ( rCtx.mpMapIX[ nRight ] == rCtx.mpMapIX[ nLeft ] )? 1 : ( rCtx.mpMapIX[ nRight ] - rCtx.mpMapIX[ nLeft ] );
669 : }
670 :
671 0 : long nSumR = 0;
672 0 : long nSumG = 0;
673 0 : long nSumB = 0;
674 0 : long nTotalWeightY = 0;
675 :
676 0 : for(int i = 0; i<= nLineRange; i++)
677 : {
678 0 : Scanline pTmpY = rCtx.mpSrc->GetScanline( nLineStart + i );
679 0 : Scanline pTmpX = pTmpY + 3L * nRowStart;
680 0 : long nSumRowR = 0;
681 0 : long nSumRowG = 0;
682 0 : long nSumRowB = 0;
683 0 : long nTotalWeightX = 0;
684 :
685 0 : for(int j = 0; j <= nRowRange; j++)
686 : {
687 0 : if(nX == nEndX )
688 : {
689 0 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
690 0 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
691 0 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
692 0 : nTotalWeightX += 1 << 7L;
693 : }
694 0 : else if( j == 0 )
695 : {
696 0 : long nWeightX = (nMax- rCtx.mpMapFX[ nLeft ]) ;
697 0 : nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
698 0 : nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
699 0 : nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
700 0 : nTotalWeightX += nWeightX;
701 : }
702 0 : else if ( nRowRange == j )
703 : {
704 0 : long nWeightX = rCtx.mpMapFX[ nRight ] ;
705 0 : nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
706 0 : nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
707 0 : nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
708 0 : nTotalWeightX += nWeightX;
709 : }
710 : else
711 : {
712 0 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
713 0 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
714 0 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
715 0 : nTotalWeightX += 1 << 7L;
716 : }
717 : }
718 :
719 0 : long nWeightY = nMax;
720 0 : if( nY == nEndY )
721 0 : nWeightY = nMax;
722 0 : else if( i == 0 )
723 0 : nWeightY = nMax - rCtx.mpMapFY[ nTop ];
724 0 : else if( nLineRange == 1 )
725 0 : nWeightY = rCtx.mpMapFY[ nTop ];
726 0 : else if ( nLineRange == i )
727 0 : nWeightY = rCtx.mpMapFY[ nBottom ];
728 :
729 0 : if (nTotalWeightX)
730 : {
731 0 : nSumRowB /= nTotalWeightX;
732 0 : nSumRowG /= nTotalWeightX;
733 0 : nSumRowR /= nTotalWeightX;
734 : }
735 0 : nSumB += nWeightY * nSumRowB;
736 0 : nSumG += nWeightY * nSumRowG;
737 0 : nSumR += nWeightY * nSumRowR;
738 0 : nTotalWeightY += nWeightY;
739 : }
740 :
741 0 : if (nTotalWeightY)
742 : {
743 0 : nSumR /= nTotalWeightY;
744 0 : nSumG /= nTotalWeightY;
745 0 : nSumB /= nTotalWeightY;
746 : }
747 0 : BitmapColor aColRes((sal_uInt8)nSumR, (sal_uInt8)nSumG, (sal_uInt8)nSumB);
748 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
749 0 : }
750 : }
751 0 : }
752 :
753 0 : void scaleNonPalleteGeneral2(ScaleContext &rCtx, long nStartY, long nEndY)
754 : {
755 0 : const long nStartX = 0, nEndX = rCtx.mnDestW - 1L;
756 0 : const long nMax = 1 << 7L;
757 :
758 0 : for( long nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
759 : {
760 0 : long nTop = rCtx.mbVMirr ? ( nY + 1 ) : nY;
761 0 : long nBottom = rCtx.mbVMirr ? nY : ( nY + 1 ) ;
762 :
763 : long nLineStart, nLineRange;
764 0 : if( nY ==nEndY )
765 : {
766 0 : nLineStart = rCtx.mpMapIY[ nY ];
767 0 : nLineRange = 0;
768 : }
769 : else
770 : {
771 0 : nLineStart = rCtx.mpMapIY[ nTop ] ;
772 0 : nLineRange = ( rCtx.mpMapIY[ nBottom ] == rCtx.mpMapIY[ nTop ] ) ? 1 :( rCtx.mpMapIY[ nBottom ] - rCtx.mpMapIY[ nTop ] );
773 : }
774 :
775 0 : for( long nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
776 : {
777 0 : long nLeft = rCtx.mbHMirr ? ( nX + 1 ) : nX;
778 0 : long nRight = rCtx.mbHMirr ? nX : ( nX + 1 ) ;
779 :
780 : long nRowStart, nRowRange;
781 0 : if( nX == nEndX )
782 : {
783 0 : nRowStart = rCtx.mpMapIX[ nX ];
784 0 : nRowRange = 0;
785 : }
786 : else
787 : {
788 0 : nRowStart = rCtx.mpMapIX[ nLeft ];
789 0 : nRowRange = ( rCtx.mpMapIX[ nRight ] == rCtx.mpMapIX[ nLeft ] )? 1 : ( rCtx.mpMapIX[ nRight ] - rCtx.mpMapIX[ nLeft ] );
790 : }
791 :
792 0 : long nSumR = 0;
793 0 : long nSumG = 0;
794 0 : long nSumB = 0;
795 0 : long nTotalWeightY = 0;
796 :
797 0 : for(int i = 0; i<= nLineRange; i++)
798 : {
799 0 : long nSumRowR = 0;
800 0 : long nSumRowG = 0;
801 0 : long nSumRowB = 0;
802 0 : long nTotalWeightX = 0;
803 :
804 0 : for(int j = 0; j <= nRowRange; j++)
805 : {
806 0 : BitmapColor aCol0 = rCtx.mpSrc->GetPixel( nLineStart + i, nRowStart + j );
807 :
808 0 : if(nX == nEndX )
809 : {
810 :
811 0 : nSumRowB += aCol0.GetBlue() << 7L;
812 0 : nSumRowG += aCol0.GetGreen() << 7L;
813 0 : nSumRowR += aCol0.GetRed() << 7L;
814 0 : nTotalWeightX += 1 << 7L;
815 : }
816 0 : else if( j == 0 )
817 : {
818 :
819 0 : long nWeightX = (nMax- rCtx.mpMapFX[ nLeft ]) ;
820 0 : nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
821 0 : nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
822 0 : nSumRowR += ( nWeightX *aCol0.GetRed()) ;
823 0 : nTotalWeightX += nWeightX;
824 : }
825 0 : else if ( nRowRange == j )
826 : {
827 :
828 0 : long nWeightX = rCtx.mpMapFX[ nRight ] ;
829 0 : nSumRowB += ( nWeightX *aCol0.GetBlue() );
830 0 : nSumRowG += ( nWeightX *aCol0.GetGreen() );
831 0 : nSumRowR += ( nWeightX *aCol0.GetRed() );
832 0 : nTotalWeightX += nWeightX;
833 : }
834 : else
835 : {
836 0 : nSumRowB += aCol0.GetBlue() << 7L;
837 0 : nSumRowG += aCol0.GetGreen() << 7L;
838 0 : nSumRowR += aCol0.GetRed() << 7L;
839 0 : nTotalWeightX += 1 << 7L;
840 : }
841 0 : }
842 :
843 0 : long nWeightY = nMax;
844 0 : if( nY == nEndY )
845 0 : nWeightY = nMax;
846 0 : else if( i == 0 )
847 0 : nWeightY = nMax - rCtx.mpMapFY[ nTop ];
848 0 : else if( nLineRange == 1 )
849 0 : nWeightY = rCtx.mpMapFY[ nTop ];
850 0 : else if ( nLineRange == i )
851 0 : nWeightY = rCtx.mpMapFY[ nBottom ];
852 :
853 0 : if (nTotalWeightX)
854 : {
855 0 : nSumRowB /= nTotalWeightX;
856 0 : nSumRowG /= nTotalWeightX;
857 0 : nSumRowR /= nTotalWeightX;
858 : }
859 :
860 0 : nSumB += nWeightY * nSumRowB;
861 0 : nSumG += nWeightY * nSumRowG;
862 0 : nSumR += nWeightY * nSumRowR;
863 0 : nTotalWeightY += nWeightY;
864 : }
865 :
866 0 : if (nTotalWeightY)
867 : {
868 0 : nSumR /= nTotalWeightY;
869 0 : nSumG /= nTotalWeightY;
870 0 : nSumB /= nTotalWeightY;
871 : }
872 :
873 0 : BitmapColor aColRes((sal_uInt8)nSumR, (sal_uInt8)nSumG, (sal_uInt8)nSumB);
874 0 : rCtx.mpDest->SetPixel( nYDst, nXDst++, aColRes );
875 0 : }
876 : }
877 0 : }
878 :
879 : } // end anonymous namespace
880 :
881 1355 : BitmapScaleSuper::BitmapScaleSuper(const double& rScaleX, const double& rScaleY) :
882 : mrScaleX(rScaleX),
883 1355 : mrScaleY(rScaleY)
884 1355 : {}
885 :
886 1355 : BitmapScaleSuper::~BitmapScaleSuper()
887 1355 : {}
888 :
889 1355 : bool BitmapScaleSuper::filter(Bitmap& rBitmap)
890 : {
891 1355 : bool bRet = false;
892 :
893 1355 : const Size aSizePix(rBitmap.GetSizePixel());
894 :
895 1355 : bool bHMirr = mrScaleX < 0;
896 1355 : bool bVMirr = mrScaleY < 0;
897 :
898 1355 : double fScaleX = std::fabs(mrScaleX);
899 1355 : double fScaleY = std::fabs(mrScaleY);
900 :
901 1355 : const long nDstW = FRound(aSizePix.Width() * fScaleX);
902 1355 : const long nDstH = FRound(aSizePix.Height() * fScaleY);
903 :
904 1355 : const double fScaleThresh = 0.6;
905 :
906 1355 : if (nDstW <= 1L || nDstH <= 1L)
907 0 : return false;
908 :
909 1355 : Bitmap::ScopedReadAccess pReadAccess(rBitmap);
910 :
911 2710 : Bitmap aOutBmp(Size(nDstW, nDstH), 24);
912 2710 : Bitmap::ScopedWriteAccess pWriteAccess(aOutBmp);
913 :
914 1355 : const long nStartY = 0;
915 1355 : const long nEndY = nDstH - 1L;
916 :
917 1355 : if (pReadAccess && pWriteAccess)
918 : {
919 : ScaleContext aContext( pReadAccess.get(),
920 : pWriteAccess.get(),
921 : pReadAccess->Width(),
922 1355 : pWriteAccess->Width(),
923 : pReadAccess->Height(),
924 1355 : pWriteAccess->Height(),
925 4065 : bVMirr, bHMirr );
926 : void (*scaleRangeFn)(ScaleContext &rCtx, long nStartY, long nEndY);
927 :
928 1355 : bool bScaleUp = fScaleX >= fScaleThresh && fScaleY >= fScaleThresh;
929 1355 : if( pReadAccess->HasPalette() )
930 : {
931 6 : switch( pReadAccess->GetScanlineFormat() )
932 : {
933 : case BMP_FORMAT_8BIT_PAL:
934 6 : scaleRangeFn = bScaleUp ? scalePallete8bit : scalePallete8bit2;
935 6 : break;
936 : default:
937 : scaleRangeFn = bScaleUp ? scalePalleteGeneral
938 0 : : scalePalleteGeneral2;
939 0 : break;
940 : }
941 : }
942 : else
943 : {
944 1349 : switch( pReadAccess->GetScanlineFormat() )
945 : {
946 : case BMP_FORMAT_24BIT_TC_BGR:
947 1349 : scaleRangeFn = bScaleUp ? scale24bitBGR : scale24bitBGR2;
948 1349 : break;
949 : case BMP_FORMAT_24BIT_TC_RGB:
950 0 : scaleRangeFn = bScaleUp ? scale24bitRGB : scale24bitRGB2;
951 0 : break;
952 : default:
953 : scaleRangeFn = bScaleUp ? scaleNonPalleteGeneral
954 0 : : scaleNonPalleteGeneral2;
955 0 : break;
956 : }
957 : }
958 1355 : scaleRangeFn( aContext, nStartY, nEndY );
959 :
960 1355 : bRet = true;
961 : }
962 :
963 1355 : if( bRet )
964 : {
965 1355 : rBitmap.AdaptBitCount(aOutBmp);
966 1355 : rBitmap = aOutBmp;
967 : }
968 :
969 2710 : return bRet;
970 1233 : }
971 :
972 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|