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/bmpacc.hxx>
19 #include <vcl/virdev.hxx>
21 #include <rtl/strbuf.hxx>
22 #include <tools/stream.hxx>
23 #include <vcl/graphicfilter.hxx>
24 #include <vcl/opengl/OpenGLHelper.hxx>
26 #include "BitmapSymmetryCheck.hxx"
31 class BitmapTest
: public CppUnit::TestFixture
37 CPPUNIT_TEST_SUITE(BitmapTest
);
38 CPPUNIT_TEST(testConvert
);
39 CPPUNIT_TEST(testScale
);
40 CPPUNIT_TEST(testCRC
);
41 CPPUNIT_TEST_SUITE_END();
44 void BitmapTest::testConvert()
46 Bitmap
aBitmap(Size(10, 10), 8);
48 aBitmap
.Erase(COL_LIGHTGRAYBLUE
);
50 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(8), aBitmap
.GetBitCount());
52 Bitmap::ScopedReadAccess
pReadAccess(aBitmap
);
53 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(8), pReadAccess
->GetBitCount());
55 if (!OpenGLHelper::isVCLOpenGLEnabled())
57 // GDI Scanlines padded to DWORD multiples, it seems
58 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(12), pReadAccess
->GetScanlineSize());
63 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uLong
>(10), pReadAccess
->GetScanlineSize());
65 CPPUNIT_ASSERT(pReadAccess
->HasPalette());
66 const BitmapColor
& rColor
= pReadAccess
->GetPaletteColor(pReadAccess
->GetPixelIndex(1, 1));
67 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor
.GetRed()));
68 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(rColor
.GetGreen()));
69 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(rColor
.GetBlue()));
72 aBitmap
.Convert(BMP_CONVERSION_24BIT
);
74 CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), aBitmap
.GetBitCount());
76 Bitmap::ScopedReadAccess
pReadAccess(aBitmap
);
78 // 24 bit Bitmap on SVP backend uses 32bit BGRX format
79 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(32), pReadAccess
->GetBitCount());
80 CPPUNIT_ASSERT_EQUAL(sal_uLong(40), pReadAccess
->GetScanlineSize());
82 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(24), pReadAccess
->GetBitCount());
84 if (!OpenGLHelper::isVCLOpenGLEnabled())
86 // GDI Scanlines padded to DWORD multiples, it seems
87 CPPUNIT_ASSERT_EQUAL(sal_uLong(32), pReadAccess
->GetScanlineSize());
92 CPPUNIT_ASSERT_EQUAL(sal_uLong(30), pReadAccess
->GetScanlineSize());
95 CPPUNIT_ASSERT(!pReadAccess
->HasPalette());
96 Color aColor
= pReadAccess
->GetPixel(0, 0);
97 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor
.GetRed()));
98 CPPUNIT_ASSERT_EQUAL(sal_Int32(204), sal_Int32(aColor
.GetGreen()));
99 CPPUNIT_ASSERT_EQUAL(sal_Int32(255), sal_Int32(aColor
.GetBlue()));
103 void BitmapTest::testScale()
105 const bool bExportBitmap(false);
107 Bitmap
aBitmap24Bit(Size(10, 10), 24);
108 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(24), aBitmap24Bit
.GetBitCount());
111 Bitmap::ScopedWriteAccess
aWriteAccess(aBitmap24Bit
);
112 aWriteAccess
->Erase(COL_WHITE
);
113 aWriteAccess
->SetLineColor(COL_BLACK
);
114 aWriteAccess
->DrawRect(Rectangle(1, 1, 8, 8));
115 aWriteAccess
->DrawRect(Rectangle(3, 3, 6, 6));
118 BitmapSymmetryCheck aBitmapSymmetryCheck
;
120 CPPUNIT_ASSERT_EQUAL(static_cast<long>(10), aBitmap24Bit
.GetSizePixel().Width());
121 CPPUNIT_ASSERT_EQUAL(static_cast<long>(10), aBitmap24Bit
.GetSizePixel().Height());
123 // Check symmetry of the bitmap
124 CPPUNIT_ASSERT(aBitmapSymmetryCheck
.check(aBitmap24Bit
));
128 SvFileStream
aStream(OUString("~/scale_before.png"), StreamMode::WRITE
| StreamMode::TRUNC
);
129 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
130 rFilter
.compressAsPNG(aBitmap24Bit
, aStream
, 9);
133 aBitmap24Bit
.Scale(2, 2, BmpScaleFlag::Fast
);
135 CPPUNIT_ASSERT_EQUAL(static_cast<long>(20), aBitmap24Bit
.GetSizePixel().Width());
136 CPPUNIT_ASSERT_EQUAL(static_cast<long>(20), aBitmap24Bit
.GetSizePixel().Height());
138 // After scaling the bitmap should still be symmetrical. This check guarantees that
139 // scaling doesn't misalign the bitmap.
140 CPPUNIT_ASSERT(aBitmapSymmetryCheck
.check(aBitmap24Bit
));
144 SvFileStream
aStream(OUString("~/scale_after.png"), StreamMode::WRITE
| StreamMode::TRUNC
);
145 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
146 rFilter
.compressAsPNG(aBitmap24Bit
, aStream
, 9);
150 typedef std::unordered_map
<sal_uInt64
, const char *> CRCHash
;
152 void checkAndInsert(CRCHash
&rHash
, sal_uInt64 nCRC
, const char *pLocation
)
154 auto it
= rHash
.find(nCRC
);
155 if (it
!= rHash
.end()) {
156 OStringBuffer
aBuf("CRC collision between ");
157 aBuf
.append(pLocation
);
158 aBuf
.append(" and ");
159 aBuf
.append(it
->second
);
160 aBuf
.append(" hash is 0x");
161 aBuf
.append((sal_Int64
)nCRC
, 16);
162 CPPUNIT_FAIL(aBuf
.toString().getStr());
164 rHash
[nCRC
] = pLocation
;
167 void checkAndInsert(CRCHash
&rHash
, Bitmap rBmp
, const char *pLocation
)
169 checkAndInsert(rHash
, rBmp
.GetChecksum(), pLocation
);
172 Bitmap
getAsBitmap(VclPtr
<OutputDevice
> pOut
)
174 return pOut
->GetBitmap(Point(), pOut
->GetOutputSizePixel());
177 void BitmapTest::testCRC()
181 Bitmap
aBitmap(Size(1023,759), 24, 0);
182 aBitmap
.Erase(COL_BLACK
);
183 checkAndInsert(aCRCs
, aBitmap
, "black bitmap");
185 checkAndInsert(aCRCs
, aBitmap
, "white bitmap");
187 ScopedVclPtrInstance
<VirtualDevice
> aVDev
;
188 aVDev
->SetBackground(Wallpaper(COL_WHITE
));
189 aVDev
->SetOutputSizePixel(Size(1023, 759));
191 #if 0 // disabled for now - it breaks on OS/X and Windows
192 Bitmap aWhiteCheck
= getAsBitmap(aVDev
);
193 CPPUNIT_ASSERT(aCRCs
.find(aWhiteCheck
.GetChecksum()) != aCRCs
.end());
196 // a 1x1 black & white checkerboard
197 aVDev
->DrawCheckered(Point(), aVDev
->GetOutputSizePixel(), 1, 1);
198 Bitmap aChecker
= getAsBitmap(aVDev
);
199 checkAndInsert(aCRCs
, aChecker
, "checkerboard");
201 checkAndInsert(aCRCs
, aChecker
, "inverted checkerboard");
206 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest
);
208 CPPUNIT_PLUGIN_IMPLEMENT();
210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */