bump product version to 7.2.5.1
[LibreOffice.git] / vcl / source / bitmap / BitmapInterpolateScaleFilter.cxx
blob973e357fb2f51c2078fa8aefc956a4d172319ad3
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 <bitmap/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 tools::Long nNewWidth = FRound(aSizePix.Width() * mfScaleX);
35 const tools::Long nNewHeight = FRound(aSizePix.Height() * mfScaleY);
36 bool bRet = false;
38 if ((nNewWidth > 1) && (nNewHeight > 1))
40 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
41 if (pReadAcc)
43 tools::Long nWidth = pReadAcc->Width();
44 tools::Long nHeight = pReadAcc->Height();
45 Bitmap aNewBmp(Size(nNewWidth, nHeight), vcl::PixelFormat::N24_BPP);
46 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
48 if (pWriteAcc)
50 const tools::Long nNewWidth1 = nNewWidth - 1;
51 const tools::Long nWidth1 = pReadAcc->Width() - 1;
52 const double fRevScaleX = static_cast<double>(nWidth1) / nNewWidth1;
54 std::unique_ptr<tools::Long[]> pLutInt(new tools::Long[nNewWidth]);
55 std::unique_ptr<tools::Long[]> pLutFrac(new tools::Long[nNewWidth]);
57 for (tools::Long nX = 0, nTemp = nWidth - 2; nX < nNewWidth; nX++)
59 double fTemp = nX * fRevScaleX;
60 pLutInt[nX] = MinMax(static_cast<tools::Long>(fTemp), 0, nTemp);
61 fTemp -= pLutInt[nX];
62 pLutFrac[nX] = static_cast<tools::Long>(fTemp * 1024.);
65 for (tools::Long nY = 0; nY < nHeight; nY++)
67 Scanline pScanlineRead = pReadAcc->GetScanline(nY);
68 if (1 == nWidth)
70 BitmapColor aCol0;
71 if (pReadAcc->HasPalette())
73 aCol0 = pReadAcc->GetPaletteColor(
74 pReadAcc->GetIndexFromData(pScanlineRead, 0));
76 else
78 aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, 0);
81 Scanline pScanline = pWriteAcc->GetScanline(nY);
82 for (tools::Long nX = 0; nX < nNewWidth; nX++)
84 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
87 else
89 Scanline pScanline = pWriteAcc->GetScanline(nY);
90 for (tools::Long nX = 0; nX < nNewWidth; nX++)
92 tools::Long nTemp = pLutInt[nX];
94 BitmapColor aCol0, aCol1;
95 if (pReadAcc->HasPalette())
97 aCol0 = pReadAcc->GetPaletteColor(
98 pReadAcc->GetIndexFromData(pScanlineRead, nTemp++));
99 aCol1 = pReadAcc->GetPaletteColor(
100 pReadAcc->GetIndexFromData(pScanlineRead, nTemp));
102 else
104 aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp++);
105 aCol1 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp);
108 nTemp = pLutFrac[nX];
110 tools::Long lXR0 = aCol0.GetRed();
111 tools::Long lXG0 = aCol0.GetGreen();
112 tools::Long lXB0 = aCol0.GetBlue();
113 tools::Long lXR1 = aCol1.GetRed() - lXR0;
114 tools::Long lXG1 = aCol1.GetGreen() - lXG0;
115 tools::Long lXB1 = aCol1.GetBlue() - lXB0;
117 aCol0.SetRed(
118 static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
119 aCol0.SetGreen(
120 static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
121 aCol0.SetBlue(
122 static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
124 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
129 bRet = true;
132 pReadAcc.reset();
133 pWriteAcc.reset();
135 if (bRet)
137 bRet = false;
138 const Bitmap aOriginal(aBitmap);
139 aBitmap = aNewBmp;
140 aNewBmp = Bitmap(Size(nNewWidth, nNewHeight), vcl::PixelFormat::N24_BPP);
141 pReadAcc = Bitmap::ScopedReadAccess(aBitmap);
142 pWriteAcc = BitmapScopedWriteAccess(aNewBmp);
144 if (pReadAcc && pWriteAcc)
146 const tools::Long nNewHeight1 = nNewHeight - 1;
147 const tools::Long nHeight1 = pReadAcc->Height() - 1;
148 const double fRevScaleY = static_cast<double>(nHeight1) / nNewHeight1;
150 std::unique_ptr<tools::Long[]> pLutInt(new tools::Long[nNewHeight]);
151 std::unique_ptr<tools::Long[]> pLutFrac(new tools::Long[nNewHeight]);
153 for (tools::Long nY = 0, nTemp = nHeight - 2; nY < nNewHeight; nY++)
155 double fTemp = nY * fRevScaleY;
156 pLutInt[nY] = MinMax(static_cast<tools::Long>(fTemp), 0, nTemp);
157 fTemp -= pLutInt[nY];
158 pLutFrac[nY] = static_cast<tools::Long>(fTemp * 1024.);
161 // after 1st step, bitmap *is* 24bit format (see above)
162 OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate "
163 "in-between format has palette, should not "
164 "happen (!)");
166 for (tools::Long nX = 0; nX < nNewWidth; nX++)
168 if (1 == nHeight)
170 BitmapColor aCol0 = pReadAcc->GetPixel(0, nX);
172 for (tools::Long nY = 0; nY < nNewHeight; nY++)
174 pWriteAcc->SetPixel(nY, nX, aCol0);
177 else
179 for (tools::Long nY = 0; nY < nNewHeight; nY++)
181 tools::Long nTemp = pLutInt[nY];
183 BitmapColor aCol0 = pReadAcc->GetPixel(nTemp++, nX);
184 BitmapColor aCol1 = pReadAcc->GetPixel(nTemp, nX);
186 nTemp = pLutFrac[nY];
188 tools::Long lXR0 = aCol0.GetRed();
189 tools::Long lXG0 = aCol0.GetGreen();
190 tools::Long lXB0 = aCol0.GetBlue();
191 tools::Long lXR1 = aCol1.GetRed() - lXR0;
192 tools::Long lXG1 = aCol1.GetGreen() - lXG0;
193 tools::Long lXB1 = aCol1.GetBlue() - lXB0;
195 aCol0.SetRed(
196 static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
197 aCol0.SetGreen(
198 static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
199 aCol0.SetBlue(
200 static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
202 pWriteAcc->SetPixel(nY, nX, aCol0);
207 bRet = true;
210 pReadAcc.reset();
211 pWriteAcc.reset();
213 if (bRet)
215 aOriginal.AdaptBitCount(aNewBmp);
216 aBitmap = aNewBmp;
222 if (!bRet)
224 // fallback to fast scale filter
225 BitmapEx aBmpEx(aBitmap);
226 bRet = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(mfScaleX, mfScaleY));
227 aBitmap = aBmpEx.GetBitmap();
230 if (bRet)
231 return BitmapEx(aBitmap);
233 return BitmapEx();
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */