diff options
21 files changed, 1342 insertions, 77 deletions
diff --git a/canvas/source/vcl/canvasbitmaphelper.cxx b/canvas/source/vcl/canvasbitmaphelper.cxx index 7b604101950c..6a9698a3bfcf 100644 --- a/canvas/source/vcl/canvasbitmaphelper.cxx +++ b/canvas/source/vcl/canvasbitmaphelper.cxx @@ -120,7 +120,7 @@ namespace vclcanvas BitmapEx aRes( mpBackBuffer->getBitmapReference() ); aRes.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize), - beFast ? BMP_SCALE_FAST : BMP_SCALE_DEFAULT ); + beFast ? BMP_SCALE_DEFAULT : BMP_SCALE_BESTQUALITY ); return uno::Reference< rendering::XBitmap >( new CanvasBitmap( aRes, *mpDevice, mpOutDevReference ) ); diff --git a/canvas/source/vcl/canvashelper.cxx b/canvas/source/vcl/canvashelper.cxx index 8c393fd59e6d..0f3718feed64 100644 --- a/canvas/source/vcl/canvashelper.cxx +++ b/canvas/source/vcl/canvashelper.cxx @@ -942,7 +942,7 @@ namespace vclcanvas Bitmap aBitmap( rOutDev.GetBitmap(aEmptyPoint, aBmpSize) ); aBitmap.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize), - beFast ? BMP_SCALE_FAST : BMP_SCALE_DEFAULT ); + beFast ? BMP_SCALE_DEFAULT : BMP_SCALE_BESTQUALITY ); return uno::Reference< rendering::XBitmap >( new CanvasBitmap( aBitmap, *mpDevice, mpOutDev ) ); diff --git a/filter/source/graphicfilter/eps/eps.cxx b/filter/source/graphicfilter/eps/eps.cxx index 3d721d9202aa..454d683393ed 100644 --- a/filter/source/graphicfilter/eps/eps.cxx +++ b/filter/source/graphicfilter/eps/eps.cxx @@ -480,7 +480,7 @@ void PSWriter::ImplWriteProlog( const Graphic* pPreview ) { Size aSizeBitmap( ( aSizePoint.Width() + 7 ) & ~7, aSizePoint.Height() ); Bitmap aTmpBitmap( pPreview->GetBitmap() ); - aTmpBitmap.Scale( aSizeBitmap, BMP_SCALE_BEST ); + aTmpBitmap.Scale( aSizeBitmap, BMP_SCALE_BESTQUALITY ); aTmpBitmap.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); BitmapReadAccess* pAcc = aTmpBitmap.AcquireReadAccess(); if ( pAcc ) diff --git a/framework/source/fwe/classes/addonsoptions.cxx b/framework/source/fwe/classes/addonsoptions.cxx index 52cdaba7dfa9..598ac6a2b5ee 100644 --- a/framework/source/fwe/classes/addonsoptions.cxx +++ b/framework/source/fwe/classes/addonsoptions.cxx @@ -1318,13 +1318,13 @@ void AddonsOptions_Impl::ReadImageFromURL( ImageSize nImageSize, const OUString& if ( aBmpSize != aNoScaleSize ) { BitmapEx aNoScaleBmp( aBitmapEx ); - aNoScaleBmp.Scale( aNoScaleSize, BMP_SCALE_BEST ); + aNoScaleBmp.Scale( aNoScaleSize, BMP_SCALE_BESTQUALITY ); } else aImageNoScale = Image( aBitmapEx ); if ( aBmpSize != aSize ) - aBitmapEx.Scale( aSize, BMP_SCALE_BEST ); + aBitmapEx.Scale( aSize, BMP_SCALE_BESTQUALITY ); aImage = Image( aBitmapEx ); } @@ -1472,7 +1472,7 @@ sal_Bool AddonsOptions_Impl::CreateImageFromSequence( Image& rImage, sal_Bool bB // Scale bitmap to fit the correct size for the menu/toolbar. Use best quality if ( aBitmapEx.GetSizePixel() != aSize ) - aBitmapEx.Scale( aSize, BMP_SCALE_BEST ); + aBitmapEx.Scale( aSize, BMP_SCALE_BESTQUALITY ); if( !aBitmapEx.IsTransparent() ) { diff --git a/framework/source/uielement/imagebuttontoolbarcontroller.cxx b/framework/source/uielement/imagebuttontoolbarcontroller.cxx index a6ba09b092df..f7e7f575ec19 100644 --- a/framework/source/uielement/imagebuttontoolbarcontroller.cxx +++ b/framework/source/uielement/imagebuttontoolbarcontroller.cxx @@ -188,7 +188,7 @@ sal_Bool ImageButtonToolbarController::ReadImageFromURL( sal_Bool bBigImage, con { ::Size aNoScaleSize( aBmpSize.Width(), aSize.Height() ); if ( aBmpSize != aNoScaleSize ) - aBitmapEx.Scale( aNoScaleSize, BMP_SCALE_BEST ); + aBitmapEx.Scale( aNoScaleSize, BMP_SCALE_BESTQUALITY ); aImage = Image( aBitmapEx ); return sal_True; } diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index c0ec5b17870c..9a2fe916ddc0 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -35,15 +35,17 @@ #define BMP_SCALE_NONE 0x00000000UL #define BMP_SCALE_FAST 0x00000001UL #define BMP_SCALE_INTERPOLATE 0x00000002UL -#define BMP_SCALE_LANCZOS 0x00000003UL -#define BMP_SCALE_BICUBIC 0x00000004UL -#define BMP_SCALE_BILINEAR 0x00000005UL -#define BMP_SCALE_BOX 0x00000006UL +#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 // Aliases, try to use these two (or BMP_SCALE_FAST/BMP_SCALE_NONE), // use a specific algorithm only if you really need to. -#define BMP_SCALE_BEST BMP_SCALE_LANCZOS -#define BMP_SCALE_DEFAULT BMP_SCALE_BOX +#define BMP_SCALE_BESTQUALITY BMP_SCALE_LANCZOS +#define BMP_SCALE_DEFAULT BMP_SCALE_SUPER + #define BMP_DITHER_NONE 0x00000000UL #define BMP_DITHER_MATRIX 0x00000001UL @@ -198,21 +200,21 @@ public: Kernel () {} virtual ~Kernel() {} - virtual double GetWidth() = 0; - virtual double Calculate( double x ) = 0; + virtual double GetWidth() const = 0; + virtual double Calculate( double x ) const = 0; }; class Lanczos3Kernel : public Kernel { public: - virtual double GetWidth() { return 3.0; } - virtual double Calculate (double x) + virtual double GetWidth() const { return 3.0; } + virtual double Calculate (double x) const { return (-3.0 <= x && x < 3.0) ? SincFilter(x) * SincFilter( x / 3.0 ) : 0.0; } - inline double SincFilter(double x) + inline double SincFilter(double x) const { if (x == 0.0) { @@ -224,8 +226,8 @@ public: }; class BicubicKernel : public Kernel { - virtual double GetWidth() { return 2.0; } - virtual double Calculate (double x) + virtual double GetWidth() const { return 2.0; } + virtual double Calculate (double x) const { if (x < 0.0) { @@ -245,8 +247,8 @@ class BicubicKernel : public Kernel { }; class BilinearKernel : public Kernel { - virtual double GetWidth() { return 1.0; } - virtual double Calculate (double x) + virtual double GetWidth() const { return 1.0; } + virtual double Calculate (double x) const { if (x < 0.0) { @@ -261,8 +263,8 @@ class BilinearKernel : public Kernel { }; class BoxKernel : public Kernel { - virtual double GetWidth() { return 0.5; } - virtual double Calculate (double x) + virtual double GetWidth() const { return 0.5; } + virtual double Calculate (double x) const { if (-0.5 <= x && x < 0.5) return 1.0; @@ -328,8 +330,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 bool ImplScaleConvolution( const double& rScaleX, const double& rScaleY, Kernel& aKernel); SAL_DLLPRIVATE bool ImplTransformAveraging( const double& rScaleX, const double& rScaleY, const Rectangle& rRotatedRectangle, const long nAngle10, const Color& rFillColor ); diff --git a/sd/source/ui/dlg/dlgass.cxx b/sd/source/ui/dlg/dlgass.cxx index 1676e051f4a9..787d9f3c9a83 100644 --- a/sd/source/ui/dlg/dlgass.cxx +++ b/sd/source/ui/dlg/dlgass.cxx @@ -80,7 +80,7 @@ void InterpolateFixedBitmap( FixedBitmap * pBitmap ) { Bitmap aBmp( pBitmap->GetBitmap() ); Size aSize = pBitmap->GetSizePixel(); - aBmp.Scale( aSize, BMP_SCALE_BEST ); + aBmp.Scale( aSize, BMP_SCALE_BESTQUALITY ); pBitmap->SetBitmap( aBmp ); } diff --git a/sd/source/ui/presenter/SlideRenderer.cxx b/sd/source/ui/presenter/SlideRenderer.cxx index ccd6e795e087..6bf192a70baa 100644 --- a/sd/source/ui/presenter/SlideRenderer.cxx +++ b/sd/source/ui/presenter/SlideRenderer.cxx @@ -223,7 +223,7 @@ BitmapEx SlideRenderer::CreatePreview ( BitmapEx aScaledPreview = aPreview.GetBitmapEx(); aScaledPreview.Scale( Size(aPreviewSize.Width,aPreviewSize.Height), - BMP_SCALE_BEST); + BMP_SCALE_BESTQUALITY); return aScaledPreview; } } diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx index 2c20852d956f..c70fad5e1124 100644 --- a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx +++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx @@ -76,7 +76,7 @@ Bitmap BitmapFactory::CreateBitmap ( false).GetBitmapEx().GetBitmap()); if (bDoSuperSampling) { - aPreview.Scale(rPixelSize, BMP_SCALE_BEST); + aPreview.Scale(rPixelSize, BMP_SCALE_BESTQUALITY); } return aPreview; diff --git a/sd/source/ui/slidesorter/view/SlsFramePainter.cxx b/sd/source/ui/slidesorter/view/SlsFramePainter.cxx index dcf950f11926..45222d53a584 100644 --- a/sd/source/ui/slidesorter/view/SlsFramePainter.cxx +++ b/sd/source/ui/slidesorter/view/SlsFramePainter.cxx @@ -149,15 +149,15 @@ FramePainter::OffsetBitmap::OffsetBitmap ( const sal_Int32 nSideBitmapSize (64); if (nHorizontalPosition == 0 && nVerticalPosition == 0) { - maBitmap.Scale(Size(nSideBitmapSize,nSideBitmapSize), BMP_SCALE_FAST); + maBitmap.Scale(Size(nSideBitmapSize,nSideBitmapSize)); } else if (nHorizontalPosition == 0) { - maBitmap.Scale(Size(nSideBitmapSize,aSize.Height()), BMP_SCALE_FAST); + maBitmap.Scale(Size(nSideBitmapSize,aSize.Height())); } else if (nVerticalPosition == 0) { - maBitmap.Scale(Size(maBitmap.GetSizePixel().Width(), nSideBitmapSize), BMP_SCALE_FAST); + maBitmap.Scale(Size(maBitmap.GetSizePixel().Width(), nSideBitmapSize)); } } diff --git a/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx b/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx index b718c8f7c160..4375dfa2b7f6 100644 --- a/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx +++ b/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx @@ -207,7 +207,7 @@ Point InsertionIndicatorOverlay::PaintRepresentatives ( // Paint the preview. Bitmap aPreview (rRepresentatives[nIndex].maBitmap); - aPreview.Scale(aPreviewSize, BMP_SCALE_BEST); + aPreview.Scale(aPreviewSize, BMP_SCALE_BESTQUALITY); rContent.DrawBitmapEx(aPageOffset, aPreview); // When the page is marked as excluded from the slide show then diff --git a/sd/source/ui/tools/PreviewRenderer.cxx b/sd/source/ui/tools/PreviewRenderer.cxx index 9aaa5b482ef5..9a355aa148e2 100644 --- a/sd/source/ui/tools/PreviewRenderer.cxx +++ b/sd/source/ui/tools/PreviewRenderer.cxx @@ -501,7 +501,7 @@ Image PreviewRenderer::ScaleBitmap ( // Paint the bitmap scaled to the desired width. BitmapEx aScaledBitmap (rBitmapEx.GetBitmap()); - aScaledBitmap.Scale (aPreviewSize, BMP_SCALE_BEST); + aScaledBitmap.Scale (aPreviewSize, BMP_SCALE_BESTQUALITY); mpPreviewDevice->DrawBitmap ( Point(1,1), aPreviewSize, diff --git a/sfx2/source/toolbox/tbxitem.cxx b/sfx2/source/toolbox/tbxitem.cxx index 8085dccbb643..b8913eb5e597 100644 --- a/sfx2/source/toolbox/tbxitem.cxx +++ b/sfx2/source/toolbox/tbxitem.cxx @@ -1533,7 +1533,7 @@ void SfxAppToolBoxControl_Impl::SetImage( const String &rURL ) if ( bBig && aImage.GetSizePixel() != aBigSize ) { BitmapEx aScaleBmpEx( aImage.GetBitmapEx() ); - aScaleBmpEx.Scale( aBigSize, BMP_SCALE_BEST ); + aScaleBmpEx.Scale( aBigSize, BMP_SCALE_BESTQUALITY ); GetToolBox().SetItemImage( GetId(), Image( aScaleBmpEx ) ); } else diff --git a/svx/source/dialog/compressgraphicdialog.cxx b/svx/source/dialog/compressgraphicdialog.cxx index c691b1532220..597bd2929db4 100644 --- a/svx/source/dialog/compressgraphicdialog.cxx +++ b/svx/source/dialog/compressgraphicdialog.cxx @@ -228,7 +228,7 @@ sal_uLong CompressGraphicsDialog::GetSelectedInterpolationType() } else if ( aSelectionText == "None" ) { return BMP_SCALE_FAST; } - return BMP_SCALE_BEST; + return BMP_SCALE_BESTQUALITY; } void CompressGraphicsDialog::Compress(SvStream& aStream) diff --git a/svx/source/gallery2/galobj.cxx b/svx/source/gallery2/galobj.cxx index 763790a15e48..290eaec38055 100644 --- a/svx/source/gallery2/galobj.cxx +++ b/svx/source/gallery2/galobj.cxx @@ -102,7 +102,7 @@ sal_Bool SgaObject::CreateThumb( const Graphic& rGraphic ) std::max( (long) (fFactor < 1. ? S_THUMB : S_THUMB / fFactor), 8L ) ); if( aThumbBmp.Scale( (double) aNewSize.Width() / aBmpSize.Width(), - (double) aNewSize.Height() / aBmpSize.Height(), BMP_SCALE_BEST ) ) + (double) aNewSize.Height() / aBmpSize.Height(), BMP_SCALE_BESTQUALITY ) ) { aThumbBmp.Convert( BMP_CONVERSION_8BIT_COLORS ); bRet = sal_True; diff --git a/toolkit/source/awt/vclxmenu.cxx b/toolkit/source/awt/vclxmenu.cxx index 2c1bdae37795..cc8f39b39ff6 100644 --- a/toolkit/source/awt/vclxmenu.cxx +++ b/toolkit/source/awt/vclxmenu.cxx @@ -664,7 +664,7 @@ namespace sal_Bool bModified( sal_False ); BitmapEx aBitmapEx = aImage.GetBitmapEx(); - bModified = aBitmapEx.Scale( aNewSize, BMP_SCALE_BEST ); + bModified = aBitmapEx.Scale( aNewSize, BMP_SCALE_BESTQUALITY ); if ( bModified ) aImage = Image( aBitmapEx ); diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx index 2b9ed69ec961..f4077eac33c3 100644 --- a/vcl/source/gdi/bitmap3.cxx +++ b/vcl/source/gdi/bitmap3.cxx @@ -31,6 +31,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; \ @@ -854,47 +855,78 @@ sal_Bool Bitmap::ImplConvertGhosted() sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag ) { - bool bRet; - - if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) ) + if(basegfx::fTools::equalZero(rScaleX) && basegfx::fTools::equalZero(rScaleY)) { - if( BMP_SCALE_FAST == nScaleFlag ) - { - bRet = ImplScaleFast( rScaleX, rScaleY ); - } - else if( BMP_SCALE_INTERPOLATE == nScaleFlag ) - { - bRet = ImplScaleInterpolate( rScaleX, rScaleY ); - } - else if( BMP_SCALE_LANCZOS == nScaleFlag ) - { - Lanczos3Kernel kernel; - bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel); - } - else if( BMP_SCALE_BICUBIC == nScaleFlag ) - { - BicubicKernel kernel; - bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel ); - } - else if( BMP_SCALE_BILINEAR == nScaleFlag ) - { - BilinearKernel kernel; - bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel ); - } - else if( BMP_SCALE_BOX == nScaleFlag ) - { - BoxKernel kernel; - bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel ); - } - else + // no scale + return true; + } + else + { + switch(nScaleFlag) { - return false; + 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 + { + // #i121233# 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; + } } } - else - bRet = true; - return bRet; + // should not happen + return false; } sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) @@ -914,6 +946,56 @@ sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) return bRet; } +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() ); @@ -1105,6 +1187,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 ); @@ -1207,7 +1290,10 @@ sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rSca aNewBmp.ReleaseAccess( pWriteAcc ); if( bRet ) + { + ImplAdaptBitCount(aNewBmp); ImplAssignWithSize( aNewBmp ); + } } } @@ -1217,6 +1303,1172 @@ sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rSca return bRet; } +// #i121233# 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; + } +} + +// #i121233# 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 ) { sal_Bool bRet = sal_False; diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index 8ea7a832c4c8..3b08b23ef290 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -353,7 +353,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(); @@ -663,7 +665,7 @@ BitmapEx BitmapEx:: AutoScaleBitmap(BitmapEx & aBitmap, const long aStandardSize } aScaledSize = Size( imgNewWidth, imgNewHeight ); - aRet.Scale( aScaledSize, BMP_SCALE_BEST ); + aRet.Scale( aScaledSize, BMP_SCALE_BESTQUALITY ); } else { diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index 1252a122e879..7775741d0d24 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -126,10 +126,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, BMP_SCALE_BEST ); + { + // #i121233# 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 c80554c1ebae..1a54a3d31706 100644 --- a/vcl/source/helper/canvasbitmap.cxx +++ b/vcl/source/helper/canvasbitmap.cxx @@ -450,7 +450,7 @@ uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( SolarMutexGuard aGuard; BitmapEx aNewBmp( m_aBitmap ); - aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FAST : BMP_SCALE_DEFAULT ); + aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_DEFAULT : BMP_SCALE_BESTQUALITY ); return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) ); } diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx index b6751b2d07e7..97804a9ba828 100644 --- a/vcl/source/window/printdlg.cxx +++ b/vcl/source/window/printdlg.cxx @@ -174,7 +174,7 @@ void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& ) else { Bitmap aPreviewBitmap(maPreviewBitmap); - aPreviewBitmap.Scale(maPreviewSize, BMP_SCALE_BEST); + aPreviewBitmap.Scale(maPreviewSize, BMP_SCALE_BESTQUALITY); DrawBitmap(aOffset, aPreviewBitmap); } |