summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2012-10-29 16:20:25 +0000
committerCaolán McNamara <caolanm@redhat.com>2013-05-09 16:35:40 +0100
commit44fb0ceeb98f45bc301d021c11af2c13f051bd4b (patch)
tree8d276c90e9d324aafbdcf01a538ad41ba71ac380
parentd6fd3fa6e840c6374f53beeae54f4aa71d73ffcd (diff)
Resolves: #i121233# Added bitmap scaling methods BMP_SCALE_SUPER
added from symphony, also 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 (cherry picked from commit bf734a151dc5169b65cf5d2a127e4142b765326c) Conflicts: canvas/source/vcl/canvasbitmaphelper.cxx canvas/source/vcl/canvashelper.cxx sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx vcl/inc/vcl/alpha.hxx vcl/inc/vcl/bitmap.hxx vcl/inc/vcl/bitmapex.hxx vcl/source/gdi/bitmap3.cxx vcl/source/gdi/impgraph.cxx vcl/source/gdi/pdfwriter_impl2.cxx vcl/source/helper/canvasbitmap.cxx (cherry picked from commit 593c86280b64d97725adde0c0a0cc4f090fb2310) Change-Id: I41cf0a7e11bdbc6510e22e762486420995ba739b
-rw-r--r--canvas/source/vcl/canvasbitmaphelper.cxx2
-rw-r--r--canvas/source/vcl/canvashelper.cxx2
-rw-r--r--filter/source/graphicfilter/eps/eps.cxx2
-rw-r--r--framework/source/fwe/classes/addonsoptions.cxx6
-rw-r--r--framework/source/uielement/imagebuttontoolbarcontroller.cxx2
-rw-r--r--include/vcl/bitmap.hxx39
-rw-r--r--sd/source/ui/dlg/dlgass.cxx2
-rw-r--r--sd/source/ui/presenter/SlideRenderer.cxx2
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx2
-rw-r--r--sd/source/ui/slidesorter/view/SlsFramePainter.cxx6
-rw-r--r--sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx2
-rw-r--r--sd/source/ui/tools/PreviewRenderer.cxx2
-rw-r--r--sfx2/source/toolbox/tbxitem.cxx2
-rw-r--r--svx/source/dialog/compressgraphicdialog.cxx2
-rw-r--r--svx/source/gallery2/galobj.cxx2
-rw-r--r--toolkit/source/awt/vclxmenu.cxx2
-rw-r--r--vcl/source/gdi/bitmap3.cxx1324
-rw-r--r--vcl/source/gdi/bitmapex.cxx6
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx8
-rw-r--r--vcl/source/helper/canvasbitmap.cxx2
-rw-r--r--vcl/source/window/printdlg.cxx2
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);
}