summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2012-10-29 16:20:25 +0000
committerArmin Le Grand <alg@apache.org>2012-10-29 16:20:25 +0000
commitbf734a151dc5169b65cf5d2a127e4142b765326c (patch)
treecd918614f76bc8f987eb21233fb355298a7e4a3e /vcl
parentcb01e556e94b0d5bc96c4ff6183a3dc3cff934c8 (diff)
#121233# Added bitmap scaling methods BMP_SCALE_SUPER (from symphony), BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and BMP_SCALE_BOX. changed defaults for internal scalings, enhanced PDF export when reduched DPI is used, added BMP_SCALE_BESTQUALITY and BMP_SCALE_FASTESTINTERPOLATE as new default for Bitmap::Scale
Notes
Notes: merged as: 44fb0ceeb98f45bc301d021c11af2c13f051bd4b
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/vcl/alpha.hxx4
-rw-r--r--vcl/inc/vcl/bitmap.hxx137
-rw-r--r--vcl/inc/vcl/bitmapex.hxx4
-rw-r--r--vcl/source/gdi/bitmap3.cxx1330
-rw-r--r--vcl/source/gdi/bitmapex.cxx4
-rw-r--r--vcl/source/gdi/impgraph.cxx2
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx8
-rw-r--r--vcl/source/helper/canvasbitmap.cxx2
8 files changed, 1465 insertions, 26 deletions
diff --git a/vcl/inc/vcl/alpha.hxx b/vcl/inc/vcl/alpha.hxx
index d76aef98d0d6..6d9c077ebbe8 100644
--- a/vcl/inc/vcl/alpha.hxx
+++ b/vcl/inc/vcl/alpha.hxx
@@ -81,8 +81,8 @@ public:
sal_Bool Erase( sal_uInt8 cTransparency );
sal_Bool Invert();
sal_Bool Mirror( sal_uLong nMirrorFlags );
- sal_Bool Scale( const Size& rNewSize, sal_uLong nScaleFlag = BMP_SCALE_FAST );
- sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_FAST );
+ sal_Bool Scale( const Size& rNewSize, sal_uLong nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE );
+ sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE );
sal_Bool Rotate( long nAngle10, sal_uInt8 cFillTransparency );
sal_Bool Replace( const Bitmap& rMask, sal_uInt8 rReplaceTransparency );
sal_Bool Replace( sal_uInt8 cSearchTransparency, sal_uInt8 cReplaceTransparency, sal_uLong nTol = 0UL );
diff --git a/vcl/inc/vcl/bitmap.hxx b/vcl/inc/vcl/bitmap.hxx
index 9c51465bdc67..be57468ff32c 100644
--- a/vcl/inc/vcl/bitmap.hxx
+++ b/vcl/inc/vcl/bitmap.hxx
@@ -40,9 +40,21 @@
// -----------------------------------------------------------------------------
-#define BMP_SCALE_NONE 0x00000000UL
-#define BMP_SCALE_FAST 0x00000001UL
-#define BMP_SCALE_INTERPOLATE 0x00000002UL
+#define BMP_SCALE_NONE 0x00000000UL
+#define BMP_SCALE_FAST 0x00000001UL
+#define BMP_SCALE_INTERPOLATE 0x00000002UL
+#define BMP_SCALE_SUPER 0x00000003UL
+#define BMP_SCALE_LANCZOS 0x00000004UL
+#define BMP_SCALE_BICUBIC 0x00000005UL
+#define BMP_SCALE_BILINEAR 0x00000006UL
+#define BMP_SCALE_BOX 0x00000007UL
+
+// new default assigns for having slots for best quality and
+// an alternative with a good compromize between speed and quality.
+// Currently BMP_SCALE_BESTQUALITY maps to BMP_SCALE_LANCZOS and
+// BMP_SCALE_FASTESTINTERPOLATE to BMP_SCALE_SUPER
+#define BMP_SCALE_BESTQUALITY 0x000000feUL
+#define BMP_SCALE_FASTESTINTERPOLATE 0x000000ffUL
// -----------------------------------------------------------------------------
@@ -159,7 +171,7 @@ class VCL_DLLPUBLIC BmpFilterParam
friend class Animation;
private:
- BmpFilter meFilter;
+ BmpFilter meFilter;
sal_uLong mnProgressStart;
sal_uLong mnProgressEnd;
@@ -214,6 +226,114 @@ public:
}
};
+// --------------------
+// Resample Kernels
+// --------------------
+
+class Kernel
+{
+public:
+ Kernel() {}
+ virtual ~Kernel() {}
+
+ virtual double GetWidth() const = 0;
+ virtual double Calculate(double x) const = 0;
+};
+
+class Lanczos3Kernel : public Kernel
+{
+public:
+ virtual double GetWidth() const
+ {
+ return 3.0;
+ }
+
+ virtual double Calculate(double x) const
+ {
+ return (-3.0 <= x && 3.0 > x) ? SincFilter(x) * SincFilter( x / 3.0 ) : 0.0;
+ }
+
+ inline double SincFilter(double x) const
+ {
+ if(0.0 == x)
+ {
+ return 1.0;
+ }
+
+ x *= M_PI;
+
+ return sin(x) / x;
+ }
+};
+
+class BicubicKernel : public Kernel
+{
+ virtual double GetWidth() const
+ {
+ return 2.0;
+ }
+
+ virtual double Calculate(double x) const
+ {
+ if(0.0 > x)
+ {
+ x = -x;
+ }
+
+ if(1.0 >= x)
+ {
+ return (1.5 * x - 2.5) * x * x + 1.0;
+ }
+ else if(2.0 > x)
+ {
+ return ((-0.5 * x + 2.5) * x - 4.0) * x + 2.0;
+ }
+
+ return 0.0;
+ }
+};
+
+class BilinearKernel : public Kernel
+{
+ virtual double GetWidth() const
+ {
+ return 1.0;
+ }
+
+ virtual double Calculate(double x) const
+ {
+ if(0.0 > x)
+ {
+ x = -x;
+ }
+
+ if(1.0 > x)
+ {
+ return 1.0 - x;
+ }
+
+ return 0.0;
+ }
+};
+
+class BoxKernel : public Kernel
+{
+ virtual double GetWidth() const
+ {
+ return 0.5;
+ }
+
+ virtual double Calculate(double x) const
+ {
+ if(-0.5 <= x && 0.5 > x)
+ {
+ return 1.0;
+ }
+
+ return 0.0;
+ }
+};
+
// ----------
// - Bitmap -
// ----------
@@ -277,8 +397,11 @@ public:
BitmapWriteAccess& rAcc, sal_Bool bRLE4 );
SAL_DLLPRIVATE static sal_Bool ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, sal_Bool bRLE4 );
+ SAL_DLLPRIVATE void ImplAdaptBitCount(Bitmap& rNew);
SAL_DLLPRIVATE sal_Bool ImplScaleFast( const double& rScaleX, const double& rScaleY );
SAL_DLLPRIVATE sal_Bool ImplScaleInterpolate( const double& rScaleX, const double& rScaleY );
+ SAL_DLLPRIVATE sal_Bool ImplScaleSuper( const double& rScaleX, const double& rScaleY );
+ SAL_DLLPRIVATE sal_Bool ImplScaleConvolution( const double& rScaleX, const double& rScaleY, const Kernel& aKernel);
SAL_DLLPRIVATE sal_Bool ImplMakeMono( sal_uInt8 cThreshold );
SAL_DLLPRIVATE sal_Bool ImplMakeMonoDither();
SAL_DLLPRIVATE sal_Bool ImplMakeGreyscales( sal_uInt16 nGreyscales );
@@ -531,8 +654,7 @@ public:
@return sal_True, if the operation was completed successfully.
*/
- sal_Bool Scale( const Size& rNewSize,
- sal_uLong nScaleFlag = BMP_SCALE_FAST );
+ sal_Bool Scale( const Size& rNewSize, sal_uLong nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE );
/** Scale the bitmap
@@ -544,8 +666,7 @@ public:
@return sal_True, if the operation was completed successfully.
*/
- sal_Bool Scale( const double& rScaleX, const double& rScaleY,
- sal_uLong nScaleFlag = BMP_SCALE_FAST );
+ sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE );
/** Rotate bitmap by the specified angle
diff --git a/vcl/inc/vcl/bitmapex.hxx b/vcl/inc/vcl/bitmapex.hxx
index cc7cd1ea3789..fa6439778eb0 100644
--- a/vcl/inc/vcl/bitmapex.hxx
+++ b/vcl/inc/vcl/bitmapex.hxx
@@ -255,7 +255,7 @@ public:
@return sal_True, if the operation was completed successfully.
*/
- sal_Bool Scale( const Size& rNewSize, sal_uLong nScaleFlag = BMP_SCALE_FAST );
+ sal_Bool Scale( const Size& rNewSize, sal_uLong nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE );
/** Scale the bitmap
@@ -267,7 +267,7 @@ public:
@return sal_True, if the operation was completed successfully.
*/
- sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_FAST );
+ sal_Bool Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE );
/** Rotate bitmap by the specified angle
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index 2f91cb5e073f..c6f87e774310 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -40,6 +40,7 @@
#define RGB15( _def_cR, _def_cG, _def_cB ) (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
#define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
+#define MAP( cVal0, cVal1, nFrac ) ((sal_uInt8)((((long)(cVal0)<<7L)+nFrac*((long)(cVal1)-(cVal0)))>>7L))
#define CALC_ERRORS \
nTemp = p1T[nX++] >> 12; \
@@ -905,21 +906,109 @@ sal_Bool Bitmap::ImplConvertGhosted()
sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
{
- sal_Bool bRet;
+#ifdef DBG_UTIL
+ // #121233# allow to test the different scalers in debug build with source
+ // level debugger (change nNumber to desired action)
+ static sal_uInt16 nNumber(0);
- if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) )
+ switch(nNumber)
{
- if( BMP_SCALE_FAST == nScaleFlag )
- bRet = ImplScaleFast( rScaleX, rScaleY );
- else if( BMP_SCALE_INTERPOLATE == nScaleFlag )
- bRet = ImplScaleInterpolate( rScaleX, rScaleY );
- else
- bRet = sal_False;
+ case 0 : break;
+ case 1: nScaleFlag = BMP_SCALE_FAST; break;
+ case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break;
+ case 3: nScaleFlag = BMP_SCALE_SUPER; break;
+ case 4: nScaleFlag = BMP_SCALE_LANCZOS; break;
+ case 5: nScaleFlag = BMP_SCALE_BICUBIC; break;
+ case 6: nScaleFlag = BMP_SCALE_BILINEAR; break;
+ case 7: nScaleFlag = BMP_SCALE_BOX; break;
+ case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break;
+ case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break;
+ }
+#endif // DBG_UTIL
+
+ if(basegfx::fTools::equalZero(rScaleX) && basegfx::fTools::equalZero(rScaleY))
+ {
+ // no scale
+ return true;
}
else
- bRet = sal_True;
+ {
+ if(BMP_SCALE_BESTQUALITY == nScaleFlag)
+ {
+ // Use LANCZOS when best quality is requested
+ nScaleFlag = BMP_SCALE_LANCZOS;
+ }
+ else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag)
+ {
+ // Use BMP_SCALE_SUPER when speed is requested, but not worst quality
+ nScaleFlag = BMP_SCALE_SUPER;
+ }
- return bRet;
+ switch(nScaleFlag)
+ {
+ default:
+ case BMP_SCALE_NONE :
+ {
+ return false;
+ break;
+ }
+ case BMP_SCALE_FAST :
+ {
+ return ImplScaleFast( rScaleX, rScaleY );
+ break;
+ }
+ case BMP_SCALE_INTERPOLATE :
+ {
+ return ImplScaleInterpolate( rScaleX, rScaleY );
+ break;
+ }
+ case BMP_SCALE_SUPER :
+ {
+ if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
+ {
+ // fallback to ImplScaleFast
+ return ImplScaleFast( rScaleX, rScaleY );
+ }
+ else
+ {
+ // #121233# use method from symphony
+ return ImplScaleSuper( rScaleX, rScaleY );
+ }
+ break;
+ }
+ case BMP_SCALE_LANCZOS :
+ {
+ const Lanczos3Kernel kernel;
+
+ return ImplScaleConvolution( rScaleX, rScaleY, kernel);
+ break;
+ }
+ case BMP_SCALE_BICUBIC :
+ {
+ const BicubicKernel kernel;
+
+ return ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ break;
+ }
+ case BMP_SCALE_BILINEAR :
+ {
+ const BilinearKernel kernel;
+
+ return ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ break;
+ }
+ case BMP_SCALE_BOX :
+ {
+ const BoxKernel kernel;
+
+ return ImplScaleConvolution( rScaleX, rScaleY, kernel );
+ break;
+ }
+ }
+ }
+
+ // should not happen
+ return false;
}
// ------------------------------------------------------------------------
@@ -943,6 +1032,58 @@ sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
// ------------------------------------------------------------------------
+void Bitmap::ImplAdaptBitCount(Bitmap& rNew)
+{
+ // aNew is the result of some operation; adapt it's BitCount to the original (this)
+ if(GetBitCount() != rNew.GetBitCount())
+ {
+ switch(GetBitCount())
+ {
+ case 1:
+ {
+ rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
+ break;
+ }
+ case 4:
+ {
+ if(HasGreyPalette())
+ {
+ rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
+ }
+ else
+ {
+ rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
+ }
+ break;
+ }
+ case 8:
+ {
+ if(HasGreyPalette())
+ {
+ rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
+ }
+ else
+ {
+ rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
+ }
+ break;
+ }
+ case 24:
+ {
+ rNew.Convert(BMP_CONVERSION_24BIT);
+ break;
+ }
+ default:
+ {
+ OSL_ENSURE(false, "BitDepth adaption failed (!)");
+ break;
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
{
const Size aSizePix( GetSizePixel() );
@@ -1136,6 +1277,7 @@ sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rSca
if( bRet )
{
bRet = sal_False;
+ ImplAdaptBitCount(aNewBmp);
ImplAssignWithSize( aNewBmp );
pReadAcc = AcquireReadAccess();
aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
@@ -1238,7 +1380,10 @@ sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rSca
aNewBmp.ReleaseAccess( pWriteAcc );
if( bRet )
+ {
+ ImplAdaptBitCount(aNewBmp);
ImplAssignWithSize( aNewBmp );
+ }
}
}
@@ -1249,6 +1394,1171 @@ sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rSca
}
// ------------------------------------------------------------------------
+// #121233# Added BMP_SCALE_SUPER from symphony code
+
+sal_Bool Bitmap::ImplScaleSuper(
+ const double& rScaleX,
+ const double& rScaleY )
+{
+ const Size aSizePix( GetSizePixel() );
+ bool bHMirr = ( rScaleX < 0 );
+ bool bVMirr = ( rScaleY < 0 );
+ double scaleX = bHMirr ? -rScaleX : rScaleX;
+ double scaleY = bVMirr ? -rScaleY : rScaleY;
+ const long nDstW = FRound( aSizePix.Width() * scaleX );
+ const long nDstH = FRound( aSizePix.Height() * scaleY );
+ const double fScaleThresh = 0.6;
+ bool bRet = false;
+
+ if( ( nDstW > 1L ) && ( nDstH > 1L ) )
+ {
+ BitmapColor aCol0, aCol1, aColRes;
+ BitmapReadAccess* pAcc = AcquireReadAccess();
+ long nW = pAcc->Width() ;
+ long nH = pAcc->Height() ;
+ Bitmap aOutBmp( Size( nDstW, nDstH ), 24 );
+ BitmapWriteAccess* pWAcc = aOutBmp.AcquireWriteAccess();
+ long* pMapIX = new long[ nDstW ];
+ long* pMapIY = new long[ nDstH ];
+ long* pMapFX = new long[ nDstW ];
+ long* pMapFY = new long[ nDstH ];
+ long nX, nY, nXDst, nYDst;;
+ double fTemp;
+ long nTemp , nTempX, nTempY, nTempFX, nTempFY;
+ sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1;
+ long nStartX = 0 , nStartY = 0;
+ long nEndX = nDstW - 1L;
+ long nEndY = nDstH - 1L;
+ long nMax = 1 << 7L;
+
+ if( pAcc && pWAcc )
+ {
+ const double fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0;
+ const double fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0;
+
+ // create horizontal mapping table
+ for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ )
+ {
+ fTemp = nX * fRevScaleX;
+
+ if( bHMirr )
+ fTemp = nTempX - fTemp;
+
+ pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
+ }
+
+ // create vertical mapping table
+ for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ )
+ {
+ fTemp = nY * fRevScaleY;
+
+ if( bVMirr )
+ fTemp = nTempY - fTemp;
+
+ pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
+ {
+ Scanline pLine0, pLine1;
+
+ for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
+ pLine0 = pAcc->GetScanline( nTempY );
+ pLine1 = pAcc->GetScanline( ++nTempY );
+
+ for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
+
+ const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] );
+ const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
+ const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] );
+ const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
+
+ cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
+ cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
+ cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
+
+ cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
+ cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
+ cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
+
+ aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
+ aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
+ aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+ }
+ }
+ }
+ else
+ {
+ Scanline pTmpY;
+ long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
+ long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
+ long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
+
+ for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTop = bVMirr ? ( nY + 1 ) : nY;
+ nBottom = bVMirr ? nY : ( nY + 1 ) ;
+
+ if( nY ==nEndY )
+ {
+ nLineStart = pMapIY[ nY ];
+ nLineRange = 0;
+ }
+ else
+ {
+ nLineStart = pMapIY[ nTop ] ;
+ nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
+ }
+
+ for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nLeft = bHMirr ? ( nX + 1 ) : nX;
+ nRight = bHMirr ? nX : ( nX + 1 ) ;
+
+ if( nX == nEndX )
+ {
+ nRowStart = pMapIX[ nX ];
+ nRowRange = 0;
+ }
+ else
+ {
+ nRowStart = pMapIX[ nLeft ];
+ nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
+ }
+
+ nSumR = nSumG = nSumB = 0;
+ nTotalWeightY = 0;
+
+ for(int i = 0; i<= nLineRange; i++)
+ {
+ pTmpY = pAcc->GetScanline( nLineStart + i );
+ nSumRowR = nSumRowG = nSumRowB = 0;
+ nTotalWeightX = 0;
+
+ for(int j = 0; j <= nRowRange; j++)
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] );
+
+ if(nX == nEndX )
+ {
+ nSumRowB += rCol.GetBlue() << 7L;
+ nSumRowG += rCol.GetGreen() << 7L;
+ nSumRowR += rCol.GetRed() << 7L;
+ nTotalWeightX += 1 << 7L;
+ }
+ else if( j == 0 )
+ {
+ nWeightX = (nMax- pMapFX[ nLeft ]) ;
+ nSumRowB += ( nWeightX *rCol.GetBlue()) ;
+ nSumRowG += ( nWeightX *rCol.GetGreen()) ;
+ nSumRowR += ( nWeightX *rCol.GetRed()) ;
+ nTotalWeightX += nWeightX;
+ }
+ else if ( nRowRange == j )
+ {
+ nWeightX = pMapFX[ nRight ] ;
+ nSumRowB += ( nWeightX *rCol.GetBlue() );
+ nSumRowG += ( nWeightX *rCol.GetGreen() );
+ nSumRowR += ( nWeightX *rCol.GetRed() );
+ nTotalWeightX += nWeightX;
+ }
+ else
+ {
+ nSumRowB += rCol.GetBlue() << 7L;
+ nSumRowG += rCol.GetGreen() << 7L;
+ nSumRowR += rCol.GetRed() << 7L;
+ nTotalWeightX += 1 << 7L;
+ }
+ }
+
+ if( nY == nEndY )
+ nWeightY = nMax;
+ else if( i == 0 )
+ nWeightY = nMax - pMapFY[ nTop ];
+ else if( nLineRange == 1 )
+ nWeightY = pMapFY[ nTop ];
+ else if ( nLineRange == i )
+ nWeightY = pMapFY[ nBottom ];
+ else
+ nWeightY = nMax;
+
+ nWeightY = nWeightY ;
+ nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
+ nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
+ nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
+ nTotalWeightY += nWeightY;
+ }
+
+ aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
+ aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
+ aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+
+ }
+ }
+ }
+}
+ else
+ {
+ if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
+ {
+ for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ];
+
+ for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
+
+ aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) );
+ aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) );
+ cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
+ cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
+ cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
+
+ aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) );
+ aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) );
+ cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
+ cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
+ cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
+
+ aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
+ aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
+ aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+ }
+ }
+
+ }
+ else
+ {
+ long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
+ long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
+ long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
+
+ for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTop = bVMirr ? ( nY + 1 ) : nY;
+ nBottom = bVMirr ? nY : ( nY + 1 ) ;
+
+ if( nY ==nEndY )
+ {
+ nLineStart = pMapIY[ nY ];
+ nLineRange = 0;
+ }
+ else
+ {
+ nLineStart = pMapIY[ nTop ] ;
+ nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
+ }
+
+ for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nLeft = bHMirr ? ( nX + 1 ) : nX;
+ nRight = bHMirr ? nX : ( nX + 1 ) ;
+
+ if( nX == nEndX )
+ {
+ nRowStart = pMapIX[ nX ];
+ nRowRange = 0;
+ }
+ else
+ {
+ nRowStart = pMapIX[ nLeft ];
+ nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
+ }
+
+ nSumR = nSumG = nSumB = 0;
+ nTotalWeightY = 0;
+
+ for(int i = 0; i<= nLineRange; i++)
+ {
+ nSumRowR = nSumRowG = nSumRowB = 0;
+ nTotalWeightX = 0;
+
+ for(int j = 0; j <= nRowRange; j++)
+ {
+ aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
+
+ if(nX == nEndX )
+ {
+
+ nSumRowB += aCol0.GetBlue() << 7L;
+ nSumRowG += aCol0.GetGreen() << 7L;
+ nSumRowR += aCol0.GetRed() << 7L;
+ nTotalWeightX += 1 << 7L;
+ }
+ else if( j == 0 )
+ {
+
+ nWeightX = (nMax- pMapFX[ nLeft ]) ;
+ nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
+ nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
+ nSumRowR += ( nWeightX *aCol0.GetRed()) ;
+ nTotalWeightX += nWeightX;
+ }
+ else if ( nRowRange == j )
+ {
+
+ nWeightX = pMapFX[ nRight ] ;
+ nSumRowB += ( nWeightX *aCol0.GetBlue() );
+ nSumRowG += ( nWeightX *aCol0.GetGreen() );
+ nSumRowR += ( nWeightX *aCol0.GetRed() );
+ nTotalWeightX += nWeightX;
+ }
+ else
+ {
+
+ nSumRowB += aCol0.GetBlue() << 7L;
+ nSumRowG += aCol0.GetGreen() << 7L;
+ nSumRowR += aCol0.GetRed() << 7L;
+ nTotalWeightX += 1 << 7L;
+ }
+ }
+
+ if( nY == nEndY )
+ nWeightY = nMax;
+ else if( i == 0 )
+ nWeightY = nMax - pMapFY[ nTop ];
+ else if( nLineRange == 1 )
+ nWeightY = pMapFY[ nTop ];
+ else if ( nLineRange == i )
+ nWeightY = pMapFY[ nBottom ];
+ else
+ nWeightY = nMax;
+
+ nWeightY = nWeightY ;
+ nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
+ nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
+ nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
+ nTotalWeightY += nWeightY;
+ }
+
+ aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
+ aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
+ aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
+ {
+ Scanline pLine0, pLine1, pTmp0, pTmp1;
+ long nOff;
+
+ for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
+ pLine0 = pAcc->GetScanline( nTempY );
+ pLine1 = pAcc->GetScanline( ++nTempY );
+
+ for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nOff = 3L * ( nTempX = pMapIX[ nX ] );
+ nTempFX = pMapFX[ nX ];
+
+ pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
+ cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
+
+ pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
+ cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
+
+ aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
+ aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
+ aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+ }
+ }
+ }
+ else
+ {
+ Scanline pTmpY, pTmpX;
+ long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
+ long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
+ long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
+
+ for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTop = bVMirr ? ( nY + 1 ) : nY;
+ nBottom = bVMirr ? nY : ( nY + 1 ) ;
+
+ if( nY ==nEndY )
+ {
+ nLineStart = pMapIY[ nY ];
+ nLineRange = 0;
+ }
+ else
+ {
+ nLineStart = pMapIY[ nTop ] ;
+ nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
+ }
+
+ for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nLeft = bHMirr ? ( nX + 1 ) : nX;
+ nRight = bHMirr ? nX : ( nX + 1 ) ;
+
+ if( nX == nEndX )
+ {
+ nRowStart = pMapIX[ nX ];
+ nRowRange = 0;
+ }
+ else
+ {
+ nRowStart = pMapIX[ nLeft ];
+ nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
+ }
+
+ nSumR = nSumG = nSumB = 0;
+ nTotalWeightY = 0;
+
+ for(int i = 0; i<= nLineRange; i++)
+ {
+ pTmpY = pAcc->GetScanline( nLineStart + i );
+ pTmpX = pTmpY + 3L * nRowStart;
+ nSumRowR = nSumRowG = nSumRowB = 0;
+ nTotalWeightX = 0;
+
+ for(int j = 0; j <= nRowRange; j++)
+ {
+ if(nX == nEndX )
+ {
+ nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
+ nTotalWeightX += 1 << 7L;
+ }
+ else if( j == 0 )
+ {
+ nWeightX = (nMax- pMapFX[ nLeft ]) ;
+ nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
+ nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
+ nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
+ nTotalWeightX += nWeightX;
+ }
+ else if ( nRowRange == j )
+ {
+ nWeightX = pMapFX[ nRight ] ;
+ nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
+ nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
+ nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
+ nTotalWeightX += nWeightX;
+ }
+ else
+ {
+ nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
+ nTotalWeightX += 1 << 7L;
+ }
+ }
+
+ if( nY == nEndY )
+ nWeightY = nMax;
+ else if( i == 0 )
+ nWeightY = nMax - pMapFY[ nTop ];
+ else if( nLineRange == 1 )
+ nWeightY = pMapFY[ nTop ];
+ else if ( nLineRange == i )
+ nWeightY = pMapFY[ nBottom ];
+ else
+ nWeightY = nMax;
+
+ nWeightY = nWeightY ;
+ nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
+ nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
+ nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
+ nTotalWeightY += nWeightY;
+ }
+
+ aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
+ aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
+ aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+
+ }
+ }
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
+ {
+ if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
+ {
+ Scanline pLine0, pLine1, pTmp0, pTmp1;
+ long nOff;
+
+ for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
+ pLine0 = pAcc->GetScanline( nTempY );
+ pLine1 = pAcc->GetScanline( ++nTempY );
+
+ for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nOff = 3L * ( nTempX = pMapIX[ nX ] );
+ nTempFX = pMapFX[ nX ];
+
+ pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
+ cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
+
+ pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
+ cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
+ cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
+
+ aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
+ aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
+ aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+ }
+ }
+ }
+ else
+ {
+ Scanline pTmpY, pTmpX;
+ long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
+ long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
+ long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
+
+ for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTop = bVMirr ? ( nY + 1 ) : nY;
+ nBottom = bVMirr ? nY : ( nY + 1 ) ;
+
+ if( nY ==nEndY )
+ {
+ nLineStart = pMapIY[ nY ];
+ nLineRange = 0;
+ }
+ else
+ {
+ nLineStart = pMapIY[ nTop ] ;
+ nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
+ }
+
+ for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nLeft = bHMirr ? ( nX + 1 ) : nX;
+ nRight = bHMirr ? nX : ( nX + 1 ) ;
+
+ if( nX == nEndX )
+ {
+ nRowStart = pMapIX[ nX ];
+ nRowRange = 0;
+ }
+ else
+ {
+ nRowStart = pMapIX[ nLeft ];
+ nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
+ }
+
+ nSumR = nSumG = nSumB = 0;
+ nTotalWeightY = 0;
+
+ for(int i = 0; i<= nLineRange; i++)
+ {
+ pTmpY = pAcc->GetScanline( nLineStart + i );
+ pTmpX = pTmpY + 3L * nRowStart;
+ nSumRowR = nSumRowG = nSumRowB = 0;
+ nTotalWeightX = 0;
+
+ for(int j = 0; j <= nRowRange; j++)
+ {
+ if(nX == nEndX )
+ {
+ nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
+ nTotalWeightX += 1 << 7L;
+ }
+ else if( j == 0 )
+ {
+ nWeightX = (nMax- pMapFX[ nLeft ]) ;
+ nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
+ nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
+ nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
+ nTotalWeightX += nWeightX;
+ }
+ else if ( nRowRange == j )
+ {
+ nWeightX = pMapFX[ nRight ] ;
+ nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
+ nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
+ nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
+ nTotalWeightX += nWeightX;
+ }
+ else
+ {
+ nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
+ nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
+ nTotalWeightX += 1 << 7L;
+ }
+ }
+
+ if( nY == nEndY )
+ nWeightY = nMax;
+ else if( i == 0 )
+ nWeightY = nMax - pMapFY[ nTop ];
+ else if( nLineRange == 1 )
+ nWeightY = pMapFY[ nTop ];
+ else if ( nLineRange == i )
+ nWeightY = pMapFY[ nBottom ];
+ else
+ nWeightY = nMax;
+
+ nWeightY = nWeightY ;
+ nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
+ nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
+ nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
+ nTotalWeightY += nWeightY;
+ }
+
+ aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
+ aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
+ aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+
+ }
+ }
+ }
+ }
+ else
+ {
+ if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
+ {
+ for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
+
+ for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
+
+ aCol0 = pAcc->GetPixel( nTempY, nTempX );
+ aCol1 = pAcc->GetPixel( nTempY, ++nTempX );
+ cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
+ cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
+ cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
+
+ aCol1 = pAcc->GetPixel( ++nTempY, nTempX );
+ aCol0 = pAcc->GetPixel( nTempY--, --nTempX );
+ cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
+ cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
+ cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
+
+ aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
+ aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
+ aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+ }
+ }
+ }
+ else
+ {
+ long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
+ long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
+ long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
+
+ for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
+ {
+ nTop = bVMirr ? ( nY + 1 ) : nY;
+ nBottom = bVMirr ? nY : ( nY + 1 ) ;
+
+ if( nY ==nEndY )
+ {
+ nLineStart = pMapIY[ nY ];
+ nLineRange = 0;
+ }
+ else
+ {
+ nLineStart = pMapIY[ nTop ] ;
+ nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
+ }
+
+ for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
+ {
+ nLeft = bHMirr ? ( nX + 1 ) : nX;
+ nRight = bHMirr ? nX : ( nX + 1 ) ;
+
+ if( nX == nEndX )
+ {
+ nRowStart = pMapIX[ nX ];
+ nRowRange = 0;
+ }
+ else
+ {
+ nRowStart = pMapIX[ nLeft ];
+ nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
+ }
+
+ nSumR = nSumG = nSumB = 0;
+ nTotalWeightY = 0;
+
+ for(int i = 0; i<= nLineRange; i++)
+ {
+ nSumRowR = nSumRowG = nSumRowB = 0;
+ nTotalWeightX = 0;
+
+ for(int j = 0; j <= nRowRange; j++)
+ {
+ aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j );
+
+ if(nX == nEndX )
+ {
+
+ nSumRowB += aCol0.GetBlue() << 7L;
+ nSumRowG += aCol0.GetGreen() << 7L;
+ nSumRowR += aCol0.GetRed() << 7L;
+ nTotalWeightX += 1 << 7L;
+ }
+ else if( j == 0 )
+ {
+
+ nWeightX = (nMax- pMapFX[ nLeft ]) ;
+ nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
+ nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
+ nSumRowR += ( nWeightX *aCol0.GetRed()) ;
+ nTotalWeightX += nWeightX;
+ }
+ else if ( nRowRange == j )
+ {
+
+ nWeightX = pMapFX[ nRight ] ;
+ nSumRowB += ( nWeightX *aCol0.GetBlue() );
+ nSumRowG += ( nWeightX *aCol0.GetGreen() );
+ nSumRowR += ( nWeightX *aCol0.GetRed() );
+ nTotalWeightX += nWeightX;
+ }
+ else
+ {
+ nSumRowB += aCol0.GetBlue() << 7L;
+ nSumRowG += aCol0.GetGreen() << 7L;
+ nSumRowR += aCol0.GetRed() << 7L;
+ nTotalWeightX += 1 << 7L;
+ }
+ }
+
+ if( nY == nEndY )
+ nWeightY = nMax;
+ else if( i == 0 )
+ nWeightY = nMax - pMapFY[ nTop ];
+ else if( nLineRange == 1 )
+ nWeightY = pMapFY[ nTop ];
+ else if ( nLineRange == i )
+ nWeightY = pMapFY[ nBottom ];
+ else
+ nWeightY = nMax;
+
+ nWeightY = nWeightY ;
+ nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
+ nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
+ nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
+ nTotalWeightY += nWeightY;
+ }
+
+ aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
+ aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
+ aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
+ pWAcc->SetPixel( nYDst, nXDst++, aColRes );
+
+ }
+ }
+ }
+ }
+ }
+
+ bRet = true;
+ }
+
+ delete[] pMapIX;
+ delete[] pMapIY;
+ delete[] pMapFX;
+ delete[] pMapFY;
+
+ ReleaseAccess( pAcc );
+ aOutBmp.ReleaseAccess( pWAcc );
+
+ if( bRet )
+ {
+ ImplAdaptBitCount(aOutBmp);
+ ImplAssignWithSize(aOutBmp);
+ }
+
+ if( !bRet )
+ bRet = ImplScaleFast( scaleX, scaleY );
+ }
+
+ return bRet;
+}
+
+//-----------------------------------------------------------------------------------
+
+namespace
+{
+ void ImplCalculateContributions(
+ const sal_uInt32 aSourceSize,
+ const sal_uInt32 aDestinationSize,
+ sal_uInt32& aNumberOfContributions,
+ double*& pWeights,
+ sal_uInt32*& pPixels,
+ sal_uInt32*& pCount,
+ const Kernel& aKernel)
+ {
+ const double fSamplingRadius(aKernel.GetWidth());
+ const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
+ const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
+ const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
+
+ aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
+ const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
+ pWeights = new double[nAllocSize];
+ pPixels = new sal_uInt32[nAllocSize];
+ pCount = new sal_uInt32[aDestinationSize];
+
+ for(sal_uInt32 i(0); i < aDestinationSize; i++)
+ {
+ const sal_uInt32 aIndex(i * aNumberOfContributions);
+ const double aCenter(i / fScale);
+ const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
+ const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
+ sal_uInt32 aCurrentCount(0);
+
+ for(sal_Int32 j(aLeft); j <= aRight; j++)
+ {
+ const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
+
+ // Reduce calculations with ignoring weights of 0.0
+ if(fabs(aWeight) < 0.0001)
+ {
+ continue;
+ }
+
+ // Handling on edges
+ const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
+ const sal_uInt32 nIndex(aIndex + aCurrentCount);
+
+ pWeights[nIndex] = aWeight;
+ pPixels[nIndex] = aPixelIndex;
+
+ aCurrentCount++;
+ }
+
+ pCount[i] = aCurrentCount;
+ }
+ }
+
+ sal_Bool ImplScaleConvolutionHor(
+ Bitmap& rSource,
+ Bitmap& rTarget,
+ const double& rScaleX,
+ const Kernel& aKernel)
+ {
+ // Do horizontal filtering
+ OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
+ const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
+ const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
+
+ if(nWidth == nNewWidth)
+ {
+ return true;
+ }
+
+ BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
+
+ if(pReadAcc)
+ {
+ double* pWeights = 0;
+ sal_uInt32* pPixels = 0;
+ sal_uInt32* pCount = 0;
+ sal_uInt32 aNumberOfContributions(0);
+
+ const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
+ ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
+ rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
+ BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
+ bool bResult(0 != pWriteAcc);
+
+ if(bResult)
+ {
+ for(sal_uInt32 y(0); y < nHeight; y++)
+ {
+ for(sal_uInt32 x(0); x < nNewWidth; x++)
+ {
+ const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
+ double aSum(0.0);
+ double aValueRed(0.0);
+ double aValueGreen(0.0);
+ double aValueBlue(0.0);
+
+ for(sal_uInt32 j(0); j < pCount[x]; j++)
+ {
+ const sal_uInt32 aIndex(aBaseIndex + j);
+ const double aWeight(pWeights[aIndex]);
+ BitmapColor aColor;
+
+ aSum += aWeight;
+
+ if(pReadAcc->HasPalette())
+ {
+ aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
+ }
+ else
+ {
+ aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
+ }
+
+ aValueRed += aWeight * aColor.GetRed();
+ aValueGreen += aWeight * aColor.GetGreen();
+ aValueBlue += aWeight * aColor.GetBlue();
+ }
+
+ const BitmapColor aResultColor(
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
+
+ pWriteAcc->SetPixel(y, x, aResultColor);
+ }
+ }
+
+ rTarget.ReleaseAccess(pWriteAcc);
+ }
+
+ rSource.ReleaseAccess(pReadAcc);
+ delete[] pWeights;
+ delete[] pCount;
+ delete[] pPixels;
+
+ if(bResult)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool ImplScaleConvolutionVer(
+ Bitmap& rSource,
+ Bitmap& rTarget,
+ const double& rScaleY,
+ const Kernel& aKernel)
+ {
+ // Do vertical filtering
+ OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
+ const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
+ const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
+
+ if(nHeight == nNewHeight)
+ {
+ return true;
+ }
+
+ BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
+
+ if(pReadAcc)
+ {
+ double* pWeights = 0;
+ sal_uInt32* pPixels = 0;
+ sal_uInt32* pCount = 0;
+ sal_uInt32 aNumberOfContributions(0);
+
+ const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
+ ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
+ rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
+ BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
+ bool bResult(0 != pWriteAcc);
+
+ if(pWriteAcc)
+ {
+ for(sal_uInt32 x(0); x < nWidth; x++)
+ {
+ for(sal_uInt32 y(0); y < nNewHeight; y++)
+ {
+ const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
+ double aSum(0.0);
+ double aValueRed(0.0);
+ double aValueGreen(0.0);
+ double aValueBlue(0.0);
+
+ for(sal_uInt32 j(0); j < pCount[y]; j++)
+ {
+ const sal_uInt32 aIndex(aBaseIndex + j);
+ const double aWeight(pWeights[aIndex]);
+ BitmapColor aColor;
+
+ aSum += aWeight;
+
+ if(pReadAcc->HasPalette())
+ {
+ aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
+ }
+ else
+ {
+ aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
+ }
+
+ aValueRed += aWeight * aColor.GetRed();
+ aValueGreen += aWeight * aColor.GetGreen();
+ aValueBlue += aWeight * aColor.GetBlue();
+ }
+
+ const BitmapColor aResultColor(
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
+ static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
+
+ if(pWriteAcc->HasPalette())
+ {
+ pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
+ }
+ else
+ {
+ pWriteAcc->SetPixel(y, x, aResultColor);
+ }
+ }
+ }
+ }
+
+ rTarget.ReleaseAccess(pWriteAcc);
+ rSource.ReleaseAccess(pReadAcc);
+
+ delete[] pWeights;
+ delete[] pCount;
+ delete[] pPixels;
+
+ if(bResult)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
+// #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and
+// BMP_SCALE_BOX derived from the original commit from Toma Vajngerl (see
+// bugzilla task for deitails) Thanks!
+sal_Bool Bitmap::ImplScaleConvolution(
+ const double& rScaleX,
+ const double& rScaleY,
+ const Kernel& aKernel)
+{
+ const bool bMirrorHor(rScaleX < 0.0);
+ const bool bMirrorVer(rScaleY < 0.0);
+ const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
+ const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
+ const sal_uInt32 nWidth(GetSizePixel().Width());
+ const sal_uInt32 nHeight(GetSizePixel().Height());
+ const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
+ const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
+ const bool bScaleHor(nWidth != nNewWidth);
+ const bool bScaleVer(nHeight != nNewHeight);
+ const bool bMirror(bMirrorHor || bMirrorVer);
+
+ if(!bMirror && !bScaleHor && !bScaleVer)
+ {
+ return true;
+ }
+
+ bool bResult(true);
+ sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
+ bool bMirrorAfter(false);
+
+ if(bMirror)
+ {
+ if(bMirrorHor)
+ {
+ nMirrorFlags |= BMP_MIRROR_HORZ;
+ }
+
+ if(bMirrorVer)
+ {
+ nMirrorFlags |= BMP_MIRROR_VERT;
+ }
+
+ const sal_uInt32 nStartSize(nWidth * nHeight);
+ const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
+
+ bMirrorAfter = nStartSize > nEndSize;
+
+ if(!bMirrorAfter)
+ {
+ bResult = Mirror(nMirrorFlags);
+ }
+ }
+
+ Bitmap aResult;
+
+ if(bResult)
+ {
+ const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
+ const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
+
+ if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
+ {
+ if(bScaleHor)
+ {
+ bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel);
+ }
+
+ if(bResult && bScaleVer)
+ {
+ bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel);
+ }
+ }
+ else
+ {
+ if(bScaleVer)
+ {
+ bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel);
+ }
+
+ if(bResult && bScaleHor)
+ {
+ bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel);
+ }
+ }
+ }
+
+ if(bResult && bMirrorAfter)
+ {
+ bResult = aResult.Mirror(nMirrorFlags);
+ }
+
+ if(bResult)
+ {
+ ImplAdaptBitCount(aResult);
+ *this = aResult;
+ }
+
+ return bResult;
+}
+
+// ------------------------------------------------------------------------
sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
{
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
index f5e37bdce759..1a518dbd09f2 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -443,7 +443,9 @@ sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uLon
bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
- aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST );
+ {
+ aMask.Scale( rScaleX, rScaleY, nScaleFlag );
+ }
aBitmapSize = aBitmap.GetSizePixel();
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index be936e555d5b..ac209e62b364 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -660,7 +660,7 @@ BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParamet
{
aRetBmpEx.Scale(
rParameters.getSizePixel(),
- rParameters.getScaleHighQuality() ? BMP_SCALE_INTERPOLATE : BMP_SCALE_FAST);
+ rParameters.getScaleHighQuality() ? BMP_SCALE_BESTQUALITY : BMP_SCALE_FASTESTINTERPOLATE);
}
}
else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index 28031aab7535..161a8502dca1 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -132,10 +132,16 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz
aNewBmpSize.Width() = FRound( fMaxPixelX );
aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
}
+
if( aNewBmpSize.Width() && aNewBmpSize.Height() )
- aBitmapEx.Scale( aNewBmpSize );
+ {
+ // #121233# Use best quality for PDF exports
+ aBitmapEx.Scale( aNewBmpSize, BMP_SCALE_BESTQUALITY );
+ }
else
+ {
aBitmapEx.SetEmpty();
+ }
}
}
diff --git a/vcl/source/helper/canvasbitmap.cxx b/vcl/source/helper/canvasbitmap.cxx
index 8ae3ccb987db..8eab29ea66c4 100644
--- a/vcl/source/helper/canvasbitmap.cxx
+++ b/vcl/source/helper/canvasbitmap.cxx
@@ -457,7 +457,7 @@ uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap(
vos::OGuard aGuard( Application::GetSolarMutex() );
BitmapEx aNewBmp( m_aBitmap );
- aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE );
+ aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FASTESTINTERPOLATE : BMP_SCALE_INTERPOLATE );
return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
}