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