bump product version to 7.2.5.1
[LibreOffice.git] / vcl / source / bitmap / BitmapMedianFilter.cxx
blob2e0b6556005d615ca7906db756c24e66602b3145
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #include <vcl/bitmap.hxx>
12 #include <vcl/bitmapex.hxx>
13 #include <vcl/BitmapMedianFilter.hxx>
15 #include <bitmap/BitmapWriteAccess.hxx>
17 #define S2(a, b) \
18 { \
19 tools::Long t; \
20 if ((t = b - a) < 0) \
21 { \
22 a += t; \
23 b -= t; \
24 } \
26 #define MN3(a, b, c) \
27 S2(a, b); \
28 S2(a, c);
29 #define MX3(a, b, c) \
30 S2(b, c); \
31 S2(a, c);
32 #define MNMX3(a, b, c) \
33 MX3(a, b, c); \
34 S2(a, b);
35 #define MNMX4(a, b, c, d) \
36 S2(a, b); \
37 S2(c, d); \
38 S2(a, c); \
39 S2(b, d);
40 #define MNMX5(a, b, c, d, e) \
41 S2(a, b); \
42 S2(c, d); \
43 MN3(a, c, e); \
44 MX3(b, d, e);
45 #define MNMX6(a, b, c, d, e, f) \
46 S2(a, d); \
47 S2(b, e); \
48 S2(c, f); \
49 MN3(a, b, c); \
50 MX3(d, e, f);
52 BitmapEx BitmapMedianFilter::execute(BitmapEx const& rBitmapEx) const
54 Bitmap aBitmap(rBitmapEx.GetBitmap());
56 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
57 bool bRet = false;
59 if (pReadAcc)
61 Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N24_BPP);
62 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
64 if (pWriteAcc)
66 const tools::Long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
67 const tools::Long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
68 std::unique_ptr<tools::Long[]> pColm(new tools::Long[nWidth2]);
69 std::unique_ptr<tools::Long[]> pRows(new tools::Long[nHeight2]);
70 std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
71 std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
72 std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
73 BitmapColor* pRowTmp1 = pColRow1.get();
74 BitmapColor* pRowTmp2 = pColRow2.get();
75 BitmapColor* pRowTmp3 = pColRow3.get();
76 BitmapColor* pColor;
77 tools::Long nY, nX, i;
78 tools::Long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
79 tools::Long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
80 tools::Long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
82 // create column LUT
83 for (i = 0; i < nWidth2; i++)
84 pColm[i] = (i > 0) ? (i - 1) : 0;
86 pColm[nWidth + 1] = pColm[nWidth];
88 // create row LUT
89 for (i = 0; i < nHeight2; i++)
90 pRows[i] = (i > 0) ? (i - 1) : 0;
92 pRows[nHeight + 1] = pRows[nHeight];
94 // read first three rows of bitmap color
95 if (nHeight2 > 2)
97 for (i = 0; i < nWidth2; i++)
99 pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
100 pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
101 pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
105 // do median filtering
106 for (nY = 0; nY < nHeight;)
108 Scanline pScanline = pWriteAcc->GetScanline(nY);
109 for (nX = 0; nX < nWidth; nX++)
111 pColor = pRowTmp1 + nX;
112 nR1 = pColor->GetRed();
113 nG1 = pColor->GetGreen();
114 nB1 = pColor->GetBlue();
115 nR2 = (++pColor)->GetRed();
116 nG2 = pColor->GetGreen();
117 nB2 = pColor->GetBlue();
118 nR3 = (++pColor)->GetRed();
119 nG3 = pColor->GetGreen();
120 nB3 = pColor->GetBlue();
122 pColor = pRowTmp2 + nX;
123 nR4 = pColor->GetRed();
124 nG4 = pColor->GetGreen();
125 nB4 = pColor->GetBlue();
126 nR5 = (++pColor)->GetRed();
127 nG5 = pColor->GetGreen();
128 nB5 = pColor->GetBlue();
129 nR6 = (++pColor)->GetRed();
130 nG6 = pColor->GetGreen();
131 nB6 = pColor->GetBlue();
133 pColor = pRowTmp3 + nX;
134 nR7 = pColor->GetRed();
135 nG7 = pColor->GetGreen();
136 nB7 = pColor->GetBlue();
137 nR8 = (++pColor)->GetRed();
138 nG8 = pColor->GetGreen();
139 nB8 = pColor->GetBlue();
140 nR9 = (++pColor)->GetRed();
141 nG9 = pColor->GetGreen();
142 nB9 = pColor->GetBlue();
144 MNMX6(nR1, nR2, nR3, nR4, nR5, nR6);
145 MNMX5(nR7, nR2, nR3, nR4, nR5);
146 MNMX4(nR8, nR2, nR3, nR4);
147 MNMX3(nR9, nR2, nR3);
149 MNMX6(nG1, nG2, nG3, nG4, nG5, nG6);
150 MNMX5(nG7, nG2, nG3, nG4, nG5);
151 MNMX4(nG8, nG2, nG3, nG4);
152 MNMX3(nG9, nG2, nG3);
154 MNMX6(nB1, nB2, nB3, nB4, nB5, nB6);
155 MNMX5(nB7, nB2, nB3, nB4, nB5);
156 MNMX4(nB8, nB2, nB3, nB4);
157 MNMX3(nB9, nB2, nB3);
159 // set destination color
160 pWriteAcc->SetPixelOnData(pScanline, nX,
161 BitmapColor(static_cast<sal_uInt8>(nR2),
162 static_cast<sal_uInt8>(nG2),
163 static_cast<sal_uInt8>(nB2)));
166 if (++nY < nHeight)
168 if (pRowTmp1 == pColRow1.get())
170 pRowTmp1 = pColRow2.get();
171 pRowTmp2 = pColRow3.get();
172 pRowTmp3 = pColRow1.get();
174 else if (pRowTmp1 == pColRow2.get())
176 pRowTmp1 = pColRow3.get();
177 pRowTmp2 = pColRow1.get();
178 pRowTmp3 = pColRow2.get();
180 else
182 pRowTmp1 = pColRow1.get();
183 pRowTmp2 = pColRow2.get();
184 pRowTmp3 = pColRow3.get();
187 for (i = 0; i < nWidth2; i++)
188 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
192 pWriteAcc.reset();
194 bRet = true;
197 pReadAcc.reset();
199 if (bRet)
201 const MapMode aMap(aBitmap.GetPrefMapMode());
202 const Size aPrefSize(aBitmap.GetPrefSize());
204 aBitmap = aNewBmp;
206 aBitmap.SetPrefMapMode(aMap);
207 aBitmap.SetPrefSize(aPrefSize);
211 if (bRet)
212 return BitmapEx(aBitmap);
214 return BitmapEx();
217 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */