1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
);
38 if ((nNewWidth
> 1) && (nNewHeight
> 1))
40 BitmapScopedReadAccess
pReadAcc(aBitmap
);
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
);
52 for (sal_Int32 nY
= 0; nY
< nHeight
; nY
++)
54 Scanline pScanlineRead
= pReadAcc
->GetScanline(nY
);
56 if (pReadAcc
->HasPalette())
58 aCol0
= pReadAcc
->GetPaletteColor(
59 pReadAcc
->GetIndexFromData(pScanlineRead
, 0));
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
);
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
;
86 = std::clamp(static_cast<sal_Int32
>(fTemp
), sal_Int32(0), nTemp
);
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
));
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
;
123 static_cast<sal_uInt8
>((lXR1
* nTemp
+ (lXR0
<< 10)) >> 10));
125 static_cast<sal_uInt8
>((lXG1
* nTemp
+ (lXG0
<< 10)) >> 10));
127 static_cast<sal_uInt8
>((lXB1
* nTemp
+ (lXB0
<< 10)) >> 10));
129 pWriteAcc
->SetPixelOnData(pScanline
, nX
, aCol0
);
143 const Bitmap
aOriginal(aBitmap
);
145 aNewBmp
= Bitmap(Size(nNewWidth
, nNewHeight
), vcl::PixelFormat::N24_BPP
);
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 "
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
);
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
;
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
;
205 static_cast<sal_uInt8
>((lXR1
* nTemp
+ (lXR0
<< 10)) >> 10));
207 static_cast<sal_uInt8
>((lXG1
* nTemp
+ (lXG0
<< 10)) >> 10));
209 static_cast<sal_uInt8
>((lXB1
* nTemp
+ (lXB0
<< 10)) >> 10));
211 pWriteAcc
->SetPixel(nY
, nX
, aCol0
);
224 aOriginal
.AdaptBitCount(aNewBmp
);
225 aBitmap
= std::move(aNewBmp
);
233 // fallback to fast scale filter
234 BitmapEx
aBmpEx(aBitmap
);
235 bRet
= BitmapFilter::Filter(aBmpEx
, BitmapFastScaleFilter(mfScaleX
, mfScaleY
));
236 aBitmap
= aBmpEx
.GetBitmap();
240 return BitmapEx(aBitmap
);
245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */