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 <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
);
38 if ((nNewWidth
> 1) && (nNewHeight
> 1))
40 Bitmap::ScopedReadAccess
pReadAcc(aBitmap
);
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
);
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
);
62 pLutFrac
[nX
] = static_cast<tools::Long
>(fTemp
* 1024.);
65 for (tools::Long nY
= 0; nY
< nHeight
; nY
++)
67 Scanline pScanlineRead
= pReadAcc
->GetScanline(nY
);
71 if (pReadAcc
->HasPalette())
73 aCol0
= pReadAcc
->GetPaletteColor(
74 pReadAcc
->GetIndexFromData(pScanlineRead
, 0));
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
);
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
));
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
;
118 static_cast<sal_uInt8
>((lXR1
* nTemp
+ (lXR0
<< 10)) >> 10));
120 static_cast<sal_uInt8
>((lXG1
* nTemp
+ (lXG0
<< 10)) >> 10));
122 static_cast<sal_uInt8
>((lXB1
* nTemp
+ (lXB0
<< 10)) >> 10));
124 pWriteAcc
->SetPixelOnData(pScanline
, nX
, aCol0
);
138 const Bitmap
aOriginal(aBitmap
);
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 "
166 for (tools::Long nX
= 0; nX
< nNewWidth
; nX
++)
170 BitmapColor aCol0
= pReadAcc
->GetPixel(0, nX
);
172 for (tools::Long nY
= 0; nY
< nNewHeight
; nY
++)
174 pWriteAcc
->SetPixel(nY
, nX
, aCol0
);
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
;
196 static_cast<sal_uInt8
>((lXR1
* nTemp
+ (lXR0
<< 10)) >> 10));
198 static_cast<sal_uInt8
>((lXG1
* nTemp
+ (lXG0
<< 10)) >> 10));
200 static_cast<sal_uInt8
>((lXB1
* nTemp
+ (lXB0
<< 10)) >> 10));
202 pWriteAcc
->SetPixel(nY
, nX
, aCol0
);
215 aOriginal
.AdaptBitCount(aNewBmp
);
224 // fallback to fast scale filter
225 BitmapEx
aBmpEx(aBitmap
);
226 bRet
= BitmapFilter::Filter(aBmpEx
, BitmapFastScaleFilter(mfScaleX
, mfScaleY
));
227 aBitmap
= aBmpEx
.GetBitmap();
231 return BitmapEx(aBitmap
);
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */