Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / source / bitmap / BitmapConvolutionMatrixFilter.cxx
blob94e0c6e02f80a81be3448d64765862e6b575f363
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 */
11 #include <tools/helpers.hxx>
12 #include <vcl/bitmap.hxx>
13 #include <vcl/bitmapex.hxx>
14 #include <vcl/bitmapaccess.hxx>
15 #include <vcl/BitmapConvolutionMatrixFilter.hxx>
16 #include <vcl/BitmapSharpenFilter.hxx>
18 #include <bitmapwriteaccess.hxx>
19 #include <array>
21 BitmapEx BitmapConvolutionMatrixFilter::execute(BitmapEx const& rBitmapEx) const
23 Bitmap aBitmap(rBitmapEx.GetBitmap());
25 const long nDivisor = 8;
26 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
27 bool bRet = false;
29 if (pReadAcc)
31 Bitmap aNewBmp(aBitmap.GetSizePixel(), 24);
32 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
34 if (pWriteAcc)
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;
51 // create LUT of products of matrix value and possible color component values
52 for (nY = 0; nY < 9; nY++)
54 for (nX = nTmp = 0, nMatrixVal = mrMatrix[nY]; nX < 256; nX++, nTmp += nMatrixVal)
56 aKoeff[nY][nX] = nTmp;
60 // create column LUT
61 for (i = 0; i < nWidth2; i++)
63 pColm[i] = (i > 0) ? (i - 1) : 0;
66 pColm[nWidth + 1] = pColm[nWidth];
68 // create row LUT
69 for (i = 0; i < nHeight2; i++)
71 pRows[i] = (i > 0) ? (i - 1) : 0;
74 pRows[nHeight + 1] = pRows[nHeight];
76 // read first three rows of bitmap color
77 for (i = 0; i < nWidth2; i++)
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]);
84 // do convolution
85 for (nY = 0; nY < nHeight;)
87 Scanline pScanline = pWriteAcc->GetScanline(nY);
88 for (nX = 0; nX < nWidth; nX++)
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()];
97 pTmp = aKoeff[1].data();
98 nSumR += pTmp[(++pColor)->GetRed()];
99 nSumG += pTmp[pColor->GetGreen()];
100 nSumB += pTmp[pColor->GetBlue()];
102 pTmp = aKoeff[2].data();
103 nSumR += pTmp[(++pColor)->GetRed()];
104 nSumG += pTmp[pColor->GetGreen()];
105 nSumB += pTmp[pColor->GetBlue()];
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()];
114 pTmp = aKoeff[4].data();
115 nSumR += pTmp[(++pColor)->GetRed()];
116 nSumG += pTmp[pColor->GetGreen()];
117 nSumB += pTmp[pColor->GetBlue()];
119 pTmp = aKoeff[5].data();
120 nSumR += pTmp[(++pColor)->GetRed()];
121 nSumG += pTmp[pColor->GetGreen()];
122 nSumB += pTmp[pColor->GetBlue()];
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()];
131 pTmp = aKoeff[7].data();
132 nSumR += pTmp[(++pColor)->GetRed()];
133 nSumG += pTmp[pColor->GetGreen()];
134 nSumB += pTmp[pColor->GetBlue()];
136 pTmp = aKoeff[8].data();
137 nSumR += pTmp[(++pColor)->GetRed()];
138 nSumG += pTmp[pColor->GetGreen()];
139 nSumB += pTmp[pColor->GetBlue()];
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))));
149 if (++nY < nHeight)
151 if (pRowTmp1 == pColRow1.get())
153 pRowTmp1 = pColRow2.get();
154 pRowTmp2 = pColRow3.get();
155 pRowTmp3 = pColRow1.get();
157 else if (pRowTmp1 == pColRow2.get())
159 pRowTmp1 = pColRow3.get();
160 pRowTmp2 = pColRow1.get();
161 pRowTmp3 = pColRow2.get();
163 else
165 pRowTmp1 = pColRow1.get();
166 pRowTmp2 = pColRow2.get();
167 pRowTmp3 = pColRow3.get();
170 for (i = 0; i < nWidth2; i++)
172 pRowTmp3[i] = pReadAcc->GetColor(pRows[nY + 2], pColm[i]);
177 pWriteAcc.reset();
179 bRet = true;
182 pReadAcc.reset();
184 if (bRet)
186 const MapMode aMap(aBitmap.GetPrefMapMode());
187 const Size aPrefSize(aBitmap.GetPrefSize());
189 aBitmap = aNewBmp;
191 aBitmap.SetPrefMapMode(aMap);
192 aBitmap.SetPrefSize(aPrefSize);
196 if (bRet)
197 return BitmapEx(aBitmap);
199 return BitmapEx();
202 static const long g_SharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
204 BitmapSharpenFilter::BitmapSharpenFilter()
205 : BitmapConvolutionMatrixFilter(g_SharpenMatrix)
208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */