diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2016-01-22 11:39:41 +0100 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2016-01-29 12:02:11 +0000 |
commit | 6f12c93703b676b1b3839caaf2c21788e5d68477 (patch) | |
tree | b62b26ed86f6e656ca66d85e828abd2475f03bc0 /vcl/source/filter/wmf/enhwmf.cxx | |
parent | 1d0f08cdf1b9396e97e068f97fd78f31b5906748 (diff) |
tdf#91017 Enhance WMF import of EMR_ALPHABLEND action
The EMR_ALPHABLEND action was added 2012/2013, but missed support for
Bitmaps with Mask/Alpha. Due to that files with WMF containing these
actions may look different from before. Added suport to load contained
Mask/Alpha information in DIBs and the needed additional processing
through the display chain. WMF import is still based on Metafile
creation, when it would be using Primitives more original data could be
preserved.
Change-Id: I577569848cee2528328181fa0c7eb7f87857d094
Reviewed-on: https://gerrit.libreoffice.org/21709
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'vcl/source/filter/wmf/enhwmf.cxx')
-rw-r--r-- | vcl/source/filter/wmf/enhwmf.cxx | 106 |
1 files changed, 89 insertions, 17 deletions
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx index 3becfbe3ed57..f8341e3adecf 100644 --- a/vcl/source/filter/wmf/enhwmf.cxx +++ b/vcl/source/filter/wmf/enhwmf.cxx @@ -23,6 +23,11 @@ #include <vcl/dibtools.hxx> #include <memory> +#ifdef DBG_UTIL +#include <tools/stream.hxx> +#include <vcl/pngwrite.hxx> +#endif + using namespace std; // GDI-Array @@ -1208,43 +1213,110 @@ bool EnhWMFReader::ReadEnhWMF() .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc ).ReadInt32( cxSrc ).ReadInt32( cySrc ) ; sal_uInt32 dwRop = SRCAND|SRCINVERT; - - Bitmap aBitmap; Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) ); if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) ) bStatus = false; else { - sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14; - if ( nSize <= ( nEndPos - nStartPos ) ) + const sal_uInt32 nSourceSize = cbBmiSrc + cbBitsSrc + 14; + if ( nSourceSize <= ( nEndPos - nStartPos ) ) { - char* pBuf = new char[ nSize ]; - SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE ); + // we need to read alpha channel data if AlphaFormat of BLENDFUNCTION is + // AC_SRC_ALPHA (==0x01). To read it, create a temp DIB-File which is ready + // for DIB-5 format + const bool bReadAlpha(0x01 == aFunc.aAlphaFormat); + const sal_uInt32 nDeltaToDIB5HeaderSize(bReadAlpha ? getDIBV5HeaderSize() - cbBmiSrc : 0); + const sal_uInt32 nTargetSize(cbBmiSrc + nDeltaToDIB5HeaderSize + cbBitsSrc + 14); + char* pBuf = new char[ nTargetSize ]; + SvMemoryStream aTmp( pBuf, nTargetSize, StreamMode::READ | StreamMode::WRITE ); + aTmp.ObjectOwnsMemory( true ); + + // write BM-Header (14 bytes) aTmp.WriteUChar( 'B' ) .WriteUChar( 'M' ) .WriteUInt32( cbBitsSrc ) .WriteUInt16( 0 ) .WriteUInt16( 0 ) - .WriteUInt32( cbBmiSrc + 14 ); + .WriteUInt32( cbBmiSrc + nDeltaToDIB5HeaderSize + 14 ); + + // copy DIBInfoHeader from source (cbBmiSrc bytes) pWMF->Seek( nStart + offBmiSrc ); pWMF->Read( pBuf + 14, cbBmiSrc ); + + if(bReadAlpha) + { + // need to add values for all stuff that DIBV5Header is bigger + // than DIBInfoHeader, all values are correctly initialized to zero, + // so we can use memset here + memset(pBuf + cbBmiSrc + 14, 0, nDeltaToDIB5HeaderSize); + } + + // copy bitmap data from source (offBitsSrc bytes) pWMF->Seek( nStart + offBitsSrc ); - pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc ); + pWMF->Read( pBuf + 14 + nDeltaToDIB5HeaderSize + cbBmiSrc, cbBitsSrc ); aTmp.Seek( 0 ); - ReadDIB(aBitmap, aTmp, true); - // test if it is sensible to crop - if ( ( cxSrc > 0 ) && ( cySrc > 0 ) && - ( xSrc >= 0 ) && ( ySrc >= 0 ) && - ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) && - ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) ) + // prepare to read and fill BitmapEx + BitmapEx aBitmapEx; + + if(bReadAlpha) { - Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) ); - aBitmap.Crop( aCropRect ); + Bitmap aBitmap; + AlphaMask aAlpha; + + if(ReadDIBV5(aBitmap, aAlpha, aTmp)) + { + aBitmapEx = BitmapEx(aBitmap, aAlpha); + } + } + else + { + Bitmap aBitmap; + + if(ReadDIB(aBitmap, aTmp, true)) + { + if(0xff != aFunc.aSrcConstantAlpha) + { + // add const alpha channel + aBitmapEx = BitmapEx( + aBitmap, + AlphaMask(aBitmap.GetSizePixel(), &aFunc.aSrcConstantAlpha)); + } + else + { + // just use Bitmap + aBitmapEx = BitmapEx(aBitmap); + } + } + } + + if(!aBitmapEx.IsEmpty()) + { + // test if it is sensible to crop + if ( ( cxSrc > 0 ) && ( cySrc > 0 ) && + ( xSrc >= 0 ) && ( ySrc >= 0 ) && + ( xSrc + cxSrc < aBitmapEx.GetSizePixel().Width() ) && + ( ySrc + cySrc < aBitmapEx.GetSizePixel().Height() ) ) + { + const Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) ); + + aBitmapEx.Crop( aCropRect ); + } + +#ifdef DBG_UTIL + static bool bDoSaveForVisualControl(false); + + if(bDoSaveForVisualControl) + { + SvFileStream aNew(OUString("c:\\metafile_content.png"), StreamMode::WRITE|StreamMode::TRUNC); + vcl::PNGWriter aPNGWriter(aBitmapEx); + aPNGWriter.Write(aNew); + } +#endif + aBmpSaveList.emplace_back(new BSaveStruct(aBitmapEx, aRect, dwRop)); } - aBmpSaveList.emplace_back(new BSaveStruct(aBitmap, aRect, dwRop)); } } } |