bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / bitmap / BitmapInterpolateScaleFilter.cxx
blob73f521480f094e50f175c18638882f92420a18ce
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 long nNewWidth = FRound(aSizePix.Width() * mfScaleX);
36 const 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 long nWidth = pReadAcc->Width();
45 long nHeight = pReadAcc->Height();
46 Bitmap aNewBmp(Size(nNewWidth, nHeight), 24);
47 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
49 if (pWriteAcc)
51 const long nNewWidth1 = nNewWidth - 1;
52 const long nWidth1 = pReadAcc->Width() - 1;
53 const double fRevScaleX = static_cast<double>(nWidth1) / nNewWidth1;
55 std::unique_ptr<long[]> pLutInt(new long[nNewWidth]);
56 std::unique_ptr<long[]> pLutFrac(new long[nNewWidth]);
58 for (long nX = 0, nTemp = nWidth - 2; nX < nNewWidth; nX++)
60 double fTemp = nX * fRevScaleX;
61 pLutInt[nX] = MinMax(static_cast<long>(fTemp), 0, nTemp);
62 fTemp -= pLutInt[nX];
63 pLutFrac[nX] = static_cast<long>(fTemp * 1024.);
66 for (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 (long nX = 0; nX < nNewWidth; nX++)
85 pWriteAcc->SetPixelOnData(pScanline, nX, aCol0);
88 else
90 Scanline pScanline = pWriteAcc->GetScanline(nY);
91 for (long nX = 0; nX < nNewWidth; nX++)
93 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 long lXR0 = aCol0.GetRed();
112 long lXG0 = aCol0.GetGreen();
113 long lXB0 = aCol0.GetBlue();
114 long lXR1 = aCol1.GetRed() - lXR0;
115 long lXG1 = aCol1.GetGreen() - lXG0;
116 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 long nNewHeight1 = nNewHeight - 1;
148 const long nHeight1 = pReadAcc->Height() - 1;
149 const double fRevScaleY = static_cast<double>(nHeight1) / nNewHeight1;
151 std::unique_ptr<long[]> pLutInt(new long[nNewHeight]);
152 std::unique_ptr<long[]> pLutFrac(new long[nNewHeight]);
154 for (long nY = 0, nTemp = nHeight - 2; nY < nNewHeight; nY++)
156 double fTemp = nY * fRevScaleY;
157 pLutInt[nY] = MinMax(static_cast<long>(fTemp), 0, nTemp);
158 fTemp -= pLutInt[nY];
159 pLutFrac[nY] = static_cast<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 (long nX = 0; nX < nNewWidth; nX++)
169 if (1 == nHeight)
171 BitmapColor aCol0 = pReadAcc->GetPixel(0, nX);
173 for (long nY = 0; nY < nNewHeight; nY++)
175 pWriteAcc->SetPixel(nY, nX, aCol0);
178 else
180 for (long nY = 0; nY < nNewHeight; nY++)
182 long nTemp = pLutInt[nY];
184 BitmapColor aCol0 = pReadAcc->GetPixel(nTemp++, nX);
185 BitmapColor aCol1 = pReadAcc->GetPixel(nTemp, nX);
187 nTemp = pLutFrac[nY];
189 long lXR0 = aCol0.GetRed();
190 long lXG0 = aCol0.GetGreen();
191 long lXB0 = aCol0.GetBlue();
192 long lXR1 = aCol1.GetRed() - lXR0;
193 long lXG1 = aCol1.GetGreen() - lXG0;
194 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: */