LibreOffice Module vcl (master) 1
BitmapMedianFilter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 */
10
11#include <vcl/bitmap.hxx>
12#include <vcl/bitmapex.hxx>
14
16
17#define S2(a, b) \
18 { \
19 sal_Int32 t; \
20 if ((t = b - a) < 0) \
21 { \
22 a += t; \
23 b -= t; \
24 } \
25 }
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);
51
53{
54 Bitmap aBitmap(rBitmapEx.GetBitmap());
55
56 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
57 bool bRet = false;
58
59 if (pReadAcc)
60 {
62 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
63
64 if (pWriteAcc)
65 {
66 const sal_Int32 nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
67 const sal_Int32 nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
68 std::unique_ptr<sal_Int32[]> pColm(new sal_Int32[nWidth2]);
69 std::unique_ptr<sal_Int32[]> pRows(new sal_Int32[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 sal_Int32 nY, nX, i;
78 sal_Int32 nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
79 sal_Int32 nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
80 sal_Int32 nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
81
82 // create column LUT
83 for (i = 0; i < nWidth2; i++)
84 pColm[i] = (i > 0) ? (i - 1) : 0;
85
86 pColm[nWidth + 1] = pColm[nWidth];
87
88 // create row LUT
89 for (i = 0; i < nHeight2; i++)
90 pRows[i] = (i > 0) ? (i - 1) : 0;
91
92 pRows[nHeight + 1] = pRows[nHeight];
93
94 // read first three rows of bitmap color
95 if (nHeight2 > 2)
96 {
97 for (i = 0; i < nWidth2; i++)
98 {
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]);
102 }
103 }
104
105 // do median filtering
106 for (nY = 0; nY < nHeight;)
107 {
108 Scanline pScanline = pWriteAcc->GetScanline(nY);
109 for (nX = 0; nX < nWidth; nX++)
110 {
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();
121
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();
132
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();
143
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);
148
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);
153
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);
158
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)));
164 }
165
166 if (++nY < nHeight)
167 {
168 if (pRowTmp1 == pColRow1.get())
169 {
170 pRowTmp1 = pColRow2.get();
171 pRowTmp2 = pColRow3.get();
172 pRowTmp3 = pColRow1.get();
173 }
174 else if (pRowTmp1 == pColRow2.get())
175 {
176 pRowTmp1 = pColRow3.get();
177 pRowTmp2 = pColRow1.get();
178 pRowTmp3 = pColRow2.get();
179 }
180 else
181 {
182 pRowTmp1 = pColRow1.get();
183 pRowTmp2 = pColRow2.get();
184 pRowTmp3 = pColRow3.get();
185 }
186
187 for (i = 0; i < nWidth2; i++)
188 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
189 }
190 }
191
192 pWriteAcc.reset();
193
194 bRet = true;
195 }
196
197 pReadAcc.reset();
198
199 if (bRet)
200 {
201 const MapMode aMap(aBitmap.GetPrefMapMode());
202 const Size aPrefSize(aBitmap.GetPrefSize());
203
204 aBitmap = aNewBmp;
205
206 aBitmap.SetPrefMapMode(aMap);
207 aBitmap.SetPrefSize(aPrefSize);
208 }
209 }
210
211 if (bRet)
212 return BitmapEx(aBitmap);
213
214 return BitmapEx();
215}
216
217/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define MNMX6(a, b, c, d, e, f)
#define MNMX3(a, b, c)
#define MNMX4(a, b, c, d)
#define MNMX5(a, b, c, d, e)
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
BitmapColor GetColor(tools::Long nY, tools::Long nX) const
void SetPrefMapMode(const MapMode &rMapMode)
const MapMode & GetPrefMapMode() const
Size GetSizePixel() const
void SetPrefSize(const Size &rSize)
const Size & GetPrefSize() const
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
int i
HashMap_OWString_Interface aMap
unsigned char sal_uInt8