LibreOffice Module vcl (master)  1
BitmapEmbossGreyFilter.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 <tools/helpers.hxx>
14 
15 #include <vcl/bitmap.hxx>
16 #include <vcl/bitmapex.hxx>
18 
20 
21 #include <algorithm>
22 
24 {
25  Bitmap aBitmap(rBitmapEx.GetBitmap());
26 
27  bool bRet = aBitmap.ImplMakeGreyscales();
28 
29  if (bRet)
30  {
31  bRet = false;
32 
33  Bitmap::ScopedReadAccess pReadAcc(aBitmap);
34 
35  if (pReadAcc)
36  {
37  Bitmap aNewBmp(aBitmap.GetSizePixel(), vcl::PixelFormat::N8_BPP,
38  &pReadAcc->GetPalette());
39  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
40 
41  if (pWriteAcc)
42  {
43  BitmapColor aGrey(sal_uInt8(0));
44  const tools::Long nWidth = pWriteAcc->Width();
45  const tools::Long nHeight = pWriteAcc->Height();
46  tools::Long nGrey11, nGrey12, nGrey13;
47  tools::Long nGrey21, nGrey22, nGrey23;
48  tools::Long nGrey31, nGrey32, nGrey33;
49  double fAzim = basegfx::deg2rad(mnAzimuthAngle100 * 0.01);
50  double fElev = basegfx::deg2rad(mnElevationAngle100 * 0.01);
51  std::unique_ptr<tools::Long[]> pHMap(new tools::Long[nWidth + 2]);
52  std::unique_ptr<tools::Long[]> pVMap(new tools::Long[nHeight + 2]);
53  tools::Long nX, nY, nNx, nNy, nDotL;
54  const tools::Long nLx = FRound(cos(fAzim) * cos(fElev) * 255.0);
55  const tools::Long nLy = FRound(sin(fAzim) * cos(fElev) * 255.0);
56  const tools::Long nLz = FRound(sin(fElev) * 255.0);
57  const auto nZ2 = ((6 * 255) / 4) * ((6 * 255) / 4);
58  const tools::Long nNzLz = ((6 * 255) / 4) * nLz;
59  const sal_uInt8 cLz
60  = static_cast<sal_uInt8>(std::clamp(nLz, tools::Long(0), tools::Long(255)));
61 
62  // fill mapping tables
63  pHMap[0] = 0;
64 
65  for (nX = 1; nX <= nWidth; nX++)
66  {
67  pHMap[nX] = nX - 1;
68  }
69 
70  pHMap[nWidth + 1] = nWidth - 1;
71 
72  pVMap[0] = 0;
73 
74  for (nY = 1; nY <= nHeight; nY++)
75  {
76  pVMap[nY] = nY - 1;
77  }
78 
79  pVMap[nHeight + 1] = nHeight - 1;
80 
81  for (nY = 0; nY < nHeight; nY++)
82  {
83  nGrey11 = pReadAcc->GetPixel(pVMap[nY], pHMap[0]).GetIndex();
84  nGrey12 = pReadAcc->GetPixel(pVMap[nY], pHMap[1]).GetIndex();
85  nGrey13 = pReadAcc->GetPixel(pVMap[nY], pHMap[2]).GetIndex();
86  nGrey21 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[0]).GetIndex();
87  nGrey22 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[1]).GetIndex();
88  nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], pHMap[2]).GetIndex();
89  nGrey31 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[0]).GetIndex();
90  nGrey32 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[1]).GetIndex();
91  nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], pHMap[2]).GetIndex();
92 
93  Scanline pScanline = pWriteAcc->GetScanline(nY);
94  for (nX = 0; nX < nWidth; nX++)
95  {
96  nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
97  nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
98 
99  if (!nNx && !nNy)
100  {
101  aGrey.SetIndex(cLz);
102  }
103  else if ((nDotL = nNx * nLx + nNy * nLy + nNzLz) < 0)
104  {
105  aGrey.SetIndex(0);
106  }
107  else
108  {
109  const double fGrey
110  = nDotL / sqrt(static_cast<double>(nNx * nNx + nNy * nNy + nZ2));
111  aGrey.SetIndex(static_cast<sal_uInt8>(std::clamp(fGrey, 0.0, 255.0)));
112  }
113 
114  pWriteAcc->SetPixelOnData(pScanline, nX, aGrey);
115 
116  if (nX < (nWidth - 1))
117  {
118  const tools::Long nNextX = pHMap[nX + 3];
119 
120  nGrey11 = nGrey12;
121  nGrey12 = nGrey13;
122  nGrey13 = pReadAcc->GetPixel(pVMap[nY], nNextX).GetIndex();
123  nGrey21 = nGrey22;
124  nGrey22 = nGrey23;
125  nGrey23 = pReadAcc->GetPixel(pVMap[nY + 1], nNextX).GetIndex();
126  nGrey31 = nGrey32;
127  nGrey32 = nGrey33;
128  nGrey33 = pReadAcc->GetPixel(pVMap[nY + 2], nNextX).GetIndex();
129  }
130  }
131  }
132 
133  pHMap.reset();
134  pVMap.reset();
135  pWriteAcc.reset();
136  bRet = true;
137  }
138 
139  pReadAcc.reset();
140 
141  if (bRet)
142  {
143  const MapMode aMap(aBitmap.GetPrefMapMode());
144  const Size aPrefSize(aBitmap.GetPrefSize());
145 
146  aBitmap = aNewBmp;
147 
148  aBitmap.SetPrefMapMode(aMap);
149  aBitmap.SetPrefSize(aPrefSize);
150  }
151  }
152  }
153 
154  if (bRet)
155  return BitmapEx(aBitmap);
156 
157  return BitmapEx();
158 }
159 
160 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
long Long
HashMap_OWString_Interface aMap
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
tools::Long FRound(double fVal)
constexpr double deg2rad(double v)
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