summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuke Deller <luke@deller.id.au>2019-10-31 01:36:22 +1100
committerMiklos Vajna <vmiklos@collabora.com>2019-10-31 08:51:49 +0100
commitef3dabd1f814d1b005efc5d5144978c1d26a8e73 (patch)
tree12e670ed7d28c2cd054aa3a3af48be42f4df468f /vcl
parent0dd56a4a745266dcf88d43150ef1d798619ab522 (diff)
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>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/qa/cppunit/GraphicTest.cxx55
-rw-r--r--vcl/source/filter/graphicfilter2.cxx72
-rw-r--r--vcl/source/gdi/impgraph.cxx16
3 files changed, 98 insertions, 45 deletions
diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx
index af5985b01f99..56e05c8bf3de 100644
--- a/vcl/qa/cppunit/GraphicTest.cxx
+++ b/vcl/qa/cppunit/GraphicTest.cxx
@@ -28,25 +28,40 @@ 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()
+BitmapEx createBitmap(bool alpha = false)
{
- Bitmap aBitmap(Size(100, 100), 24);
+ Bitmap aBitmap(Size(120, 100), 24);
aBitmap.Erase(COL_LIGHTRED);
- return BitmapEx(aBitmap);
+ 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)
+void createBitmapAndExportForType(SvStream& rStream, OUString const& sType, bool alpha)
{
- BitmapEx aBitmapEx = createBitmap();
+ BitmapEx aBitmapEx = createBitmap(alpha);
uno::Sequence<beans::PropertyValue> aFilterData;
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
@@ -56,11 +71,11 @@ void createBitmapAndExportForType(SvStream& rStream, OUString const& sType)
rStream.Seek(STREAM_SEEK_TO_BEGIN);
}
-Graphic makeUnloadedGraphic(OUString const& sType)
+Graphic makeUnloadedGraphic(OUString const& sType, bool alpha = false)
{
SvMemoryStream aStream;
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
- createBitmapAndExportForType(aStream, sType);
+ createBitmapAndExportForType(aStream, sType, alpha);
return rGraphicFilter.ImportUnloadedGraphic(aStream);
}
@@ -81,10 +96,15 @@ void GraphicTest::testUnloadedGraphic()
// check GetSizePixel doesn't load graphic
aGraphic = makeUnloadedGraphic("png");
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
- CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Width());
+ 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);
@@ -101,7 +121,7 @@ void GraphicTest::testUnloadedGraphicLoading()
// check available
CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
- CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Width());
+ 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);
@@ -157,6 +177,23 @@ void GraphicTest::testUnloadedGraphicWmf()
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);
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
index 03e1ac228067..5640e7c96ed2 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -99,6 +99,8 @@ void GraphicDescriptor::ImpConstruct()
nBitsPerPixel = 0;
nPlanes = 0;
mnNumberOfImageComponents = 0;
+ bIsTransparent = false;
+ bIsAlpha = false;
}
bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
@@ -548,6 +550,11 @@ bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
rStm.ReadUChar( cByte );
nBitsPerPixel = cByte;
+ // Colour type - check whether it supports alpha values
+ sal_uInt8 cColType = 0;
+ rStm.ReadUChar( cColType );
+ bIsAlpha = bIsTransparent = ( cColType == 4 || cColType == 6 );
+
// Planes always 1;
// compression always
nPlanes = 1;
@@ -555,46 +562,53 @@ bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
sal_uInt32 nLen32 = 0;
nTemp32 = 0;
- rStm.SeekRel( 8 );
+ rStm.SeekRel( 7 );
- // read up to the pHYs-Chunk or the start of the image
+ // read up to the start of the image
rStm.ReadUInt32( nLen32 );
rStm.ReadUInt32( nTemp32 );
- while( ( nTemp32 != 0x70485973 ) && ( nTemp32 != 0x49444154 )
- && rStm.good() )
+ while( ( nTemp32 != 0x49444154 ) && rStm.good() )
{
- rStm.SeekRel( 4 + nLen32 );
- rStm.ReadUInt32( nLen32 );
- rStm.ReadUInt32( nTemp32 );
- }
+ if ( nTemp32 == 0x70485973 ) // physical pixel dimensions
+ {
+ sal_uLong nXRes;
+ sal_uLong nYRes;
- if (nTemp32 == 0x70485973 && rStm.good())
- {
- sal_uLong nXRes;
- sal_uLong nYRes;
+ // horizontal resolution
+ nTemp32 = 0;
+ rStm.ReadUInt32( nTemp32 );
+ nXRes = nTemp32;
- // horizontal resolution
- nTemp32 = 0;
- rStm.ReadUInt32( nTemp32 );
- nXRes = nTemp32;
+ // vertical resolution
+ nTemp32 = 0;
+ rStm.ReadUInt32( nTemp32 );
+ nYRes = nTemp32;
- // vertical resolution
- nTemp32 = 0;
- rStm.ReadUInt32( nTemp32 );
- nYRes = nTemp32;
+ // unit
+ cByte = 0;
+ rStm.ReadUChar( cByte );
- // unit
- cByte = 0;
- rStm.ReadUChar( cByte );
+ if ( cByte )
+ {
+ if ( nXRes )
+ aLogSize.setWidth( (aPixSize.Width() * 100000) / nXRes );
- if ( cByte )
- {
- if ( nXRes )
- aLogSize.setWidth( (aPixSize.Width() * 100000) / nXRes );
+ if ( nYRes )
+ aLogSize.setHeight( (aPixSize.Height() * 100000) / nYRes );
+ }
- if ( nYRes )
- aLogSize.setHeight( (aPixSize.Height() * 100000) / nYRes );
+ nLen32 -= 9;
+ }
+ else if ( nTemp32 == 0x74524e53 ) // transparency
+ {
+ bIsTransparent = true;
+ bIsAlpha = ( cColType != 0 && cColType != 2 );
}
+
+ // skip forward to next chunk
+ rStm.SeekRel( 4 + nLen32 );
+ rStm.ReadUInt32( nLen32 );
+ rStm.ReadUInt32( nTemp32 );
}
}
}
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 0a215fede7b0..17c371e6d77f 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -545,10 +545,11 @@ void ImpGraphic::ImplSetPrepared(bool bAnimated, const Size* pSizeHint)
maSwapInfo.maPrefSize = *pSizeHint;
maSwapInfo.maPrefMapMode = MapMode(MapUnit::Map100thMM);
}
- else
+
+ GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+ if (aDescriptor.Detect(true))
{
- GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
- if (aDescriptor.Detect(true))
+ if (!pSizeHint)
{
// If we have logic size, work with that, as later pixel -> logic
// conversion will work with the output device DPI, not the graphic
@@ -564,14 +565,15 @@ void ImpGraphic::ImplSetPrepared(bool bAnimated, const Size* pSizeHint)
maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
}
-
- maSwapInfo.maSizePixel = aDescriptor.GetSizePixel();
}
+
+ maSwapInfo.maSizePixel = aDescriptor.GetSizePixel();
+ maSwapInfo.mbIsTransparent = aDescriptor.IsTransparent();
+ maSwapInfo.mbIsAlpha = aDescriptor.IsAlpha();
}
+
maSwapInfo.mnAnimationLoopCount = 0;
maSwapInfo.mbIsEPS = false;
- maSwapInfo.mbIsTransparent = false;
- maSwapInfo.mbIsAlpha = false;
maSwapInfo.mbIsAnimated = bAnimated;
}