bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / bitmap / BitmapMedianFilter.cxx
blob60edc557a9de01c4de4c26b0b877552bd4eaf263
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/bitmapaccess.hxx>
14 #include <vcl/BitmapMedianFilter.hxx>
16 #include <bitmapwriteaccess.hxx>
18 #define S2(a, b) \
19 { \
20 long t; \
21 if ((t = b - a) < 0) \
22 { \
23 a += t; \
24 b -= t; \
25 } \
27 #define MN3(a, b, c) \
28 S2(a, b); \
29 S2(a, c);
30 #define MX3(a, b, c) \
31 S2(b, c); \
32 S2(a, c);
33 #define MNMX3(a, b, c) \
34 MX3(a, b, c); \
35 S2(a, b);
36 #define MNMX4(a, b, c, d) \
37 S2(a, b); \
38 S2(c, d); \
39 S2(a, c); \
40 S2(b, d);
41 #define MNMX5(a, b, c, d, e) \
42 S2(a, b); \
43 S2(c, d); \
44 MN3(a, c, e); \
45 MX3(b, d, e);
46 #define MNMX6(a, b, c, d, e, f) \
47 S2(a, d); \
48 S2(b, e); \
49 S2(c, f); \
50 MN3(a, b, c); \
51 MX3(d, e, f);
53 BitmapEx BitmapMedianFilter::execute(BitmapEx const& rBitmapEx) const
55 Bitmap aBitmap(rBitmapEx.GetBitmap());
57 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
58 bool bRet = false;
60 if (pReadAcc)
62 Bitmap aNewBmp(aBitmap.GetSizePixel(), 24);
63 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
65 if (pWriteAcc)
67 const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
68 const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
69 std::unique_ptr<long[]> pColm(new long[nWidth2]);
70 std::unique_ptr<long[]> pRows(new long[nHeight2]);
71 std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
72 std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
73 std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
74 BitmapColor* pRowTmp1 = pColRow1.get();
75 BitmapColor* pRowTmp2 = pColRow2.get();
76 BitmapColor* pRowTmp3 = pColRow3.get();
77 BitmapColor* pColor;
78 long nY, nX, i;
79 long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
80 long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
81 long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
83 // create column LUT
84 for (i = 0; i < nWidth2; i++)
85 pColm[i] = (i > 0) ? (i - 1) : 0;
87 pColm[nWidth + 1] = pColm[nWidth];
89 // create row LUT
90 for (i = 0; i < nHeight2; i++)
91 pRows[i] = (i > 0) ? (i - 1) : 0;
93 pRows[nHeight + 1] = pRows[nHeight];
95 // read first three rows of bitmap color
96 if (nHeight2 > 2)
98 for (i = 0; i < nWidth2; i++)
100 pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
101 pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
102 pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
106 // do median filtering
107 for (nY = 0; nY < nHeight;)
109 Scanline pScanline = pWriteAcc->GetScanline(nY);
110 for (nX = 0; nX < nWidth; nX++)
112 pColor = pRowTmp1 + nX;
113 nR1 = pColor->GetRed();
114 nG1 = pColor->GetGreen();
115 nB1 = pColor->GetBlue();
116 nR2 = (++pColor)->GetRed();
117 nG2 = pColor->GetGreen();
118 nB2 = pColor->GetBlue();
119 nR3 = (++pColor)->GetRed();
120 nG3 = pColor->GetGreen();
121 nB3 = pColor->GetBlue();
123 pColor = pRowTmp2 + nX;
124 nR4 = pColor->GetRed();
125 nG4 = pColor->GetGreen();
126 nB4 = pColor->GetBlue();
127 nR5 = (++pColor)->GetRed();
128 nG5 = pColor->GetGreen();
129 nB5 = pColor->GetBlue();
130 nR6 = (++pColor)->GetRed();
131 nG6 = pColor->GetGreen();
132 nB6 = pColor->GetBlue();
134 pColor = pRowTmp3 + nX;
135 nR7 = pColor->GetRed();
136 nG7 = pColor->GetGreen();
137 nB7 = pColor->GetBlue();
138 nR8 = (++pColor)->GetRed();
139 nG8 = pColor->GetGreen();
140 nB8 = pColor->GetBlue();
141 nR9 = (++pColor)->GetRed();
142 nG9 = pColor->GetGreen();
143 nB9 = pColor->GetBlue();
145 MNMX6(nR1, nR2, nR3, nR4, nR5, nR6);
146 MNMX5(nR7, nR2, nR3, nR4, nR5);
147 MNMX4(nR8, nR2, nR3, nR4);
148 MNMX3(nR9, nR2, nR3);
150 MNMX6(nG1, nG2, nG3, nG4, nG5, nG6);
151 MNMX5(nG7, nG2, nG3, nG4, nG5);
152 MNMX4(nG8, nG2, nG3, nG4);
153 MNMX3(nG9, nG2, nG3);
155 MNMX6(nB1, nB2, nB3, nB4, nB5, nB6);
156 MNMX5(nB7, nB2, nB3, nB4, nB5);
157 MNMX4(nB8, nB2, nB3, nB4);
158 MNMX3(nB9, nB2, nB3);
160 // set destination color
161 pWriteAcc->SetPixelOnData(pScanline, nX,
162 BitmapColor(static_cast<sal_uInt8>(nR2),
163 static_cast<sal_uInt8>(nG2),
164 static_cast<sal_uInt8>(nB2)));
167 if (++nY < nHeight)
169 if (pRowTmp1 == pColRow1.get())
171 pRowTmp1 = pColRow2.get();
172 pRowTmp2 = pColRow3.get();
173 pRowTmp3 = pColRow1.get();
175 else if (pRowTmp1 == pColRow2.get())
177 pRowTmp1 = pColRow3.get();
178 pRowTmp2 = pColRow1.get();
179 pRowTmp3 = pColRow2.get();
181 else
183 pRowTmp1 = pColRow1.get();
184 pRowTmp2 = pColRow2.get();
185 pRowTmp3 = pColRow3.get();
188 for (i = 0; i < nWidth2; i++)
189 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
193 pWriteAcc.reset();
195 bRet = true;
198 pReadAcc.reset();
200 if (bRet)
202 const MapMode aMap(aBitmap.GetPrefMapMode());
203 const Size aPrefSize(aBitmap.GetPrefSize());
205 aBitmap = aNewBmp;
207 aBitmap.SetPrefMapMode(aMap);
208 aBitmap.SetPrefSize(aPrefSize);
212 if (bRet)
213 return BitmapEx(aBitmap);
215 return BitmapEx();
218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */