LibreOffice Module vcl (master)  1
BitmapSobelGreyFilter.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 <sal/config.h>
12 
13 #include <vcl/bitmap.hxx>
14 #include <vcl/bitmapex.hxx>
16 
18 
19 #include <algorithm>
20 
22 {
23  Bitmap aBitmap(rBitmapEx.GetBitmap());
24 
25  bool bRet = aBitmap.ImplMakeGreyscales();
26 
27  if (bRet)
28  {
29  bRet = false;
30 
31  Bitmap::ScopedReadAccess pReadAcc(aBitmap);
32 
33  if (pReadAcc)
34  {
35  Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP,
36  &pReadAcc->GetPalette());
37  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
38 
39  if (pWriteAcc)
40  {
41  BitmapColor aGrey(sal_uInt8(0));
42  const tools::Long nWidth = pWriteAcc->Width();
43  const tools::Long nHeight = pWriteAcc->Height();
44  const tools::Long nMask111 = -1, nMask121 = 0, nMask131 = 1;
45  const tools::Long nMask211 = -2, nMask221 = 0, nMask231 = 2;
46  const tools::Long nMask311 = -1, nMask321 = 0, nMask331 = 1;
47  const tools::Long nMask112 = 1, nMask122 = 2, nMask132 = 1;
48  const tools::Long nMask212 = 0, nMask222 = 0, nMask232 = 0;
49  const tools::Long nMask312 = -1, nMask322 = -2, nMask332 = -1;
50  tools::Long nGrey11, nGrey12, nGrey13;
51  tools::Long nGrey21, nGrey22, nGrey23;
52  tools::Long nGrey31, nGrey32, nGrey33;
53  std::unique_ptr<long[]> pHMap(new long[nWidth + 2]);
54  std::unique_ptr<long[]> pVMap(new long[nHeight + 2]);
55  tools::Long nX, nY, nSum1, nSum2;
56 
57  // fill mapping tables
58  pHMap[0] = 0;
59 
60  for (nX = 1; nX <= nWidth; nX++)
61  {
62  pHMap[nX] = nX - 1;
63  }
64 
65  pHMap[nWidth + 1] = nWidth - 1;
66 
67  pVMap[0] = 0;
68 
69  for (nY = 1; nY <= nHeight; nY++)
70  {
71  pVMap[nY] = nY - 1;
72  }
73 
74  pVMap[nHeight + 1] = nHeight - 1;
75 
76  for (nY = 0; nY < nHeight; nY++)
77  {
78  nGrey11 = pReadAcc->GetPixel(pVMap[nY], pHMap[0]).GetIndex();
79  nGrey12 = pReadAcc->GetPixel(pVMap[nY], pHMap[1]).GetIndex();
80  nGrey13 = pReadAcc->GetPixel(pVMap[nY], pHMap[2]).GetIndex();
81  nGrey21 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[0]).GetIndex();
82  nGrey22 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[1]).GetIndex();
83  nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[2]).GetIndex();
84  nGrey31 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[0]).GetIndex();
85  nGrey32 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[1]).GetIndex();
86  nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[2]).GetIndex();
87 
88  Scanline pScanline = pWriteAcc->GetScanline(nY);
89  for (nX = 0; nX < nWidth; nX++)
90  {
91  nSum1 = nSum2 = 0;
92 
93  nSum1 += nMask111 * nGrey11;
94  nSum2 += nMask112 * nGrey11;
95 
96  nSum1 += nMask121 * nGrey12;
97  nSum2 += nMask122 * nGrey12;
98 
99  nSum1 += nMask131 * nGrey13;
100  nSum2 += nMask132 * nGrey13;
101 
102  nSum1 += nMask211 * nGrey21;
103  nSum2 += nMask212 * nGrey21;
104 
105  nSum1 += nMask221 * nGrey22;
106  nSum2 += nMask222 * nGrey22;
107 
108  nSum1 += nMask231 * nGrey23;
109  nSum2 += nMask232 * nGrey23;
110 
111  nSum1 += nMask311 * nGrey31;
112  nSum2 += nMask312 * nGrey31;
113 
114  nSum1 += nMask321 * nGrey32;
115  nSum2 += nMask322 * nGrey32;
116 
117  nSum1 += nMask331 * nGrey33;
118  nSum2 += nMask332 * nGrey33;
119 
120  nSum1 = static_cast<tools::Long>(
121  sqrt(static_cast<double>(nSum1 * nSum1 + nSum2 * nSum2)));
122 
123  aGrey.SetIndex(~static_cast<sal_uInt8>(
124  std::clamp(nSum1, tools::Long(0), tools::Long(255))));
125  pWriteAcc->SetPixelOnData(pScanline, nX, aGrey);
126 
127  if (nX < (nWidth - 1))
128  {
129  const tools::Long nNextX = pHMap[nX + 3];
130 
131  nGrey11 = nGrey12;
132  nGrey12 = nGrey13;
133  nGrey13 = pReadAcc->GetPixel(pVMap[nY], nNextX).GetIndex();
134  nGrey21 = nGrey22;
135  nGrey22 = nGrey23;
136  nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], nNextX).GetIndex();
137  nGrey31 = nGrey32;
138  nGrey32 = nGrey33;
139  nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], nNextX).GetIndex();
140  }
141  }
142  }
143 
144  pHMap.reset();
145  pVMap.reset();
146  pWriteAcc.reset();
147  bRet = true;
148  }
149 
150  pReadAcc.reset();
151 
152  if (bRet)
153  {
154  const MapMode aMap(aBitmap.GetPrefMapMode());
155  const Size aPrefSize(aBitmap.GetPrefSize());
156 
157  aBitmap = aNewBmp;
158 
159  aBitmap.SetPrefMapMode(aMap);
160  aBitmap.SetPrefSize(aPrefSize);
161  }
162  }
163  }
164 
165  if (bRet)
166  return BitmapEx(aBitmap);
167 
168  return BitmapEx();
169 }
170 
171 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
long Long
HashMap_OWString_Interface aMap
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
void SetIndex(sal_uInt8 cIndex)
Definition: BitmapColor.hxx:75
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:229
unsigned char sal_uInt8
const BitmapPalette & GetPalette() const
SAL_DLLPRIVATE bool ImplMakeGreyscales()
BitmapColor GetPixel(tools::Long nY, tools::Long nX) const