Files
libreoffice/vcl/qa/cppunit/GraphicTest.cxx
Luke Deller ef3dabd1f8 Fix IsTransparent() for unloaded graphics
Fix Graphic::IsAlpha() and Graphic::IsTransparent() for unloaded
graphics. This fixes tdf#118036.

GraphicDescriptor::Detect(true) is currently used to read the image size
from the header of images which are not being fully loaded yet.  This
change extends GraphicDescriptor to also report whether the image
supports transparency or alpha, implemented only for PNG format so far.

Change-Id: I1753c0d11491f1dc518e23da8d7b3842945770cb
Reviewed-on: https://gerrit.libreoffice.org/81785
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
2019-10-31 08:51:49 +01:00

204 lines
6.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <vcl/bitmapaccess.hxx>
#include <vcl/graph.hxx>
#include <vcl/graphicfilter.hxx>
#include <tools/stream.hxx>
using namespace css;
namespace
{
class GraphicTest : public CppUnit::TestFixture
{
void testUnloadedGraphic();
void testUnloadedGraphicLoading();
void testUnloadedGraphicWmf();
void testUnloadedGraphicAlpha();
CPPUNIT_TEST_SUITE(GraphicTest);
CPPUNIT_TEST(testUnloadedGraphic);
CPPUNIT_TEST(testUnloadedGraphicLoading);
CPPUNIT_TEST(testUnloadedGraphicWmf);
CPPUNIT_TEST(testUnloadedGraphicAlpha);
CPPUNIT_TEST_SUITE_END();
};
BitmapEx createBitmap(bool alpha = false)
{
Bitmap aBitmap(Size(120, 100), 24);
aBitmap.Erase(COL_LIGHTRED);
aBitmap.SetPrefSize(Size(6000, 5000));
aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
if (alpha)
{
sal_uInt8 uAlphaValue = 0x80;
AlphaMask aAlphaMask(Size(120, 100), &uAlphaValue);
return BitmapEx(aBitmap, aAlphaMask);
}
else
{
return BitmapEx(aBitmap);
}
}
void createBitmapAndExportForType(SvStream& rStream, OUString const& sType, bool alpha)
{
BitmapEx aBitmapEx = createBitmap(alpha);
uno::Sequence<beans::PropertyValue> aFilterData;
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(sType);
rGraphicFilter.ExportGraphic(aBitmapEx, "none", rStream, nFilterFormat, &aFilterData);
rStream.Seek(STREAM_SEEK_TO_BEGIN);
}
Graphic makeUnloadedGraphic(OUString const& sType, bool alpha = false)
{
SvMemoryStream aStream;
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
createBitmapAndExportForType(aStream, sType, alpha);
return rGraphicFilter.ImportUnloadedGraphic(aStream);
}
void GraphicTest::testUnloadedGraphic()
{
// make unloaded test graphic
Graphic aGraphic = makeUnloadedGraphic("png");
Graphic aGraphic2 = aGraphic;
// check available
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
CPPUNIT_ASSERT_EQUAL(false, aGraphic2.isAvailable());
CPPUNIT_ASSERT_EQUAL(true, aGraphic2.makeAvailable());
CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
CPPUNIT_ASSERT_EQUAL(true, aGraphic2.isAvailable());
// check GetSizePixel doesn't load graphic
aGraphic = makeUnloadedGraphic("png");
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
CPPUNIT_ASSERT_EQUAL(120L, aGraphic.GetSizePixel().Width());
CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Height());
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
// check GetPrefSize doesn't load graphic
CPPUNIT_ASSERT_EQUAL(6000L, aGraphic.GetPrefSize().Width());
CPPUNIT_ASSERT_EQUAL(5000L, aGraphic.GetPrefSize().Height());
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
// check GetSizeBytes loads graphic
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
}
void GraphicTest::testUnloadedGraphicLoading()
{
const OUString aFormats[] = { "png", "gif", "jpg" };
for (OUString const& sFormat : aFormats)
{
Graphic aGraphic = makeUnloadedGraphic(sFormat);
// check available
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
CPPUNIT_ASSERT_EQUAL(120L, aGraphic.GetSizePixel().Width());
CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Height());
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
Bitmap aBitmap(aGraphic.GetBitmapEx().GetBitmap());
{
Bitmap::ScopedReadAccess pReadAccess(aBitmap);
for (long y = 0; y < aGraphic.GetSizePixel().Height(); y++)
{
for (long x = 0; x < aGraphic.GetSizePixel().Width(); x++)
{
if (pReadAccess->HasPalette())
{
Color aColor
= pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(y, x));
CPPUNIT_ASSERT_EQUAL(OUString("ff0000"), aColor.AsRGBHexString());
}
else
{
Color aColor = pReadAccess->GetPixel(y, x);
if (sFormat != "jpg")
CPPUNIT_ASSERT_EQUAL(OUString("ff0000"), aColor.AsRGBHexString());
}
}
}
}
}
}
void GraphicTest::testUnloadedGraphicWmf()
{
// Create some in-memory WMF data, set its own preferred size to 99x99.
BitmapEx aBitmapEx = createBitmap();
SvMemoryStream aStream;
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName("wmf");
Graphic aGraphic(aBitmapEx);
aGraphic.SetPrefSize(Size(99, 99));
aGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
rGraphicFilter.ExportGraphic(aGraphic, "none", aStream, nFilterFormat);
aStream.Seek(STREAM_SEEK_TO_BEGIN);
// Now lazy-load this WMF data, with a custom preferred size of 42x42.
Size aMtfSize100(42, 42);
aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
aGraphic.makeAvailable();
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 42x42
// - Actual : 99x99
// i.e. the custom preferred size was lost after lazy-load.
CPPUNIT_ASSERT_EQUAL(Size(42, 42), aGraphic.GetPrefSize());
}
void GraphicTest::testUnloadedGraphicAlpha()
{
// make unloaded test graphic with alpha
Graphic aGraphic = makeUnloadedGraphic("png", true);
CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAlpha());
CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsTransparent());
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
// make unloaded test graphic without alpha
aGraphic = makeUnloadedGraphic("png", false);
CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsAlpha());
CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsTransparent());
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
}
} // namespace
CPPUNIT_TEST_SUITE_REGISTRATION(GraphicTest);
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */