Revert "tdf#158280 Replace usage of InputDialog with SvxNameDialog"
[LibreOffice.git] / vcl / qa / cppunit / BitmapScaleTest.cxx
blob4559b1d3eef3d629f8259476e3a9d3762e31bf8f
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/.
8 */
10 #include <cppunit/TestAssert.h>
11 #include <cppunit/TestFixture.h>
12 #include <cppunit/extensions/HelperMacros.h>
14 #include <vcl/bitmap.hxx>
16 #include <tools/stream.hxx>
17 #include <vcl/graphicfilter.hxx>
19 #include <BitmapSymmetryCheck.hxx>
20 #include <vcl/BitmapWriteAccess.hxx>
22 namespace
24 class BitmapScaleTest : public CppUnit::TestFixture
26 void testScale();
27 void testScale2();
28 void testScaleSymmetry();
30 CPPUNIT_TEST_SUITE(BitmapScaleTest);
31 CPPUNIT_TEST(testScale);
32 CPPUNIT_TEST(testScale2);
33 CPPUNIT_TEST(testScaleSymmetry);
34 CPPUNIT_TEST_SUITE_END();
37 bool checkBitmapColor(Bitmap const& rBitmap, Color const& rExpectedColor)
39 bool bResult = true;
40 Bitmap aBitmap(rBitmap);
41 BitmapScopedReadAccess pReadAccess(aBitmap);
42 tools::Long nHeight = pReadAccess->Height();
43 tools::Long nWidth = pReadAccess->Width();
44 for (tools::Long y = 0; y < nHeight; ++y)
46 Scanline pScanlineRead = pReadAccess->GetScanline(y);
47 for (tools::Long x = 0; x < nWidth; ++x)
49 Color aColor = pReadAccess->GetPixelFromData(pScanlineRead, x);
50 if (aColor != rExpectedColor)
51 bResult = false;
55 return bResult;
58 void assertColorsAreSimilar(int maxDifference, int line, const BitmapColor& expected,
59 const BitmapColor& actual)
61 // Check that the two colors match or are reasonably similar.
62 if (expected.GetColorError(actual) <= maxDifference)
63 return;
65 std::stringstream stream;
66 stream << "Line: " << line;
68 CPPUNIT_ASSERT_EQUAL_MESSAGE(stream.str(), expected, actual);
71 void BitmapScaleTest::testScale()
73 const bool bExportBitmap(false);
74 using tools::Rectangle;
76 static const BmpScaleFlag scaleMethods[]
77 = { BmpScaleFlag::Default, BmpScaleFlag::Fast, BmpScaleFlag::BestQuality,
78 BmpScaleFlag::Interpolate, BmpScaleFlag::Lanczos, BmpScaleFlag::BiCubic,
79 BmpScaleFlag::BiLinear };
80 for (BmpScaleFlag scaleMethod : scaleMethods)
82 struct ScaleSize
84 Size srcSize;
85 Size destSize;
87 static const ScaleSize scaleSizes[]
88 = { // test no-op
89 { Size(16, 16), Size(16, 16) },
90 // powers of 2 (OpenGL may use texture atlas)
91 { Size(16, 16), Size(14, 14) },
92 { Size(14, 14), Size(16, 16) }, // both upscaling and downscaling
93 // "random" sizes
94 { Size(18, 18), Size(14, 14) },
95 { Size(14, 14), Size(18, 18) },
96 // different x/y ratios
97 { Size(16, 30), Size(14, 18) },
98 { Size(14, 18), Size(16, 30) },
99 // ratio larger than 16 (triggers different paths in some OpenGL algorithms)
100 { Size(18 * 20, 18 * 20), Size(14, 14) },
101 { Size(14, 14), Size(18 * 20, 18 * 20) },
102 // Boundary cases.
103 { Size(1, 1), Size(1, 1) },
104 { Size(16, 1), Size(12, 1) },
105 { Size(1, 16), Size(1, 12) }
107 for (const ScaleSize& scaleSize : scaleSizes)
109 OString testStr = "Testing scale (" + scaleSize.srcSize.toString() + ")->("
110 + scaleSize.destSize.toString() + "), method "
111 + OString::number(static_cast<int>(scaleMethod));
112 fprintf(stderr, "%s\n", testStr.getStr());
113 Bitmap bitmap(scaleSize.srcSize, vcl::PixelFormat::N24_BPP);
115 // Fill each quarter of the source bitmap with a different color,
116 // and center with yet another color.
117 BitmapScopedWriteAccess writeAccess(bitmap);
118 const int halfW = scaleSize.srcSize.getWidth() / 2;
119 const int halfH = scaleSize.srcSize.getHeight() / 2;
120 const Size aSize(std::max(halfW, 1), std::max(halfH, 1));
122 writeAccess->SetFillColor(COL_GREEN);
123 writeAccess->FillRect(Rectangle(Point(0, 0), aSize));
124 writeAccess->SetFillColor(COL_RED);
125 writeAccess->FillRect(Rectangle(Point(0, halfH), aSize));
126 writeAccess->SetFillColor(COL_YELLOW);
127 writeAccess->FillRect(Rectangle(Point(halfW, 0), aSize));
128 writeAccess->SetFillColor(COL_BLACK);
129 writeAccess->FillRect(Rectangle(Point(halfW, halfH), aSize));
130 writeAccess->SetFillColor(COL_BLUE);
131 writeAccess->FillRect(Rectangle(Point(halfW / 2, halfH / 2), aSize));
133 if (bExportBitmap)
135 SvFileStream aStream(u"~/scale_before.png"_ustr,
136 StreamMode::WRITE | StreamMode::TRUNC);
137 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
138 rFilter.compressAsPNG(BitmapEx(bitmap), aStream);
140 CPPUNIT_ASSERT(bitmap.Scale(scaleSize.destSize, scaleMethod));
141 if (bExportBitmap)
143 SvFileStream aStream(u"~/scale_after.png"_ustr,
144 StreamMode::WRITE | StreamMode::TRUNC);
145 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
146 rFilter.compressAsPNG(BitmapEx(bitmap), aStream);
148 CPPUNIT_ASSERT_EQUAL(scaleSize.destSize, bitmap.GetSizePixel());
149 const int lastW = scaleSize.destSize.getWidth() - 1;
150 const int lastH = scaleSize.destSize.getHeight() - 1;
151 if (scaleSize.srcSize.getWidth() == 1 && scaleSize.srcSize.getHeight() == 1)
153 BitmapReadAccess readAccess(bitmap);
154 assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(0, 0));
155 assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(lastH, 0));
156 assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(0, lastW));
157 assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(lastH, lastW));
158 assertColorsAreSimilar(2, __LINE__, COL_BLUE,
159 readAccess.GetColor(lastH / 2, lastW / 2));
161 else if (lastW && lastH)
163 // Scaling should keep each quarter of the resulting bitmap have the same color,
164 // so check that color in each corner of the result bitmap is the same color,
165 // or reasonably close (some algorithms may alter the color very slightly).
166 BitmapReadAccess readAccess(bitmap);
167 assertColorsAreSimilar(2, __LINE__, COL_GREEN, readAccess.GetColor(0, 0));
168 assertColorsAreSimilar(2, __LINE__, COL_RED, readAccess.GetColor(lastH, 0));
169 assertColorsAreSimilar(2, __LINE__, COL_YELLOW, readAccess.GetColor(0, lastW));
170 assertColorsAreSimilar(2, __LINE__, COL_BLACK, readAccess.GetColor(lastH, lastW));
171 assertColorsAreSimilar(2, __LINE__, COL_BLUE,
172 readAccess.GetColor(lastH / 2, lastW / 2));
174 else if (lastW)
176 BitmapReadAccess readAccess(bitmap);
177 assertColorsAreSimilar(2, __LINE__, COL_RED, readAccess.GetColor(0, 0));
178 assertColorsAreSimilar(2, __LINE__, COL_BLACK, readAccess.GetColor(0, lastW));
179 assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(0, lastW / 2));
181 else if (lastH)
183 BitmapReadAccess readAccess(bitmap);
184 assertColorsAreSimilar(2, __LINE__, COL_YELLOW, readAccess.GetColor(0, 0));
185 assertColorsAreSimilar(2, __LINE__, COL_BLACK, readAccess.GetColor(lastH, 0));
186 assertColorsAreSimilar(2, __LINE__, COL_BLUE, readAccess.GetColor(lastH / 2, 0));
192 void BitmapScaleTest::testScale2()
194 const bool bExportBitmap(false);
196 Bitmap aBitmap24Bit(Size(4096, 4096), vcl::PixelFormat::N24_BPP);
197 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap24Bit.getPixelFormat());
198 Color aBitmapColor = COL_YELLOW;
200 BitmapScopedWriteAccess aWriteAccess(aBitmap24Bit);
201 aWriteAccess->Erase(aBitmapColor);
204 if (bExportBitmap)
206 SvFileStream aStream(u"scale_before.png"_ustr, StreamMode::WRITE | StreamMode::TRUNC);
207 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
208 rFilter.compressAsPNG(BitmapEx(aBitmap24Bit), aStream);
211 // Scale - 65x65
212 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Width());
213 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Height());
214 Bitmap aScaledBitmap = aBitmap24Bit;
215 aScaledBitmap.Scale(Size(65, 65));
217 if (bExportBitmap)
219 SvFileStream aStream(u"scale_after_65x65.png"_ustr, StreamMode::WRITE | StreamMode::TRUNC);
220 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
221 rFilter.compressAsPNG(BitmapEx(aScaledBitmap), aStream);
224 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(65), aScaledBitmap.GetSizePixel().Width());
225 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(65), aScaledBitmap.GetSizePixel().Height());
226 CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
228 // Scale - 64x64
229 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Width());
230 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Height());
231 aScaledBitmap = aBitmap24Bit;
232 aScaledBitmap.Scale(Size(64, 64));
234 if (bExportBitmap)
236 SvFileStream aStream(u"scale_after_64x64.png"_ustr, StreamMode::WRITE | StreamMode::TRUNC);
237 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
238 rFilter.compressAsPNG(BitmapEx(aScaledBitmap), aStream);
241 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(64), aScaledBitmap.GetSizePixel().Width());
242 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(64), aScaledBitmap.GetSizePixel().Height());
243 CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
245 // Scale - 63x63
246 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Width());
247 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(4096), aBitmap24Bit.GetSizePixel().Height());
248 aScaledBitmap = aBitmap24Bit;
249 aScaledBitmap.Scale(Size(63, 63));
251 if (bExportBitmap)
253 SvFileStream aStream(u"scale_after_63x63.png"_ustr, StreamMode::WRITE | StreamMode::TRUNC);
254 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
255 rFilter.compressAsPNG(BitmapEx(aScaledBitmap), aStream);
258 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(63), aScaledBitmap.GetSizePixel().Width());
259 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(63), aScaledBitmap.GetSizePixel().Height());
260 CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
263 void BitmapScaleTest::testScaleSymmetry()
265 const bool bExportBitmap(false);
267 Bitmap aBitmap24Bit(Size(10, 10), vcl::PixelFormat::N24_BPP);
268 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap24Bit.getPixelFormat());
271 BitmapScopedWriteAccess aWriteAccess(aBitmap24Bit);
272 aWriteAccess->Erase(COL_WHITE);
273 aWriteAccess->SetLineColor(COL_BLACK);
274 aWriteAccess->DrawRect(tools::Rectangle(1, 1, 8, 8));
275 aWriteAccess->DrawRect(tools::Rectangle(3, 3, 6, 6));
278 BitmapSymmetryCheck aBitmapSymmetryCheck;
280 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(10), aBitmap24Bit.GetSizePixel().Width());
281 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(10), aBitmap24Bit.GetSizePixel().Height());
283 // Check symmetry of the bitmap
284 CPPUNIT_ASSERT(BitmapSymmetryCheck::check(aBitmap24Bit));
286 if (bExportBitmap)
288 SvFileStream aStream(u"~/scale_before.png"_ustr, StreamMode::WRITE | StreamMode::TRUNC);
289 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
290 rFilter.compressAsPNG(BitmapEx(aBitmap24Bit), aStream);
293 aBitmap24Bit.Scale(2, 2, BmpScaleFlag::Fast);
295 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(20), aBitmap24Bit.GetSizePixel().Width());
296 CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(20), aBitmap24Bit.GetSizePixel().Height());
298 // After scaling the bitmap should still be symmetrical. This check guarantees that
299 // scaling doesn't misalign the bitmap.
300 CPPUNIT_ASSERT(BitmapSymmetryCheck::check(aBitmap24Bit));
302 if (bExportBitmap)
304 SvFileStream aStream(u"~/scale_after.png"_ustr, StreamMode::WRITE | StreamMode::TRUNC);
305 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
306 rFilter.compressAsPNG(BitmapEx(aBitmap24Bit), aStream);
310 } // namespace
312 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapScaleTest);
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */