/* -*- 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 #include #include #include #include #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) const { 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; std::unique_ptr pColm(new long[nWidth2]); std::unique_ptr pRows(new long[nHeight2]); std::unique_ptr pColRow1(new BitmapColor[nWidth2]); std::unique_ptr pColRow2(new BitmapColor[nWidth2]); std::unique_ptr pColRow3(new BitmapColor[nWidth2]); BitmapColor* pRowTmp1 = pColRow1.get(); BitmapColor* pRowTmp2 = pColRow2.get(); BitmapColor* pRowTmp3 = pColRow3.get(); 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++) { pColor = pRowTmp1 + nX; nR1 = pColor->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(); pColor = pRowTmp2 + nX; nR4 = pColor->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(); pColor = pRowTmp3 + nX; nR7 = pColor->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(nR2), static_cast(nG2), static_cast(nB2))); } if (++nY < nHeight) { if (pRowTmp1 == pColRow1.get()) { pRowTmp1 = pColRow2.get(); pRowTmp2 = pColRow3.get(); pRowTmp3 = pColRow1.get(); } else if (pRowTmp1 == pColRow2.get()) { pRowTmp1 = pColRow3.get(); pRowTmp2 = pColRow1.get(); pRowTmp3 = pColRow2.get(); } else { pRowTmp1 = pColRow1.get(); pRowTmp2 = pColRow2.get(); pRowTmp3 = pColRow3.get(); } for (i = 0; i < nWidth2; i++) pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]); } } 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: */