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 if (!pReadAcc)
58 return BitmapEx();
59
61 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
62 if (!pWriteAcc)
63 return BitmapEx();
64
65 const sal_Int32 nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
66 const sal_Int32 nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
67 std::unique_ptr<sal_Int32[]> pColm(new sal_Int32[nWidth2]);
68 std::unique_ptr<sal_Int32[]> pRows(new sal_Int32[nHeight2]);
69 std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
70 std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
71 std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
72 BitmapColor* pRowTmp1 = pColRow1.get();
73 BitmapColor* pRowTmp2 = pColRow2.get();
74 BitmapColor* pRowTmp3 = pColRow3.get();
75 BitmapColor* pColor;
76 sal_Int32 nY, nX, i;
77 sal_Int32 nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
78 sal_Int32 nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
79 sal_Int32 nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
80
81 // create column LUT
82 for (i = 0; i < nWidth2; i++)
83 pColm[i] = (i > 0) ? (i - 1) : 0;
84
85 pColm[nWidth + 1] = pColm[nWidth];
86
87 // create row LUT
88 for (i = 0; i < nHeight2; i++)
89 pRows[i] = (i > 0) ? (i - 1) : 0;
90
91 pRows[nHeight + 1] = pRows[nHeight];
92
93 // read first three rows of bitmap color
94 if (nHeight2 > 2)
95 {
96 for (i = 0; i < nWidth2; i++)
97 {
98 pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
99 pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
100 pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
101 }
102 }
103
104 // do median filtering
105 for (nY = 0; nY < nHeight;)
106 {
107 Scanline pScanline = pWriteAcc->GetScanline(nY);
108 for (nX = 0; nX < nWidth; nX++)
109 {
110 pColor = pRowTmp1 + nX;
111 nR1 = pColor->GetRed();
112 nG1 = pColor->GetGreen();
113 nB1 = pColor->GetBlue();
114 nR2 = (++pColor)->GetRed();
115 nG2 = pColor->GetGreen();
116 nB2 = pColor->GetBlue();
117 nR3 = (++pColor)->GetRed();
118 nG3 = pColor->GetGreen();
119 nB3 = pColor->GetBlue();
120
121 pColor = pRowTmp2 + nX;
122 nR4 = pColor->GetRed();
123 nG4 = pColor->GetGreen();
124 nB4 = pColor->GetBlue();
125 nR5 = (++pColor)->GetRed();
126 nG5 = pColor->GetGreen();
127 nB5 = pColor->GetBlue();
128 nR6 = (++pColor)->GetRed();
129 nG6 = pColor->GetGreen();
130 nB6 = pColor->GetBlue();
131
132 pColor = pRowTmp3 + nX;
133 nR7 = pColor->GetRed();
134 nG7 = pColor->GetGreen();
135 nB7 = pColor->GetBlue();
136 nR8 = (++pColor)->GetRed();
137 nG8 = pColor->GetGreen();
138 nB8 = pColor->GetBlue();
139 nR9 = (++pColor)->GetRed();
140 nG9 = pColor->GetGreen();
141 nB9 = pColor->GetBlue();
142
143 MNMX6(nR1, nR2, nR3, nR4, nR5, nR6);
144 MNMX5(nR7, nR2, nR3, nR4, nR5);
145 MNMX4(nR8, nR2, nR3, nR4);
146 MNMX3(nR9, nR2, nR3);
147
148 MNMX6(nG1, nG2, nG3, nG4, nG5, nG6);
149 MNMX5(nG7, nG2, nG3, nG4, nG5);
150 MNMX4(nG8, nG2, nG3, nG4);
151 MNMX3(nG9, nG2, nG3);
152
153 MNMX6(nB1, nB2, nB3, nB4, nB5, nB6);
154 MNMX5(nB7, nB2, nB3, nB4, nB5);
155 MNMX4(nB8, nB2, nB3, nB4);
156 MNMX3(nB9, nB2, nB3);
157
158 // set destination color
159 pWriteAcc->SetPixelOnData(pScanline, nX,
160 BitmapColor(static_cast<sal_uInt8>(nR2),
161 static_cast<sal_uInt8>(nG2),
162 static_cast<sal_uInt8>(nB2)));
163 }
164
165 if (++nY < nHeight)
166 {
167 if (pRowTmp1 == pColRow1.get())
168 {
169 pRowTmp1 = pColRow2.get();
170 pRowTmp2 = pColRow3.get();
171 pRowTmp3 = pColRow1.get();
172 }
173 else if (pRowTmp1 == pColRow2.get())
174 {
175 pRowTmp1 = pColRow3.get();
176 pRowTmp2 = pColRow1.get();
177 pRowTmp3 = pColRow2.get();
178 }
179 else
180 {
181 pRowTmp1 = pColRow1.get();
182 pRowTmp2 = pColRow2.get();
183 pRowTmp3 = pColRow3.get();
184 }
185
186 for (i = 0; i < nWidth2; i++)
187 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
188 }
189 }
190
191 pWriteAcc.reset();
192 pReadAcc.reset();
193
194 const MapMode aMap(aBitmap.GetPrefMapMode());
195 const Size aPrefSize(aBitmap.GetPrefSize());
196
197 aBitmap = aNewBmp;
198
199 aBitmap.SetPrefMapMode(aMap);
200 aBitmap.SetPrefSize(aPrefSize);
201
202 return BitmapEx(aBitmap);
203}
204
205/* 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:217
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