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  tools::Long 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  {
61  Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N24_BPP);
62  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
63 
64  if (pWriteAcc)
65  {
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;
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: */
sal_uInt8 GetRed() const
long Long
HashMap_OWString_Interface aMap
sal_uInt8 GetBlue() const
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
int i
#define MNMX4(a, b, c, d)
#define MNMX5(a, b, c, d, e)
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:229
sal_uInt8 GetGreen() const
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
#define MNMX6(a, b, c, d, e, f)
#define MNMX3(a, b, c)