vcl: move Bitmap::ImplScaleFast() and Bitmap::ImplScaleInterpolate()
Bitmap::ImplScaleFast() -> BitmapFastScaleFilter
Bitmap::ImplScaleInterpolate() -> BitmapInterpolateScaleFilter
Change-Id: Ieb39cc21df5d98563945968cec81b7c51f64177f
Reviewed-on: https://gerrit.libreoffice.org/52899
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 3a819ce..93d1faf 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -313,10 +313,12 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/graphic/UnoGraphicTransformer \
vcl/source/bitmap/bitmap \
vcl/source/bitmap/bitmapfilter \
vcl/source/bitmap/BitmapInterpolateScaleFilter \
vcl/source/bitmap/BitmapLightenFilter \
vcl/source/bitmap/BitmapDisabledImageFilter \
vcl/source/bitmap/BitmapColorizeFilter \
vcl/source/bitmap/bitmappaint \
vcl/source/bitmap/BitmapFastScaleFilter \
vcl/source/bitmap/BitmapScaleSuperFilter \
vcl/source/bitmap/BitmapScaleConvolutionFilter \
vcl/source/bitmap/BitmapSymmetryCheck \
diff --git a/vcl/inc/BitmapFastScaleFilter.hxx b/vcl/inc/BitmapFastScaleFilter.hxx
new file mode 100644
index 0000000..c1ee11b
--- /dev/null
+++ b/vcl/inc/BitmapFastScaleFilter.hxx
@@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef VCL_INC_BITMAPFASTSCALEFILTER_HXX
#define VCL_INC_BITMAPFASTSCALEFILTER_HXX
#include <vcl/bitmapex.hxx>
#include <vcl/BitmapFilter.hxx>
class VCL_DLLPUBLIC BitmapFastScaleFilter : public BitmapFilter
{
public:
explicit BitmapFastScaleFilter(double fScaleX, double fScaleY)
: mfScaleX(fScaleX)
, mfScaleY(fScaleY)
{
}
explicit BitmapFastScaleFilter(Size aSize)
: maSize(aSize)
{
}
virtual BitmapEx execute(BitmapEx const& rBitmapEx) override;
private:
double mfScaleX;
double mfScaleY;
Size maSize;
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/BitmapInterpolateScaleFilter.hxx b/vcl/inc/BitmapInterpolateScaleFilter.hxx
new file mode 100644
index 0000000..0fbe9ac3
--- /dev/null
+++ b/vcl/inc/BitmapInterpolateScaleFilter.hxx
@@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef VCL_INC_BITMAPINTERPOLATESCALEFILTER_HXX
#define VCL_INC_BITMAPINTERPOLATESCALEFILTER_HXX
#include <vcl/bitmapex.hxx>
#include <vcl/BitmapFilter.hxx>
class VCL_DLLPUBLIC BitmapInterpolateScaleFilter : public BitmapFilter
{
public:
explicit BitmapInterpolateScaleFilter(double fScaleX, double fScaleY)
: mfScaleX(fScaleX)
, mfScaleY(fScaleY)
{
}
explicit BitmapInterpolateScaleFilter(Size aSize)
: maSize(aSize)
{
}
virtual BitmapEx execute(BitmapEx const& rBitmapEx) override;
private:
double mfScaleX;
double mfScaleY;
Size maSize;
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/bitmap/BitmapFastScaleFilter.cxx b/vcl/source/bitmap/BitmapFastScaleFilter.cxx
new file mode 100644
index 0000000..6bf1700
--- /dev/null
+++ b/vcl/source/bitmap/BitmapFastScaleFilter.cxx
@@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <tools/helpers.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/bitmapaccess.hxx>
#include <bitmapwriteaccess.hxx>
#include <BitmapFastScaleFilter.hxx>
BitmapEx BitmapFastScaleFilter::execute(BitmapEx const& rBitmapEx)
{
SAL_INFO("vcl.gdi", "BitmapFastScaleFilter::execute()");
Bitmap aBitmap(rBitmapEx.GetBitmap());
const Size aSizePix(aBitmap.GetSizePixel());
const long nNewWidth = FRound(aSizePix.Width() * mfScaleX);
const long nNewHeight = FRound(aSizePix.Height() * mfScaleY);
bool bRet = false;
SAL_INFO("vcl.gdi", "New width: " << nNewWidth << "\nNew height: " << nNewHeight);
if (nNewWidth && nNewHeight)
{
Bitmap::ScopedReadAccess pReadAcc(aBitmap);
if (pReadAcc)
{
Bitmap aNewBmp(Size(nNewWidth, nNewHeight), aBitmap.GetBitCount(),
&pReadAcc->GetPalette());
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if (pWriteAcc)
{
const long nScanlineSize = pWriteAcc->GetScanlineSize();
const long nNewWidth1 = nNewWidth - 1;
const long nNewHeight1 = nNewHeight - 1;
if (nNewWidth1 && nNewHeight1)
{
const double nWidth = pReadAcc->Width();
const double nHeight = pReadAcc->Height();
std::unique_ptr<long[]> pLutX(new long[nNewWidth]);
std::unique_ptr<long[]> pLutY(new long[nNewHeight]);
for (long nX = 0; nX < nNewWidth; nX++)
{
pLutX[nX] = long(nX * nWidth / nNewWidth);
}
for (long nY = 0; nY < nNewHeight; nY++)
{
pLutY[nY] = long(nY * nHeight / nNewHeight);
}
long nActY = 0;
while (nActY < nNewHeight)
{
long nMapY = pLutY[nActY];
Scanline pScanline = pWriteAcc->GetScanline(nActY);
Scanline pScanlineRead = pReadAcc->GetScanline(nMapY);
for (long nX = 0; nX < nNewWidth; nX++)
{
pWriteAcc->SetPixelOnData(
pScanline, nX,
pReadAcc->GetPixelFromData(pScanlineRead, pLutX[nX]));
}
while ((nActY < nNewHeight1) && (pLutY[nActY + 1] == nMapY))
{
memcpy(pWriteAcc->GetScanline(nActY + 1), pWriteAcc->GetScanline(nActY),
nScanlineSize);
nActY++;
}
nActY++;
}
bRet = true;
}
pWriteAcc.reset();
}
pReadAcc.reset();
if (bRet)
{
aBitmap.ReassignWithSize(aNewBmp);
SAL_INFO("vcl.gdi", "Bitmap size: " << aBitmap.GetSizePixel());
}
else
{
SAL_WARN("vcl.gdi", "no resize");
}
}
}
Bitmap aMask(rBitmapEx.GetMask());
if (bRet && (rBitmapEx.GetTransparentType() == TransparentType::Bitmap) && !aMask.IsEmpty())
bRet = aMask.Scale(maSize, BmpScaleFlag::Fast);
SAL_WARN_IF(!aMask.IsEmpty() && aBitmap.GetSizePixel() != aMask.GetSizePixel(), "vcl",
"BitmapEx::Scale(): size mismatch for bitmap and alpha mask.");
if (bRet)
return BitmapEx(aBitmap, aMask);
return BitmapEx();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/bitmap/BitmapInterpolateScaleFilter.cxx b/vcl/source/bitmap/BitmapInterpolateScaleFilter.cxx
new file mode 100644
index 0000000..43e4d2f
--- /dev/null
+++ b/vcl/source/bitmap/BitmapInterpolateScaleFilter.cxx
@@ -0,0 +1,236 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <tools/helpers.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/bitmapaccess.hxx>
#include <bitmapwriteaccess.hxx>
#include <BitmapFastScaleFilter.hxx>
#include <BitmapInterpolateScaleFilter.hxx>
BitmapEx BitmapInterpolateScaleFilter::execute(BitmapEx const& rBitmapEx)
{
Bitmap aBitmap(rBitmapEx.GetBitmap());
const Size aSizePix(aBitmap.GetSizePixel());
const long nNewWidth = FRound(aSizePix.Width() * mfScaleX);
const long nNewHeight = FRound(aSizePix.Height() * mfScaleY);
bool bRet = false;
if ((nNewWidth > 1) && (nNewHeight > 1))
{
Bitmap::ScopedReadAccess pReadAcc(aBitmap);
if (pReadAcc)
{
long nWidth = pReadAcc->Width();
long nHeight = pReadAcc->Height();
Bitmap aNewBmp(Size(nNewWidth, nHeight), 24);
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if (pWriteAcc)
{
const long nNewWidth1 = nNewWidth - 1;
const long nWidth1 = pReadAcc->Width() - 1;
const double fRevScaleX = static_cast<double>(nWidth1) / nNewWidth1;
std::unique_ptr<long[]> pLutInt(new long[nNewWidth]);
std::unique_ptr<long[]> pLutFrac(new long[nNewWidth]);
for (long nX = 0, nTemp = nWidth - 2; nX < nNewWidth; nX++)
{
double fTemp = nX * fRevScaleX;
pLutInt[nX] = MinMax(static_cast<long>(fTemp), 0, nTemp);
fTemp -= pLutInt[nX];
pLutFrac[nX] = static_cast<long>(fTemp * 1024.);
}
for (long nY = 0; nY < nHeight; nY++)
{
Scanline pScanlineRead = pReadAcc->GetScanline(nY);
if (1 == nWidth)
{
BitmapColor aCol0;
if (pReadAcc->HasPalette())
{
aCol0 = pReadAcc->GetPaletteColor(
pReadAcc->GetIndexFromData(pScanlineRead, 0));
}
else
{
aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, 0);
}
Scanline pScanline = pWriteAcc->GetScanline(nY);
for (long nX = 0; nX < nNewWidth; nX++)
{
pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
}
}
else
{
Scanline pScanline = pWriteAcc->GetScanline(nY);
for (long nX = 0; nX < nNewWidth; nX++)
{
long nTemp = pLutInt[nX];
BitmapColor aCol0, aCol1;
if (pReadAcc->HasPalette())
{
aCol0 = pReadAcc->GetPaletteColor(
pReadAcc->GetIndexFromData(pScanlineRead, nTemp++));
aCol1 = pReadAcc->GetPaletteColor(
pReadAcc->GetIndexFromData(pScanlineRead, nTemp));
}
else
{
aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp++);
aCol1 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp);
}
nTemp = pLutFrac[nX];
long lXR0 = aCol0.GetRed();
long lXG0 = aCol0.GetGreen();
long lXB0 = aCol0.GetBlue();
long lXR1 = aCol1.GetRed() - lXR0;
long lXG1 = aCol1.GetGreen() - lXG0;
long lXB1 = aCol1.GetBlue() - lXB0;
aCol0.SetRed(
static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
aCol0.SetGreen(
static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
aCol0.SetBlue(
static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
}
}
}
bRet = true;
}
pReadAcc.reset();
pWriteAcc.reset();
if (bRet)
{
bRet = false;
const Bitmap aOriginal(aBitmap);
aBitmap = aNewBmp;
aNewBmp = Bitmap(Size(nNewWidth, nNewHeight), 24);
pReadAcc = Bitmap::ScopedReadAccess(aBitmap);
pWriteAcc = BitmapScopedWriteAccess(aNewBmp);
if (pReadAcc && pWriteAcc)
{
const long nNewHeight1 = nNewHeight - 1;
const long nHeight1 = pReadAcc->Height() - 1;
const double fRevScaleY = static_cast<double>(nHeight1) / nNewHeight1;
std::unique_ptr<long[]> pLutInt(new long[nNewHeight]);
std::unique_ptr<long[]> pLutFrac(new long[nNewHeight]);
for (long nY = 0, nTemp = nHeight - 2; nY < nNewHeight; nY++)
{
double fTemp = nY * fRevScaleY;
pLutInt[nY] = MinMax(static_cast<long>(fTemp), 0, nTemp);
fTemp -= pLutInt[nY];
pLutFrac[nY] = static_cast<long>(fTemp * 1024.);
}
// after 1st step, bitmap *is* 24bit format (see above)
OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate "
"in-between format has palette, should not "
"happen (!)");
for (long nX = 0; nX < nNewWidth; nX++)
{
if (1 == nHeight)
{
BitmapColor aCol0 = pReadAcc->GetPixel(0, nX);
for (long nY = 0; nY < nNewHeight; nY++)
{
pWriteAcc->SetPixel(nY, nX, aCol0);
}
}
else
{
for (long nY = 0; nY < nNewHeight; nY++)
{
long nTemp = pLutInt[nY];
BitmapColor aCol0 = pReadAcc->GetPixel(nTemp++, nX);
BitmapColor aCol1 = pReadAcc->GetPixel(nTemp, nX);
nTemp = pLutFrac[nY];
long lXR0 = aCol0.GetRed();
long lXG0 = aCol0.GetGreen();
long lXB0 = aCol0.GetBlue();
long lXR1 = aCol1.GetRed() - lXR0;
long lXG1 = aCol1.GetGreen() - lXG0;
long lXB1 = aCol1.GetBlue() - lXB0;
aCol0.SetRed(
static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
aCol0.SetGreen(
static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
aCol0.SetBlue(
static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
pWriteAcc->SetPixel(nY, nX, aCol0);
}
}
}
bRet = true;
}
pReadAcc.reset();
pWriteAcc.reset();
if (bRet)
{
aOriginal.AdaptBitCount(aNewBmp);
aBitmap = aNewBmp;
}
}
}
}
if (!bRet)
{
// fallback to fast scale filter
BitmapEx aBmpEx(aBitmap);
bRet = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(mfScaleX, mfScaleY));
aBitmap = aBmpEx.GetBitmap();
}
if (bRet)
return BitmapEx(aBitmap);
return BitmapEx();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index b933e41..b42731e 100755
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -32,6 +32,8 @@
#include <impoctree.hxx>
#include <BitmapScaleSuperFilter.hxx>
#include <BitmapScaleConvolutionFilter.hxx>
#include <BitmapFastScaleFilter.hxx>
#include <BitmapInterpolateScaleFilter.hxx>
#include <bitmapwriteaccess.hxx>
#include <octree.hxx>
@@ -761,16 +763,16 @@ bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag n
switch(nScaleFlag)
{
case BmpScaleFlag::Fast:
bRetval = ImplScaleFast( rScaleX, rScaleY );
bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
break;
case BmpScaleFlag::Interpolate:
bRetval = ImplScaleInterpolate(rScaleX, rScaleY);
bRetval = BitmapFilter::Filter(aBmpEx, BitmapInterpolateScaleFilter(rScaleX, rScaleY));
break;
case BmpScaleFlag::Default:
if (GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
bRetval = ImplScaleFast(rScaleX, rScaleY);
bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
else
bRetval = BitmapFilter::Filter(aBmpEx, BitmapScaleSuperFilter(rScaleX, rScaleY));
break;
@@ -789,7 +791,7 @@ bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag n
break;
}
if (bRetval && nScaleFlag != BmpScaleFlag::Fast && nScaleFlag != BmpScaleFlag::Interpolate)
if (bRetval)
*this = aBmpEx.GetBitmapRef();
OSL_ENSURE(!bRetval || nStartCount == GetBitCount(), "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
@@ -872,261 +874,6 @@ void Bitmap::AdaptBitCount(Bitmap& rNew) const
}
}
bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
{
const Size aSizePix( GetSizePixel() );
const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
bool bRet = false;
if( nNewWidth && nNewHeight )
{
ScopedReadAccess pReadAcc(*this);
if(pReadAcc)
{
Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if( pWriteAcc )
{
const long nScanlineSize = pWriteAcc->GetScanlineSize();
const long nNewWidth1 = nNewWidth - 1;
const long nNewHeight1 = nNewHeight - 1;
if( nNewWidth1 && nNewHeight1 )
{
const double nWidth = pReadAcc->Width();
const double nHeight = pReadAcc->Height();
std::unique_ptr<long[]> pLutX(new long[ nNewWidth ]);
std::unique_ptr<long[]> pLutY(new long[ nNewHeight ]);
for( long nX = 0; nX < nNewWidth; nX++ )
pLutX[ nX ] = long(nX * nWidth / nNewWidth);
for( long nY = 0; nY < nNewHeight; nY++ )
pLutY[ nY ] = long(nY * nHeight / nNewHeight);
long nActY = 0;
while( nActY < nNewHeight )
{
long nMapY = pLutY[ nActY ];
Scanline pScanline = pWriteAcc->GetScanline(nActY);
Scanline pScanlineRead = pReadAcc->GetScanline(nMapY);
for( long nX = 0; nX < nNewWidth; nX++ )
pWriteAcc->SetPixelOnData( pScanline, nX, pReadAcc->GetPixelFromData( pScanlineRead , pLutX[ nX ] ) );
while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
{
memcpy( pWriteAcc->GetScanline( nActY + 1 ),
pWriteAcc->GetScanline( nActY ), nScanlineSize );
nActY++;
}
nActY++;
}
bRet = true;
}
pWriteAcc.reset();
}
pReadAcc.reset();
if (bRet)
ReassignWithSize(aNewBmp);
}
}
return bRet;
}
bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
{
const Size aSizePix( GetSizePixel() );
const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
bool bRet = false;
if( ( nNewWidth > 1 ) && ( nNewHeight > 1 ) )
{
ScopedReadAccess pReadAcc(*this);
if( pReadAcc )
{
long nWidth = pReadAcc->Width();
long nHeight = pReadAcc->Height();
Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 );
BitmapScopedWriteAccess pWriteAcc(aNewBmp);
if( pWriteAcc )
{
const long nNewWidth1 = nNewWidth - 1;
const long nWidth1 = pReadAcc->Width() - 1;
const double fRevScaleX = static_cast<double>(nWidth1) / nNewWidth1;
std::unique_ptr<long[]> pLutInt(new long[ nNewWidth ]);
std::unique_ptr<long[]> pLutFrac(new long[ nNewWidth ]);
for( long nX = 0, nTemp = nWidth - 2; nX < nNewWidth; nX++ )
{
double fTemp = nX * fRevScaleX;
pLutInt[ nX ] = MinMax( static_cast<long>(fTemp), 0, nTemp );
fTemp -= pLutInt[ nX ];
pLutFrac[ nX ] = static_cast<long>( fTemp * 1024. );
}
for( long nY = 0; nY < nHeight; nY++ )
{
Scanline pScanlineRead = pReadAcc->GetScanline(nY);
if( 1 == nWidth )
{
BitmapColor aCol0;
if( pReadAcc->HasPalette() )
{
aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, 0 ) );
}
else
{
aCol0 = pReadAcc->GetPixelFromData( pScanlineRead, 0 );
}
Scanline pScanline = pWriteAcc->GetScanline(nY);
for( long nX = 0; nX < nNewWidth; nX++ )
{
pWriteAcc->SetPixelOnData( pScanline, nX, aCol0 );
}
}
else
{
Scanline pScanline = pWriteAcc->GetScanline(nY);
for( long nX = 0; nX < nNewWidth; nX++ )
{
long nTemp = pLutInt[ nX ];
BitmapColor aCol0, aCol1;
if( pReadAcc->HasPalette() )
{
aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nTemp++ ) );
aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nTemp ) );
}
else
{
aCol0 = pReadAcc->GetPixelFromData( pScanlineRead, nTemp++ );
aCol1 = pReadAcc->GetPixelFromData( pScanlineRead, nTemp );
}
nTemp = pLutFrac[ nX ];
long lXR0 = aCol0.GetRed();
long lXG0 = aCol0.GetGreen();
long lXB0 = aCol0.GetBlue();
long lXR1 = aCol1.GetRed() - lXR0;
long lXG1 = aCol1.GetGreen() - lXG0;
long lXB1 = aCol1.GetBlue() - lXB0;
aCol0.SetRed( static_cast<sal_uInt8>( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
aCol0.SetGreen( static_cast<sal_uInt8>( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
aCol0.SetBlue( static_cast<sal_uInt8>( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
pWriteAcc->SetPixelOnData( pScanline, nX, aCol0 );
}
}
}
bRet = true;
}
pReadAcc.reset();
pWriteAcc.reset();
if( bRet )
{
bRet = false;
const Bitmap aOriginal(*this);
*this = aNewBmp;
aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
pReadAcc = ScopedReadAccess(*this);
pWriteAcc = BitmapScopedWriteAccess(aNewBmp);
if( pReadAcc && pWriteAcc )
{
const long nNewHeight1 = nNewHeight - 1;
const long nHeight1 = pReadAcc->Height() - 1;
const double fRevScaleY = static_cast<double>(nHeight1) / nNewHeight1;
std::unique_ptr<long[]> pLutInt(new long[ nNewHeight ]);
std::unique_ptr<long[]> pLutFrac(new long[ nNewHeight ]);
for( long nY = 0, nTemp = nHeight - 2; nY < nNewHeight; nY++ )
{
double fTemp = nY * fRevScaleY;
pLutInt[ nY ] = MinMax( static_cast<long>(fTemp), 0, nTemp );
fTemp -= pLutInt[ nY ];
pLutFrac[ nY ] = static_cast<long>( fTemp * 1024. );
}
// after 1st step, bitmap *is* 24bit format (see above)
OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)");
for( long nX = 0; nX < nNewWidth; nX++ )
{
if( 1 == nHeight )
{
BitmapColor aCol0 = pReadAcc->GetPixel( 0, nX );
for( long nY = 0; nY < nNewHeight; nY++ )
{
pWriteAcc->SetPixel( nY, nX, aCol0 );
}
}
else
{
for( long nY = 0; nY < nNewHeight; nY++ )
{
long nTemp = pLutInt[ nY ];
BitmapColor aCol0 = pReadAcc->GetPixel( nTemp++, nX );
BitmapColor aCol1 = pReadAcc->GetPixel( nTemp, nX );
nTemp = pLutFrac[ nY ];
long lXR0 = aCol0.GetRed();
long lXG0 = aCol0.GetGreen();
long lXB0 = aCol0.GetBlue();
long lXR1 = aCol1.GetRed() - lXR0;
long lXG1 = aCol1.GetGreen() - lXG0;
long lXB1 = aCol1.GetBlue() - lXB0;
aCol0.SetRed( static_cast<sal_uInt8>( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
aCol0.SetGreen( static_cast<sal_uInt8>( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
aCol0.SetBlue( static_cast<sal_uInt8>( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
pWriteAcc->SetPixel( nY, nX, aCol0 );
}
}
}
bRet = true;
}
pReadAcc.reset();
pWriteAcc.reset();
if( bRet )
{
aOriginal.AdaptBitCount(aNewBmp);
*this = aNewBmp;
}
}
}
}
if (!bRet)
bRet = ImplScaleFast(rScaleX, rScaleY);
return bRet;
}
bool Bitmap::Dither( BmpDitherFlags nDitherFlags )
{
bool bRet = false;
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
old mode 100644
new mode 100755
index d107c55..5b03870
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -19,11 +19,10 @@
#include <rtl/crc.h>
#include <rtl/strbuf.hxx>
#include <o3tl/any.hxx>
#include <tools/debug.hxx>
#include <unotools/resmgr.hxx>
#include <tools/stream.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <unotools/resmgr.hxx>
#include <vcl/ImageTree.hxx>
#include <vcl/salbtype.hxx>
@@ -40,9 +39,12 @@
#include <salbmp.hxx>
#include <salinst.hxx>
#include <svdata.hxx>
#include <BitmapFastScaleFilter.hxx>
#include <bitmapwriteaccess.hxx>
#include <image.h>
#include <o3tl/any.hxx>
#include <com/sun/star/beans/XFastPropertySet.hpp>
#include <memory>
@@ -119,7 +121,6 @@ BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
meTransparent ( !rMask ? TransparentType::NONE : TransparentType::Bitmap ),
mbAlpha ( false )
{
SAL_INFO("vcl.gdi", "Bitmap size: " << maBitmapSize);
// Ensure a mask is exactly one bit deep
if( !!maMask && maMask.GetBitCount() != 1 )
{