diff options
author | Chris Sherlock <chris.sherlock79@gmail.com> | 2018-04-19 07:02:34 +1000 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2018-04-22 05:31:29 +0200 |
commit | 5b5d84df69765b9bd2fccb76a16d824720eea462 (patch) | |
tree | 8f8c57798967f50f7a696e625f75d3ecef1e63a7 | |
parent | 8559353af24123c7a736e64311d57d85bb3cb44c (diff) |
vcl: ImplMedianFilter() -> BitmapMedianFilter
Change-Id: I72a0546c11d6ef8a8a4eb467d566d639c88dc8b9
Reviewed-on: https://gerrit.libreoffice.org/53130
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | include/vcl/BitmapMedianFilter.hxx | 28 | ||||
-rw-r--r-- | include/vcl/bitmap.hxx | 1 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/source/bitmap/BitmapMedianFilter.cxx | 226 | ||||
-rw-r--r-- | vcl/source/gdi/bitmap4.cxx | 175 |
5 files changed, 261 insertions, 170 deletions
diff --git a/include/vcl/BitmapMedianFilter.hxx b/include/vcl/BitmapMedianFilter.hxx new file mode 100644 index 000000000000..e51a66eabcb7 --- /dev/null +++ b/include/vcl/BitmapMedianFilter.hxx @@ -0,0 +1,28 @@ +/* -*- 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_BITMAPMEDIANFILTER_HXX +#define INCLUDED_VCL_BITMAPMEDIANFILTER_HXX + +#include <vcl/BitmapFilter.hxx> + +class BitmapEx; + +class VCL_DLLPUBLIC BitmapMedianFilter : public BitmapFilter +{ +public: + BitmapMedianFilter() {} + + virtual BitmapEx execute(BitmapEx const& rBitmapEx) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index df6d094a9886..b89b2004fed6 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -658,7 +658,6 @@ public: SAL_DLLPRIVATE bool ImplDitherFloyd(); SAL_DLLPRIVATE bool ImplDitherFloyd16(); - SAL_DLLPRIVATE bool ImplMedianFilter(); SAL_DLLPRIVATE bool ImplSobelGrey(); SAL_DLLPRIVATE bool ImplEmbossGrey( const BmpFilterParam* pFilterParam ); SAL_DLLPRIVATE bool ImplSolarize( const BmpFilterParam* pFilterParam ); diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 57cd8d3962c7..ba26fb7fa91e 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -313,6 +313,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/bitmap/bitmap \ vcl/source/bitmap/bitmapfilter \ vcl/source/bitmap/BitmapConvolutionMatrixFilter \ + vcl/source/bitmap/BitmapMedianFilter \ vcl/source/bitmap/BitmapInterpolateScaleFilter \ vcl/source/bitmap/BitmapLightenFilter \ vcl/source/bitmap/BitmapDisabledImageFilter \ diff --git a/vcl/source/bitmap/BitmapMedianFilter.cxx b/vcl/source/bitmap/BitmapMedianFilter.cxx new file mode 100644 index 000000000000..45f1149a1c0c --- /dev/null +++ b/vcl/source/bitmap/BitmapMedianFilter.cxx @@ -0,0 +1,226 @@ +/* -*- 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/BitmapMedianFilter.hxx> + +#include <bitmapwriteaccess.hxx> + +#define S2(a, b) \ + { \ + long t; \ + if ((t = b - a) < 0) \ + { \ + a += t; \ + b -= t; \ + } \ + } +#define MN3(a, b, c) \ + S2(a, b); \ + S2(a, c); +#define MX3(a, b, c) \ + S2(b, c); \ + S2(a, c); +#define MNMX3(a, b, c) \ + MX3(a, b, c); \ + S2(a, b); +#define MNMX4(a, b, c, d) \ + S2(a, b); \ + S2(c, d); \ + S2(a, c); \ + S2(b, d); +#define MNMX5(a, b, c, d, e) \ + S2(a, b); \ + S2(c, d); \ + MN3(a, c, e); \ + MX3(b, d, e); +#define MNMX6(a, b, c, d, e, f) \ + S2(a, d); \ + S2(b, e); \ + S2(c, f); \ + MN3(a, b, c); \ + MX3(d, e, f); + +BitmapEx BitmapMedianFilter::execute(BitmapEx const& rBitmapEx) +{ + Bitmap aBitmap(rBitmapEx.GetBitmap()); + + 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; + long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9; + long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9; + long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9; + + // 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 + if (nHeight2 > 2) + { + 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 median filtering + for (nY = 0; nY < nHeight;) + { + Scanline pScanline = pWriteAcc->GetScanline(nY); + for (nX = 0; nX < nWidth; nX++) + { + nR1 = (pColor = pRowTmp1 + nX)->GetRed(); + nG1 = pColor->GetGreen(); + nB1 = pColor->GetBlue(); + nR2 = (++pColor)->GetRed(); + nG2 = pColor->GetGreen(); + nB2 = pColor->GetBlue(); + nR3 = (++pColor)->GetRed(); + nG3 = pColor->GetGreen(); + nB3 = pColor->GetBlue(); + + nR4 = (pColor = pRowTmp2 + nX)->GetRed(); + nG4 = pColor->GetGreen(); + nB4 = pColor->GetBlue(); + nR5 = (++pColor)->GetRed(); + nG5 = pColor->GetGreen(); + nB5 = pColor->GetBlue(); + nR6 = (++pColor)->GetRed(); + nG6 = pColor->GetGreen(); + nB6 = pColor->GetBlue(); + + nR7 = (pColor = pRowTmp3 + nX)->GetRed(); + nG7 = pColor->GetGreen(); + nB7 = pColor->GetBlue(); + nR8 = (++pColor)->GetRed(); + nG8 = pColor->GetGreen(); + nB8 = pColor->GetBlue(); + nR9 = (++pColor)->GetRed(); + nG9 = pColor->GetGreen(); + nB9 = pColor->GetBlue(); + + MNMX6(nR1, nR2, nR3, nR4, nR5, nR6); + MNMX5(nR7, nR2, nR3, nR4, nR5); + MNMX4(nR8, nR2, nR3, nR4); + MNMX3(nR9, nR2, nR3); + + MNMX6(nG1, nG2, nG3, nG4, nG5, nG6); + MNMX5(nG7, nG2, nG3, nG4, nG5); + MNMX4(nG8, nG2, nG3, nG4); + MNMX3(nG9, nG2, nG3); + + MNMX6(nB1, nB2, nB3, nB4, nB5, nB6); + MNMX5(nB7, nB2, nB3, nB4, nB5); + MNMX4(nB8, nB2, nB3, nB4); + MNMX3(nB9, nB2, nB3); + + // set destination color + pWriteAcc->SetPixelOnData(pScanline, nX, + BitmapColor(static_cast<sal_uInt8>(nR2), + static_cast<sal_uInt8>(nG2), + static_cast<sal_uInt8>(nB2))); + } + + 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[] 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 f13aa0bb9d24..a82498ed633a 100644 --- a/vcl/source/gdi/bitmap4.cxx +++ b/vcl/source/gdi/bitmap4.cxx @@ -22,20 +22,13 @@ #include <vcl/bitmap.hxx> #include <vcl/BitmapSmoothenFilter.hxx> #include <vcl/BitmapSharpenFilter.hxx> +#include <vcl/BitmapMedianFilter.hxx> #include <bitmapwriteaccess.hxx> #include <memory> #include <stdlib.h> -#define S2(a,b) { long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } } -#define MN3(a,b,c) S2(a,b); S2(a,c); -#define MX3(a,b,c) S2(b,c); S2(a,c); -#define MNMX3(a,b,c) MX3(a,b,c); S2(a,b); -#define MNMX4(a,b,c,d) S2(a,b); S2(c,d); S2(a,c); S2(b,d); -#define MNMX5(a,b,c,d,e) S2(a,b); S2(c,d); MN3(a,c,e); MX3(b,d,e); -#define MNMX6(a,b,c,d,e,f) S2(a,d); S2(b,e); S2(c,f); MN3(a,b,c); MX3(d,e,f); - static inline sal_uInt8 lcl_getDuotoneColorComponent( sal_uInt8 base, sal_uInt16 color1, sal_uInt16 color2 ) { color2 = color2*base/0xFF; @@ -67,7 +60,11 @@ bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam ) break; case BmpFilter::RemoveNoise: - bRet = ImplMedianFilter(); + { + BitmapEx aBmpEx(*this); + bRet = BitmapFilter::Filter(aBmpEx, BitmapMedianFilter()); + *this = aBmpEx.GetBitmap(); + } break; case BmpFilter::SobelGrey: @@ -107,166 +104,6 @@ bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam ) } -bool Bitmap::ImplMedianFilter() -{ - 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; - long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9; - long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9; - long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9; - - // 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 - if (nHeight2 > 2) - { - 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 median filtering - for( nY = 0; nY < nHeight; ) - { - Scanline pScanline = pWriteAcc->GetScanline(nY); - for( nX = 0; nX < nWidth; nX++ ) - { - nR1 = ( pColor = pRowTmp1 + nX )->GetRed(); - nG1 = pColor->GetGreen(); - nB1 = pColor->GetBlue(); - nR2 = ( ++pColor )->GetRed(); - nG2 = pColor->GetGreen(); - nB2 = pColor->GetBlue(); - nR3 = ( ++pColor )->GetRed(); - nG3 = pColor->GetGreen(); - nB3 = pColor->GetBlue(); - - nR4 = ( pColor = pRowTmp2 + nX )->GetRed(); - nG4 = pColor->GetGreen(); - nB4 = pColor->GetBlue(); - nR5 = ( ++pColor )->GetRed(); - nG5 = pColor->GetGreen(); - nB5 = pColor->GetBlue(); - nR6 = ( ++pColor )->GetRed(); - nG6 = pColor->GetGreen(); - nB6 = pColor->GetBlue(); - - nR7 = ( pColor = pRowTmp3 + nX )->GetRed(); - nG7 = pColor->GetGreen(); - nB7 = pColor->GetBlue(); - nR8 = ( ++pColor )->GetRed(); - nG8 = pColor->GetGreen(); - nB8 = pColor->GetBlue(); - nR9 = ( ++pColor )->GetRed(); - nG9 = pColor->GetGreen(); - nB9 = pColor->GetBlue(); - - MNMX6( nR1, nR2, nR3, nR4, nR5, nR6 ); - MNMX5( nR7, nR2, nR3, nR4, nR5 ); - MNMX4( nR8, nR2, nR3, nR4 ); - MNMX3( nR9, nR2, nR3 ); - - MNMX6( nG1, nG2, nG3, nG4, nG5, nG6 ); - MNMX5( nG7, nG2, nG3, nG4, nG5 ); - MNMX4( nG8, nG2, nG3, nG4 ); - MNMX3( nG9, nG2, nG3 ); - - MNMX6( nB1, nB2, nB3, nB4, nB5, nB6 ); - MNMX5( nB7, nB2, nB3, nB4, nB5 ); - MNMX4( nB8, nB2, nB3, nB4 ); - MNMX3( nB9, nB2, nB3 ); - - // set destination color - pWriteAcc->SetPixelOnData( pScanline, nX, BitmapColor( static_cast<sal_uInt8>(nR2), static_cast<sal_uInt8>(nG2), static_cast<sal_uInt8>(nB2) ) ); - } - - 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[] 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::ImplSobelGrey() { bool bRet = ImplMakeGreyscales( 256 ); |