tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / vcl / source / bitmap / BitmapInterpolateScaleFilter.cxx
blob8b9baa5b6af421c62af7449ce214018a8589efdd
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 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/helpers.hxx>
21 #include <osl/diagnose.h>
23 #include <vcl/bitmapex.hxx>
25 #include <vcl/BitmapWriteAccess.hxx>
26 #include <bitmap/BitmapFastScaleFilter.hxx>
27 #include <bitmap/BitmapInterpolateScaleFilter.hxx>
29 BitmapEx BitmapInterpolateScaleFilter::execute(BitmapEx const& rBitmapEx) const
31 Bitmap aBitmap(rBitmapEx.GetBitmap());
33 const Size aSizePix(aBitmap.GetSizePixel());
34 const sal_Int32 nNewWidth = basegfx::fround(aSizePix.Width() * mfScaleX);
35 const sal_Int32 nNewHeight = basegfx::fround(aSizePix.Height() * mfScaleY);
36 bool bRet = false;
38 if ((nNewWidth > 1) && (nNewHeight > 1))
40 BitmapScopedReadAccess pReadAcc(aBitmap);
41 if (pReadAcc)
43 sal_Int32 nWidth = pReadAcc->Width();
44 sal_Int32 nHeight = pReadAcc->Height();
45 Bitmap aNewBmp(Size(nNewWidth, nHeight), vcl::PixelFormat::N24_BPP);
46 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
48 if (pWriteAcc)
50 if (1 == nWidth)
52 for (sal_Int32 nY = 0; nY < nHeight; nY++)
54 Scanline pScanlineRead = pReadAcc->GetScanline(nY);
55 BitmapColor aCol0;
56 if (pReadAcc->HasPalette())
58 aCol0 = pReadAcc->GetPaletteColor(
59 pReadAcc->GetIndexFromData(pScanlineRead, 0));
61 else
63 aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, 0);
66 Scanline pScanline = pWriteAcc->GetScanline(nY);
67 for (sal_Int32 nX = 0; nX < nNewWidth; nX++)
69 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
73 else
75 const sal_Int32 nNewWidth1 = nNewWidth - 1;
76 const sal_Int32 nWidth1 = pReadAcc->Width() - 1;
77 const double fRevScaleX = static_cast<double>(nWidth1) / nNewWidth1;
79 std::unique_ptr<sal_Int32[]> pLutInt(new sal_Int32[nNewWidth]);
80 std::unique_ptr<sal_Int32[]> pLutFrac(new sal_Int32[nNewWidth]);
82 for (sal_Int32 nX = 0, nTemp = nWidth - 2; nX < nNewWidth; nX++)
84 double fTemp = nX * fRevScaleX;
85 pLutInt[nX]
86 = std::clamp(static_cast<sal_Int32>(fTemp), sal_Int32(0), nTemp);
87 fTemp -= pLutInt[nX];
88 pLutFrac[nX] = static_cast<sal_Int32>(fTemp * 1024.);
91 for (sal_Int32 nY = 0; nY < nHeight; nY++)
93 Scanline pScanlineRead = pReadAcc->GetScanline(nY);
94 Scanline pScanline = pWriteAcc->GetScanline(nY);
95 for (sal_Int32 nX = 0; nX < nNewWidth; nX++)
97 sal_Int32 nTemp = pLutInt[nX];
99 BitmapColor aCol0, aCol1;
100 if (pReadAcc->HasPalette())
102 aCol0 = pReadAcc->GetPaletteColor(
103 pReadAcc->GetIndexFromData(pScanlineRead, nTemp++));
104 aCol1 = pReadAcc->GetPaletteColor(
105 pReadAcc->GetIndexFromData(pScanlineRead, nTemp));
107 else
109 aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp++);
110 aCol1 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp);
113 nTemp = pLutFrac[nX];
115 sal_Int32 lXR0 = aCol0.GetRed();
116 sal_Int32 lXG0 = aCol0.GetGreen();
117 sal_Int32 lXB0 = aCol0.GetBlue();
118 sal_Int32 lXR1 = aCol1.GetRed() - lXR0;
119 sal_Int32 lXG1 = aCol1.GetGreen() - lXG0;
120 sal_Int32 lXB1 = aCol1.GetBlue() - lXB0;
122 aCol0.SetRed(
123 static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
124 aCol0.SetGreen(
125 static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
126 aCol0.SetBlue(
127 static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
129 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
134 bRet = true;
137 pReadAcc.reset();
138 pWriteAcc.reset();
140 if (bRet)
142 bRet = false;
143 const Bitmap aOriginal(aBitmap);
144 aBitmap = aNewBmp;
145 aNewBmp = Bitmap(Size(nNewWidth, nNewHeight), vcl::PixelFormat::N24_BPP);
146 pReadAcc = aBitmap;
147 pWriteAcc = aNewBmp;
149 if (pReadAcc && pWriteAcc)
151 // after 1st step, bitmap *is* 24bit format (see above)
152 OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate "
153 "in-between format has palette, should not "
154 "happen (!)");
156 if (1 == nHeight)
158 for (sal_Int32 nX = 0; nX < nNewWidth; nX++)
160 BitmapColor aCol0 = pReadAcc->GetPixel(0, nX);
162 for (sal_Int32 nY = 0; nY < nNewHeight; nY++)
164 pWriteAcc->SetPixel(nY, nX, aCol0);
168 else
170 const sal_Int32 nNewHeight1 = nNewHeight - 1;
171 const sal_Int32 nHeight1 = pReadAcc->Height() - 1;
172 const double fRevScaleY = static_cast<double>(nHeight1) / nNewHeight1;
174 std::unique_ptr<sal_Int32[]> pLutInt(new sal_Int32[nNewHeight]);
175 std::unique_ptr<sal_Int32[]> pLutFrac(new sal_Int32[nNewHeight]);
177 for (sal_Int32 nY = 0, nTemp = nHeight - 2; nY < nNewHeight; nY++)
179 double fTemp = nY * fRevScaleY;
180 pLutInt[nY]
181 = std::clamp(static_cast<sal_Int32>(fTemp), sal_Int32(0), nTemp);
182 fTemp -= pLutInt[nY];
183 pLutFrac[nY] = static_cast<sal_Int32>(fTemp * 1024.);
186 for (sal_Int32 nX = 0; nX < nNewWidth; nX++)
188 for (sal_Int32 nY = 0; nY < nNewHeight; nY++)
190 sal_Int32 nTemp = pLutInt[nY];
192 BitmapColor aCol0 = pReadAcc->GetPixel(nTemp++, nX);
193 BitmapColor aCol1 = pReadAcc->GetPixel(nTemp, nX);
195 nTemp = pLutFrac[nY];
197 sal_Int32 lXR0 = aCol0.GetRed();
198 sal_Int32 lXG0 = aCol0.GetGreen();
199 sal_Int32 lXB0 = aCol0.GetBlue();
200 sal_Int32 lXR1 = aCol1.GetRed() - lXR0;
201 sal_Int32 lXG1 = aCol1.GetGreen() - lXG0;
202 sal_Int32 lXB1 = aCol1.GetBlue() - lXB0;
204 aCol0.SetRed(
205 static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
206 aCol0.SetGreen(
207 static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
208 aCol0.SetBlue(
209 static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
211 pWriteAcc->SetPixel(nY, nX, aCol0);
216 bRet = true;
219 pReadAcc.reset();
220 pWriteAcc.reset();
222 if (bRet)
224 aOriginal.AdaptBitCount(aNewBmp);
225 aBitmap = std::move(aNewBmp);
231 if (!bRet)
233 // fallback to fast scale filter
234 BitmapEx aBmpEx(aBitmap);
235 bRet = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(mfScaleX, mfScaleY));
236 aBitmap = aBmpEx.GetBitmap();
239 if (bRet)
240 return BitmapEx(aBitmap);
242 return BitmapEx();
245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */