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 tools::Long nDivisor = 8;
27  Bitmap::ScopedReadAccess pReadAcc(aBitmap);
28  bool bRet = false;
29 
30  if (pReadAcc)
31  {
32  Bitmap aNewBmp(aBitmap.GetSizePixel(), 24);
33  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
34 
35  if (pWriteAcc)
36  {
37  const tools::Long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
38  const tools::Long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
39  std::unique_ptr<tools::Long[]> pColm(new tools::Long[nWidth2]);
40  std::unique_ptr<tools::Long[]> pRows(new tools::Long[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  tools::Long 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 
203 const sal_Int32 g_SharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
204 
207 {
208 }
209 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetRed() const
Filter image based on a 3x3 convolution matrix.
long Long
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)
HashMap_OWString_Interface aMap
sal_uInt8 GetBlue() const
const sal_Int32 g_SharpenMatrix[]
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
int i
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
BitmapColor GetColor(tools::Long nY, tools::Long nX) const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:231
sal_uInt8 GetGreen() const