include/vcl/BitmapConvolutionMatrixFilter.hxx | 38 +++ include/vcl/bitmap.hxx | 2 vcl/Library_vcl.mk | 1 vcl/source/bitmap/BitmapConvolutionMatrixFilter.cxx | 199 ++++++++++++++++++++ vcl/source/gdi/bitmap4.cxx | 163 ---------------- 5 files changed, 242 insertions(+), 161 deletions(-)
New commits: commit 7b06fcddf8d9a0b51bf396d29487f1fd715b82d3 Author: Chris Sherlock <chris.sherloc...@gmail.com> Date: Wed Apr 18 21:06:15 2018 +1000 vcl: ImplConvolute3() -> BitmapConvolutionMatrixFilter Change-Id: I0203e98d29192ef098719c0a297b967710b8729a Reviewed-on: https://gerrit.libreoffice.org/53097 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/include/vcl/BitmapConvolutionMatrixFilter.hxx b/include/vcl/BitmapConvolutionMatrixFilter.hxx new file mode 100644 index 000000000000..d27bfffb0fcd --- /dev/null +++ b/include/vcl/BitmapConvolutionMatrixFilter.hxx @@ -0,0 +1,38 @@ +/* -*- 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 INCLUDED_VCL_BITMAPCONVOLUTIONMATRIXFILTER_HXX +#define INCLUDED_VCL_BITMAPCONVOLUTIONMATRIXFILTER_HXX + +#include <vcl/BitmapFilter.hxx> + +class BitmapEx; + +/** Filter image based on a 3x3 convolution matrix + */ +class VCL_DLLPUBLIC BitmapConvolutionMatrixFilter : public BitmapFilter +{ +public: + BitmapConvolutionMatrixFilter(const long* pMatrix) + : mpMatrix(pMatrix) + { + } + + ~BitmapConvolutionMatrixFilter() override { delete mpMatrix; } + + virtual BitmapEx execute(BitmapEx const& rBitmapEx) override; + +private: + const long* mpMatrix; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index 07573b1af1b0..df6d094a9886 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -658,8 +658,6 @@ public: SAL_DLLPRIVATE bool ImplDitherFloyd(); SAL_DLLPRIVATE bool ImplDitherFloyd16(); - SAL_DLLPRIVATE bool ImplConvolute3( const long* pMatrix ); - SAL_DLLPRIVATE bool ImplMedianFilter(); SAL_DLLPRIVATE bool ImplSobelGrey(); SAL_DLLPRIVATE bool ImplEmbossGrey( const BmpFilterParam* pFilterParam ); diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 8a2edf75b2b4..644620981c94 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -312,6 +312,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/graphic/UnoGraphicTransformer \ vcl/source/bitmap/bitmap \ vcl/source/bitmap/bitmapfilter \ + vcl/source/bitmap/BitmapConvolutionMatrixFilter \ vcl/source/bitmap/BitmapInterpolateScaleFilter \ vcl/source/bitmap/BitmapLightenFilter \ vcl/source/bitmap/BitmapDisabledImageFilter \ diff --git a/vcl/source/bitmap/BitmapConvolutionMatrixFilter.cxx b/vcl/source/bitmap/BitmapConvolutionMatrixFilter.cxx new file mode 100644 index 000000000000..fea2e6dac4f4 --- /dev/null +++ b/vcl/source/bitmap/BitmapConvolutionMatrixFilter.cxx @@ -0,0 +1,199 @@ +/* -*- 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/. + * + */ + +#include <basegfx/color/bcolortools.hxx> + +#include <vcl/bitmap.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/bitmapaccess.hxx> +#include <vcl/BitmapConvolutionMatrixFilter.hxx> + +#include <bitmapwriteaccess.hxx> + +BitmapEx BitmapConvolutionMatrixFilter::execute(BitmapEx const& rBitmapEx) +{ + Bitmap aBitmap(rBitmapEx.GetBitmap()); + + const long nDivisor = 8; + Bitmap::ScopedReadAccess pReadAcc(aBitmap); + bool bRet = false; + + if (pReadAcc) + { + Bitmap aNewBmp(aBitmap.GetSizePixel(), 24); + BitmapScopedWriteAccess pWriteAcc(aNewBmp); + + if (pWriteAcc) + { + const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2; + const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2; + long* pColm = new long[nWidth2]; + long* pRows = new long[nHeight2]; + BitmapColor* pColRow1 + = reinterpret_cast<BitmapColor*>(new sal_uInt8[sizeof(BitmapColor) * nWidth2]); + BitmapColor* pColRow2 + = reinterpret_cast<BitmapColor*>(new sal_uInt8[sizeof(BitmapColor) * nWidth2]); + BitmapColor* pColRow3 + = reinterpret_cast<BitmapColor*>(new sal_uInt8[sizeof(BitmapColor) * nWidth2]); + BitmapColor* pRowTmp1 = pColRow1; + BitmapColor* pRowTmp2 = pColRow2; + BitmapColor* pRowTmp3 = pColRow3; + BitmapColor* pColor; + long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp; + long(*pKoeff)[256] = new long[9][256]; + long* pTmp; + + // create LUT of products of matrix value and possible color component values + for (nY = 0; nY < 9; nY++) + { + for (nX = nTmp = 0, nMatrixVal = mpMatrix[nY]; nX < 256; nX++, nTmp += nMatrixVal) + { + pKoeff[nY][nX] = nTmp; + } + } + + // create column LUT + for (i = 0; i < nWidth2; i++) + { + pColm[i] = (i > 0) ? (i - 1) : 0; + } + + pColm[nWidth + 1] = pColm[nWidth]; + + // create row LUT + for (i = 0; i < nHeight2; i++) + { + pRows[i] = (i > 0) ? (i - 1) : 0; + } + + pRows[nHeight + 1] = pRows[nHeight]; + + // read first three rows of bitmap color + for (i = 0; i < nWidth2; i++) + { + pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]); + pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]); + pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]); + } + + // do convolution + for (nY = 0; nY < nHeight;) + { + Scanline pScanline = pWriteAcc->GetScanline(nY); + for (nX = 0; nX < nWidth; nX++) + { + // first row + nSumR = (pTmp = pKoeff[0])[(pColor = pRowTmp1 + nX)->GetRed()]; + nSumG = pTmp[pColor->GetGreen()]; + nSumB = pTmp[pColor->GetBlue()]; + + nSumR += (pTmp = pKoeff[1])[(++pColor)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + nSumR += (pTmp = pKoeff[2])[(++pColor)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + // second row + nSumR += (pTmp = pKoeff[3])[(pColor = pRowTmp2 + nX)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + nSumR += (pTmp = pKoeff[4])[(++pColor)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + nSumR += (pTmp = pKoeff[5])[(++pColor)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + // third row + nSumR += (pTmp = pKoeff[6])[(pColor = pRowTmp3 + nX)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + nSumR += (pTmp = pKoeff[7])[(++pColor)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + nSumR += (pTmp = pKoeff[8])[(++pColor)->GetRed()]; + nSumG += pTmp[pColor->GetGreen()]; + nSumB += pTmp[pColor->GetBlue()]; + + // calculate destination color + pWriteAcc->SetPixelOnData( + pScanline, nX, + BitmapColor(static_cast<sal_uInt8>(MinMax(nSumR / nDivisor, 0, 255)), + static_cast<sal_uInt8>(MinMax(nSumG / nDivisor, 0, 255)), + static_cast<sal_uInt8>(MinMax(nSumB / nDivisor, 0, 255)))); + } + + if (++nY < nHeight) + { + if (pRowTmp1 == pColRow1) + { + pRowTmp1 = pColRow2; + pRowTmp2 = pColRow3; + pRowTmp3 = pColRow1; + } + else if (pRowTmp1 == pColRow2) + { + pRowTmp1 = pColRow3; + pRowTmp2 = pColRow1; + pRowTmp3 = pColRow2; + } + else + { + pRowTmp1 = pColRow1; + pRowTmp2 = pColRow2; + pRowTmp3 = pColRow3; + } + + for (i = 0; i < nWidth2; i++) + { + pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]); + } + } + } + + delete[] pKoeff; + delete[] reinterpret_cast<sal_uInt8*>(pColRow1); + delete[] reinterpret_cast<sal_uInt8*>(pColRow2); + delete[] reinterpret_cast<sal_uInt8*>(pColRow3); + delete[] pColm; + delete[] pRows; + + pWriteAcc.reset(); + + bRet = true; + } + + pReadAcc.reset(); + + if (bRet) + { + const MapMode aMap(aBitmap.GetPrefMapMode()); + const Size aPrefSize(aBitmap.GetPrefSize()); + + aBitmap = aNewBmp; + + aBitmap.SetPrefMapMode(aMap); + aBitmap.SetPrefSize(aPrefSize); + } + } + + if (bRet) + return BitmapEx(aBitmap); + + return BitmapEx(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/bitmap4.cxx b/vcl/source/gdi/bitmap4.cxx index 1c739c380bc7..8e4d7a7d2f36 100644 --- a/vcl/source/gdi/bitmap4.cxx +++ b/vcl/source/gdi/bitmap4.cxx @@ -22,6 +22,7 @@ #include <vcl/bitmap.hxx> #include <vcl/BitmapGaussianSeparableBlurFilter.hxx> #include <vcl/BitmapSeparableUnsharpenFilter.hxx> +#include <vcl/BitmapConvolutionMatrixFilter.hxx> #include <bitmapwriteaccess.hxx> @@ -76,7 +77,9 @@ bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam ) case BmpFilter::Sharpen: { const long pSharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 }; - bRet = ImplConvolute3( &pSharpenMatrix[ 0 ] ); + BitmapEx aBmpEx(*this); + bRet = BitmapFilter::Filter(aBmpEx, BitmapConvolutionMatrixFilter(&pSharpenMatrix[0])); + *this = aBmpEx.GetBitmap(); } break; @@ -120,164 +123,6 @@ bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam ) return bRet; } -bool Bitmap::ImplConvolute3( const long* pMatrix ) -{ - const long nDivisor = 8; - ScopedReadAccess pReadAcc(*this); - bool bRet = false; - - if( pReadAcc ) - { - Bitmap aNewBmp( GetSizePixel(), 24 ); - BitmapScopedWriteAccess pWriteAcc(aNewBmp); - - if( pWriteAcc ) - { - const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2; - const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2; - long* pColm = new long[ nWidth2 ]; - long* pRows = new long[ nHeight2 ]; - BitmapColor* pColRow1 = reinterpret_cast<BitmapColor*>(new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ]); - BitmapColor* pColRow2 = reinterpret_cast<BitmapColor*>(new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ]); - BitmapColor* pColRow3 = reinterpret_cast<BitmapColor*>(new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ]); - BitmapColor* pRowTmp1 = pColRow1; - BitmapColor* pRowTmp2 = pColRow2; - BitmapColor* pRowTmp3 = pColRow3; - BitmapColor* pColor; - long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp; - long (*pKoeff)[ 256 ] = new long[ 9 ][ 256 ]; - long* pTmp; - - // create LUT of products of matrix value and possible color component values - for( nY = 0; nY < 9; nY++ ) - for( nX = nTmp = 0, nMatrixVal = pMatrix[ nY ]; nX < 256; nX++, nTmp += nMatrixVal ) - pKoeff[ nY ][ nX ] = nTmp; - - // create column LUT - for( i = 0; i < nWidth2; i++ ) - pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0; - - pColm[ nWidth + 1 ] = pColm[ nWidth ]; - - // create row LUT - for( i = 0; i < nHeight2; i++ ) - pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0; - - pRows[ nHeight + 1 ] = pRows[ nHeight ]; - - // read first three rows of bitmap color - for( i = 0; i < nWidth2; i++ ) - { - pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] ); - pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] ); - pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] ); - } - - // do convolution - for( nY = 0; nY < nHeight; ) - { - Scanline pScanline = pWriteAcc->GetScanline(nY); - for( nX = 0; nX < nWidth; nX++ ) - { - // first row - nSumR = ( pTmp = pKoeff[ 0 ] )[ ( pColor = pRowTmp1 + nX )->GetRed() ]; - nSumG = pTmp[ pColor->GetGreen() ]; - nSumB = pTmp[ pColor->GetBlue() ]; - - nSumR += ( pTmp = pKoeff[ 1 ] )[ ( ++pColor )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - nSumR += ( pTmp = pKoeff[ 2 ] )[ ( ++pColor )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - // second row - nSumR += ( pTmp = pKoeff[ 3 ] )[ ( pColor = pRowTmp2 + nX )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - nSumR += ( pTmp = pKoeff[ 4 ] )[ ( ++pColor )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - nSumR += ( pTmp = pKoeff[ 5 ] )[ ( ++pColor )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - // third row - nSumR += ( pTmp = pKoeff[ 6 ] )[ ( pColor = pRowTmp3 + nX )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - nSumR += ( pTmp = pKoeff[ 7 ] )[ ( ++pColor )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - nSumR += ( pTmp = pKoeff[ 8 ] )[ ( ++pColor )->GetRed() ]; - nSumG += pTmp[ pColor->GetGreen() ]; - nSumB += pTmp[ pColor->GetBlue() ]; - - // calculate destination color - pWriteAcc->SetPixelOnData( pScanline, nX, BitmapColor( static_cast<sal_uInt8>(MinMax( nSumR / nDivisor, 0, 255 )), - static_cast<sal_uInt8>(MinMax( nSumG / nDivisor, 0, 255 )), - static_cast<sal_uInt8>(MinMax( nSumB / nDivisor, 0, 255 )) ) ); - } - - if( ++nY < nHeight ) - { - if( pRowTmp1 == pColRow1 ) - { - pRowTmp1 = pColRow2; - pRowTmp2 = pColRow3; - pRowTmp3 = pColRow1; - } - else if( pRowTmp1 == pColRow2 ) - { - pRowTmp1 = pColRow3; - pRowTmp2 = pColRow1; - pRowTmp3 = pColRow2; - } - else - { - pRowTmp1 = pColRow1; - pRowTmp2 = pColRow2; - pRowTmp3 = pColRow3; - } - - for( i = 0; i < nWidth2; i++ ) - pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] ); - } - } - - delete[] pKoeff; - delete[] reinterpret_cast<sal_uInt8*>(pColRow1); - delete[] reinterpret_cast<sal_uInt8*>(pColRow2); - delete[] reinterpret_cast<sal_uInt8*>(pColRow3); - delete[] pColm; - delete[] pRows; - - pWriteAcc.reset(); - - bRet = true; - } - - pReadAcc.reset(); - - if( bRet ) - { - const MapMode aMap( maPrefMapMode ); - const Size aSize( maPrefSize ); - - *this = aNewBmp; - - maPrefMapMode = aMap; - maPrefSize = aSize; - } - } - - return bRet; -} bool Bitmap::ImplMedianFilter() { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits