use RawBitmap and BitmapEx in icgm filter

Change-Id: Icaffda666c27f733c0d490905e91a68b72073bcb
Reviewed-on: https://gerrit.libreoffice.org/49502
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
This commit is contained in:
Noel Grandin
2018-02-09 16:27:35 +02:00
committed by Michael Meeks
parent fc763bd9b9
commit ac98ff5e86
5 changed files with 201 additions and 200 deletions

View File

@@ -545,7 +545,7 @@ void CGMImpressOutAct::DrawEllipticalArc( FloatPoint const & rCenter, FloatPoint
void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor* pBmpDesc )
{
if ( pBmpDesc->mbStatus && pBmpDesc->mpBitmap )
if ( pBmpDesc->mbStatus && !!pBmpDesc->mxBitmap )
{
FloatPoint aOrigin = pBmpDesc->mnOrigin;
double fdx = pBmpDesc->mndx;
@@ -555,7 +555,7 @@ void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor* pBmpDesc )
if ( pBmpDesc->mbVMirror )
nMirr |= BmpMirrorFlags::Vertical;
if ( nMirr != BmpMirrorFlags::NONE )
pBmpDesc->mpBitmap->Mirror( nMirr );
pBmpDesc->mxBitmap.Mirror( nMirr ); // FIXME
mpCGM->ImplMapPoint( aOrigin );
mpCGM->ImplMapX( fdx );
@@ -571,9 +571,8 @@ void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor* pBmpDesc )
ImplSetOrientation( aOrigin, pBmpDesc->mnOrientation );
}
uno::Reference< awt::XBitmap > xBitmap( VCLUnoHelper::CreateBitmap( BitmapEx( *( pBmpDesc->mpBitmap ) ) ) );
uno::Reference< awt::XBitmap > xBitmap( VCLUnoHelper::CreateBitmap( pBmpDesc->mxBitmap ) );
maXPropSet->setPropertyValue( "GraphicObjectFillBitmap", uno::Any(xBitmap) );
}
}
}

View File

@@ -19,11 +19,13 @@
#include "main.hxx"
#include <vcl/BitmapTools.hxx>
#include <memory>
namespace {
constexpr BitmapColor BMCOL(sal_uInt32 _col) {
return BitmapColor( static_cast<sal_Int8>(_col >> 16 ), static_cast<sal_Int8>( _col >> 8 ), static_cast<sal_Int8>(_col) );
Color BMCOL(sal_uInt32 _col) {
return Color( static_cast<sal_Int8>(_col >> 16 ), static_cast<sal_Int8>( _col >> 8 ), static_cast<sal_Int8>(_col) );
}
}
@@ -64,196 +66,153 @@ void CGMBitmap::ImplGetBitmap( CGMBitmapDescriptor& rDesc )
{
rDesc.mbStatus = true;
if (ImplGetDimensions(rDesc) && rDesc.mpBuf && isLegalBitsPerPixel(rDesc.mnDstBitsPerPixel))
{
rDesc.mpBitmap = new Bitmap( Size( rDesc.mnX, rDesc.mnY ), static_cast<sal_uInt16>(rDesc.mnDstBitsPerPixel) );
if ( ( rDesc.mpAcc = rDesc.mpBitmap->AcquireWriteAccess() ) != nullptr )
{
if (!(ImplGetDimensions(rDesc) && rDesc.mpBuf && isLegalBitsPerPixel(rDesc.mnDstBitsPerPixel)))
return;
// the picture may either be read from left to right or right to left, from top to bottom ...
vcl::bitmap::RawBitmap aBitmap( Size( rDesc.mnX, rDesc.mnY ) );
long nxCount = rDesc.mnX + 1; // +1 because we are using prefix decreasing
long nyCount = rDesc.mnY + 1;
long nx, ny, nxC;
// the picture may either be read from left to right or right to left, from top to bottom ...
switch ( rDesc.mnDstBitsPerPixel )
{
case 1 :
{
if ( rDesc.mnLocalColorPrecision == 1 )
ImplSetCurrentPalette( rDesc );
else
{
rDesc.mpAcc->SetPaletteEntryCount( 2 );
rDesc.mpAcc->SetPaletteColor( 0, BMCOL( mpCGM->pElement->nBackGroundColor ) );
rDesc.mpAcc->SetPaletteColor( 1,
( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
? BMCOL( mpCGM->pElement->pFillBundle->GetColor() )
: BMCOL( mpCGM->pElement->aFillBundle.GetColor() ) ) ;
}
for ( ny = 0; --nyCount ; ny++, rDesc.mpBuf += rDesc.mnScanSize )
{
nxC = nxCount;
Scanline pScanline = rDesc.mpAcc->GetScanline( ny );
for ( nx = 0; --nxC; nx++ )
{ // this is not fast, but a one bit/pixel format is rarely used
rDesc.mpAcc->SetPixelOnData(pScanline, nx, BitmapColor(static_cast<sal_uInt8>( (*( rDesc.mpBuf + (nx >> 3)) >> ((nx & 7)^7))) & 1));
}
}
}
break;
long nxCount = rDesc.mnX + 1; // +1 because we are using prefix decreasing
long nyCount = rDesc.mnY + 1;
long nx, ny, nxC;
case 2 :
{
ImplSetCurrentPalette( rDesc );
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
{
nxC = nxCount;
Scanline pScanline = rDesc.mpAcc->GetScanline( ny );
for ( nx = 0; --nxC; nx++ )
{ // this is not fast, but a two bits/pixel format is rarely used
rDesc.mpAcc->SetPixelOnData(pScanline, nx, BitmapColor(static_cast<sal_uInt8>( (*(rDesc.mpBuf + (nx >> 2)) >> (((nx & 3)^3) << 1))) & 3));
}
}
}
break;
case 4 :
{
ImplSetCurrentPalette( rDesc );
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
{
nxC = nxCount;
Scanline pScanline = rDesc.mpAcc->GetScanline( ny );
sal_Int8 nDat;
sal_uInt8* pTemp = rDesc.mpBuf;
for ( nx = 0; --nxC; nx++ )
{
nDat = *pTemp++;
rDesc.mpAcc->SetPixelOnData(pScanline, nx, BitmapColor(static_cast<sal_uInt8>(nDat >> 4)));
if ( --nxC )
{
++nx;
rDesc.mpAcc->SetPixelOnData(pScanline, nx, BitmapColor(static_cast<sal_uInt8>(nDat & 15)));
}
else
break;
}
}
}
break;
case 8 :
{
ImplSetCurrentPalette( rDesc );
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
{
sal_uInt8* pTemp = rDesc.mpBuf;
Scanline pScanline = rDesc.mpAcc->GetScanline( ny );
nxC = nxCount;
for ( nx = 0; --nxC; nx++ )
{
rDesc.mpAcc->SetPixelOnData(pScanline, nx, BitmapColor(*(pTemp++)));
}
}
}
break;
case 24 :
{
BitmapColor aBitmapColor;
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize )
{
sal_uInt8* pTemp = rDesc.mpBuf;
nxC = nxCount;
Scanline pScanline = rDesc.mpAcc->GetScanline( ny );
for ( nx = 0; --nxC; nx++ )
{
aBitmapColor.SetRed( *pTemp++ );
aBitmapColor.SetGreen( *pTemp++ );
aBitmapColor.SetBlue( *pTemp++ );
rDesc.mpAcc->SetPixelOnData(pScanline, nx, aBitmapColor);
}
}
}
break;
}
double nX = rDesc.mnR.X - rDesc.mnQ.X;
double nY = rDesc.mnR.Y - rDesc.mnQ.Y;
rDesc.mndy = sqrt( nX * nX + nY * nY );
nX = rDesc.mnR.X - rDesc.mnP.X;
nY = rDesc.mnR.Y - rDesc.mnP.Y;
rDesc.mndx = sqrt( nX * nX + nY * nY );
nX = rDesc.mnR.X - rDesc.mnP.X;
nY = rDesc.mnR.Y - rDesc.mnP.Y;
double fSqrt = sqrt(nX * nX + nY * nY);
rDesc.mnOrientation = fSqrt != 0.0 ? (acos(nX / fSqrt) * 57.29577951308) : 0.0;
if ( nY > 0 )
rDesc.mnOrientation = 360 - rDesc.mnOrientation;
nX = rDesc.mnQ.X - rDesc.mnR.X;
nY = rDesc.mnQ.Y - rDesc.mnR.Y;
double fAngle = 0.01745329251994 * ( 360 - rDesc.mnOrientation );
double fSin = sin(fAngle);
double fCos = cos(fAngle);
nX = fCos * nX + fSin * nY;
nY = -( fSin * nX - fCos * nY );
fSqrt = sqrt(nX * nX + nY * nY);
fAngle = fSqrt != 0.0 ? (acos(nX / fSqrt) * 57.29577951308) : 0.0;
if ( nY > 0 )
fAngle = 360 - fAngle;
if ( fAngle > 180 ) // is the picture build upwards or downwards ?
{
rDesc.mnOrigin = rDesc.mnP;
}
else
{
rDesc.mbVMirror = true;
rDesc.mnOrigin = rDesc.mnP;
rDesc.mnOrigin.X += rDesc.mnQ.X - rDesc.mnR.X;
rDesc.mnOrigin.Y += rDesc.mnQ.Y - rDesc.mnR.Y;
switch ( rDesc.mnDstBitsPerPixel ) {
case 1 : {
std::vector<Color> palette(2);
if ( rDesc.mnLocalColorPrecision == 1 )
palette = ImplGeneratePalette( rDesc );
else {
palette[0] = BMCOL( mpCGM->pElement->nBackGroundColor );
palette[1] = ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
? BMCOL( mpCGM->pElement->pFillBundle->GetColor() )
: BMCOL( mpCGM->pElement->aFillBundle.GetColor() );
};
for ( ny = 0; --nyCount ; ny++, rDesc.mpBuf += rDesc.mnScanSize ) {
nxC = nxCount;
for ( nx = 0; --nxC; nx++ ) {
// this is not fast, but a one bit/pixel format is rarely used
sal_uInt8 colorIndex = static_cast<sal_uInt8>( (*( rDesc.mpBuf + (nx >> 3)) >> ((nx & 7)^7))) & 1;
aBitmap.SetPixel(ny, nx, palette[colorIndex]);
}
}
else
rDesc.mbStatus = false;
}
else
rDesc.mbStatus = false;
break;
if ( rDesc.mpAcc )
{
Bitmap::ReleaseAccess( rDesc.mpAcc );
rDesc.mpAcc = nullptr;
}
if ( !rDesc.mbStatus )
{
if ( rDesc.mpBitmap )
{
delete rDesc.mpBitmap;
rDesc.mpBitmap = nullptr;
case 2 : {
auto palette = ImplGeneratePalette( rDesc );
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize ) {
nxC = nxCount;
for ( nx = 0; --nxC; nx++ ) {
// this is not fast, but a two bits/pixel format is rarely used
aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>( (*(rDesc.mpBuf + (nx >> 2)) >> (((nx & 3)^3) << 1))) & 3]);
}
}
}
break;
case 4 : {
auto palette = ImplGeneratePalette( rDesc );
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize ) {
nxC = nxCount;
sal_Int8 nDat;
sal_uInt8* pTemp = rDesc.mpBuf;
for ( nx = 0; --nxC; nx++ ) {
nDat = *pTemp++;
aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>(nDat >> 4)]);
if ( --nxC ) {
++nx;
aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>(nDat & 15)]);
} else
break;
}
}
}
break;
case 8 : {
auto palette = ImplGeneratePalette( rDesc );
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize ) {
sal_uInt8* pTemp = rDesc.mpBuf;
nxC = nxCount;
for ( nx = 0; --nxC; nx++ ) {
aBitmap.SetPixel(ny, nx, palette[*(pTemp++)]);
}
}
}
break;
case 24 : {
Color aBitmapColor;
for ( ny = 0; --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize ) {
sal_uInt8* pTemp = rDesc.mpBuf;
nxC = nxCount;
for ( nx = 0; --nxC; nx++ ) {
aBitmapColor.SetRed( *pTemp++ );
aBitmapColor.SetGreen( *pTemp++ );
aBitmapColor.SetBlue( *pTemp++ );
aBitmap.SetPixel(ny, nx, aBitmapColor);
}
}
}
break;
}
double nX = rDesc.mnR.X - rDesc.mnQ.X;
double nY = rDesc.mnR.Y - rDesc.mnQ.Y;
rDesc.mndy = sqrt( nX * nX + nY * nY );
nX = rDesc.mnR.X - rDesc.mnP.X;
nY = rDesc.mnR.Y - rDesc.mnP.Y;
rDesc.mndx = sqrt( nX * nX + nY * nY );
nX = rDesc.mnR.X - rDesc.mnP.X;
nY = rDesc.mnR.Y - rDesc.mnP.Y;
double fSqrt = sqrt(nX * nX + nY * nY);
rDesc.mnOrientation = fSqrt != 0.0 ? (acos(nX / fSqrt) * 57.29577951308) : 0.0;
if ( nY > 0 )
rDesc.mnOrientation = 360 - rDesc.mnOrientation;
nX = rDesc.mnQ.X - rDesc.mnR.X;
nY = rDesc.mnQ.Y - rDesc.mnR.Y;
double fAngle = 0.01745329251994 * ( 360 - rDesc.mnOrientation );
double fSin = sin(fAngle);
double fCos = cos(fAngle);
nX = fCos * nX + fSin * nY;
nY = -( fSin * nX - fCos * nY );
fSqrt = sqrt(nX * nX + nY * nY);
fAngle = fSqrt != 0.0 ? (acos(nX / fSqrt) * 57.29577951308) : 0.0;
if ( nY > 0 )
fAngle = 360 - fAngle;
if ( fAngle > 180 ) { // is the picture build upwards or downwards ?
rDesc.mnOrigin = rDesc.mnP;
} else {
rDesc.mbVMirror = true;
rDesc.mnOrigin = rDesc.mnP;
rDesc.mnOrigin.X += rDesc.mnQ.X - rDesc.mnR.X;
rDesc.mnOrigin.Y += rDesc.mnQ.Y - rDesc.mnR.Y;
}
if ( rDesc.mbStatus )
rDesc.mxBitmap = vcl::bitmap::CreateFromData(std::move(aBitmap));
}
void CGMBitmap::ImplSetCurrentPalette( CGMBitmapDescriptor& rDesc )
std::vector<Color> CGMBitmap::ImplGeneratePalette( CGMBitmapDescriptor& rDesc )
{
sal_uInt16 nColors = sal::static_int_cast< sal_uInt16 >(
1 << rDesc.mnDstBitsPerPixel);
rDesc.mpAcc->SetPaletteEntryCount( nColors );
std::vector<Color> palette( nColors );
for ( sal_uInt16 i = 0; i < nColors; i++ )
{
rDesc.mpAcc->SetPaletteColor( i, BMCOL( mpCGM->pElement->aLatestColorTable[ i ] ) );
palette[i] = BMCOL( mpCGM->pElement->aLatestColorTable[ i ] );
}
return palette;
}
@@ -354,9 +313,9 @@ void CGMBitmap::ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescri
{ // Insert on Bottom
if ( mpCGM->mnVDCYmul == -1 )
rDest.mnOrigin = rSource.mnOrigin; // new origin
rDest.mpBitmap->Expand( 0, rSource.mnY );
rDest.mpBitmap->CopyPixel( tools::Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
tools::Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), rSource.mpBitmap );
rDest.mxBitmap.Expand( 0, rSource.mnY );
rDest.mxBitmap.CopyPixel( tools::Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
tools::Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), &rSource.mxBitmap );
FloatPoint aFloatPoint;
aFloatPoint.X = rSource.mnQ.X - rSource.mnR.X;
aFloatPoint.Y = rSource.mnQ.Y - rSource.mnR.Y;
@@ -369,9 +328,9 @@ void CGMBitmap::ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescri
{ // Insert on Top
if ( mpCGM->mnVDCYmul == 1 )
rDest.mnOrigin = rSource.mnOrigin; // new origin
rDest.mpBitmap->Expand( 0, rSource.mnY );
rDest.mpBitmap->CopyPixel( tools::Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
tools::Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), rSource.mpBitmap );
rDest.mxBitmap.Expand( 0, rSource.mnY );
rDest.mxBitmap.CopyPixel( tools::Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
tools::Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), &rSource.mxBitmap );
rDest.mnP = rSource.mnP;
rDest.mnR = rSource.mnR;
}
@@ -382,7 +341,7 @@ void CGMBitmap::ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescri
std::unique_ptr<CGMBitmap> CGMBitmap::GetNext()
{
std::unique_ptr<CGMBitmap> xCGMTempBitmap;
if (pCGMBitmapDescriptor->mpBitmap && pCGMBitmapDescriptor->mbStatus)
if (!!pCGMBitmapDescriptor->mxBitmap && pCGMBitmapDescriptor->mbStatus)
{
xCGMTempBitmap.reset(new CGMBitmap(*mpCGM));
if ( ( static_cast<long>(xCGMTempBitmap->pCGMBitmapDescriptor->mnOrientation) == static_cast<long>(pCGMBitmapDescriptor->mnOrientation) ) &&

View File

@@ -20,9 +20,9 @@
#ifndef INCLUDED_FILTER_SOURCE_GRAPHICFILTER_ICGM_BITMAP_HXX
#define INCLUDED_FILTER_SOURCE_GRAPHICFILTER_ICGM_BITMAP_HXX
#include <memory>
#include "cgm.hxx"
#include <vcl/bitmapaccess.hxx>
#include <vcl/bitmapex.hxx>
#include <vector>
class CGM;
@@ -30,8 +30,7 @@ class CGMBitmapDescriptor
{
public:
sal_uInt8* mpBuf;
Bitmap* mpBitmap;
BitmapWriteAccess* mpAcc;
BitmapEx mxBitmap;
bool mbStatus;
bool mbVMirror;
sal_uInt32 mnDstBitsPerPixel;
@@ -48,8 +47,6 @@ class CGMBitmapDescriptor
CGMBitmapDescriptor()
: mpBuf(nullptr)
, mpBitmap(nullptr)
, mpAcc(nullptr)
, mbStatus(false)
, mbVMirror(false)
, mnDstBitsPerPixel(0)
@@ -62,12 +59,6 @@ class CGMBitmapDescriptor
, mnLocalColorPrecision(0)
, mnCompressionMode(0)
{ };
~CGMBitmapDescriptor()
{
if ( mpAcc )
::Bitmap::ReleaseAccess( mpAcc );
delete mpBitmap;
};
};
class CGMBitmap
@@ -76,7 +67,7 @@ class CGMBitmap
std::unique_ptr<CGMBitmapDescriptor>
pCGMBitmapDescriptor;
bool ImplGetDimensions( CGMBitmapDescriptor& );
void ImplSetCurrentPalette( CGMBitmapDescriptor& );
std::vector<Color> ImplGeneratePalette( CGMBitmapDescriptor& );
void ImplGetBitmap( CGMBitmapDescriptor& );
void ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescriptor& rDest );
public:

View File

@@ -11,13 +11,36 @@
#define INCLUDED_VCL_BITMAP_TOOLS_HXX
#include <vcl/bitmapex.hxx>
#include <tools/stream.hxx>
#include <vcl/ImageTree.hxx>
#include <vcl/salbtype.hxx>
#include <tools/stream.hxx>
namespace vcl {
namespace bitmap {
/**
* intended to be used to feed into CreateFromData to create a BitmapEx
*/
class VCL_DLLPUBLIC RawBitmap
{
friend BitmapEx VCL_DLLPUBLIC CreateFromData( RawBitmap&& rawBitmap );
std::unique_ptr<sal_uInt8[]> mpData;
Size maSize;
public:
RawBitmap(Size const & rSize)
: mpData(new sal_uInt8[ rSize.getWidth() * 3 * rSize.getHeight()]),
maSize(rSize)
{
}
void SetPixel(long nY, long nX, BitmapColor nColor)
{
long p = nY * maSize.getWidth() + nX;
mpData[ p++ ] = nColor.GetRed();
mpData[ p++ ] = nColor.GetGreen();
mpData[ p ] = nColor.GetBlue();
}
};
BitmapEx VCL_DLLPUBLIC loadFromName(const OUString& rFileName, const ImageLoadFlags eFlags = ImageLoadFlags::NONE);
void loadFromSvg(SvStream& rStream, const OUString& sPath, BitmapEx& rBitmapEx, double fScaleFactor);
@@ -32,6 +55,7 @@ void loadFromSvg(SvStream& rStream, const OUString& sPath, BitmapEx& rBitmapEx,
*/
BitmapEx VCL_DLLPUBLIC CreateFromData( sal_uInt8 const *pData, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int32 nStride, sal_uInt16 nBitCount );
BitmapEx VCL_DLLPUBLIC CreateFromData( RawBitmap && data );
}} // end vcl::bitmap

View File

@@ -135,6 +135,34 @@ BitmapEx CreateFromData( sal_uInt8 const *pData, sal_Int32 nWidth, sal_Int32 nHe
return aBmp;
}
/** Copy block of image data into the bitmap.
Assumes that the Bitmap has been constructed with the desired size.
*/
BitmapEx CreateFromData( RawBitmap&& rawBitmap )
{
Bitmap aBmp( rawBitmap.maSize, /*nBitCount*/24 );
Bitmap::ScopedWriteAccess pWrite(aBmp);
assert(pWrite.get());
if( !pWrite )
return BitmapEx();
auto nHeight = rawBitmap.maSize.getHeight();
auto nWidth = rawBitmap.maSize.getWidth();
for( long y = 0; y < nHeight; ++y )
{
sal_uInt8 const *p = rawBitmap.mpData.get() + y * nWidth;
Scanline pScanline = pWrite->GetScanline(y);
for (long x = 0; x < nWidth; ++x)
{
BitmapColor col(p[0], p[1], p[2]);
pWrite->SetPixelOnData(pScanline, x, col);
p += 3;
}
}
return aBmp;
}
}} // end vcl::bitmap
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */