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 if (!pReadAcc)
29 return BitmapEx();
30
32 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
33 if (!pWriteAcc)
34 return BitmapEx();
35
36 const sal_Int32 nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
37 const sal_Int32 nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
38 std::unique_ptr<sal_Int32[]> pColm(new sal_Int32[nWidth2]);
39 std::unique_ptr<sal_Int32[]> pRows(new sal_Int32[nHeight2]);
40 std::unique_ptr<BitmapColor[]> pColRow1(new BitmapColor[nWidth2]);
41 std::unique_ptr<BitmapColor[]> pColRow2(new BitmapColor[nWidth2]);
42 std::unique_ptr<BitmapColor[]> pColRow3(new BitmapColor[nWidth2]);
43 BitmapColor* pRowTmp1 = pColRow1.get();
44 BitmapColor* pRowTmp2 = pColRow2.get();
45 BitmapColor* pRowTmp3 = pColRow3.get();
46 BitmapColor* pColor;
47 sal_Int32 nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
48 std::array<std::array<sal_Int32, 256>, 9> aKoeff;
49 sal_Int32* pTmp;
50
51 // create LUT of products of matrix value and possible color component values
52 for (nY = 0; nY < 9; nY++)
53 {
54 for (nX = nTmp = 0, nMatrixVal = mrMatrix[nY]; nX < 256; nX++, nTmp += nMatrixVal)
55 {
56 aKoeff[nY][nX] = nTmp;
57 }
58 }
59
60 // create column LUT
61 for (i = 0; i < nWidth2; i++)
62 {
63 pColm[i] = (i > 0) ? (i - 1) : 0;
64 }
65
66 pColm[nWidth + 1] = pColm[nWidth];
67
68 // create row LUT
69 for (i = 0; i < nHeight2; i++)
70 {
71 pRows[i] = (i > 0) ? (i - 1) : 0;
72 }
73
74 pRows[nHeight + 1] = pRows[nHeight];
75
76 // read first three rows of bitmap color
77 for (i = 0; i < nWidth2; i++)
78 {
79 pColRow1[i] = pReadAcc->GetColor(pRows[0], pColm[i]);
80 pColRow2[i] = pReadAcc->GetColor(pRows[1], pColm[i]);
81 pColRow3[i] = pReadAcc->GetColor(pRows[2], pColm[i]);
82 }
83
84 // do convolution
85 for (nY = 0; nY < nHeight;)
86 {
87 Scanline pScanline = pWriteAcc->GetScanline(nY);
88 for (nX = 0; nX < nWidth; nX++)
89 {
90 // first row
91 pTmp = aKoeff[0].data();
92 pColor = pRowTmp1 + nX;
93 nSumR = pTmp[pColor->GetRed()];
94 nSumG = pTmp[pColor->GetGreen()];
95 nSumB = pTmp[pColor->GetBlue()];
96
97 pTmp = aKoeff[1].data();
98 nSumR += pTmp[(++pColor)->GetRed()];
99 nSumG += pTmp[pColor->GetGreen()];
100 nSumB += pTmp[pColor->GetBlue()];
101
102 pTmp = aKoeff[2].data();
103 nSumR += pTmp[(++pColor)->GetRed()];
104 nSumG += pTmp[pColor->GetGreen()];
105 nSumB += pTmp[pColor->GetBlue()];
106
107 // second row
108 pTmp = aKoeff[3].data();
109 pColor = pRowTmp2 + nX;
110 nSumR += pTmp[pColor->GetRed()];
111 nSumG += pTmp[pColor->GetGreen()];
112 nSumB += pTmp[pColor->GetBlue()];
113
114 pTmp = aKoeff[4].data();
115 nSumR += pTmp[(++pColor)->GetRed()];
116 nSumG += pTmp[pColor->GetGreen()];
117 nSumB += pTmp[pColor->GetBlue()];
118
119 pTmp = aKoeff[5].data();
120 nSumR += pTmp[(++pColor)->GetRed()];
121 nSumG += pTmp[pColor->GetGreen()];
122 nSumB += pTmp[pColor->GetBlue()];
123
124 // third row
125 pTmp = aKoeff[6].data();
126 pColor = pRowTmp3 + nX;
127 nSumR += pTmp[pColor->GetRed()];
128 nSumG += pTmp[pColor->GetGreen()];
129 nSumB += pTmp[pColor->GetBlue()];
130
131 pTmp = aKoeff[7].data();
132 nSumR += pTmp[(++pColor)->GetRed()];
133 nSumG += pTmp[pColor->GetGreen()];
134 nSumB += pTmp[pColor->GetBlue()];
135
136 pTmp = aKoeff[8].data();
137 nSumR += pTmp[(++pColor)->GetRed()];
138 nSumG += pTmp[pColor->GetGreen()];
139 nSumB += pTmp[pColor->GetBlue()];
140
141 // calculate destination color
142 pWriteAcc->SetPixelOnData(
143 pScanline, nX,
144 BitmapColor(static_cast<sal_uInt8>(MinMax(nSumR / nDivisor, 0, 255)),
145 static_cast<sal_uInt8>(MinMax(nSumG / nDivisor, 0, 255)),
146 static_cast<sal_uInt8>(MinMax(nSumB / nDivisor, 0, 255))));
147 }
148
149 if (++nY < nHeight)
150 {
151 if (pRowTmp1 == pColRow1.get())
152 {
153 pRowTmp1 = pColRow2.get();
154 pRowTmp2 = pColRow3.get();
155 pRowTmp3 = pColRow1.get();
156 }
157 else if (pRowTmp1 == pColRow2.get())
158 {
159 pRowTmp1 = pColRow3.get();
160 pRowTmp2 = pColRow1.get();
161 pRowTmp3 = pColRow2.get();
162 }
163 else
164 {
165 pRowTmp1 = pColRow1.get();
166 pRowTmp2 = pColRow2.get();
167 pRowTmp3 = pColRow3.get();
168 }
169
170 for (i = 0; i < nWidth2; i++)
171 {
172 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
173 }
174 }
175 }
176
177 pWriteAcc.reset();
178 pReadAcc.reset();
179
180 const MapMode aMap(aBitmap.GetPrefMapMode());
181 const Size aPrefSize(aBitmap.GetPrefSize());
182
183 aBitmap = aNewBmp;
184
185 aBitmap.SetPrefMapMode(aMap);
186 aBitmap.SetPrefSize(aPrefSize);
187
188 return BitmapEx(aBitmap);
189}
190
191const sal_Int32 g_SharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
192
195{
196}
197/* 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:217
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