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