nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / bitmap / BitmapInterpolateScaleFilter.cxx
blobeb1d027bb2952028f6a7a4017f37731cda123fb7
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>
24 #include <vcl/bitmapaccess.hxx>
26 #include <bitmapwriteaccess.hxx>
27 #include <BitmapFastScaleFilter.hxx>
28 #include <BitmapInterpolateScaleFilter.hxx>
30 BitmapEx BitmapInterpolateScaleFilter::execute(BitmapEx const& rBitmapEx) const
32 Bitmap aBitmap(rBitmapEx.GetBitmap());
34 const Size aSizePix(aBitmap.GetSizePixel());
35 const tools::Long nNewWidth = FRound(aSizePix.Width() * mfScaleX);
36 const tools::Long nNewHeight = FRound(aSizePix.Height() * mfScaleY);
37 bool bRet = false;
39 if ((nNewWidth > 1) && (nNewHeight > 1))
41 Bitmap::ScopedReadAccess pReadAcc(aBitmap);
42 if (pReadAcc)
44 tools::Long nWidth = pReadAcc->Width();
45 tools::Long nHeight = pReadAcc->Height();
46 Bitmap aNewBmp(Size(nNewWidth, nHeight), 24);
47 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
49 if (pWriteAcc)
51 const tools::Long nNewWidth1 = nNewWidth - 1;
52 const tools::Long nWidth1 = pReadAcc->Width() - 1;
53 const double fRevScaleX = static_cast<double>(nWidth1) / nNewWidth1;
55 std::unique_ptr<tools::Long[]> pLutInt(new tools::Long[nNewWidth]);
56 std::unique_ptr<tools::Long[]> pLutFrac(new tools::Long[nNewWidth]);
58 for (tools::Long nX = 0, nTemp = nWidth - 2; nX < nNewWidth; nX++)
60 double fTemp = nX * fRevScaleX;
61 pLutInt[nX] = MinMax(static_cast<tools::Long>(fTemp), 0, nTemp);
62 fTemp -= pLutInt[nX];
63 pLutFrac[nX] = static_cast<tools::Long>(fTemp * 1024.);
66 for (tools::Long nY = 0; nY < nHeight; nY++)
68 Scanline pScanlineRead = pReadAcc->GetScanline(nY);
69 if (1 == nWidth)
71 BitmapColor aCol0;
72 if (pReadAcc->HasPalette())
74 aCol0 = pReadAcc->GetPaletteColor(
75 pReadAcc->GetIndexFromData(pScanlineRead, 0));
77 else
79 aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, 0);
82 Scanline pScanline = pWriteAcc->GetScanline(nY);
83 for (tools::Long nX = 0; nX < nNewWidth; nX++)
85 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
88 else
90 Scanline pScanline = pWriteAcc->GetScanline(nY);
91 for (tools::Long nX = 0; nX < nNewWidth; nX++)
93 tools::Long nTemp = pLutInt[nX];
95 BitmapColor aCol0, aCol1;
96 if (pReadAcc->HasPalette())
98 aCol0 = pReadAcc->GetPaletteColor(
99 pReadAcc->GetIndexFromData(pScanlineRead, nTemp++));
100 aCol1 = pReadAcc->GetPaletteColor(
101 pReadAcc->GetIndexFromData(pScanlineRead, nTemp));
103 else
105 aCol0 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp++);
106 aCol1 = pReadAcc->GetPixelFromData(pScanlineRead, nTemp);
109 nTemp = pLutFrac[nX];
111 tools::Long lXR0 = aCol0.GetRed();
112 tools::Long lXG0 = aCol0.GetGreen();
113 tools::Long lXB0 = aCol0.GetBlue();
114 tools::Long lXR1 = aCol1.GetRed() - lXR0;
115 tools::Long lXG1 = aCol1.GetGreen() - lXG0;
116 tools::Long lXB1 = aCol1.GetBlue() - lXB0;
118 aCol0.SetRed(
119 static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
120 aCol0.SetGreen(
121 static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
122 aCol0.SetBlue(
123 static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
125 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
130 bRet = true;
133 pReadAcc.reset();
134 pWriteAcc.reset();
136 if (bRet)
138 bRet = false;
139 const Bitmap aOriginal(aBitmap);
140 aBitmap = aNewBmp;
141 aNewBmp = Bitmap(Size(nNewWidth, nNewHeight), 24);
142 pReadAcc = Bitmap::ScopedReadAccess(aBitmap);
143 pWriteAcc = BitmapScopedWriteAccess(aNewBmp);
145 if (pReadAcc && pWriteAcc)
147 const tools::Long nNewHeight1 = nNewHeight - 1;
148 const tools::Long nHeight1 = pReadAcc->Height() - 1;
149 const double fRevScaleY = static_cast<double>(nHeight1) / nNewHeight1;
151 std::unique_ptr<tools::Long[]> pLutInt(new tools::Long[nNewHeight]);
152 std::unique_ptr<tools::Long[]> pLutFrac(new tools::Long[nNewHeight]);
154 for (tools::Long nY = 0, nTemp = nHeight - 2; nY < nNewHeight; nY++)
156 double fTemp = nY * fRevScaleY;
157 pLutInt[nY] = MinMax(static_cast<tools::Long>(fTemp), 0, nTemp);
158 fTemp -= pLutInt[nY];
159 pLutFrac[nY] = static_cast<tools::Long>(fTemp * 1024.);
162 // after 1st step, bitmap *is* 24bit format (see above)
163 OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate "
164 "in-between format has palette, should not "
165 "happen (!)");
167 for (tools::Long nX = 0; nX < nNewWidth; nX++)
169 if (1 == nHeight)
171 BitmapColor aCol0 = pReadAcc->GetPixel(0, nX);
173 for (tools::Long nY = 0; nY < nNewHeight; nY++)
175 pWriteAcc->SetPixel(nY, nX, aCol0);
178 else
180 for (tools::Long nY = 0; nY < nNewHeight; nY++)
182 tools::Long nTemp = pLutInt[nY];
184 BitmapColor aCol0 = pReadAcc->GetPixel(nTemp++, nX);
185 BitmapColor aCol1 = pReadAcc->GetPixel(nTemp, nX);
187 nTemp = pLutFrac[nY];
189 tools::Long lXR0 = aCol0.GetRed();
190 tools::Long lXG0 = aCol0.GetGreen();
191 tools::Long lXB0 = aCol0.GetBlue();
192 tools::Long lXR1 = aCol1.GetRed() - lXR0;
193 tools::Long lXG1 = aCol1.GetGreen() - lXG0;
194 tools::Long lXB1 = aCol1.GetBlue() - lXB0;
196 aCol0.SetRed(
197 static_cast<sal_uInt8>((lXR1 * nTemp + (lXR0 << 10)) >> 10));
198 aCol0.SetGreen(
199 static_cast<sal_uInt8>((lXG1 * nTemp + (lXG0 << 10)) >> 10));
200 aCol0.SetBlue(
201 static_cast<sal_uInt8>((lXB1 * nTemp + (lXB0 << 10)) >> 10));
203 pWriteAcc->SetPixel(nY, nX, aCol0);
208 bRet = true;
211 pReadAcc.reset();
212 pWriteAcc.reset();
214 if (bRet)
216 aOriginal.AdaptBitCount(aNewBmp);
217 aBitmap = aNewBmp;
223 if (!bRet)
225 // fallback to fast scale filter
226 BitmapEx aBmpEx(aBitmap);
227 bRet = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(mfScaleX, mfScaleY));
228 aBitmap = aBmpEx.GetBitmap();
231 if (bRet)
232 return BitmapEx(aBitmap);
234 return BitmapEx();
237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */