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 #include <vcl/bitmap.hxx>
13 #include <vcl/bitmapex.hxx>
14 #include <vcl/bitmapaccess.hxx>
17 
18 #include <bitmapwriteaccess.hxx>
19 #include <array>
20 
22 {
23  Bitmap aBitmap(rBitmapEx.GetBitmap());
24 
25  const long nDivisor = 8;
26  Bitmap::ScopedReadAccess pReadAcc(aBitmap);
27  bool bRet = false;
28 
29  if (pReadAcc)
30  {
31  Bitmap aNewBmp(aBitmap.GetSizePixel(), 24);
32  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
33 
34  if (pWriteAcc)
35  {
36  const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
37  const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
38  std::unique_ptr<long[]> pColm(new long[nWidth2]);
39  std::unique_ptr<long[]> pRows(new long[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  long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
48  std::array<std::array<long, 256>, 9> aKoeff;
49  long* 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 
179  bRet = true;
180  }
181 
182  pReadAcc.reset();
183 
184  if (bRet)
185  {
186  const MapMode aMap(aBitmap.GetPrefMapMode());
187  const Size aPrefSize(aBitmap.GetPrefSize());
188 
189  aBitmap = aNewBmp;
190 
191  aBitmap.SetPrefMapMode(aMap);
192  aBitmap.SetPrefSize(aPrefSize);
193  }
194  }
195 
196  if (bRet)
197  return BitmapEx(aBitmap);
198 
199  return BitmapEx();
200 }
201 
202 static const long g_SharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
203 
206 {
207 }
208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetRed() const
Filter image based on a 3x3 convolution matrix.
sal_uInt8 GetBlue() const
Bitmap GetBitmap(const Color *pTransReplaceColor=nullptr) const
Definition: bitmapex.cxx:236
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
static const long g_SharpenMatrix[]
virtual BitmapEx execute(BitmapEx const &rBitmapEx) const override
int i
sal_uInt8 GetGreen() const
BitmapColor GetColor(long nY, long nX) const
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, long nMin, long nMax)