nss: upgrade to release 3.73
[LibreOffice.git] / vcl / qa / cppunit / BitmapTest.cxx
blob490a2d3ce8c7ff93772d7c53721292b8327e8c71
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>
13 #include <cppunit/plugin/TestPlugIn.h>
15 #include <unordered_map>
17 #include <vcl/bitmap.hxx>
18 #include <vcl/bitmapaccess.hxx>
19 #include <vcl/virdev.hxx>
21 #include <rtl/strbuf.hxx>
22 #include <config_features.h>
23 #if HAVE_FEATURE_OPENGL
24 #include <vcl/opengl/OpenGLHelper.hxx>
25 #endif
26 #include <vcl/skia/SkiaHelper.hxx>
27 #include <vcl/BitmapMonochromeFilter.hxx>
29 #include <bitmapwriteaccess.hxx>
31 #include <svdata.hxx>
32 #include <salinst.hxx>
33 #include <bitmap/Octree.hxx>
35 namespace
37 class BitmapTest : public CppUnit::TestFixture
39 void testCreation();
40 void testEmpty();
41 void testMonochrome();
42 void testN4Greyscale();
43 void testN8Greyscale();
44 void testConvert();
45 void testCRC();
46 void testGreyPalette();
47 void testCustom8BitPalette();
48 void testErase();
49 void testBitmap32();
50 void testOctree();
51 void testEmptyAccess();
53 CPPUNIT_TEST_SUITE(BitmapTest);
54 CPPUNIT_TEST(testCreation);
55 CPPUNIT_TEST(testEmpty);
56 CPPUNIT_TEST(testMonochrome);
57 CPPUNIT_TEST(testConvert);
58 CPPUNIT_TEST(testN4Greyscale);
59 CPPUNIT_TEST(testN8Greyscale);
60 CPPUNIT_TEST(testCRC);
61 CPPUNIT_TEST(testGreyPalette);
62 CPPUNIT_TEST(testCustom8BitPalette);
63 CPPUNIT_TEST(testErase);
64 CPPUNIT_TEST(testBitmap32);
65 CPPUNIT_TEST(testOctree);
66 CPPUNIT_TEST(testEmptyAccess);
67 CPPUNIT_TEST_SUITE_END();
70 void assertColorsAreSimilar(int maxDifference, const std::string& message,
71 const BitmapColor& expected, const BitmapColor& actual)
73 // Check that the two colors match or are reasonably similar.
74 if (expected == actual)
75 return;
76 if (abs(expected.GetRed() - actual.GetRed()) <= maxDifference
77 && abs(expected.GetGreen() - actual.GetGreen()) <= maxDifference
78 && abs(expected.GetBlue() - actual.GetBlue()) <= maxDifference
79 && abs(expected.GetAlpha() - actual.GetAlpha()) <= maxDifference)
81 return;
83 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual);
86 void BitmapTest::testCreation()
89 Bitmap aBmp;
90 Size aSize = aBmp.GetSizePixel();
91 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(0), aSize.Width());
92 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(0), aSize.Height());
93 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
94 CPPUNIT_ASSERT_MESSAGE("Not empty", aBmp.IsEmpty());
95 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16>(0),
96 aBmp.GetBitCount());
97 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(1), aBmp.GetColorCount());
98 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong>(0),
99 aBmp.GetSizeBytes());
103 Bitmap aBmp(Size(10, 10), 1);
104 Size aSize = aBmp.GetSizePixel();
105 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
106 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
107 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
108 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
109 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16>(1),
110 aBmp.GetBitCount());
111 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(2), aBmp.GetColorCount());
112 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong>(12),
113 aBmp.GetSizeBytes());
117 Bitmap aBmp(Size(10, 10), 4);
118 Size aSize = aBmp.GetSizePixel();
119 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
120 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
121 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
122 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
123 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16>(4),
124 aBmp.GetBitCount());
125 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(16), aBmp.GetColorCount());
126 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong>(50),
127 aBmp.GetSizeBytes());
131 Bitmap aBmp(Size(10, 10), 8);
132 Size aSize = aBmp.GetSizePixel();
133 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
134 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
135 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
136 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
137 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16>(8),
138 aBmp.GetBitCount());
139 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(256), aBmp.GetColorCount());
140 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong>(100),
141 aBmp.GetSizeBytes());
145 Bitmap aBmp(Size(10, 10), 24);
146 Size aSize = aBmp.GetSizePixel();
147 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
148 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
149 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
150 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
151 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16>(24),
152 aBmp.GetBitCount());
153 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(16777216),
154 aBmp.GetColorCount());
155 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong>(300),
156 aBmp.GetSizeBytes());
159 // Check backend capabilities and return from the test successfully
160 // if the backend doesn't support 32-bit bitmap
161 auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
162 if (pBackendCapabilities->mbSupportsBitmap32)
164 Bitmap aBmp(Size(10, 10), 32);
165 Size aSize = aBmp.GetSizePixel();
166 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
167 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
168 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
169 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
171 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", sal_uInt16(32), aBmp.GetBitCount());
172 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(4294967296ull),
173 aBmp.GetColorCount());
174 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", sal_uLong(400), aBmp.GetSizeBytes());
178 void BitmapTest::testEmpty()
180 Bitmap aBitmap(Size(10, 10), 8);
181 aBitmap.Erase(COL_LIGHTGRAYBLUE);
183 CPPUNIT_ASSERT(!aBitmap.IsEmpty());
185 aBitmap.SetEmpty();
186 CPPUNIT_ASSERT(aBitmap.IsEmpty());
189 Bitmap createTestBitmap()
191 Bitmap aBmp(Size(4, 4), 24);
192 BitmapWriteAccess aBmpAccess(aBmp);
194 // row 1
195 aBmpAccess.SetPixel(0, 0, BitmapColor(COL_BLACK));
196 aBmpAccess.SetPixel(0, 1, BitmapColor(COL_BLUE));
197 aBmpAccess.SetPixel(0, 2, BitmapColor(COL_GREEN));
198 aBmpAccess.SetPixel(0, 3, BitmapColor(COL_CYAN));
200 // row 2
201 aBmpAccess.SetPixel(1, 0, BitmapColor(COL_RED));
202 aBmpAccess.SetPixel(1, 1, BitmapColor(COL_MAGENTA));
203 aBmpAccess.SetPixel(1, 2, BitmapColor(COL_BROWN));
204 aBmpAccess.SetPixel(1, 3, BitmapColor(COL_GRAY));
206 // row 3
207 aBmpAccess.SetPixel(2, 0, BitmapColor(COL_LIGHTGRAY));
208 aBmpAccess.SetPixel(2, 1, BitmapColor(COL_LIGHTBLUE));
209 aBmpAccess.SetPixel(2, 2, BitmapColor(COL_LIGHTGREEN));
210 aBmpAccess.SetPixel(2, 3, BitmapColor(COL_LIGHTCYAN));
212 // row 4
213 aBmpAccess.SetPixel(3, 0, BitmapColor(COL_LIGHTRED));
214 aBmpAccess.SetPixel(3, 1, BitmapColor(COL_LIGHTMAGENTA));
215 aBmpAccess.SetPixel(3, 2, BitmapColor(COL_YELLOW));
216 aBmpAccess.SetPixel(3, 3, BitmapColor(COL_WHITE));
218 return aBmp;
221 void BitmapTest::testMonochrome()
223 Bitmap aBmp = createTestBitmap();
225 BitmapEx aBmpEx(aBmp);
226 BitmapFilter::Filter(aBmpEx, BitmapMonochromeFilter(63));
227 aBmp = aBmpEx.GetBitmap();
228 BitmapReadAccess aBmpReadAccess(aBmp);
230 CPPUNIT_ASSERT_EQUAL_MESSAGE("Black pixel wrong monochrome value", BitmapColor(COL_BLACK),
231 aBmpReadAccess.GetColor(0, 0));
232 CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue pixel wrong monochrome value", BitmapColor(COL_BLACK),
233 aBmpReadAccess.GetColor(0, 1));
234 CPPUNIT_ASSERT_EQUAL_MESSAGE("Green pixel wrong monochrome value", BitmapColor(COL_WHITE),
235 aBmpReadAccess.GetColor(0, 2));
236 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cyan pixel wrong monochrome value", BitmapColor(COL_WHITE),
237 aBmpReadAccess.GetColor(0, 3));
238 CPPUNIT_ASSERT_EQUAL_MESSAGE("Red pixel wrong monochrome value", BitmapColor(COL_BLACK),
239 aBmpReadAccess.GetColor(1, 0));
240 CPPUNIT_ASSERT_EQUAL_MESSAGE("Magenta pixel wrong monochrome value", BitmapColor(COL_BLACK),
241 aBmpReadAccess.GetColor(1, 1));
242 CPPUNIT_ASSERT_EQUAL_MESSAGE("Brown pixel wrong monochrome value", BitmapColor(COL_WHITE),
243 aBmpReadAccess.GetColor(1, 2));
244 CPPUNIT_ASSERT_EQUAL_MESSAGE("Gray pixel wrong monochrome value", BitmapColor(COL_WHITE),
245 aBmpReadAccess.GetColor(1, 3));
246 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light gray pixel wrong monochrome value", BitmapColor(COL_WHITE),
247 aBmpReadAccess.GetColor(2, 0));
248 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light blue pixel wrong monochrome value", BitmapColor(COL_BLACK),
249 aBmpReadAccess.GetColor(2, 1));
250 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light green pixel wrong monochrome value", BitmapColor(COL_WHITE),
251 aBmpReadAccess.GetColor(2, 2));
252 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light cyan pixel wrong monochrome value", BitmapColor(COL_WHITE),
253 aBmpReadAccess.GetColor(2, 3));
254 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light red pixel wrong monochrome value", BitmapColor(COL_WHITE),
255 aBmpReadAccess.GetColor(3, 0));
256 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light magenta pixel wrong monochrome value",
257 BitmapColor(COL_WHITE), aBmpReadAccess.GetColor(3, 1));
258 CPPUNIT_ASSERT_EQUAL_MESSAGE("Yellow pixel wrong monochrome value", BitmapColor(COL_WHITE),
259 aBmpReadAccess.GetColor(3, 2));
260 CPPUNIT_ASSERT_EQUAL_MESSAGE("White pixel wrong monochrome value", BitmapColor(COL_WHITE),
261 aBmpReadAccess.GetColor(3, 3));
264 void BitmapTest::testN4Greyscale()
266 Bitmap aBmp = createTestBitmap();
267 BitmapPalette aGreyscalePalette = Bitmap::GetGreyPalette(16);
269 aBmp.Convert(BmpConversion::N4BitGreys);
270 BitmapReadAccess aBmpReadAccess(aBmp);
272 CPPUNIT_ASSERT_EQUAL_MESSAGE("Black pixel wrong 8-bit greyscale value", aGreyscalePalette[0],
273 aBmpReadAccess.GetColor(0, 0));
274 CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue pixel wrong 8-bit greyscale value", aGreyscalePalette[0],
275 aBmpReadAccess.GetColor(0, 1));
276 CPPUNIT_ASSERT_EQUAL_MESSAGE("Green pixel wrong 8-bit greyscale value", aGreyscalePalette[4],
277 aBmpReadAccess.GetColor(0, 2));
278 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cyan pixel wrong 8-bit greyscale value", aGreyscalePalette[5],
279 aBmpReadAccess.GetColor(0, 3));
280 CPPUNIT_ASSERT_EQUAL_MESSAGE("Red pixel wrong 8-bit greyscale value", aGreyscalePalette[2],
281 aBmpReadAccess.GetColor(1, 0));
282 CPPUNIT_ASSERT_EQUAL_MESSAGE("Magenta pixel wrong 8-bit greyscale value", aGreyscalePalette[3],
283 aBmpReadAccess.GetColor(1, 1));
284 CPPUNIT_ASSERT_EQUAL_MESSAGE("Brown pixel wrong 8-bit greyscale value", aGreyscalePalette[7],
285 aBmpReadAccess.GetColor(1, 2));
286 CPPUNIT_ASSERT_EQUAL_MESSAGE("Gray pixel wrong 8-bit greyscale value", aGreyscalePalette[8],
287 aBmpReadAccess.GetColor(1, 3));
288 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light gray pixel wrong 8-bit greyscale value",
289 aGreyscalePalette[12], aBmpReadAccess.GetColor(2, 0));
290 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light blue pixel wrong 8-bit greyscale value",
291 aGreyscalePalette[1], aBmpReadAccess.GetColor(2, 1));
292 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light green pixel wrong 8-bit greyscale value",
293 aGreyscalePalette[9], aBmpReadAccess.GetColor(2, 2));
294 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light cyan pixel wrong 8-bit greyscale value",
295 aGreyscalePalette[11], aBmpReadAccess.GetColor(2, 3));
296 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light red pixel wrong 8-bit greyscale value",
297 aGreyscalePalette[4], aBmpReadAccess.GetColor(3, 0));
298 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light magenta pixel wrong 8-bit greyscale value",
299 aGreyscalePalette[6], aBmpReadAccess.GetColor(3, 1));
300 CPPUNIT_ASSERT_EQUAL_MESSAGE("Yellow pixel wrong 8-bit greyscale value", aGreyscalePalette[14],
301 aBmpReadAccess.GetColor(3, 2));
302 CPPUNIT_ASSERT_EQUAL_MESSAGE("White pixel wrong 8-bit greyscale value", aGreyscalePalette[15],
303 aBmpReadAccess.GetColor(3, 3));
306 void BitmapTest::testN8Greyscale()
308 Bitmap aBmp = createTestBitmap();
309 BitmapPalette aGreyscalePalette = Bitmap::GetGreyPalette(256);
311 aBmp.Convert(BmpConversion::N8BitGreys);
312 BitmapReadAccess aBmpReadAccess(aBmp);
314 assertColorsAreSimilar(1, "Black pixel wrong 8-bit greyscale value", aGreyscalePalette[0],
315 aBmpReadAccess.GetColor(0, 0));
316 assertColorsAreSimilar(1, "Blue pixel wrong 8-bit greyscale value", aGreyscalePalette[14],
317 aBmpReadAccess.GetColor(0, 1));
318 assertColorsAreSimilar(1, "Green pixel wrong 8-bit greyscale value", aGreyscalePalette[75],
319 aBmpReadAccess.GetColor(0, 2));
320 assertColorsAreSimilar(1, "Cyan pixel wrong 8-bit greyscale value", aGreyscalePalette[89],
321 aBmpReadAccess.GetColor(0, 3));
322 assertColorsAreSimilar(1, "Red pixel wrong 8-bit greyscale value", aGreyscalePalette[38],
323 aBmpReadAccess.GetColor(1, 0));
324 assertColorsAreSimilar(1, "Magenta pixel wrong 8-bit greyscale value", aGreyscalePalette[52],
325 aBmpReadAccess.GetColor(1, 1));
326 assertColorsAreSimilar(1, "Brown pixel wrong 8-bit greyscale value", aGreyscalePalette[114],
327 aBmpReadAccess.GetColor(1, 2));
328 assertColorsAreSimilar(1, "Gray pixel wrong 8-bit greyscale value", aGreyscalePalette[128],
329 aBmpReadAccess.GetColor(1, 3));
330 assertColorsAreSimilar(1, "Light gray pixel wrong 8-bit greyscale value",
331 aGreyscalePalette[192], aBmpReadAccess.GetColor(2, 0));
332 assertColorsAreSimilar(1, "Light blue pixel wrong 8-bit greyscale value", aGreyscalePalette[27],
333 aBmpReadAccess.GetColor(2, 1));
334 assertColorsAreSimilar(1, "Light green pixel wrong 8-bit greyscale value",
335 aGreyscalePalette[150], aBmpReadAccess.GetColor(2, 2));
336 assertColorsAreSimilar(1, "Light cyan pixel wrong 8-bit greyscale value",
337 aGreyscalePalette[178], aBmpReadAccess.GetColor(2, 3));
338 assertColorsAreSimilar(1, "Light red pixel wrong 8-bit greyscale value", aGreyscalePalette[76],
339 aBmpReadAccess.GetColor(3, 0));
340 assertColorsAreSimilar(1, "Light magenta pixel wrong 8-bit greyscale value",
341 aGreyscalePalette[104], aBmpReadAccess.GetColor(3, 1));
342 assertColorsAreSimilar(1, "Yellow pixel wrong 8-bit greyscale value", aGreyscalePalette[227],
343 aBmpReadAccess.GetColor(3, 2));
344 assertColorsAreSimilar(1, "White pixel wrong 8-bit greyscale value", aGreyscalePalette[255],
345 aBmpReadAccess.GetColor(3, 3));
348 void BitmapTest::testConvert()
350 Bitmap aBitmap(Size(10, 10), 8);
352 aBitmap.Erase(COL_LIGHTGRAYBLUE);
354 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), aBitmap.GetBitCount());
356 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
357 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), pReadAccess->GetBitCount());
358 #if defined MACOSX || defined IOS
359 //it would be nice to find and change the stride for quartz to be the same as everyone else
360 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(10), pReadAccess->GetScanlineSize());
361 #else
362 if (!SkiaHelper::isVCLSkiaEnabled())
363 #if HAVE_FEATURE_OPENGL
364 if (!OpenGLHelper::isVCLOpenGLEnabled())
365 #endif
366 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize());
367 #endif
368 CPPUNIT_ASSERT(pReadAccess->HasPalette());
369 const BitmapColor& rColor = pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(1, 1));
370 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor.GetRed()));
371 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor.GetGreen()));
372 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(rColor.GetBlue()));
375 aBitmap.Convert(BmpConversion::N24Bit);
377 CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), aBitmap.GetBitCount());
379 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
380 // 24 bit Bitmap on SVP backend can now use 24bit RGB everywhere.
381 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(24), pReadAccess->GetBitCount());
383 if (SkiaHelper::isVCLSkiaEnabled()) // aligned to 4 bytes
384 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
385 else
386 #if HAVE_FEATURE_OPENGL
387 if (OpenGLHelper::isVCLOpenGLEnabled())
388 CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess->GetScanlineSize());
389 else
390 #endif
391 #if defined LINUX || defined FREEBSD
393 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
395 #elif defined(_WIN32)
397 // GDI Scanlines padded to DWORD multiples, it seems
398 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
400 #else
402 CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess->GetScanlineSize());
404 #endif
406 CPPUNIT_ASSERT(!pReadAccess->HasPalette());
407 Color aColor = pReadAccess->GetPixel(0, 0);
408 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor.GetRed()));
409 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor.GetGreen()));
410 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(aColor.GetBlue()));
414 typedef std::unordered_map<sal_uInt64, const char*> CRCHash;
416 void checkAndInsert(CRCHash& rHash, sal_uInt64 nCRC, const char* pLocation)
418 auto it = rHash.find(nCRC);
419 if (it != rHash.end())
421 OStringBuffer aBuf("CRC collision between ");
422 aBuf.append(pLocation);
423 aBuf.append(" and ");
424 aBuf.append(it->second);
425 aBuf.append(" hash is 0x");
426 aBuf.append(static_cast<sal_Int64>(nCRC), 16);
427 CPPUNIT_FAIL(aBuf.toString().getStr());
429 rHash[nCRC] = pLocation;
432 void checkAndInsert(CRCHash& rHash, Bitmap const& rBmp, const char* pLocation)
434 checkAndInsert(rHash, rBmp.GetChecksum(), pLocation);
437 Bitmap getAsBitmap(VclPtr<OutputDevice> const& pOut)
439 return pOut->GetBitmap(Point(), pOut->GetOutputSizePixel());
442 void BitmapTest::testCRC()
444 CRCHash aCRCs;
446 Bitmap aBitmap(Size(1023, 759), 24, nullptr);
447 aBitmap.Erase(COL_BLACK);
448 checkAndInsert(aCRCs, aBitmap, "black bitmap");
449 aBitmap.Invert();
450 checkAndInsert(aCRCs, aBitmap, "white bitmap");
452 ScopedVclPtrInstance<VirtualDevice> aVDev;
453 aVDev->SetBackground(Wallpaper(COL_WHITE));
454 aVDev->SetOutputSizePixel(Size(1023, 759));
456 #if 0 // disabled for now - oddly breaks on OS/X - but why ?
457 Bitmap aWhiteCheck = getAsBitmap(aVDev);
458 CPPUNIT_ASSERT(aCRCs.find(aWhiteCheck.GetChecksum()) != aCRCs.end());
459 #endif
461 // a 1x1 black & white checkerboard
462 aVDev->DrawCheckered(Point(), aVDev->GetOutputSizePixel(), 1, Color(0, 0, 1));
463 Bitmap aChecker = getAsBitmap(aVDev);
464 checkAndInsert(aCRCs, aChecker, "checkerboard");
465 aChecker.Invert();
466 checkAndInsert(aCRCs, aChecker, "inverted checkerboard");
469 void BitmapTest::testGreyPalette()
472 BitmapPalette aPalette = Bitmap::GetGreyPalette(2);
473 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(2),
474 aPalette.GetEntryCount());
475 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
476 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(255, 255, 255), aPalette[1]);
480 BitmapPalette aPalette = Bitmap::GetGreyPalette(4);
481 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(4),
482 aPalette.GetEntryCount());
483 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
484 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(85, 85, 85), aPalette[1]);
485 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(170, 170, 170), aPalette[2]);
486 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(255, 255, 255), aPalette[3]);
490 BitmapPalette aPalette = Bitmap::GetGreyPalette(16);
491 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(16),
492 aPalette.GetEntryCount());
493 // this is a *real* specific number of greys, incremented in units of 17 so may
494 // as well test them all...
495 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
496 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(17, 17, 17), aPalette[1]);
497 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(34, 34, 34), aPalette[2]);
498 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(51, 51, 51), aPalette[3]);
499 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 5 wrong", BitmapColor(68, 68, 68), aPalette[4]);
500 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 6 wrong", BitmapColor(85, 85, 85), aPalette[5]);
501 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 7 wrong", BitmapColor(102, 102, 102), aPalette[6]);
502 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 8 wrong", BitmapColor(119, 119, 119), aPalette[7]);
503 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 9 wrong", BitmapColor(136, 136, 136), aPalette[8]);
504 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 10 wrong", BitmapColor(153, 153, 153), aPalette[9]);
505 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 11 wrong", BitmapColor(170, 170, 170), aPalette[10]);
506 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 12 wrong", BitmapColor(187, 187, 187), aPalette[11]);
507 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 13 wrong", BitmapColor(204, 204, 204), aPalette[12]);
508 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 14 wrong", BitmapColor(221, 221, 221), aPalette[13]);
509 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 15 wrong", BitmapColor(238, 238, 238), aPalette[14]);
510 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 16 wrong", BitmapColor(255, 255, 255), aPalette[15]);
514 BitmapPalette aPalette = Bitmap::GetGreyPalette(256);
515 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries",
516 static_cast<sal_uInt16>(256), aPalette.GetEntryCount());
517 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
518 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 127 wrong", BitmapColor(127, 127, 127), aPalette[127]);
519 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 255 wrong", BitmapColor(255, 255, 255), aPalette[255]);
523 void BitmapTest::testCustom8BitPalette()
525 BitmapPalette aCustomPalette;
526 aCustomPalette.SetEntryCount(256);
527 for (sal_uInt16 i = 0; i < 256; i++)
529 aCustomPalette[i] = BitmapColor(sal_uInt8(i), sal_uInt8(0xCC), sal_uInt8(0x22));
531 Bitmap aBitmap(Size(3, 2), 8, &aCustomPalette);
534 BitmapScopedWriteAccess pAccess(aBitmap);
535 pAccess->SetPixelIndex(0, 0, 0);
536 pAccess->SetPixelIndex(0, 1, 1);
537 pAccess->SetPixelIndex(0, 2, 2);
539 pAccess->SetPixelIndex(1, 0, 253);
540 pAccess->SetPixelIndex(1, 1, 254);
541 pAccess->SetPixelIndex(1, 2, 255);
545 Bitmap::ScopedReadAccess pAccess(aBitmap);
546 CPPUNIT_ASSERT_EQUAL(0, int(pAccess->GetPixelIndex(0, 0)));
547 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xCC, 0x22), pAccess->GetColor(0, 0));
549 CPPUNIT_ASSERT_EQUAL(1, int(pAccess->GetPixelIndex(0, 1)));
550 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x01, 0xCC, 0x22), pAccess->GetColor(0, 1));
552 CPPUNIT_ASSERT_EQUAL(2, int(pAccess->GetPixelIndex(0, 2)));
553 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x02, 0xCC, 0x22), pAccess->GetColor(0, 2));
555 CPPUNIT_ASSERT_EQUAL(253, int(pAccess->GetPixelIndex(1, 0)));
556 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFD, 0xCC, 0x22), pAccess->GetColor(1, 0));
558 CPPUNIT_ASSERT_EQUAL(254, int(pAccess->GetPixelIndex(1, 1)));
559 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFE, 0xCC, 0x22), pAccess->GetColor(1, 1));
561 CPPUNIT_ASSERT_EQUAL(255, int(pAccess->GetPixelIndex(1, 2)));
562 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xCC, 0x22), pAccess->GetColor(1, 2));
566 void BitmapTest::testErase()
568 Bitmap aBitmap(Size(3, 3), 24);
570 BitmapScopedWriteAccess pWriteAccess(aBitmap);
571 pWriteAccess->Erase(Color(0x11, 0x22, 0x33));
574 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
575 BitmapColor aColor(pReadAccess->GetPixel(0, 0));
576 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x11, 0x22, 0x33, 0x00), aColor);
580 void BitmapTest::testBitmap32()
582 // Check backend capabilities and return from the test successfully
583 // if the backend doesn't support 32-bit bitmap
584 auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
585 if (!pBackendCapabilities->mbSupportsBitmap32)
586 return;
588 Bitmap aBitmap(Size(3, 3), 32);
590 BitmapScopedWriteAccess pWriteAccess(aBitmap);
591 pWriteAccess->Erase(Color(0xFF, 0x11, 0x22, 0x33));
592 pWriteAccess->SetPixel(1, 1, BitmapColor(0x44, 0xFF, 0xBB, 0x00));
593 pWriteAccess->SetPixel(2, 2, BitmapColor(0x99, 0x77, 0x66, 0x55));
596 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
597 BitmapColor aColor = pReadAccess->GetPixel(0, 0);
598 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0xFF), aColor);
600 aColor = pReadAccess->GetPixel(1, 1);
601 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x44, 0xFF, 0xBB, 0x00), aColor);
603 aColor = pReadAccess->GetPixel(2, 2);
604 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x99, 0x77, 0x66, 0x55), aColor);
608 void BitmapTest::testOctree()
610 Size aSize(1000, 100);
611 Bitmap aBitmap(aSize, 24);
613 BitmapScopedWriteAccess pWriteAccess(aBitmap);
614 for (tools::Long y = 0; y < aSize.Height(); ++y)
616 for (tools::Long x = 0; x < aSize.Width(); ++x)
618 double fPercent = double(x) / double(aSize.Width());
619 pWriteAccess->SetPixel(y, x,
620 BitmapColor(255.0 * fPercent, 64.0 + (128.0 * fPercent),
621 255.0 - 255.0 * fPercent));
627 // Reduce to 1 color
628 Bitmap::ScopedReadAccess pAccess(aBitmap);
629 Octree aOctree(*pAccess, 1);
630 auto aBitmapPalette = aOctree.GetPalette();
631 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), aBitmapPalette.GetEntryCount());
632 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7e, 0x7f, 0x7f), aBitmapPalette[0]);
636 // Reduce to 4 color
637 Bitmap::ScopedReadAccess pAccess(aBitmap);
638 Octree aOctree(*pAccess, 4);
639 auto aBitmapPalette = aOctree.GetPalette();
640 CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), aBitmapPalette.GetEntryCount());
641 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x7f, 0x7f), aBitmapPalette[0]);
642 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x3e, 0x5f, 0xbf), aBitmapPalette[1]);
643 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x80, 0x7f), aBitmapPalette[2]);
644 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xbe, 0x9f, 0x3f), aBitmapPalette[3]);
648 // Reduce to 256 color
649 Bitmap::ScopedReadAccess pAccess(aBitmap);
650 Octree aOctree(*pAccess, 256);
651 auto aBitmapPalette = aOctree.GetPalette();
652 CPPUNIT_ASSERT_EQUAL(sal_uInt16(74), aBitmapPalette.GetEntryCount());
656 void BitmapTest::testEmptyAccess()
658 Bitmap empty;
659 BitmapInfoAccess access(empty);
660 CPPUNIT_ASSERT_EQUAL(tools::Long(0), access.Width());
661 CPPUNIT_ASSERT_EQUAL(tools::Long(0), access.Height());
664 } // namespace
666 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest);
668 CPPUNIT_PLUGIN_IMPLEMENT();
670 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */