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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <test/bootstrapfixture.hxx>
25 #include <tools/stream.hxx>
26 #include <vcl/filter/PngImageReader.hxx>
27 #include <vcl/filter/PngImageWriter.hxx>
28 #include <vcl/bitmap/BitmapMonochromeFilter.hxx>
29 #include <vcl/BitmapWriteAccess.hxx>
30 #include <vcl/alpha.hxx>
31 #include <vcl/graphicfilter.hxx>
32 #include <unotools/tempfile.hxx>
46 // Checks that a pngs BitmapEx is the same after reading and
47 // after writing. Takes a vector of function pointers if there's need to test
49 void checkImportExportPng(const OUString
& sFilePath
, const Case
& aCase
)
51 SvFileStream
aFileStream(sFilePath
, StreamMode::READ
);
52 SvMemoryStream aExportStream
;
53 BitmapEx aImportedBitmapEx
;
54 BitmapEx aExportedImportedBitmapEx
;
56 bool bOpenOk
= !aFileStream
.GetError() && aFileStream
.GetBufferSize() > 0;
57 CPPUNIT_ASSERT_MESSAGE(OString("Failed to open file: " + sFilePath
.toUtf8()).getStr(), bOpenOk
);
59 // Read the png from the file
61 vcl::PngImageReader
aPngReader(aFileStream
);
62 bool bReadOk
= aPngReader
.read(aImportedBitmapEx
);
63 CPPUNIT_ASSERT_MESSAGE(OString("Failed to read png from: " + sFilePath
.toUtf8()).getStr(),
65 Bitmap aImportedBitmap
= aImportedBitmapEx
.GetBitmap();
66 BitmapScopedInfoAccess
pAccess(aImportedBitmap
);
67 auto nActualWidth
= aImportedBitmapEx
.GetSizePixel().Width();
68 auto nActualHeight
= aImportedBitmapEx
.GetSizePixel().Height();
69 auto nActualBpp
= vcl::pixelFormatBitCount(aImportedBitmapEx
.GetBitmap().getPixelFormat());
70 auto bActualHasPalette
= pAccess
->HasPalette();
71 auto bActualIsAlpha
= aImportedBitmapEx
.IsAlpha();
72 CPPUNIT_ASSERT_EQUAL_MESSAGE(
73 OString("Width comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
74 aCase
.mnWidth
, nActualWidth
);
75 CPPUNIT_ASSERT_EQUAL_MESSAGE(
76 OString("Height comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
77 aCase
.mnHeight
, nActualHeight
);
78 CPPUNIT_ASSERT_EQUAL_MESSAGE(
79 OString("Bpp comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
80 aCase
.mnBpp
, nActualBpp
);
81 CPPUNIT_ASSERT_EQUAL_MESSAGE(
82 OString("HasPalette comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
83 aCase
.mbHasPalette
, bActualHasPalette
);
84 CPPUNIT_ASSERT_EQUAL_MESSAGE(
85 OString("IsAlpha comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
86 aCase
.mbIsAlpha
, bActualIsAlpha
);
89 // Write the imported png to a stream
91 vcl::PngImageWriter
aPngWriter(aExportStream
);
92 bool bWriteOk
= aPngWriter
.write(aImportedBitmapEx
);
93 CPPUNIT_ASSERT_MESSAGE(OString("Failed to write png: " + sFilePath
.toUtf8()).getStr(),
95 aExportStream
.Seek(0);
98 // Read the png again from the exported stream
100 vcl::PngImageReader
aPngReader(aExportStream
);
101 bool bReadOk
= aPngReader
.read(aExportedImportedBitmapEx
);
102 CPPUNIT_ASSERT_MESSAGE(
103 OString("Failed to read exported png: " + sFilePath
.toUtf8()).getStr(), bReadOk
);
104 Bitmap aExportedImportedBitmap
= aExportedImportedBitmapEx
.GetBitmap();
105 BitmapScopedInfoAccess
pAccess(aExportedImportedBitmap
);
106 auto nActualWidth
= aExportedImportedBitmapEx
.GetSizePixel().Width();
107 auto nActualHeight
= aExportedImportedBitmapEx
.GetSizePixel().Height();
109 = vcl::pixelFormatBitCount(aExportedImportedBitmapEx
.GetBitmap().getPixelFormat());
110 auto bActualHasPalette
= pAccess
->HasPalette();
111 auto bActualIsAlpha
= aExportedImportedBitmapEx
.IsAlpha();
112 CPPUNIT_ASSERT_EQUAL_MESSAGE(
113 OString("Width comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
114 aCase
.mnWidth
, nActualWidth
);
115 CPPUNIT_ASSERT_EQUAL_MESSAGE(
116 OString("Height comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
117 aCase
.mnHeight
, nActualHeight
);
118 CPPUNIT_ASSERT_EQUAL_MESSAGE(
119 OString("Bpp comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
120 aCase
.mnBpp
, nActualBpp
);
121 CPPUNIT_ASSERT_EQUAL_MESSAGE(
122 OString("HasPalette comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
123 aCase
.mbHasPalette
, bActualHasPalette
);
124 CPPUNIT_ASSERT_EQUAL_MESSAGE(
125 OString("IsAlpha comparison failed for exported png:" + sFilePath
.toUtf8()).getStr(),
126 aCase
.mbIsAlpha
, bActualIsAlpha
);
129 // Compare imported and exported BitmapEx
130 // This compares size, inner bitmap and alpha mask
131 bool bIsSame
= (aExportedImportedBitmapEx
== aImportedBitmapEx
);
132 CPPUNIT_ASSERT_MESSAGE(
133 OString("Import->Export png test failed for png: " + sFilePath
.toUtf8()).getStr(), bIsSame
);
136 // Checks that aPngReader.read returns false on corrupted files
137 void checkImportCorruptedPng(const OUString
& sFilePath
)
139 SvFileStream
aFileStream(sFilePath
, StreamMode::READ
);
140 BitmapEx aImportedBitmapEx
;
142 bool bOpenOk
= !aFileStream
.GetError() && aFileStream
.GetBufferSize() > 0;
143 CPPUNIT_ASSERT_MESSAGE(OString("Failed to open file: " + sFilePath
.toUtf8()).getStr(), bOpenOk
);
144 vcl::PngImageReader
aPngReader(aFileStream
);
145 bool bReadOk
= aPngReader
.read(aImportedBitmapEx
);
146 // Make sure this file was not read successfully
147 CPPUNIT_ASSERT_MESSAGE(
148 OString("Corrupted png should not be opened: " + sFilePath
.toUtf8()).getStr(), !bReadOk
);
152 class PngFilterTest
: public test::BootstrapFixture
154 // Should keep the temp files (should be false)
155 static constexpr bool bKeepTemp
= true;
159 OUString
getFullUrl(std::u16string_view sFileName
)
161 return m_directories
.getURLFromSrc(maDataUrl
) + sFileName
;
166 : BootstrapFixture(true, false)
167 , maDataUrl(u
"/vcl/qa/cppunit/png/data/"_ustr
)
174 void testMsGifInPng();
175 void testPngRoundtrip8BitGrey();
176 void testPngRoundtrip24();
177 void testPngRoundtrip24_8();
178 void testPngRoundtrip32();
179 void testPngWrite8BitRGBPalette();
180 void testTdf153180MonochromeFilterPngExport();
183 CPPUNIT_TEST_SUITE(PngFilterTest
);
184 CPPUNIT_TEST(testPng
);
185 CPPUNIT_TEST(testApng
);
186 CPPUNIT_TEST(testPngSuite
);
187 CPPUNIT_TEST(testMsGifInPng
);
188 CPPUNIT_TEST(testPngRoundtrip8BitGrey
);
189 CPPUNIT_TEST(testPngRoundtrip24
);
190 CPPUNIT_TEST(testPngRoundtrip24_8
);
191 CPPUNIT_TEST(testPngRoundtrip32
);
192 CPPUNIT_TEST(testPngWrite8BitRGBPalette
);
193 CPPUNIT_TEST(testDump
);
194 CPPUNIT_TEST(testTdf153180MonochromeFilterPngExport
);
195 CPPUNIT_TEST_SUITE_END();
198 void PngFilterTest::testPng()
200 for (const OUString
& aFileName
: { u
"rect-1bit-pal.png"_ustr
})
202 SvFileStream
aFileStream(getFullUrl(aFileName
), StreamMode::READ
);
204 vcl::PngImageReader
aPngReader(aFileStream
);
206 aPngReader
.read(aBitmapEx
);
208 Bitmap aBitmap
= aBitmapEx
.GetBitmap();
210 BitmapScopedReadAccess
pAccess(aBitmap
);
211 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess
->Width());
212 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess
->Height());
214 if (pAccess
->GetBitCount() == 24 || pAccess
->GetBitCount() == 32)
216 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
217 pAccess
->GetPixel(0, 0));
218 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
219 pAccess
->GetPixel(3, 3));
220 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
221 pAccess
->GetPixel(3, 0));
222 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
223 pAccess
->GetPixel(0, 3));
225 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x00, 0x00),
226 pAccess
->GetPixel(1, 1));
227 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x00, 0x00),
228 pAccess
->GetPixel(1, 2));
229 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x00, 0x00),
230 pAccess
->GetPixel(2, 1));
231 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x00, 0x00),
232 pAccess
->GetPixel(2, 2));
236 CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
241 OUString aFilenames
[] = {
242 u
"color-rect-8bit-RGB.png"_ustr
,
243 u
"color-rect-8bit-RGB-interlaced.png"_ustr
,
244 u
"color-rect-4bit-pal.png"_ustr
,
247 for (const OUString
& aFileName
: aFilenames
)
249 SvFileStream
aFileStream(getFullUrl(aFileName
), StreamMode::READ
);
251 vcl::PngImageReader
aPngReader(aFileStream
);
253 aPngReader
.read(aBitmapEx
);
255 Bitmap aBitmap
= aBitmapEx
.GetBitmap();
257 BitmapScopedReadAccess
pAccess(aBitmap
);
258 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess
->Width());
259 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess
->Height());
260 if (pAccess
->GetBitCount() == 24 || pAccess
->GetBitCount() == 32)
262 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
263 pAccess
->GetPixel(0, 0));
264 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
265 pAccess
->GetPixel(3, 3));
266 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
267 pAccess
->GetPixel(3, 0));
268 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
269 pAccess
->GetPixel(0, 3));
271 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0x00, 0x00, 0x00),
272 pAccess
->GetPixel(1, 1));
273 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0xFF, 0x00, 0x00),
274 pAccess
->GetPixel(1, 2));
275 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0xFF, 0x00),
276 pAccess
->GetPixel(2, 1));
277 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0x00, 0x00),
278 pAccess
->GetPixel(2, 2));
282 CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
286 for (const OUString
& aFileName
: { u
"alpha-rect-8bit-RGBA.png"_ustr
})
288 SvFileStream
aFileStream(getFullUrl(aFileName
), StreamMode::READ
);
290 vcl::PngImageReader
aPngReader(aFileStream
);
292 aPngReader
.read(aBitmapEx
);
294 Bitmap aBitmap
= aBitmapEx
.GetBitmap();
296 BitmapScopedReadAccess
pAccess(aBitmap
);
297 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess
->Width());
298 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAccess
->Height());
300 if (pAccess
->GetBitCount() == 24)
302 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
303 pAccess
->GetPixel(0, 0));
304 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
305 pAccess
->GetPixel(3, 3));
306 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
307 pAccess
->GetPixel(3, 0));
308 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x00),
309 pAccess
->GetPixel(0, 3));
311 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0x00, 0x00, 0x00),
312 pAccess
->GetPixel(1, 1));
313 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0xFF, 0x00, 0x00),
314 pAccess
->GetPixel(1, 2));
315 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0xFF, 0x00),
316 pAccess
->GetPixel(2, 1));
317 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0x00, 0x00),
318 pAccess
->GetPixel(2, 2));
320 AlphaMask aAlpha
= aBitmapEx
.GetAlphaMask();
322 BitmapScopedReadAccess
pAlphaAccess(aAlpha
);
323 CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), pAlphaAccess
->GetBitCount());
324 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAlphaAccess
->Width());
325 CPPUNIT_ASSERT_EQUAL(tools::Long(4), pAlphaAccess
->Height());
327 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x7F, 0x00),
328 pAlphaAccess
->GetPixel(0, 0));
329 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x7F, 0x00),
330 pAlphaAccess
->GetPixel(3, 3));
331 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x7F, 0x00),
332 pAlphaAccess
->GetPixel(3, 0));
333 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x7F, 0x00),
334 pAlphaAccess
->GetPixel(0, 3));
336 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0xBF, 0x00),
337 pAlphaAccess
->GetPixel(1, 1));
338 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x3F, 0x00),
339 pAlphaAccess
->GetPixel(1, 2));
340 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0x3F, 0x00),
341 pAlphaAccess
->GetPixel(2, 1));
342 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0xBF, 0x00),
343 pAlphaAccess
->GetPixel(2, 2));
346 else if (pAccess
->GetBitCount() == 32)
348 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x80),
349 pAccess
->GetPixel(0, 0));
350 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x80),
351 pAccess
->GetPixel(3, 3));
352 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x80),
353 pAccess
->GetPixel(3, 0));
354 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0xFF, 0x80),
355 pAccess
->GetPixel(0, 3));
357 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0x00, 0x00, 0x40),
358 pAccess
->GetPixel(1, 1));
359 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0xFF, 0x00, 0xC0),
360 pAccess
->GetPixel(1, 2));
361 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0x00, 0x00, 0xFF, 0xC0),
362 pAccess
->GetPixel(2, 1));
363 CPPUNIT_ASSERT_EQUAL(BitmapColor(ColorTransparency
, 0xFF, 0xFF, 0x00, 0x40),
364 pAccess
->GetPixel(2, 2));
368 CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
374 void PngFilterTest::testApng()
376 SvFileStream
aFileStream(getFullUrl(u
"apng_simple.apng"), StreamMode::READ
);
377 vcl::PngImageReader
aPngReader(aFileStream
);
379 bool bSuccess
= aPngReader
.read(aGraphic
);
380 CPPUNIT_ASSERT(bSuccess
);
381 CPPUNIT_ASSERT(aGraphic
.IsAnimated());
382 CPPUNIT_ASSERT_EQUAL(size_t(2), aGraphic
.GetAnimation().GetAnimationFrames().size());
384 AnimationFrame aFrame1
= *aGraphic
.GetAnimation().GetAnimationFrames()[0];
385 AnimationFrame aFrame2
= *aGraphic
.GetAnimation().GetAnimationFrames()[1];
387 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, aFrame1
.maBitmapEx
.GetPixelColor(0, 0));
388 CPPUNIT_ASSERT_EQUAL(Color(0x72d1c8), aFrame1
.maBitmapEx
.GetPixelColor(2, 2));
389 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, aFrame2
.maBitmapEx
.GetPixelColor(0, 0));
391 // Roundtrip the APNG
392 SvMemoryStream aOutStream
;
393 vcl::PngImageWriter
aPngWriter(aOutStream
);
394 bSuccess
= aPngWriter
.write(aGraphic
);
395 CPPUNIT_ASSERT(bSuccess
);
397 aOutStream
.Seek(STREAM_SEEK_TO_BEGIN
);
398 vcl::PngImageReader
aPngReader2(aOutStream
);
400 bSuccess
= aPngReader2
.read(aGraphic2
);
401 CPPUNIT_ASSERT(bSuccess
);
402 CPPUNIT_ASSERT(aGraphic2
.IsAnimated());
403 CPPUNIT_ASSERT_EQUAL(size_t(2), aGraphic2
.GetAnimation().GetAnimationFrames().size());
405 AnimationFrame aFrame1Roundtripped
= *aGraphic2
.GetAnimation().GetAnimationFrames()[0];
406 AnimationFrame aFrame2Roundtripped
= *aGraphic2
.GetAnimation().GetAnimationFrames()[1];
408 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, aFrame1Roundtripped
.maBitmapEx
.GetPixelColor(0, 0));
409 CPPUNIT_ASSERT_EQUAL(Color(0x72d1c8), aFrame1Roundtripped
.maBitmapEx
.GetPixelColor(2, 2));
410 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, aFrame2Roundtripped
.maBitmapEx
.GetPixelColor(0, 0));
412 // Make sure the two frames have the same properties
413 CPPUNIT_ASSERT_EQUAL(aFrame1
.maPositionPixel
, aFrame1Roundtripped
.maPositionPixel
);
414 CPPUNIT_ASSERT_EQUAL(aFrame1
.maSizePixel
, aFrame1Roundtripped
.maSizePixel
);
415 CPPUNIT_ASSERT_EQUAL(aFrame1
.mnWait
, aFrame1Roundtripped
.mnWait
);
416 CPPUNIT_ASSERT_EQUAL(aFrame1
.meDisposal
, aFrame1Roundtripped
.meDisposal
);
417 CPPUNIT_ASSERT_EQUAL(aFrame1
.meBlend
, aFrame1Roundtripped
.meBlend
);
419 CPPUNIT_ASSERT_EQUAL(aFrame2
.maPositionPixel
, aFrame2Roundtripped
.maPositionPixel
);
420 CPPUNIT_ASSERT_EQUAL(aFrame2
.maSizePixel
, aFrame2Roundtripped
.maSizePixel
);
421 CPPUNIT_ASSERT_EQUAL(aFrame2
.mnWait
, aFrame2Roundtripped
.mnWait
);
422 CPPUNIT_ASSERT_EQUAL(aFrame2
.meDisposal
, aFrame2Roundtripped
.meDisposal
);
423 CPPUNIT_ASSERT_EQUAL(aFrame2
.meBlend
, aFrame2Roundtripped
.meBlend
);
426 void PngFilterTest::testPngSuite()
428 // Test the PngSuite test files by Willem van Schaik
429 // filename: g04i2c08.png
431 // test feature (in this case gamma) ------+| ||||
432 // parameter of test (here gamma-value) ----+ ||||
433 // interlaced or non-interlaced --------------+|||
434 // color-type (numerical) ---------------------+||
435 // color-type (descriptive) --------------------+|
436 // bit-depth ------------------------------------+
438 // Some notes about the cases:
439 // - RGB palette PNGs get converted to a bitmap with png_set_palette_to_rgb
440 // - Grayscale PNGs with alpha also do with png_set_gray_to_rgb
441 // - Grayscale PNGs without alpha use BitmapEx palette utilities
442 // - 1, 2, 4 bit grayscale w/o alpha gets converted to 8 bit with png_set_expand_gray_1_2_4_to_8
443 // - 16 bit per channel gets converted to 8 bit per channel with png_set_scale_16
444 // - PNGs that are not size related have size 32x32
445 // - Internally BitmapEx is never 32 bpp, instead it's 24 bpp (rgb) and uses an 8 bpp alpha mask
446 std::pair
<std::u16string_view
, Case
> aCases
[] = {
447 // Basic formats, not interlaced
463 } }, // 2 bit grayscale
471 } }, // 4 bit grayscale
479 } }, // 8 bit grayscale
487 } }, // 16 bit grayscale
511 } }, // 1 bit palette
519 } }, // 2 bit palette
527 } }, // 4 bit palette
535 } }, // 8 bit palette
543 } }, // 8 bit grayscale + 8 bit alpha
551 } }, // 16 bit grayscale + 16 bit alpha
568 // Basic formats, interlaced
584 } }, // 2 bit grayscale
592 } }, // 4 bit grayscale
600 } }, // 8 bit grayscale
608 } }, // 16 bit grayscale
632 } }, // 1 bit palette
640 } }, // 2 bit palette
648 } }, // 4 bit palette
656 } }, // 8 bit palette
664 } }, // 8 bit grayscale + 8 bit alpha
672 } }, // 16 bit grayscale + 16 bit alpha
689 // // Odd sizes, not interlaced
834 // // Odd sizes, interlaced
987 } }, // 8 bit grayscale alpha no background chunk, interlaced
995 } }, // 16 bit grayscale alpha no background chunk, interlaced
1003 } }, // 3 * 8 bits rgb color alpha, no background chunk
1011 } }, // 3 * 16 bits rgb color alpha, no background chunk
1019 } }, // 8 bit grayscale alpha, black background chunk
1027 } }, // 16 bit grayscale alpha, gray background chunk
1035 } }, // 3 * 8 bits rgb color alpha, white background chunk
1043 } }, // 3 * 16 bits rgb color alpha, yellow background chunk
1052 } }, // transparent, black background chunk
1060 } }, // transparent, blue background chunk
1068 } }, // transparent, black background chunk
1076 } }, // transparent, green background chunk
1084 } }, // transparent, light-gray background chunk
1092 } }, // transparent, red background chunk
1100 } }, // transparent, white background chunk
1108 } }, // transparent, white background chunk
1116 } }, // transparent, yellow background chunk
1124 } }, // transparent, but no background chunk
1132 } }, // multiple levels of transparency, 3 entries
1141 } }, // grayscale, file-gamma = 0.35
1149 } }, // color, file-gamma = 0.35
1157 } }, // paletted, file-gamma = 0.35
1165 } }, // grayscale, file-gamma = 0.45
1173 } }, // color, file-gamma = 0.45
1181 } }, // paletted, file-gamma = 0.45
1189 } }, // grayscale, file-gamma = 0.55
1197 } }, // color, file-gamma = 0.55
1205 } }, // paletted, file-gamma = 0.55
1213 } }, // grayscale, file-gamma = 0.70
1221 } }, // color, file-gamma = 0.70
1229 } }, // paletted, file-gamma = 0.70
1237 } }, // grayscale, file-gamma = 1.00
1245 } }, // color, file-gamma = 1.00
1253 } }, // paletted, file-gamma = 1.00
1261 } }, // grayscale, file-gamma = 2.50
1269 } }, // color, file-gamma = 2.50
1277 } }, // paletted, file-gamma = 2.50
1286 } }, // grayscale no interlacing, filter-type 0
1294 } }, // color no interlacing, filter-type 0
1302 } }, // grayscale no interlacing, filter-type 1
1310 } }, // color no interlacing, filter-type 1
1318 } }, // grayscale no interlacing, filter-type 2
1326 } }, // color no interlacing, filter-type 2
1334 } }, // grayscale no interlacing, filter-type 3
1342 } }, // color no interlacing, filter-type 3
1350 } }, // grayscale no interlacing, filter-type 4
1358 } }, // color no interlacing, filter-type 4
1366 } }, // grayscale bit-depth 4, filter changing per scanline
1367 // Additional palettes
1375 } }, // six-cube palette-chunk in true-color image
1383 } }, // six-cube palette-chunk in true-color+alpha image
1391 } }, // six-cube suggested palette (1 byte) in grayscale image
1399 } }, // six-cube suggested palette (1 byte) in true-color image
1407 } }, // six-cube suggested palette (2 bytes) in grayscale image
1415 } }, // six-cube suggested palette (2 bytes) in true-color image
1424 } }, // chroma chunk w:0.31270.329 r:0.640.33 g:0.300.60 b:0.15,0.06
1432 } }, // chroma chunk w:0.31270.329 r:0.640.33 g:0.300.60 b:0.15,0.06
1440 } }, // physical pixel dimensions, 8x32 flat pixels
1448 } }, // physical pixel dimensions, 32x8 high pixels
1456 } }, // physical pixel dimensions, 8x8 square pixels
1464 } }, // physical pixel dimensions, 1000 pixels per 1 meter
1472 } }, // histogram 15 colors
1480 } }, // histogram 256 colors
1488 } }, // grayscale modification time, 01-jan-2000 12:34:56
1496 } }, // grayscale modification time, 01-jan-1970 00:00:00
1504 } }, // grayscale modification time, 31-dec-1999 23:59:59
1512 } }, // color, 13 significant bits
1520 } }, // paletted, 3 significant bits
1528 } }, // color, 5 significant bits
1536 } }, // paletted, 5 significant bits
1544 } }, // color, 8 significant bits (reference)
1552 } }, // paletted, 8 significant bits (reference)
1560 } }, // grayscale no textual data
1568 } }, // grayscale with textual data
1576 } }, // grayscale with compressed textual data
1584 } }, // grayscale international UTF-8, english
1592 } }, // grayscale international UTF-8, finnish
1600 } }, // grayscale international UTF-8, greek
1608 } }, // grayscale international UTF-8, hindi
1616 } }, // grayscale international UTF-8, japanese
1624 } }, // chunk with jpeg exif data
1633 } }, // grayscale mother image with 1 idat-chunk
1641 } }, // color mother image with 1 idat-chunk
1649 } }, // grayscale image with 2 idat-chunks
1657 } }, // color image with 2 idat-chunks
1665 } }, // grayscale image with 4 unequal sized idat-chunks
1673 } }, // color image with 4 unequal sized idat-chunks
1681 } }, // grayscale image with all idat-chunks length one
1689 } }, // color image with all idat-chunks length one
1698 } }, // color no interlacing, compression level 0 (none)
1706 } }, // color no interlacing, compression level 3
1714 } }, // color no interlacing, compression level 6 (default)
1722 } }, // color no interlacing, compression level 9 (maximum)
1725 for (const auto & [ aCaseName
, aCase
] : aCases
)
1727 checkImportExportPng(getFullUrl(aCaseName
), aCase
);
1730 OUString aCorruptedFilenames
[] = {
1731 u
"xs1n0g01.png"_ustr
, // signature byte 1 MSBit reset to zero
1732 u
"xs2n0g01.png"_ustr
, // signature byte 2 is a 'Q'
1733 u
"xs4n0g01.png"_ustr
, // signature byte 4 lowercase
1734 u
"xs7n0g01.png"_ustr
, // 7th byte a space instead of control-Z
1735 u
"xcrn0g04.png"_ustr
, // added cr bytes
1736 u
"xlfn0g04.png"_ustr
, // added lf bytes
1737 u
"xhdn0g08.png"_ustr
, // incorrect IHDR checksum
1738 u
"xc1n0g08.png"_ustr
, // color type 1
1739 u
"xc9n2c08.png"_ustr
, // color type 9
1740 u
"xd0n2c08.png"_ustr
, // bit-depth 0
1741 u
"xd3n2c08.png"_ustr
, // bit-depth 3
1742 u
"xd9n2c08.png"_ustr
, // bit-depth 99
1743 u
"xdtn0g01.png"_ustr
, // missing IDAT chunk
1744 u
"xcsn0g01.png"_ustr
, // incorrect IDAT checksum
1747 for (const auto& aFilename
: aCorruptedFilenames
)
1749 checkImportCorruptedPng(getFullUrl(aFilename
));
1753 void PngFilterTest::testMsGifInPng()
1755 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
1758 const OUString
aURL(getFullUrl(u
"ms-gif.png"));
1759 SvFileStream
aFileStream(aURL
, StreamMode::READ
);
1760 ErrCode aResult
= rFilter
.ImportGraphic(aGraphic
, aURL
, aFileStream
);
1761 CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE
, aResult
);
1762 CPPUNIT_ASSERT(aGraphic
.IsGfxLink());
1763 // The image is technically a PNG, but it has an animated Gif as a chunk (Microsoft extension).
1764 CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeGif
, aGraphic
.GetSharedGfxLink()->GetType());
1765 CPPUNIT_ASSERT(aGraphic
.IsAnimated());
1768 // Tests msOG chunk export support
1769 const OUString
aURL(getFullUrl(u
"dummy.gif"));
1770 SvFileStream
aGIFStream(aURL
, StreamMode::READ
);
1771 sal_uInt32 nGIFSize
= aGIFStream
.TellEnd();
1772 const char* const pHeader
= "MSOFFICE9.0";
1773 auto nHeaderSize
= strlen(pHeader
);
1774 uno::Sequence
<sal_Int8
> aGIFSequence(nHeaderSize
+ nGIFSize
);
1775 sal_Int8
* pSequence
= aGIFSequence
.getArray();
1776 for (size_t i
= 0; i
< nHeaderSize
; i
++)
1777 *pSequence
++ = pHeader
[i
];
1778 aGIFStream
.Seek(STREAM_SEEK_TO_BEGIN
);
1779 aGIFStream
.ReadBytes(pSequence
, nGIFSize
);
1780 // Create msOG chunk
1781 beans::PropertyValue aChunkProperty
, aFilterProperty
;
1782 aChunkProperty
.Name
= "msOG";
1783 aChunkProperty
.Value
<<= aGIFSequence
;
1784 uno::Sequence
<beans::PropertyValue
> aAdditionalChunkSequence
{ aChunkProperty
};
1785 aFilterProperty
.Name
= "AdditionalChunks";
1786 aFilterProperty
.Value
<<= aAdditionalChunkSequence
;
1787 uno::Sequence
<beans::PropertyValue
> aPNGParameters
{ aFilterProperty
};
1788 // Export the png with the chunk
1789 utl::TempFileNamed
aTempFile(u
"testPngExportMsGif", true, u
".png");
1791 aTempFile
.EnableKillingFile();
1793 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::WRITE
);
1794 BitmapEx
aDummyBitmap(Size(8, 8), vcl::PixelFormat::N24_BPP
);
1795 vcl::PngImageWriter
aPngWriter(rStream
);
1796 aPngWriter
.setParameters(aPNGParameters
);
1797 bool bWriteSuccess
= aPngWriter
.write(aDummyBitmap
);
1798 CPPUNIT_ASSERT_EQUAL(true, bWriteSuccess
);
1799 aTempFile
.CloseStream();
1802 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::READ
);
1804 // Import the png and check that it is a gif
1806 ErrCode aResult
= rFilter
.ImportGraphic(aGraphic
, aTempFile
.GetURL(), rStream
);
1807 CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE
, aResult
);
1808 CPPUNIT_ASSERT(aGraphic
.IsGfxLink());
1809 CPPUNIT_ASSERT_EQUAL(GfxLinkType::NativeGif
, aGraphic
.GetSharedGfxLink()->GetType());
1810 CPPUNIT_ASSERT(aGraphic
.IsAnimated());
1815 void PngFilterTest::testPngRoundtrip8BitGrey()
1817 utl::TempFileNamed
aTempFile(u
"testPngRoundtrip8BitGrey");
1819 aTempFile
.EnableKillingFile();
1821 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::WRITE
);
1822 Bitmap
aBitmap(Size(16, 16), vcl::PixelFormat::N8_BPP
, &Bitmap::GetGreyPalette(256));
1824 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
1825 pWriteAccess
->Erase(COL_BLACK
);
1826 for (int i
= 0; i
< 8; ++i
)
1828 for (int j
= 0; j
< 8; ++j
)
1830 pWriteAccess
->SetPixel(i
, j
, COL_GRAY
);
1833 for (int i
= 8; i
< 16; ++i
)
1835 for (int j
= 8; j
< 16; ++j
)
1837 pWriteAccess
->SetPixel(i
, j
, COL_LIGHTGRAY
);
1841 BitmapEx
aBitmapEx(aBitmap
);
1843 vcl::PngImageWriter
aPngWriter(rStream
);
1844 CPPUNIT_ASSERT_EQUAL(true, aPngWriter
.write(aBitmapEx
));
1845 aTempFile
.CloseStream();
1848 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::READ
);
1850 vcl::PngImageReader
aPngReader(rStream
);
1852 CPPUNIT_ASSERT_EQUAL(true, aPngReader
.read(aBitmapEx
));
1854 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aBitmapEx
.GetSizePixel());
1856 CPPUNIT_ASSERT_EQUAL(COL_GRAY
, aBitmapEx
.GetPixelColor(0, 0));
1857 CPPUNIT_ASSERT_EQUAL(COL_LIGHTGRAY
, aBitmapEx
.GetPixelColor(15, 15));
1858 CPPUNIT_ASSERT_EQUAL(COL_BLACK
, aBitmapEx
.GetPixelColor(15, 0));
1859 CPPUNIT_ASSERT_EQUAL(COL_BLACK
, aBitmapEx
.GetPixelColor(0, 15));
1863 void PngFilterTest::testPngRoundtrip24()
1865 utl::TempFileNamed
aTempFile(u
"testPngRoundtrip24");
1867 aTempFile
.EnableKillingFile();
1869 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::WRITE
);
1870 Bitmap
aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP
);
1872 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
1873 pWriteAccess
->Erase(COL_BLACK
);
1874 for (int i
= 0; i
< 8; ++i
)
1876 for (int j
= 0; j
< 8; ++j
)
1878 pWriteAccess
->SetPixel(i
, j
, COL_LIGHTRED
);
1881 for (int i
= 8; i
< 16; ++i
)
1883 for (int j
= 8; j
< 16; ++j
)
1885 pWriteAccess
->SetPixel(i
, j
, COL_LIGHTBLUE
);
1889 BitmapEx
aBitmapEx(aBitmap
);
1891 vcl::PngImageWriter
aPngWriter(rStream
);
1892 CPPUNIT_ASSERT_EQUAL(true, aPngWriter
.write(aBitmapEx
));
1895 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::READ
);
1898 vcl::PngImageReader
aPngReader(rStream
);
1900 CPPUNIT_ASSERT_EQUAL(true, aPngReader
.read(aBitmapEx
));
1902 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aBitmapEx
.GetSizePixel());
1904 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, aBitmapEx
.GetPixelColor(0, 0));
1905 CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE
, aBitmapEx
.GetPixelColor(15, 15));
1906 CPPUNIT_ASSERT_EQUAL(COL_BLACK
, aBitmapEx
.GetPixelColor(15, 0));
1907 CPPUNIT_ASSERT_EQUAL(COL_BLACK
, aBitmapEx
.GetPixelColor(0, 15));
1911 void PngFilterTest::testPngRoundtrip24_8()
1913 utl::TempFileNamed
aTempFile(u
"testPngRoundtrip24_8");
1915 aTempFile
.EnableKillingFile();
1917 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::WRITE
);
1918 Bitmap
aBitmap(Size(16, 16), vcl::PixelFormat::N24_BPP
);
1919 AlphaMask
aAlpha(Size(16, 16));
1921 BitmapScopedWriteAccess
pWriteAccessBitmap(aBitmap
);
1922 BitmapScopedWriteAccess
pWriteAccessAlpha(aAlpha
);
1923 pWriteAccessAlpha
->Erase(Color(0xAA, 0xAA, 0xAA));
1924 pWriteAccessBitmap
->Erase(COL_BLACK
);
1925 for (int i
= 0; i
< 8; ++i
)
1927 for (int j
= 0; j
< 8; ++j
)
1929 pWriteAccessBitmap
->SetPixel(i
, j
, COL_LIGHTRED
);
1930 pWriteAccessAlpha
->SetPixel(i
, j
, Color(0xBB, 0xBB, 0xBB));
1933 for (int i
= 8; i
< 16; ++i
)
1935 for (int j
= 8; j
< 16; ++j
)
1937 pWriteAccessBitmap
->SetPixel(i
, j
, COL_LIGHTBLUE
);
1938 pWriteAccessAlpha
->SetPixel(i
, j
, Color(0xCC, 0xCC, 0xCC));
1942 BitmapEx
aBitmapEx(aBitmap
, aAlpha
);
1943 vcl::PngImageWriter
aPngWriter(rStream
);
1944 CPPUNIT_ASSERT_EQUAL(true, aPngWriter
.write(aBitmapEx
));
1947 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::READ
);
1950 vcl::PngImageReader
aPngReader(rStream
);
1952 CPPUNIT_ASSERT_EQUAL(true, aPngReader
.read(aBitmapEx
));
1954 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aBitmapEx
.GetSizePixel());
1956 CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha
, 0xBB, 0xFF, 0x00, 0x00),
1957 aBitmapEx
.GetPixelColor(0, 0));
1958 CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha
, 0xCC, 0x00, 0x00, 0xFF),
1959 aBitmapEx
.GetPixelColor(15, 15));
1960 CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha
, 0xAA, 0x00, 0x00, 0x00),
1961 aBitmapEx
.GetPixelColor(15, 0));
1962 CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha
, 0xAA, 0x00, 0x00, 0x00),
1963 aBitmapEx
.GetPixelColor(0, 15));
1967 void PngFilterTest::testPngRoundtrip32() {}
1969 void PngFilterTest::testPngWrite8BitRGBPalette()
1971 SvMemoryStream aExportStream
;
1972 BitmapPalette aRedPalette
;
1973 aRedPalette
.SetEntryCount(256);
1974 for (sal_uInt16 i
= 0; i
< 256; i
++)
1976 aRedPalette
[i
].SetRed(i
);
1977 aRedPalette
[i
].SetGreen(0);
1978 aRedPalette
[i
].SetBlue(0);
1981 Bitmap
aBitmap(Size(16, 16), vcl::PixelFormat::N8_BPP
, &aRedPalette
);
1983 BitmapScopedWriteAccess
pWriteAccessBitmap(aBitmap
);
1984 for (int i
= 0; i
< 16; i
++)
1986 for (int j
= 0; j
< 16; j
++)
1988 pWriteAccessBitmap
->SetPixelIndex(i
, j
, i
* 16 + j
);
1992 BitmapEx
aBitmapEx(aBitmap
);
1993 vcl::PngImageWriter
aPngWriter(aExportStream
);
1994 CPPUNIT_ASSERT_EQUAL(true, aPngWriter
.write(aBitmapEx
));
1996 aExportStream
.Seek(0);
1998 vcl::PngImageReader
aPngReader(aExportStream
);
2000 CPPUNIT_ASSERT_EQUAL(true, aPngReader
.read(aBitmapEx
));
2002 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aBitmapEx
.GetSizePixel());
2004 for (int i
= 0; i
< 16; i
++)
2006 for (int j
= 0; j
< 16; j
++)
2008 CPPUNIT_ASSERT_EQUAL(aRedPalette
[i
* 16 + j
].GetRGBColor(),
2009 aBitmapEx
.GetPixelColor(j
, i
));
2015 void PngFilterTest::testTdf153180MonochromeFilterPngExport()
2017 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
2019 Graphic aGraphicOriginal
;
2021 // 3 * 16 bits rgb color alpha, no background chunk
2022 const OUString
aURL(getFullUrl(u
"bgan6a16.png"));
2023 SvFileStream
aFileStream(aURL
, StreamMode::READ
);
2024 ErrCode aResult
= rFilter
.ImportGraphic(aGraphicOriginal
, aURL
, aFileStream
);
2025 CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE
, aResult
);
2026 CPPUNIT_ASSERT(aGraphicOriginal
.IsAlpha());
2029 // Apply the monochrome filter to the graphic but keep the alpha.
2030 BitmapEx
aBitmapEx(aGraphicOriginal
.GetBitmapEx());
2031 AlphaMask
aAlphaMask(aBitmapEx
.GetAlphaMask());
2033 BitmapEx
aTmpBmpEx(aBitmapEx
.GetBitmap());
2034 BitmapFilter::Filter(aTmpBmpEx
, BitmapMonochromeFilter
{ sal_uInt8
{ 127 } });
2036 Graphic aGraphicAfterFilter
{ BitmapEx(aTmpBmpEx
.GetBitmap(), aAlphaMask
) };
2037 CPPUNIT_ASSERT(aGraphicAfterFilter
.IsAlpha());
2039 // export the resulting graphic
2040 utl::TempFileNamed
aTempFile(u
"testPngExportTdf153180", true, u
".png");
2042 aTempFile
.EnableKillingFile();
2044 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::WRITE
);
2045 vcl::PngImageWriter
aPngWriter(rStream
);
2046 bool bWriteSuccess
= aPngWriter
.write(aGraphicAfterFilter
.GetBitmapEx());
2047 CPPUNIT_ASSERT_EQUAL(true, bWriteSuccess
);
2048 aTempFile
.CloseStream();
2051 SvStream
& rStream
= *aTempFile
.GetStream(StreamMode::READ
);
2053 // Import the png and check that it still has alpha
2055 ErrCode aResult
= rFilter
.ImportGraphic(aGraphic
, aTempFile
.GetURL(), rStream
);
2056 CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE
, aResult
);
2058 // Without the accompanying patch would fail with:
2060 // -Expression : aGraphic.IsAlpha()
2061 CPPUNIT_ASSERT(aGraphic
.IsAlpha());
2065 void PngFilterTest::testDump()
2067 utl::TempFileNamed aTempFile
;
2068 Bitmap
aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP
);
2070 BitmapScopedWriteAccess
pWriteAccessBitmap(aBitmap
);
2071 pWriteAccessBitmap
->SetPixel(0, 0, BitmapColor());
2073 BitmapEx
aBitmapEx(aBitmap
);
2074 aBitmapEx
.DumpAsPng(aTempFile
.GetURL().toUtf8().getStr());
2075 SvStream
* pStream
= aTempFile
.GetStream(StreamMode::READ
);
2076 CPPUNIT_ASSERT_GREATER(static_cast<sal_uInt64
>(0), pStream
->remainingSize());
2079 CPPUNIT_TEST_SUITE_REGISTRATION(PngFilterTest
);
2081 CPPUNIT_PLUGIN_IMPLEMENT();
2083 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */