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 {
38 &pReadAcc->GetPalette());
39 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
40
41 if (pWriteAcc)
42 {
43 BitmapColor aGrey(sal_uInt8(0));
44 const sal_Int32 nWidth = pWriteAcc->Width();
45 const sal_Int32 nHeight = pWriteAcc->Height();
46 sal_Int32 nGrey11, nGrey12, nGrey13;
47 sal_Int32 nGrey21, nGrey22, nGrey23;
48 sal_Int32 nGrey31, nGrey32, nGrey33;
49 double fAzim = basegfx::deg2rad<100>(mnAzimuthAngle100);
50 double fElev = basegfx::deg2rad<100>(mnElevationAngle100);
51 std::unique_ptr<sal_Int32[]> pHMap(new sal_Int32[nWidth + 2]);
52 std::unique_ptr<sal_Int32[]> pVMap(new sal_Int32[nHeight + 2]);
53 sal_Int32 nX, nY, nNx, nNy, nDotL;
54 const sal_Int32 nLx = FRound(cos(fAzim) * cos(fElev) * 255.0);
55 const sal_Int32 nLy = FRound(sin(fAzim) * cos(fElev) * 255.0);
56 const sal_Int32 nLz = FRound(sin(fElev) * 255.0);
57 const auto nZ2 = ((6 * 255) / 4) * ((6 * 255) / 4);
58 const sal_Int32 nNzLz = ((6 * 255) / 4) * nLz;
59 const sal_uInt8 cLz
60 = static_cast<sal_uInt8>(std::clamp(nLz, sal_Int32(0), sal_Int32(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 sal_Int32 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 * Scanline
Definition: Scanline.hxx:26
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
void SetIndex(sal_uInt8 cIndex)
Definition: BitmapColor.hxx:75
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
const BitmapPalette & GetPalette() const
BitmapColor GetPixel(tools::Long nY, tools::Long nX) const
void SetPrefMapMode(const MapMode &rMapMode)
const MapMode & GetPrefMapMode() const
Size GetSizePixel() const
void SetPrefSize(const Size &rSize)
SAL_DLLPRIVATE bool ImplMakeGreyscales()
const Size & GetPrefSize() const
tools::Long FRound(double fVal)
HashMap_OWString_Interface aMap
unsigned char sal_uInt8