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/.
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>
26 #include <vcl/BitmapMonochromeFilter.hxx>
28 #include <bitmapwriteaccess.hxx>
31 #include <salinst.hxx>
32 #include <bitmap/Octree.hxx>
36 class BitmapTest
: public CppUnit::TestFixture
40 void testMonochrome();
41 void testN4Greyscale();
42 void testN8Greyscale();
45 void testGreyPalette();
46 void testCustom8BitPalette();
51 CPPUNIT_TEST_SUITE(BitmapTest
);
52 CPPUNIT_TEST(testCreation
);
53 CPPUNIT_TEST(testEmpty
);
54 CPPUNIT_TEST(testMonochrome
);
55 CPPUNIT_TEST(testConvert
);
56 CPPUNIT_TEST(testN4Greyscale
);
57 CPPUNIT_TEST(testN8Greyscale
);
58 CPPUNIT_TEST(testCRC
);
59 CPPUNIT_TEST(testGreyPalette
);
60 CPPUNIT_TEST(testCustom8BitPalette
);
61 CPPUNIT_TEST(testErase
);
62 CPPUNIT_TEST(testBitmap32
);
63 CPPUNIT_TEST(testOctree
);
64 CPPUNIT_TEST_SUITE_END();
67 void assertColorsAreSimilar(int maxDifference
, const std::string
& message
,
68 const BitmapColor
& expected
, const BitmapColor
& actual
)
70 // Check that the two colors match or are reasonably similar.
71 if (expected
== actual
)
73 if (abs(expected
.GetRed() - actual
.GetRed()) <= maxDifference
74 && abs(expected
.GetGreen() - actual
.GetGreen()) <= maxDifference
75 && abs(expected
.GetBlue() - actual
.GetBlue()) <= maxDifference
76 && abs(expected
.GetAlpha() - actual
.GetAlpha()) <= maxDifference
)
80 CPPUNIT_ASSERT_EQUAL_MESSAGE(message
, expected
, actual
);
83 void BitmapTest::testCreation()
87 Size aSize
= aBmp
.GetSizePixel();
88 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<long>(0), aSize
.Width());
89 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(0), aSize
.Height());
90 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp
.GetPrefSize());
91 CPPUNIT_ASSERT_MESSAGE("Not empty", aBmp
.IsEmpty());
92 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16
>(0),
94 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(1), aBmp
.GetColorCount());
95 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong
>(0),
100 Bitmap
aBmp(Size(10, 10), 1);
101 Size aSize
= aBmp
.GetSizePixel();
102 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<long>(10), aSize
.Width());
103 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(10), aSize
.Height());
104 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp
.GetPrefSize());
105 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp
.IsEmpty());
106 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16
>(1),
108 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(2), aBmp
.GetColorCount());
109 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong
>(12),
110 aBmp
.GetSizeBytes());
114 Bitmap
aBmp(Size(10, 10), 4);
115 Size aSize
= aBmp
.GetSizePixel();
116 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<long>(10), aSize
.Width());
117 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(10), aSize
.Height());
118 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp
.GetPrefSize());
119 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp
.IsEmpty());
120 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16
>(4),
122 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(16), aBmp
.GetColorCount());
123 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong
>(50),
124 aBmp
.GetSizeBytes());
128 Bitmap
aBmp(Size(10, 10), 8);
129 Size aSize
= aBmp
.GetSizePixel();
130 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<long>(10), aSize
.Width());
131 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(10), aSize
.Height());
132 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp
.GetPrefSize());
133 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp
.IsEmpty());
134 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16
>(8),
136 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(256), aBmp
.GetColorCount());
137 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong
>(100),
138 aBmp
.GetSizeBytes());
142 Bitmap
aBmp(Size(10, 10), 24);
143 Size aSize
= aBmp
.GetSizePixel();
144 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<long>(10), aSize
.Width());
145 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(10), aSize
.Height());
146 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp
.GetPrefSize());
147 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp
.IsEmpty());
148 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16
>(24),
150 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(16777216),
151 aBmp
.GetColorCount());
152 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong
>(300),
153 aBmp
.GetSizeBytes());
156 // Check backend capabilities and return from the test successfully
157 // if the backend doesn't support 32-bit bitmap
158 auto pBackendCapabilities
= ImplGetSVData()->mpDefInst
->GetBackendCapabilities();
159 if (pBackendCapabilities
->mbSupportsBitmap32
)
161 Bitmap
aBmp(Size(10, 10), 32);
162 Size aSize
= aBmp
.GetSizePixel();
163 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<long>(10), aSize
.Width());
164 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(10), aSize
.Height());
165 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp
.GetPrefSize());
166 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp
.IsEmpty());
168 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", sal_uInt16(32), aBmp
.GetBitCount());
169 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(4294967296ull),
170 aBmp
.GetColorCount());
171 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", sal_uLong(400), aBmp
.GetSizeBytes());
175 void BitmapTest::testEmpty()
177 Bitmap
aBitmap(Size(10, 10), 8);
178 aBitmap
.Erase(COL_LIGHTGRAYBLUE
);
180 CPPUNIT_ASSERT(!aBitmap
.IsEmpty());
183 CPPUNIT_ASSERT(aBitmap
.IsEmpty());
186 Bitmap
createTestBitmap()
188 Bitmap
aBmp(Size(4, 4), 24);
189 BitmapWriteAccess
aBmpAccess(aBmp
);
192 aBmpAccess
.SetPixel(0, 0, BitmapColor(COL_BLACK
));
193 aBmpAccess
.SetPixel(0, 1, BitmapColor(COL_BLUE
));
194 aBmpAccess
.SetPixel(0, 2, BitmapColor(COL_GREEN
));
195 aBmpAccess
.SetPixel(0, 3, BitmapColor(COL_CYAN
));
198 aBmpAccess
.SetPixel(1, 0, BitmapColor(COL_RED
));
199 aBmpAccess
.SetPixel(1, 1, BitmapColor(COL_MAGENTA
));
200 aBmpAccess
.SetPixel(1, 2, BitmapColor(COL_BROWN
));
201 aBmpAccess
.SetPixel(1, 3, BitmapColor(COL_GRAY
));
204 aBmpAccess
.SetPixel(2, 0, BitmapColor(COL_LIGHTGRAY
));
205 aBmpAccess
.SetPixel(2, 1, BitmapColor(COL_LIGHTBLUE
));
206 aBmpAccess
.SetPixel(2, 2, BitmapColor(COL_LIGHTGREEN
));
207 aBmpAccess
.SetPixel(2, 3, BitmapColor(COL_LIGHTCYAN
));
210 aBmpAccess
.SetPixel(3, 0, BitmapColor(COL_LIGHTRED
));
211 aBmpAccess
.SetPixel(3, 1, BitmapColor(COL_LIGHTMAGENTA
));
212 aBmpAccess
.SetPixel(3, 2, BitmapColor(COL_YELLOW
));
213 aBmpAccess
.SetPixel(3, 3, BitmapColor(COL_WHITE
));
218 void BitmapTest::testMonochrome()
220 Bitmap aBmp
= createTestBitmap();
222 BitmapEx
aBmpEx(aBmp
);
223 BitmapFilter::Filter(aBmpEx
, BitmapMonochromeFilter(63));
224 aBmp
= aBmpEx
.GetBitmap();
225 BitmapReadAccess
aBmpReadAccess(aBmp
);
227 CPPUNIT_ASSERT_EQUAL_MESSAGE("Black pixel wrong monochrome value", BitmapColor(COL_BLACK
),
228 aBmpReadAccess
.GetColor(0, 0));
229 CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue pixel wrong monochrome value", BitmapColor(COL_BLACK
),
230 aBmpReadAccess
.GetColor(0, 1));
231 CPPUNIT_ASSERT_EQUAL_MESSAGE("Green pixel wrong monochrome value", BitmapColor(COL_WHITE
),
232 aBmpReadAccess
.GetColor(0, 2));
233 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cyan pixel wrong monochrome value", BitmapColor(COL_WHITE
),
234 aBmpReadAccess
.GetColor(0, 3));
235 CPPUNIT_ASSERT_EQUAL_MESSAGE("Red pixel wrong monochrome value", BitmapColor(COL_BLACK
),
236 aBmpReadAccess
.GetColor(1, 0));
237 CPPUNIT_ASSERT_EQUAL_MESSAGE("Magenta pixel wrong monochrome value", BitmapColor(COL_BLACK
),
238 aBmpReadAccess
.GetColor(1, 1));
239 CPPUNIT_ASSERT_EQUAL_MESSAGE("Brown pixel wrong monochrome value", BitmapColor(COL_WHITE
),
240 aBmpReadAccess
.GetColor(1, 2));
241 CPPUNIT_ASSERT_EQUAL_MESSAGE("Gray pixel wrong monochrome value", BitmapColor(COL_WHITE
),
242 aBmpReadAccess
.GetColor(1, 3));
243 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light gray pixel wrong monochrome value", BitmapColor(COL_WHITE
),
244 aBmpReadAccess
.GetColor(2, 0));
245 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light blue pixel wrong monochrome value", BitmapColor(COL_BLACK
),
246 aBmpReadAccess
.GetColor(2, 1));
247 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light green pixel wrong monochrome value", BitmapColor(COL_WHITE
),
248 aBmpReadAccess
.GetColor(2, 2));
249 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light cyan pixel wrong monochrome value", BitmapColor(COL_WHITE
),
250 aBmpReadAccess
.GetColor(2, 3));
251 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light red pixel wrong monochrome value", BitmapColor(COL_WHITE
),
252 aBmpReadAccess
.GetColor(3, 0));
253 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light magenta pixel wrong monochrome value",
254 BitmapColor(COL_WHITE
), aBmpReadAccess
.GetColor(3, 1));
255 CPPUNIT_ASSERT_EQUAL_MESSAGE("Yellow pixel wrong monochrome value", BitmapColor(COL_WHITE
),
256 aBmpReadAccess
.GetColor(3, 2));
257 CPPUNIT_ASSERT_EQUAL_MESSAGE("White pixel wrong monochrome value", BitmapColor(COL_WHITE
),
258 aBmpReadAccess
.GetColor(3, 3));
261 void BitmapTest::testN4Greyscale()
263 Bitmap aBmp
= createTestBitmap();
264 BitmapPalette aGreyscalePalette
= Bitmap::GetGreyPalette(16);
266 aBmp
.Convert(BmpConversion::N4BitGreys
);
267 BitmapReadAccess
aBmpReadAccess(aBmp
);
269 CPPUNIT_ASSERT_EQUAL_MESSAGE("Black pixel wrong 8-bit greyscale value", aGreyscalePalette
[0],
270 aBmpReadAccess
.GetColor(0, 0));
271 CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue pixel wrong 8-bit greyscale value", aGreyscalePalette
[0],
272 aBmpReadAccess
.GetColor(0, 1));
273 CPPUNIT_ASSERT_EQUAL_MESSAGE("Green pixel wrong 8-bit greyscale value", aGreyscalePalette
[4],
274 aBmpReadAccess
.GetColor(0, 2));
275 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cyan pixel wrong 8-bit greyscale value", aGreyscalePalette
[5],
276 aBmpReadAccess
.GetColor(0, 3));
277 CPPUNIT_ASSERT_EQUAL_MESSAGE("Red pixel wrong 8-bit greyscale value", aGreyscalePalette
[2],
278 aBmpReadAccess
.GetColor(1, 0));
279 CPPUNIT_ASSERT_EQUAL_MESSAGE("Magenta pixel wrong 8-bit greyscale value", aGreyscalePalette
[3],
280 aBmpReadAccess
.GetColor(1, 1));
281 CPPUNIT_ASSERT_EQUAL_MESSAGE("Brown pixel wrong 8-bit greyscale value", aGreyscalePalette
[7],
282 aBmpReadAccess
.GetColor(1, 2));
283 CPPUNIT_ASSERT_EQUAL_MESSAGE("Gray pixel wrong 8-bit greyscale value", aGreyscalePalette
[8],
284 aBmpReadAccess
.GetColor(1, 3));
285 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light gray pixel wrong 8-bit greyscale value",
286 aGreyscalePalette
[12], aBmpReadAccess
.GetColor(2, 0));
287 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light blue pixel wrong 8-bit greyscale value",
288 aGreyscalePalette
[1], aBmpReadAccess
.GetColor(2, 1));
289 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light green pixel wrong 8-bit greyscale value",
290 aGreyscalePalette
[9], aBmpReadAccess
.GetColor(2, 2));
291 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light cyan pixel wrong 8-bit greyscale value",
292 aGreyscalePalette
[11], aBmpReadAccess
.GetColor(2, 3));
293 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light red pixel wrong 8-bit greyscale value",
294 aGreyscalePalette
[4], aBmpReadAccess
.GetColor(3, 0));
295 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light magenta pixel wrong 8-bit greyscale value",
296 aGreyscalePalette
[6], aBmpReadAccess
.GetColor(3, 1));
297 CPPUNIT_ASSERT_EQUAL_MESSAGE("Yellow pixel wrong 8-bit greyscale value", aGreyscalePalette
[14],
298 aBmpReadAccess
.GetColor(3, 2));
299 CPPUNIT_ASSERT_EQUAL_MESSAGE("White pixel wrong 8-bit greyscale value", aGreyscalePalette
[15],
300 aBmpReadAccess
.GetColor(3, 3));
303 void BitmapTest::testN8Greyscale()
305 Bitmap aBmp
= createTestBitmap();
306 BitmapPalette aGreyscalePalette
= Bitmap::GetGreyPalette(256);
308 aBmp
.Convert(BmpConversion::N8BitGreys
);
309 BitmapReadAccess
aBmpReadAccess(aBmp
);
311 assertColorsAreSimilar(1, "Black pixel wrong 8-bit greyscale value", aGreyscalePalette
[0],
312 aBmpReadAccess
.GetColor(0, 0));
313 assertColorsAreSimilar(1, "Blue pixel wrong 8-bit greyscale value", aGreyscalePalette
[14],
314 aBmpReadAccess
.GetColor(0, 1));
315 assertColorsAreSimilar(1, "Green pixel wrong 8-bit greyscale value", aGreyscalePalette
[75],
316 aBmpReadAccess
.GetColor(0, 2));
317 assertColorsAreSimilar(1, "Cyan pixel wrong 8-bit greyscale value", aGreyscalePalette
[89],
318 aBmpReadAccess
.GetColor(0, 3));
319 assertColorsAreSimilar(1, "Red pixel wrong 8-bit greyscale value", aGreyscalePalette
[38],
320 aBmpReadAccess
.GetColor(1, 0));
321 assertColorsAreSimilar(1, "Magenta pixel wrong 8-bit greyscale value", aGreyscalePalette
[52],
322 aBmpReadAccess
.GetColor(1, 1));
323 assertColorsAreSimilar(1, "Brown pixel wrong 8-bit greyscale value", aGreyscalePalette
[114],
324 aBmpReadAccess
.GetColor(1, 2));
325 assertColorsAreSimilar(1, "Gray pixel wrong 8-bit greyscale value", aGreyscalePalette
[128],
326 aBmpReadAccess
.GetColor(1, 3));
327 assertColorsAreSimilar(1, "Light gray pixel wrong 8-bit greyscale value",
328 aGreyscalePalette
[192], aBmpReadAccess
.GetColor(2, 0));
329 assertColorsAreSimilar(1, "Light blue pixel wrong 8-bit greyscale value", aGreyscalePalette
[27],
330 aBmpReadAccess
.GetColor(2, 1));
331 assertColorsAreSimilar(1, "Light green pixel wrong 8-bit greyscale value",
332 aGreyscalePalette
[150], aBmpReadAccess
.GetColor(2, 2));
333 assertColorsAreSimilar(1, "Light cyan pixel wrong 8-bit greyscale value",
334 aGreyscalePalette
[178], aBmpReadAccess
.GetColor(2, 3));
335 assertColorsAreSimilar(1, "Light red pixel wrong 8-bit greyscale value", aGreyscalePalette
[76],
336 aBmpReadAccess
.GetColor(3, 0));
337 assertColorsAreSimilar(1, "Light magenta pixel wrong 8-bit greyscale value",
338 aGreyscalePalette
[104], aBmpReadAccess
.GetColor(3, 1));
339 assertColorsAreSimilar(1, "Yellow pixel wrong 8-bit greyscale value", aGreyscalePalette
[227],
340 aBmpReadAccess
.GetColor(3, 2));
341 assertColorsAreSimilar(1, "White pixel wrong 8-bit greyscale value", aGreyscalePalette
[255],
342 aBmpReadAccess
.GetColor(3, 3));
345 void BitmapTest::testConvert()
347 Bitmap
aBitmap(Size(10, 10), 8);
349 aBitmap
.Erase(COL_LIGHTGRAYBLUE
);
351 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(8), aBitmap
.GetBitCount());
353 Bitmap::ScopedReadAccess
pReadAccess(aBitmap
);
354 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(8), pReadAccess
->GetBitCount());
355 #if defined MACOSX || defined IOS
356 //it would be nice to find and change the stride for quartz to be the same as everyone else
357 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(10), pReadAccess
->GetScanlineSize());
359 #if HAVE_FEATURE_OPENGL
360 if (!OpenGLHelper::isVCLOpenGLEnabled())
361 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(12), pReadAccess
->GetScanlineSize());
364 CPPUNIT_ASSERT(pReadAccess
->HasPalette());
365 const BitmapColor
& rColor
= pReadAccess
->GetPaletteColor(pReadAccess
->GetPixelIndex(1, 1));
366 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor
.GetRed()));
367 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor
.GetGreen()));
368 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(rColor
.GetBlue()));
371 aBitmap
.Convert(BmpConversion::N24Bit
);
373 CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), aBitmap
.GetBitCount());
375 Bitmap::ScopedReadAccess
pReadAccess(aBitmap
);
376 // 24 bit Bitmap on SVP backend can now use 24bit RGB everywhere.
377 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(24), pReadAccess
->GetBitCount());
379 #if defined LINUX || defined FREEBSD
380 #if HAVE_FEATURE_OPENGL
381 if (OpenGLHelper::isVCLOpenGLEnabled())
382 CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess
->GetScanlineSize());
385 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess
->GetScanlineSize());
388 if (!OpenGLHelper::isVCLOpenGLEnabled())
390 // GDI Scanlines padded to DWORD multiples, it seems
391 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess
->GetScanlineSize());
396 CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess
->GetScanlineSize());
400 CPPUNIT_ASSERT(!pReadAccess
->HasPalette());
401 Color aColor
= pReadAccess
->GetPixel(0, 0);
402 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor
.GetRed()));
403 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor
.GetGreen()));
404 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(aColor
.GetBlue()));
408 typedef std::unordered_map
<sal_uInt64
, const char*> CRCHash
;
410 void checkAndInsert(CRCHash
& rHash
, sal_uInt64 nCRC
, const char* pLocation
)
412 auto it
= rHash
.find(nCRC
);
413 if (it
!= rHash
.end())
415 OStringBuffer
aBuf("CRC collision between ");
416 aBuf
.append(pLocation
);
417 aBuf
.append(" and ");
418 aBuf
.append(it
->second
);
419 aBuf
.append(" hash is 0x");
420 aBuf
.append(static_cast<sal_Int64
>(nCRC
), 16);
421 CPPUNIT_FAIL(aBuf
.toString().getStr());
423 rHash
[nCRC
] = pLocation
;
426 void checkAndInsert(CRCHash
& rHash
, Bitmap
const& rBmp
, const char* pLocation
)
428 checkAndInsert(rHash
, rBmp
.GetChecksum(), pLocation
);
431 Bitmap
getAsBitmap(VclPtr
<OutputDevice
> const& pOut
)
433 return pOut
->GetBitmap(Point(), pOut
->GetOutputSizePixel());
436 void BitmapTest::testCRC()
440 Bitmap
aBitmap(Size(1023, 759), 24, nullptr);
441 aBitmap
.Erase(COL_BLACK
);
442 checkAndInsert(aCRCs
, aBitmap
, "black bitmap");
444 checkAndInsert(aCRCs
, aBitmap
, "white bitmap");
446 ScopedVclPtrInstance
<VirtualDevice
> aVDev
;
447 aVDev
->SetBackground(Wallpaper(COL_WHITE
));
448 aVDev
->SetOutputSizePixel(Size(1023, 759));
450 #if 0 // disabled for now - oddly breaks on OS/X - but why ?
451 Bitmap aWhiteCheck
= getAsBitmap(aVDev
);
452 CPPUNIT_ASSERT(aCRCs
.find(aWhiteCheck
.GetChecksum()) != aCRCs
.end());
455 // a 1x1 black & white checkerboard
456 aVDev
->DrawCheckered(Point(), aVDev
->GetOutputSizePixel(), 1, Color(0, 0, 1));
457 Bitmap aChecker
= getAsBitmap(aVDev
);
458 checkAndInsert(aCRCs
, aChecker
, "checkerboard");
460 checkAndInsert(aCRCs
, aChecker
, "inverted checkerboard");
463 void BitmapTest::testGreyPalette()
466 BitmapPalette aPalette
= Bitmap::GetGreyPalette(2);
467 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16
>(2),
468 aPalette
.GetEntryCount());
469 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette
[0]);
470 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(255, 255, 255), aPalette
[1]);
474 BitmapPalette aPalette
= Bitmap::GetGreyPalette(4);
475 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16
>(4),
476 aPalette
.GetEntryCount());
477 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette
[0]);
478 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(85, 85, 85), aPalette
[1]);
479 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(170, 170, 170), aPalette
[2]);
480 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(255, 255, 255), aPalette
[3]);
484 BitmapPalette aPalette
= Bitmap::GetGreyPalette(16);
485 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16
>(16),
486 aPalette
.GetEntryCount());
487 // this is a *real* specific number of greys, incremented in units of 17 so may
488 // as well test them all...
489 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette
[0]);
490 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(17, 17, 17), aPalette
[1]);
491 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(34, 34, 34), aPalette
[2]);
492 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(51, 51, 51), aPalette
[3]);
493 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 5 wrong", BitmapColor(68, 68, 68), aPalette
[4]);
494 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 6 wrong", BitmapColor(85, 85, 85), aPalette
[5]);
495 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 7 wrong", BitmapColor(102, 102, 102), aPalette
[6]);
496 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 8 wrong", BitmapColor(119, 119, 119), aPalette
[7]);
497 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 9 wrong", BitmapColor(136, 136, 136), aPalette
[8]);
498 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 10 wrong", BitmapColor(153, 153, 153), aPalette
[9]);
499 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 11 wrong", BitmapColor(170, 170, 170), aPalette
[10]);
500 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 12 wrong", BitmapColor(187, 187, 187), aPalette
[11]);
501 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 13 wrong", BitmapColor(204, 204, 204), aPalette
[12]);
502 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 14 wrong", BitmapColor(221, 221, 221), aPalette
[13]);
503 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 15 wrong", BitmapColor(238, 238, 238), aPalette
[14]);
504 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 16 wrong", BitmapColor(255, 255, 255), aPalette
[15]);
508 BitmapPalette aPalette
= Bitmap::GetGreyPalette(256);
509 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries",
510 static_cast<sal_uInt16
>(256), aPalette
.GetEntryCount());
511 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette
[0]);
512 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 127 wrong", BitmapColor(127, 127, 127), aPalette
[127]);
513 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 255 wrong", BitmapColor(255, 255, 255), aPalette
[255]);
517 void BitmapTest::testCustom8BitPalette()
519 BitmapPalette aCustomPalette
;
520 aCustomPalette
.SetEntryCount(256);
521 for (sal_uInt16 i
= 0; i
< 256; i
++)
523 aCustomPalette
[i
] = BitmapColor(sal_uInt8(i
), sal_uInt8(0xCC), sal_uInt8(0x22));
525 Bitmap
aBitmap(Size(3, 2), 8, &aCustomPalette
);
528 BitmapScopedWriteAccess
pAccess(aBitmap
);
529 pAccess
->SetPixelIndex(0, 0, 0);
530 pAccess
->SetPixelIndex(0, 1, 1);
531 pAccess
->SetPixelIndex(0, 2, 2);
533 pAccess
->SetPixelIndex(1, 0, 253);
534 pAccess
->SetPixelIndex(1, 1, 254);
535 pAccess
->SetPixelIndex(1, 2, 255);
539 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
540 CPPUNIT_ASSERT_EQUAL(0, int(pAccess
->GetPixelIndex(0, 0)));
541 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xCC, 0x22), pAccess
->GetColor(0, 0));
543 CPPUNIT_ASSERT_EQUAL(1, int(pAccess
->GetPixelIndex(0, 1)));
544 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x01, 0xCC, 0x22), pAccess
->GetColor(0, 1));
546 CPPUNIT_ASSERT_EQUAL(2, int(pAccess
->GetPixelIndex(0, 2)));
547 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x02, 0xCC, 0x22), pAccess
->GetColor(0, 2));
549 CPPUNIT_ASSERT_EQUAL(253, int(pAccess
->GetPixelIndex(1, 0)));
550 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFD, 0xCC, 0x22), pAccess
->GetColor(1, 0));
552 CPPUNIT_ASSERT_EQUAL(254, int(pAccess
->GetPixelIndex(1, 1)));
553 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFE, 0xCC, 0x22), pAccess
->GetColor(1, 1));
555 CPPUNIT_ASSERT_EQUAL(255, int(pAccess
->GetPixelIndex(1, 2)));
556 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xCC, 0x22), pAccess
->GetColor(1, 2));
560 void BitmapTest::testErase()
562 Bitmap
aBitmap(Size(3, 3), 24);
564 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
565 pWriteAccess
->Erase(Color(0x11, 0x22, 0x33));
568 Bitmap::ScopedReadAccess
pReadAccess(aBitmap
);
569 BitmapColor
aColor(pReadAccess
->GetPixel(0, 0));
570 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x11, 0x22, 0x33, 0x00), aColor
);
574 void BitmapTest::testBitmap32()
576 // Check backend capabilities and return from the test successfully
577 // if the backend doesn't support 32-bit bitmap
578 auto pBackendCapabilities
= ImplGetSVData()->mpDefInst
->GetBackendCapabilities();
579 if (!pBackendCapabilities
->mbSupportsBitmap32
)
582 Bitmap
aBitmap(Size(3, 3), 32);
584 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
585 pWriteAccess
->Erase(Color(0xFF, 0x11, 0x22, 0x33));
586 pWriteAccess
->SetPixel(1, 1, BitmapColor(0x44, 0xFF, 0xBB, 0x00));
587 pWriteAccess
->SetPixel(2, 2, BitmapColor(0x99, 0x77, 0x66, 0x55));
590 Bitmap::ScopedReadAccess
pReadAccess(aBitmap
);
591 BitmapColor aColor
= pReadAccess
->GetPixel(0, 0);
592 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0xFF), aColor
);
594 aColor
= pReadAccess
->GetPixel(1, 1);
595 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x44, 0xFF, 0xBB, 0x00), aColor
);
597 aColor
= pReadAccess
->GetPixel(2, 2);
598 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x99, 0x77, 0x66, 0x55), aColor
);
602 void BitmapTest::testOctree()
604 Size
aSize(1000, 100);
605 Bitmap
aBitmap(aSize
, 24);
607 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
608 for (long y
= 0; y
< aSize
.Height(); ++y
)
610 for (long x
= 0; x
< aSize
.Width(); ++x
)
612 double fPercent
= double(x
) / double(aSize
.Width());
613 pWriteAccess
->SetPixel(y
, x
,
614 BitmapColor(255.0 * fPercent
, 64.0 + (128.0 * fPercent
),
615 255.0 - 255.0 * fPercent
));
622 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
623 Octree
aOctree(*pAccess
.get(), 1);
624 auto aBitmapPalette
= aOctree
.GetPalette();
625 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), aBitmapPalette
.GetEntryCount());
626 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7e, 0x7f, 0x7f), aBitmapPalette
[0]);
631 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
632 Octree
aOctree(*pAccess
.get(), 4);
633 auto aBitmapPalette
= aOctree
.GetPalette();
634 CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), aBitmapPalette
.GetEntryCount());
635 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x7f, 0x7f), aBitmapPalette
[0]);
636 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x3e, 0x5f, 0xbf), aBitmapPalette
[1]);
637 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x80, 0x7f), aBitmapPalette
[2]);
638 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xbe, 0x9f, 0x3f), aBitmapPalette
[3]);
642 // Reduce to 256 color
643 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
644 Octree
aOctree(*pAccess
.get(), 256);
645 auto aBitmapPalette
= aOctree
.GetPalette();
646 CPPUNIT_ASSERT_EQUAL(sal_uInt16(74), aBitmapPalette
.GetEntryCount());
652 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest
);
654 CPPUNIT_PLUGIN_IMPLEMENT();
656 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */