LibreOffice Module vcl (master) 1
BitmapConvolutionMatrixFilter.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 <tools/helpers.hxx>
12
13#include <vcl/bitmap.hxx>
14#include <vcl/bitmapex.hxx>
17
19
20#include <array>
21
23{
24 Bitmap aBitmap(rBitmapEx.GetBitmap());
25
26 const sal_Int32 nDivisor = 8;
27 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
28 bool bRet = false;
29
30 if (pReadAcc)
31 {
33 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
34
35 if (pWriteAcc)
36 {
37 const sal_Int32 nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
38 const sal_Int32 nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
39 std::unique_ptr<sal_Int32[]> pColm(new sal_Int32[nWidth2]);
40 std::unique_ptr<sal_Int32[]> pRows(new sal_Int32[nHeight2]);
41 std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
42 std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
43 std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
44 BitmapColor* pRowTmp1 = pColRow1.get();
45 BitmapColor* pRowTmp2 = pColRow2.get();
46 BitmapColor* pRowTmp3 = pColRow3.get();
47 BitmapColor* pColor;
48 sal_Int32 nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
49 std::array<std::array<sal_Int32, 256>, 9> aKoeff;
50 sal_Int32* pTmp;
51
52 // create LUT of products of matrix value and possible color component values
53 for (nY = 0; nY < 9; nY++)
54 {
55 for (nX = nTmp = 0, nMatrixVal = mrMatrix[nY]; nX < 256; nX++, nTmp += nMatrixVal)
56 {
57 aKoeff[nY][nX] = nTmp;
58 }
59 }
60
61 // create column LUT
62 for (i = 0; i < nWidth2; i++)
63 {
64 pColm[i] = (i > 0) ? (i - 1) : 0;
65 }
66
67 pColm[nWidth + 1] = pColm[nWidth];
68
69 // create row LUT
70 for (i = 0; i < nHeight2; i++)
71 {
72 pRows[i] = (i > 0) ? (i - 1) : 0;
73 }
74
75 pRows[nHeight + 1] = pRows[nHeight];
76
77 // read first three rows of bitmap color
78 for (i = 0; i < nWidth2; i++)
79 {
80 pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
81 pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
82 pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
83 }
84
85 // do convolution
86 for (nY = 0; nY < nHeight;)
87 {
88 Scanline pScanline = pWriteAcc->GetScanline(nY);
89 for (nX = 0; nX < nWidth; nX++)
90 {
91 // first row
92 pTmp = aKoeff[0].data();
93 pColor = pRowTmp1 + nX;
94 nSumR = pTmp[pColor->GetRed()];
95 nSumG = pTmp[pColor->GetGreen()];
96 nSumB = pTmp[pColor->GetBlue()];
97
98 pTmp = aKoeff[1].data();
99 nSumR += pTmp[(++pColor)->GetRed()];
100 nSumG += pTmp[pColor->GetGreen()];
101 nSumB += pTmp[pColor->GetBlue()];
102
103 pTmp = aKoeff[2].data();
104 nSumR += pTmp[(++pColor)->GetRed()];
105 nSumG += pTmp[pColor->GetGreen()];
106 nSumB += pTmp[pColor->GetBlue()];
107
108 // second row
109 pTmp = aKoeff[3].data();
110 pColor = pRowTmp2 + nX;
111 nSumR += pTmp[pColor->GetRed()];
112 nSumG += pTmp[pColor->GetGreen()];
113 nSumB += pTmp[pColor->GetBlue()];
114
115 pTmp = aKoeff[4].data();
116 nSumR += pTmp[(++pColor)->GetRed()];
117 nSumG += pTmp[pColor->GetGreen()];
118 nSumB += pTmp[pColor->GetBlue()];
119
120 pTmp = aKoeff[5].data();
121 nSumR += pTmp[(++pColor)->GetRed()];
122 nSumG += pTmp[pColor->GetGreen()];
123 nSumB += pTmp[pColor->GetBlue()];
124
125 // third row
126 pTmp = aKoeff[6].data();
127 pColor = pRowTmp3 + nX;
128 nSumR += pTmp[pColor->GetRed()];
129 nSumG += pTmp[pColor->GetGreen()];
130 nSumB += pTmp[pColor->GetBlue()];
131
132 pTmp = aKoeff[7].data();
133 nSumR += pTmp[(++pColor)->GetRed()];
134 nSumG += pTmp[pColor->GetGreen()];
135 nSumB += pTmp[pColor->GetBlue()];
136
137 pTmp = aKoeff[8].data();
138 nSumR += pTmp[(++pColor)->GetRed()];
139 nSumG += pTmp[pColor->GetGreen()];
140 nSumB += pTmp[pColor->GetBlue()];
141
142 // calculate destination color
143 pWriteAcc->SetPixelOnData(
144 pScanline, nX,
145 BitmapColor(static_cast<sal_uInt8>(MinMax(nSumR / nDivisor, 0, 255)),
146 static_cast<sal_uInt8>(MinMax(nSumG / nDivisor, 0, 255)),
147 static_cast<sal_uInt8>(MinMax(nSumB / nDivisor, 0, 255))));
148 }
149
150 if (++nY < nHeight)
151 {
152 if (pRowTmp1 == pColRow1.get())
153 {
154 pRowTmp1 = pColRow2.get();
155 pRowTmp2 = pColRow3.get();
156 pRowTmp3 = pColRow1.get();
157 }
158 else if (pRowTmp1 == pColRow2.get())
159 {
160 pRowTmp1 = pColRow3.get();
161 pRowTmp2 = pColRow1.get();
162 pRowTmp3 = pColRow2.get();
163 }
164 else
165 {
166 pRowTmp1 = pColRow1.get();
167 pRowTmp2 = pColRow2.get();
168 pRowTmp3 = pColRow3.get();
169 }
170
171 for (i = 0; i < nWidth2; i++)
172 {
173 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
174 }
175 }
176 }
177
178 pWriteAcc.reset();
179
180 bRet = true;
181 }
182
183 pReadAcc.reset();
184
185 if (bRet)
186 {
187 const MapMode aMap(aBitmap.GetPrefMapMode());
188 const Size aPrefSize(aBitmap.GetPrefSize());
189
190 aBitmap = aNewBmp;
191
192 aBitmap.SetPrefMapMode(aMap);
193 aBitmap.SetPrefSize(aPrefSize);
194 }
195 }
196
197 if (bRet)
198 return BitmapEx(aBitmap);
199
200 return BitmapEx();
201}
202
203const sal_Int32 g_SharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
204
207{
208}
209/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_Int32 g_SharpenMatrix[]
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
Filter image based on a 3x3 convolution matrix.
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
BitmapColor GetColor(tools::Long nY, tools::Long nX) const
void SetPrefMapMode(const MapMode &rMapMode)
const MapMode & GetPrefMapMode() const
Size GetSizePixel() const
void SetPrefSize(const Size &rSize)
const Size & GetPrefSize() const
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)
int i
HashMap_OWString_Interface aMap
unsigned char sal_uInt8