calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / vcl / qa / cppunit / BitmapTest.cxx
blob79f779f2a8092389906d5d568348de6b79ba3d25
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
9 #include <cppunit/TestAssert.h>
10 #include <cppunit/TestFixture.h>
11 #include <cppunit/extensions/HelperMacros.h>
12 #include <cppunit/plugin/TestPlugIn.h>
14 #include <config_features.h>
16 #include <rtl/strbuf.hxx>
18 #include <vcl/BitmapTools.hxx>
19 #include <vcl/bitmap.hxx>
20 #include <vcl/virdev.hxx>
21 #include <vcl/skia/SkiaHelper.hxx>
22 #include <vcl/BitmapMonochromeFilter.hxx>
24 #include <bitmap/BitmapWriteAccess.hxx>
25 #include <bitmap/Octree.hxx>
26 #include <salinst.hxx>
27 #include <svdata.hxx>
29 #include <unordered_map>
31 namespace
33 class BitmapTest : public CppUnit::TestFixture
35 void testCreation();
36 void testEmpty();
37 void testMonochrome();
38 void testN8Greyscale();
39 void testConvert();
40 void testCRC();
41 void testGreyPalette();
42 void testCustom8BitPalette();
43 void testErase();
44 void testBitmap32();
45 void testOctree();
46 void testEmptyAccess();
47 void testDitherSize();
48 void testMirror();
49 void testCrop();
50 void testCroppedDownsampledBitmap();
52 CPPUNIT_TEST_SUITE(BitmapTest);
53 CPPUNIT_TEST(testCreation);
54 CPPUNIT_TEST(testEmpty);
55 CPPUNIT_TEST(testMonochrome);
56 CPPUNIT_TEST(testConvert);
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(testEmptyAccess);
65 CPPUNIT_TEST(testDitherSize);
66 CPPUNIT_TEST(testMirror);
67 CPPUNIT_TEST(testCrop);
68 CPPUNIT_TEST(testCroppedDownsampledBitmap);
69 CPPUNIT_TEST_SUITE_END();
72 void assertColorsAreSimilar(int maxDifference, const std::string& message,
73 const BitmapColor& expected, const BitmapColor& actual)
75 // Check that the two colors match or are reasonably similar.
76 if (expected.GetColorError(actual) <= maxDifference)
77 return;
78 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual);
81 void BitmapTest::testCreation()
84 Bitmap aBmp;
85 Size aSize = aBmp.GetSizePixel();
86 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(0), aSize.Width());
87 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(0), aSize.Height());
88 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
89 CPPUNIT_ASSERT_MESSAGE("Not empty", aBmp.IsEmpty());
90 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::INVALID,
91 aBmp.getPixelFormat());
92 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(0),
93 aBmp.GetSizeBytes());
97 Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N1_BPP);
98 Size aSize = aBmp.GetSizePixel();
99 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
100 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
101 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
102 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
103 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N1_BPP,
104 aBmp.getPixelFormat());
105 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(12),
106 aBmp.GetSizeBytes());
110 Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N8_BPP);
111 Size aSize = aBmp.GetSizePixel();
112 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
113 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
114 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
115 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
116 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N8_BPP,
117 aBmp.getPixelFormat());
118 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(100),
119 aBmp.GetSizeBytes());
123 Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N24_BPP);
124 Size aSize = aBmp.GetSizePixel();
125 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
126 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
127 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
128 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
129 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N24_BPP,
130 aBmp.getPixelFormat());
131 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_Int64>(300),
132 aBmp.GetSizeBytes());
135 // Check backend capabilities and return from the test successfully
136 // if the backend doesn't support 32-bit bitmap
137 if (ImplGetSVData()->mpDefInst->supportsBitmap32())
139 Bitmap aBmp(Size(10, 10), vcl::PixelFormat::N32_BPP);
140 Size aSize = aBmp.GetSizePixel();
141 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong width", static_cast<tools::Long>(10), aSize.Width());
142 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<tools::Long>(10), aSize.Height());
143 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
144 CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
145 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pixel format", vcl::PixelFormat::N32_BPP,
146 aBmp.getPixelFormat());
147 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", sal_Int64(400), aBmp.GetSizeBytes());
151 void BitmapTest::testEmpty()
153 Bitmap aBitmap(Size(10, 10), vcl::PixelFormat::N8_BPP);
154 aBitmap.Erase(COL_LIGHTGRAYBLUE);
156 CPPUNIT_ASSERT(!aBitmap.IsEmpty());
158 aBitmap.SetEmpty();
159 CPPUNIT_ASSERT(aBitmap.IsEmpty());
162 Bitmap createTestBitmap()
164 Bitmap aBmp(Size(4, 4), vcl::PixelFormat::N24_BPP);
165 BitmapWriteAccess aBmpAccess(aBmp);
167 // row 1
168 aBmpAccess.SetPixel(0, 0, BitmapColor(COL_BLACK));
169 aBmpAccess.SetPixel(0, 1, BitmapColor(COL_BLUE));
170 aBmpAccess.SetPixel(0, 2, BitmapColor(COL_GREEN));
171 aBmpAccess.SetPixel(0, 3, BitmapColor(COL_CYAN));
173 // row 2
174 aBmpAccess.SetPixel(1, 0, BitmapColor(COL_RED));
175 aBmpAccess.SetPixel(1, 1, BitmapColor(COL_MAGENTA));
176 aBmpAccess.SetPixel(1, 2, BitmapColor(COL_BROWN));
177 aBmpAccess.SetPixel(1, 3, BitmapColor(COL_GRAY));
179 // row 3
180 aBmpAccess.SetPixel(2, 0, BitmapColor(COL_LIGHTGRAY));
181 aBmpAccess.SetPixel(2, 1, BitmapColor(COL_LIGHTBLUE));
182 aBmpAccess.SetPixel(2, 2, BitmapColor(COL_LIGHTGREEN));
183 aBmpAccess.SetPixel(2, 3, BitmapColor(COL_LIGHTCYAN));
185 // row 4
186 aBmpAccess.SetPixel(3, 0, BitmapColor(COL_LIGHTRED));
187 aBmpAccess.SetPixel(3, 1, BitmapColor(COL_LIGHTMAGENTA));
188 aBmpAccess.SetPixel(3, 2, BitmapColor(COL_YELLOW));
189 aBmpAccess.SetPixel(3, 3, BitmapColor(COL_WHITE));
191 return aBmp;
194 void BitmapTest::testMonochrome()
196 Bitmap aBmp = createTestBitmap();
198 BitmapEx aBmpEx(aBmp);
199 BitmapFilter::Filter(aBmpEx, BitmapMonochromeFilter(63));
200 aBmp = aBmpEx.GetBitmap();
201 BitmapReadAccess aBmpReadAccess(aBmp);
203 CPPUNIT_ASSERT_EQUAL_MESSAGE("Black pixel wrong monochrome value", BitmapColor(COL_BLACK),
204 aBmpReadAccess.GetColor(0, 0));
205 CPPUNIT_ASSERT_EQUAL_MESSAGE("Blue pixel wrong monochrome value", BitmapColor(COL_BLACK),
206 aBmpReadAccess.GetColor(0, 1));
207 CPPUNIT_ASSERT_EQUAL_MESSAGE("Green pixel wrong monochrome value", BitmapColor(COL_WHITE),
208 aBmpReadAccess.GetColor(0, 2));
209 CPPUNIT_ASSERT_EQUAL_MESSAGE("Cyan pixel wrong monochrome value", BitmapColor(COL_WHITE),
210 aBmpReadAccess.GetColor(0, 3));
211 CPPUNIT_ASSERT_EQUAL_MESSAGE("Red pixel wrong monochrome value", BitmapColor(COL_BLACK),
212 aBmpReadAccess.GetColor(1, 0));
213 CPPUNIT_ASSERT_EQUAL_MESSAGE("Magenta pixel wrong monochrome value", BitmapColor(COL_BLACK),
214 aBmpReadAccess.GetColor(1, 1));
215 CPPUNIT_ASSERT_EQUAL_MESSAGE("Brown pixel wrong monochrome value", BitmapColor(COL_WHITE),
216 aBmpReadAccess.GetColor(1, 2));
217 CPPUNIT_ASSERT_EQUAL_MESSAGE("Gray pixel wrong monochrome value", BitmapColor(COL_WHITE),
218 aBmpReadAccess.GetColor(1, 3));
219 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light gray pixel wrong monochrome value", BitmapColor(COL_WHITE),
220 aBmpReadAccess.GetColor(2, 0));
221 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light blue pixel wrong monochrome value", BitmapColor(COL_BLACK),
222 aBmpReadAccess.GetColor(2, 1));
223 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light green pixel wrong monochrome value", BitmapColor(COL_WHITE),
224 aBmpReadAccess.GetColor(2, 2));
225 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light cyan pixel wrong monochrome value", BitmapColor(COL_WHITE),
226 aBmpReadAccess.GetColor(2, 3));
227 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light red pixel wrong monochrome value", BitmapColor(COL_WHITE),
228 aBmpReadAccess.GetColor(3, 0));
229 CPPUNIT_ASSERT_EQUAL_MESSAGE("Light magenta pixel wrong monochrome value",
230 BitmapColor(COL_WHITE), aBmpReadAccess.GetColor(3, 1));
231 CPPUNIT_ASSERT_EQUAL_MESSAGE("Yellow pixel wrong monochrome value", BitmapColor(COL_WHITE),
232 aBmpReadAccess.GetColor(3, 2));
233 CPPUNIT_ASSERT_EQUAL_MESSAGE("White pixel wrong monochrome value", BitmapColor(COL_WHITE),
234 aBmpReadAccess.GetColor(3, 3));
237 void BitmapTest::testN8Greyscale()
239 Bitmap aBmp = createTestBitmap();
240 BitmapPalette aGreyscalePalette = Bitmap::GetGreyPalette(256);
242 aBmp.Convert(BmpConversion::N8BitGreys);
243 BitmapReadAccess aBmpReadAccess(aBmp);
245 assertColorsAreSimilar(1, "Black pixel wrong 8-bit greyscale value", aGreyscalePalette[0],
246 aBmpReadAccess.GetColor(0, 0));
247 assertColorsAreSimilar(1, "Blue pixel wrong 8-bit greyscale value", aGreyscalePalette[14],
248 aBmpReadAccess.GetColor(0, 1));
249 assertColorsAreSimilar(1, "Green pixel wrong 8-bit greyscale value", aGreyscalePalette[75],
250 aBmpReadAccess.GetColor(0, 2));
251 assertColorsAreSimilar(1, "Cyan pixel wrong 8-bit greyscale value", aGreyscalePalette[89],
252 aBmpReadAccess.GetColor(0, 3));
253 assertColorsAreSimilar(1, "Red pixel wrong 8-bit greyscale value", aGreyscalePalette[38],
254 aBmpReadAccess.GetColor(1, 0));
255 assertColorsAreSimilar(1, "Magenta pixel wrong 8-bit greyscale value", aGreyscalePalette[52],
256 aBmpReadAccess.GetColor(1, 1));
257 assertColorsAreSimilar(1, "Brown pixel wrong 8-bit greyscale value", aGreyscalePalette[114],
258 aBmpReadAccess.GetColor(1, 2));
259 assertColorsAreSimilar(1, "Gray pixel wrong 8-bit greyscale value", aGreyscalePalette[128],
260 aBmpReadAccess.GetColor(1, 3));
261 assertColorsAreSimilar(1, "Light gray pixel wrong 8-bit greyscale value",
262 aGreyscalePalette[192], aBmpReadAccess.GetColor(2, 0));
263 assertColorsAreSimilar(1, "Light blue pixel wrong 8-bit greyscale value", aGreyscalePalette[27],
264 aBmpReadAccess.GetColor(2, 1));
265 assertColorsAreSimilar(1, "Light green pixel wrong 8-bit greyscale value",
266 aGreyscalePalette[150], aBmpReadAccess.GetColor(2, 2));
267 assertColorsAreSimilar(1, "Light cyan pixel wrong 8-bit greyscale value",
268 aGreyscalePalette[178], aBmpReadAccess.GetColor(2, 3));
269 assertColorsAreSimilar(1, "Light red pixel wrong 8-bit greyscale value", aGreyscalePalette[76],
270 aBmpReadAccess.GetColor(3, 0));
271 assertColorsAreSimilar(1, "Light magenta pixel wrong 8-bit greyscale value",
272 aGreyscalePalette[104], aBmpReadAccess.GetColor(3, 1));
273 assertColorsAreSimilar(1, "Yellow pixel wrong 8-bit greyscale value", aGreyscalePalette[227],
274 aBmpReadAccess.GetColor(3, 2));
275 assertColorsAreSimilar(1, "White pixel wrong 8-bit greyscale value", aGreyscalePalette[255],
276 aBmpReadAccess.GetColor(3, 3));
279 void BitmapTest::testConvert()
281 Bitmap aBitmap(Size(10, 10), vcl::PixelFormat::N8_BPP);
283 aBitmap.Erase(COL_LIGHTGRAYBLUE);
285 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat());
287 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
288 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), pReadAccess->GetBitCount());
289 #if defined MACOSX || defined IOS
290 if (SkiaHelper::isVCLSkiaEnabled())
291 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize());
292 else
293 //it would be nice to find and change the stride for quartz to be the same as everyone else
294 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(10), pReadAccess->GetScanlineSize());
295 #else
296 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize());
297 #endif
298 CPPUNIT_ASSERT(pReadAccess->HasPalette());
299 const BitmapColor& rColor = pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(1, 1));
300 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor.GetRed()));
301 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor.GetGreen()));
302 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(rColor.GetBlue()));
305 aBitmap.Convert(BmpConversion::N24Bit);
307 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat());
309 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
310 // 24 bit Bitmap on SVP backend can now use 24bit RGB everywhere.
311 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(24), pReadAccess->GetBitCount());
313 if (SkiaHelper::isVCLSkiaEnabled()) // aligned to 4 bytes
314 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
315 else
316 #if defined LINUX || defined FREEBSD
318 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
320 #elif defined(_WIN32)
322 // GDI Scanlines padded to DWORD multiples, it seems
323 CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize());
325 #else
327 CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess->GetScanlineSize());
329 #endif
331 CPPUNIT_ASSERT(!pReadAccess->HasPalette());
332 Color aColor = pReadAccess->GetPixel(0, 0);
333 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor.GetRed()));
334 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor.GetGreen()));
335 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(aColor.GetBlue()));
339 typedef std::unordered_map<sal_uInt64, const char*> CRCHash;
341 void checkAndInsert(CRCHash& rHash, sal_uInt64 nCRC, const char* pLocation)
343 auto it = rHash.find(nCRC);
344 if (it != rHash.end())
346 OStringBuffer aBuf("CRC collision between ");
347 aBuf.append(pLocation);
348 aBuf.append(" and ");
349 aBuf.append(it->second);
350 aBuf.append(" hash is 0x");
351 aBuf.append(static_cast<sal_Int64>(nCRC), 16);
352 CPPUNIT_FAIL(aBuf.toString().getStr());
354 rHash[nCRC] = pLocation;
357 void checkAndInsert(CRCHash& rHash, Bitmap const& rBmp, const char* pLocation)
359 checkAndInsert(rHash, rBmp.GetChecksum(), pLocation);
362 Bitmap getAsBitmap(VclPtr<OutputDevice> const& pOut)
364 return pOut->GetBitmap(Point(), pOut->GetOutputSizePixel());
367 void BitmapTest::testCRC()
369 CRCHash aCRCs;
371 Bitmap aBitmap(Size(1023, 759), vcl::PixelFormat::N24_BPP);
372 aBitmap.Erase(COL_BLACK);
373 checkAndInsert(aCRCs, aBitmap, "black bitmap");
374 aBitmap.Invert();
375 checkAndInsert(aCRCs, aBitmap, "white bitmap");
377 ScopedVclPtrInstance<VirtualDevice> aVDev;
378 aVDev->SetBackground(Wallpaper(COL_WHITE));
379 aVDev->SetOutputSizePixel(Size(1023, 759));
381 #if 0 // disabled for now - oddly breaks on OS/X - but why ?
382 Bitmap aWhiteCheck = getAsBitmap(aVDev);
383 CPPUNIT_ASSERT(aCRCs.find(aWhiteCheck.GetChecksum()) != aCRCs.end());
384 #endif
386 // a 1x1 black & white checkerboard
387 aVDev->DrawCheckered(Point(), aVDev->GetOutputSizePixel(), 1, Color(0, 0, 1));
388 Bitmap aChecker = getAsBitmap(aVDev);
389 checkAndInsert(aCRCs, aChecker, "checkerboard");
390 aChecker.Invert();
391 checkAndInsert(aCRCs, aChecker, "inverted checkerboard");
394 void BitmapTest::testGreyPalette()
397 BitmapPalette aPalette = Bitmap::GetGreyPalette(2);
398 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(2),
399 aPalette.GetEntryCount());
400 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
401 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(255, 255, 255), aPalette[1]);
405 BitmapPalette aPalette = Bitmap::GetGreyPalette(4);
406 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(4),
407 aPalette.GetEntryCount());
408 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
409 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(85, 85, 85), aPalette[1]);
410 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(170, 170, 170), aPalette[2]);
411 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(255, 255, 255), aPalette[3]);
415 BitmapPalette aPalette = Bitmap::GetGreyPalette(16);
416 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries", static_cast<sal_uInt16>(16),
417 aPalette.GetEntryCount());
418 // this is a *real* specific number of greys, incremented in units of 17 so may
419 // as well test them all...
420 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
421 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 2 wrong", BitmapColor(17, 17, 17), aPalette[1]);
422 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 3 wrong", BitmapColor(34, 34, 34), aPalette[2]);
423 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 4 wrong", BitmapColor(51, 51, 51), aPalette[3]);
424 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 5 wrong", BitmapColor(68, 68, 68), aPalette[4]);
425 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 6 wrong", BitmapColor(85, 85, 85), aPalette[5]);
426 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 7 wrong", BitmapColor(102, 102, 102), aPalette[6]);
427 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 8 wrong", BitmapColor(119, 119, 119), aPalette[7]);
428 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 9 wrong", BitmapColor(136, 136, 136), aPalette[8]);
429 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 10 wrong", BitmapColor(153, 153, 153), aPalette[9]);
430 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 11 wrong", BitmapColor(170, 170, 170), aPalette[10]);
431 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 12 wrong", BitmapColor(187, 187, 187), aPalette[11]);
432 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 13 wrong", BitmapColor(204, 204, 204), aPalette[12]);
433 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 14 wrong", BitmapColor(221, 221, 221), aPalette[13]);
434 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 15 wrong", BitmapColor(238, 238, 238), aPalette[14]);
435 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 16 wrong", BitmapColor(255, 255, 255), aPalette[15]);
439 BitmapPalette aPalette = Bitmap::GetGreyPalette(256);
440 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong number of palette entries",
441 static_cast<sal_uInt16>(256), aPalette.GetEntryCount());
442 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 1 wrong", BitmapColor(0, 0, 0), aPalette[0]);
443 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 127 wrong", BitmapColor(127, 127, 127), aPalette[127]);
444 CPPUNIT_ASSERT_EQUAL_MESSAGE("Entry 255 wrong", BitmapColor(255, 255, 255), aPalette[255]);
448 void BitmapTest::testCustom8BitPalette()
450 BitmapPalette aCustomPalette;
451 aCustomPalette.SetEntryCount(256);
452 for (sal_uInt16 i = 0; i < 256; i++)
454 aCustomPalette[i] = BitmapColor(sal_uInt8(i), sal_uInt8(0xCC), sal_uInt8(0x22));
456 Bitmap aBitmap(Size(3, 2), vcl::PixelFormat::N8_BPP, &aCustomPalette);
459 BitmapScopedWriteAccess pAccess(aBitmap);
460 pAccess->SetPixelIndex(0, 0, 0);
461 pAccess->SetPixelIndex(0, 1, 1);
462 pAccess->SetPixelIndex(0, 2, 2);
464 pAccess->SetPixelIndex(1, 0, 253);
465 pAccess->SetPixelIndex(1, 1, 254);
466 pAccess->SetPixelIndex(1, 2, 255);
470 Bitmap::ScopedReadAccess pAccess(aBitmap);
471 CPPUNIT_ASSERT_EQUAL(0, int(pAccess->GetPixelIndex(0, 0)));
472 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xCC, 0x22), pAccess->GetColor(0, 0));
474 CPPUNIT_ASSERT_EQUAL(1, int(pAccess->GetPixelIndex(0, 1)));
475 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x01, 0xCC, 0x22), pAccess->GetColor(0, 1));
477 CPPUNIT_ASSERT_EQUAL(2, int(pAccess->GetPixelIndex(0, 2)));
478 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x02, 0xCC, 0x22), pAccess->GetColor(0, 2));
480 CPPUNIT_ASSERT_EQUAL(253, int(pAccess->GetPixelIndex(1, 0)));
481 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFD, 0xCC, 0x22), pAccess->GetColor(1, 0));
483 CPPUNIT_ASSERT_EQUAL(254, int(pAccess->GetPixelIndex(1, 1)));
484 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFE, 0xCC, 0x22), pAccess->GetColor(1, 1));
486 CPPUNIT_ASSERT_EQUAL(255, int(pAccess->GetPixelIndex(1, 2)));
487 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xCC, 0x22), pAccess->GetColor(1, 2));
491 void BitmapTest::testErase()
493 Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N24_BPP);
495 BitmapScopedWriteAccess pWriteAccess(aBitmap);
496 pWriteAccess->Erase(Color(0x11, 0x22, 0x33));
499 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
500 BitmapColor aColor(pReadAccess->GetPixel(0, 0));
501 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x11, 0x22, 0x33, 0x00), aColor);
505 void BitmapTest::testBitmap32()
507 // Check backend capabilities and return from the test successfully
508 // if the backend doesn't support 32-bit bitmap
509 if (!ImplGetSVData()->mpDefInst->supportsBitmap32())
510 return;
512 Bitmap aBitmap(Size(3, 3), vcl::PixelFormat::N32_BPP);
514 BitmapScopedWriteAccess pWriteAccess(aBitmap);
515 pWriteAccess->Erase(Color(ColorTransparency, 0xFF, 0x11, 0x22, 0x33));
516 pWriteAccess->SetPixel(1, 1, BitmapColor(ColorTransparency, 0x44, 0xFF, 0xBB, 0x00));
517 pWriteAccess->SetPixel(2, 2, BitmapColor(ColorTransparency, 0x99, 0x77, 0x66, 0x55));
520 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
521 BitmapColor aColor = pReadAccess->GetPixel(0, 0);
522 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x00, 0x00, 0x00, 0xFF), aColor);
524 aColor = pReadAccess->GetPixel(1, 1);
525 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x44, 0xFF, 0xBB, 0x00), aColor);
527 aColor = pReadAccess->GetPixel(2, 2);
528 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency, 0x99, 0x77, 0x66, 0x55), aColor);
532 void BitmapTest::testOctree()
534 Size aSize(1000, 100);
535 Bitmap aBitmap(aSize, vcl::PixelFormat::N24_BPP);
537 BitmapScopedWriteAccess pWriteAccess(aBitmap);
538 for (tools::Long y = 0; y < aSize.Height(); ++y)
540 for (tools::Long x = 0; x < aSize.Width(); ++x)
542 double fPercent = double(x) / double(aSize.Width());
543 pWriteAccess->SetPixel(y, x,
544 BitmapColor(255.0 * fPercent, 64.0 + (128.0 * fPercent),
545 255.0 - 255.0 * fPercent));
551 // Reduce to 1 color
552 Bitmap::ScopedReadAccess pAccess(aBitmap);
553 Octree aOctree(*pAccess, 1);
554 auto aBitmapPalette = aOctree.GetPalette();
555 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), aBitmapPalette.GetEntryCount());
556 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7e, 0x7f, 0x7f), aBitmapPalette[0]);
560 // Reduce to 4 color
561 Bitmap::ScopedReadAccess pAccess(aBitmap);
562 Octree aOctree(*pAccess, 4);
563 auto aBitmapPalette = aOctree.GetPalette();
564 CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), aBitmapPalette.GetEntryCount());
565 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x7f, 0x7f), aBitmapPalette[0]);
566 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x3e, 0x5f, 0xbf), aBitmapPalette[1]);
567 CPPUNIT_ASSERT_EQUAL(BitmapColor(0x7f, 0x80, 0x7f), aBitmapPalette[2]);
568 CPPUNIT_ASSERT_EQUAL(BitmapColor(0xbe, 0x9f, 0x3f), aBitmapPalette[3]);
572 // Reduce to 256 color
573 Bitmap::ScopedReadAccess pAccess(aBitmap);
574 Octree aOctree(*pAccess, 256);
575 auto aBitmapPalette = aOctree.GetPalette();
576 CPPUNIT_ASSERT_EQUAL(sal_uInt16(74), aBitmapPalette.GetEntryCount());
580 void BitmapTest::testEmptyAccess()
582 Bitmap empty;
583 BitmapInfoAccess access(empty);
584 CPPUNIT_ASSERT_EQUAL(tools::Long(0), access.Width());
585 CPPUNIT_ASSERT_EQUAL(tools::Long(0), access.Height());
588 void BitmapTest::testDitherSize()
590 // no need to do anything for a 1x1 pixel bitmap
592 Bitmap aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP);
593 CPPUNIT_ASSERT(aBitmap.Dither());
596 // cannot dither a bitmap with a width of 2 or 3 pixels
598 Bitmap aBitmap(Size(2, 4), vcl::PixelFormat::N24_BPP);
599 CPPUNIT_ASSERT(!aBitmap.Dither());
603 Bitmap aBitmap(Size(3, 4), vcl::PixelFormat::N24_BPP);
604 CPPUNIT_ASSERT(!aBitmap.Dither());
607 // cannot dither a bitmap with a height of 2 pixels
609 Bitmap aBitmap(Size(4, 2), vcl::PixelFormat::N24_BPP);
610 CPPUNIT_ASSERT(!aBitmap.Dither());
613 // only dither bitmaps with a width > 3 pixels and height > 2 pixels
615 Bitmap aBitmap(Size(4, 3), vcl::PixelFormat::N24_BPP);
616 CPPUNIT_ASSERT(aBitmap.Dither());
620 void BitmapTest::testMirror()
622 vcl::PixelFormat bppArray[]
623 = { vcl::PixelFormat::N8_BPP, vcl::PixelFormat::N24_BPP, vcl::PixelFormat::N32_BPP };
625 for (vcl::PixelFormat bpp : bppArray)
627 Bitmap bitmap(Size(11, 11), bpp);
629 bitmap.Erase(COL_MAGENTA);
630 BitmapWriteAccess write(bitmap);
631 if (write.HasPalette())
633 // Note that SetPixel() and GetColor() take arguments as Y,X.
634 write.SetPixel(0, 0, BitmapColor(write.GetBestPaletteIndex(COL_BLACK)));
635 write.SetPixel(10, 0, BitmapColor(write.GetBestPaletteIndex(COL_WHITE)));
636 write.SetPixel(0, 10, BitmapColor(write.GetBestPaletteIndex(COL_RED)));
637 write.SetPixel(10, 10, BitmapColor(write.GetBestPaletteIndex(COL_BLUE)));
638 write.SetPixel(5, 0, BitmapColor(write.GetBestPaletteIndex(COL_GREEN)));
639 write.SetPixel(0, 5, BitmapColor(write.GetBestPaletteIndex(COL_YELLOW)));
641 else
643 write.SetPixel(0, 0, COL_BLACK);
644 write.SetPixel(10, 0, COL_WHITE);
645 write.SetPixel(0, 10, COL_RED);
646 write.SetPixel(10, 10, COL_BLUE);
647 write.SetPixel(5, 0, COL_GREEN);
648 write.SetPixel(0, 5, COL_YELLOW);
651 bitmap.Mirror(BmpMirrorFlags::Horizontal);
653 BitmapReadAccess read(bitmap);
654 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), read.GetColor(0, 10));
655 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), read.GetColor(10, 10));
656 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), read.GetColor(0, 0));
657 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLUE), read.GetColor(10, 0));
658 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_GREEN), read.GetColor(5, 10));
659 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_YELLOW), read.GetColor(0, 5));
661 bitmap.Mirror(BmpMirrorFlags::Vertical);
663 BitmapReadAccess read(bitmap);
664 // Now is effectively mirrored in both directions.
665 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), read.GetColor(10, 10));
666 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), read.GetColor(0, 10));
667 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), read.GetColor(10, 0));
668 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLUE), read.GetColor(0, 0));
669 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_GREEN), read.GetColor(5, 10));
670 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_YELLOW), read.GetColor(10, 5));
672 bitmap.Mirror(BmpMirrorFlags::Vertical | BmpMirrorFlags::Horizontal);
674 BitmapReadAccess read(bitmap);
675 // Now is back the original.
676 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK), read.GetColor(0, 0));
677 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), read.GetColor(10, 0));
678 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), read.GetColor(0, 10));
679 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLUE), read.GetColor(10, 10));
680 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_GREEN), read.GetColor(5, 0));
681 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_YELLOW), read.GetColor(0, 5));
686 void BitmapTest::testCroppedDownsampledBitmap()
688 Bitmap aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP);
689 Bitmap aDownsampledBmp(vcl::bitmap::GetDownsampledBitmap(Size(10, 10), Point(20, 20),
690 Size(5, 5), aBitmap, 72, 72));
691 CPPUNIT_ASSERT(aDownsampledBmp.IsEmpty());
694 void BitmapTest::testCrop()
696 Bitmap aBitmap(Bitmap(Size(16, 16), vcl::PixelFormat::N24_BPP));
699 Bitmap aCroppedBmp(aBitmap);
700 CPPUNIT_ASSERT_MESSAGE("Crop was fully outside of bitmap bounds",
701 !aCroppedBmp.Crop(tools::Rectangle(Point(20, 20), Size(5, 5))));
702 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aCroppedBmp.GetSizePixel());
706 Bitmap aCroppedBmp(aBitmap);
707 CPPUNIT_ASSERT_MESSAGE("Crop same size as bitmap",
708 !aCroppedBmp.Crop(tools::Rectangle(Point(0, 0), Size(16, 16))));
709 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aCroppedBmp.GetSizePixel());
713 Bitmap aCroppedBmp(aBitmap);
714 CPPUNIT_ASSERT_MESSAGE("Crop larger than bitmap",
715 !aCroppedBmp.Crop(tools::Rectangle(Point(0, 0), Size(100, 100))));
716 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aCroppedBmp.GetSizePixel());
720 Bitmap aCroppedBmp(aBitmap);
721 CPPUNIT_ASSERT_MESSAGE("Crop partially overcrops bitmap",
722 aCroppedBmp.Crop(tools::Rectangle(Point(10, 10), Size(100, 100))));
723 CPPUNIT_ASSERT_EQUAL(Size(6, 6), aCroppedBmp.GetSizePixel());
727 Bitmap aCroppedBmp(aBitmap);
728 CPPUNIT_ASSERT_MESSAGE("Crop inside bitmap",
729 aCroppedBmp.Crop(tools::Rectangle(Point(5, 5), Size(10, 10))));
730 CPPUNIT_ASSERT_EQUAL(Size(10, 10), aCroppedBmp.GetSizePixel());
733 } // namespace
735 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest);
737 CPPUNIT_PLUGIN_IMPLEMENT();
739 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */