diff options
Diffstat (limited to 'svx/source/xoutdev/_xoutbmp.cxx')
-rw-r--r-- | svx/source/xoutdev/_xoutbmp.cxx | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx new file mode 100644 index 000000000000..bbb09866d243 --- /dev/null +++ b/svx/source/xoutdev/_xoutbmp.cxx @@ -0,0 +1,771 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include <sot/factory.hxx> +#include <tools/urlobj.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/bmpacc.hxx> +#include <tools/poly.hxx> +#include <vcl/virdev.hxx> +#include <vcl/wrkwin.hxx> +#include <svl/solar.hrc> +#include <sfx2/docfile.hxx> +#include <sfx2/app.hxx> +#include "xoutbmp.hxx" +#include <svtools/FilterConfigItem.hxx> +#include <svtools/filter.hxx> + +// ----------- +// - Defines - +// ----------- + +#define FORMAT_BMP String(RTL_CONSTASCII_USTRINGPARAM("bmp")) +#define FORMAT_GIF String(RTL_CONSTASCII_USTRINGPARAM("gif")) +#define FORMAT_JPG String(RTL_CONSTASCII_USTRINGPARAM("jpg")) +#define FORMAT_PNG String(RTL_CONSTASCII_USTRINGPARAM("png")) + +// -------------- +// - XOutBitmap - +// -------------- + +GraphicFilter* XOutBitmap::pGrfFilter = NULL; + +// ----------------------------------------------------------------------------- + +BitmapEx XOutBitmap::CreateQuickDrawBitmapEx( const Graphic& rGraphic, const OutputDevice& rCompDev, + const MapMode& rMapMode, const Size& rLogSize, + const Point& rPoint, const Size& rSize ) +{ + BitmapEx aRetBmp; + + if( rGraphic.IsAlpha() ) + aRetBmp = rGraphic.GetBitmapEx(); + else + { + VirtualDevice aVDev( rCompDev ); + MapMode aMap( rMapMode ); + + aMap.SetOrigin( Point() ); + aVDev.SetMapMode( aMap ); + + Point aPoint( aVDev.LogicToPixel( rPoint ) ); + Size aOldSize( aVDev.LogicToPixel( rSize ) ); + Size aAbsSize( aOldSize ); + Size aQSizePix( aVDev.LogicToPixel( rLogSize ) ); + + aVDev.SetMapMode( MapMode() ); + + if( aOldSize.Width() < 0 ) + aAbsSize.Width() = -aAbsSize.Width(); + + if( aOldSize.Height() < 0 ) + aAbsSize.Height() = -aAbsSize.Height(); + + if( aVDev.SetOutputSizePixel( aAbsSize ) ) + { + Point aNewOrg( -aPoint.X(), -aPoint.Y() ); + const Point aNullPoint; + + // horizontale Spiegelung ggf. beruecksichtigen + if( aOldSize.Width() < 0 ) + { + aNewOrg.X() -= aOldSize.Width(); + + // und jetzt noch einen abziehen + aNewOrg.X()--; + } + + // vertikale Spiegelung ggf. beruecksichtigen + if( rSize.Height() < 0 ) + { + aNewOrg.Y() -= aOldSize.Height(); + + // und jetzt noch einen abziehen + aNewOrg.Y()--; + } + + if( rGraphic.GetType() != GRAPHIC_BITMAP ) + { + rGraphic.Draw( &aVDev, aNewOrg, aQSizePix ); + + const Bitmap aBmp( aVDev.GetBitmap( aNullPoint, aAbsSize ) ); + Bitmap aMask; + + Graphic( rGraphic.GetGDIMetaFile().GetMonochromeMtf( COL_BLACK ) ).Draw( &aVDev, aNewOrg, aQSizePix ); + aMask = aVDev.GetBitmap( aNullPoint, aAbsSize ); + aRetBmp = BitmapEx( aBmp, aMask ); + } + else + { + Bitmap aBmp( rGraphic.GetBitmap() ); + +// UNX has got problems with 1x1 bitmaps which are transparent (KA 02.11.1998) +#ifdef UNX + const Size aBmpSize( aBmp.GetSizePixel() ); + BOOL bFullTrans = FALSE; + + if( aBmpSize.Width() == 1 && aBmpSize.Height() == 1 && rGraphic.IsTransparent() ) + { + Bitmap aTrans( rGraphic.GetBitmapEx().GetMask() ); + BitmapReadAccess* pMAcc = aBmp.AcquireReadAccess(); + + if( pMAcc ) + { + if( pMAcc->GetColor( 0, 0 ) == BitmapColor( Color( COL_WHITE ) ) ) + bFullTrans = TRUE; + + aTrans.ReleaseAccess( pMAcc ); + } + } + + if( !bFullTrans ) +#endif // UNX + + { + DitherBitmap( aBmp ); + aVDev.DrawBitmap( aNewOrg, aQSizePix, aBmp ); + aBmp = aVDev.GetBitmap( aNullPoint, aAbsSize ); + + if( !rGraphic.IsTransparent() ) + aRetBmp = BitmapEx( aBmp ); + else + { + Bitmap aTrans( rGraphic.GetBitmapEx().GetMask() ); + + if( !aTrans ) + aRetBmp = BitmapEx( aBmp, rGraphic.GetBitmapEx().GetTransparentColor() ); + else + { + aVDev.DrawBitmap( aNewOrg, aQSizePix, aTrans ); + aRetBmp = BitmapEx( aBmp, aVDev.GetBitmap( Point(), aAbsSize ) ); + } + } + } + } + } + } + + return aRetBmp; +} + +// ------------------------------------------------------------------------ + +void XOutBitmap::DrawQuickDrawBitmapEx( OutputDevice* pOutDev, const Point& rPt, + const Size& rSize, const BitmapEx& rBmpEx ) +{ + const Size aBmpSizePix( rBmpEx.GetSizePixel() ); + const Size aSizePix( pOutDev->LogicToPixel( rSize ) ); + + if ( ( aSizePix.Width() - aBmpSizePix.Width() ) || ( aSizePix.Height() - aBmpSizePix.Height() ) ) + rBmpEx.Draw( pOutDev, rPt, rSize ); + else + rBmpEx.Draw( pOutDev, rPt ); +} + +// ------------------------------------------------------------------------ + +void XOutBitmap::DrawTiledBitmapEx( OutputDevice* pOutDev, + const Point& rStartPt, const Size& rGrfSize, + const Rectangle& rTileRect, const BitmapEx& rBmpEx ) +{ + Rectangle aClipRect( pOutDev->LogicToPixel( pOutDev->GetClipRegion().GetBoundRect() ) ); + Rectangle aPixRect( pOutDev->LogicToPixel( rTileRect ) ); + const Size aPixSize( pOutDev->LogicToPixel( rGrfSize ) ); + const Point aPixPoint( pOutDev->LogicToPixel( rStartPt ) ); + Point aOrg; + const long nWidth = aPixSize.Width(); + const long nHeight = aPixSize.Height(); + long nXPos = aPixPoint.X() + ( ( aPixRect.Left() - aPixPoint.X() ) / nWidth ) * nWidth; + long nYPos = aPixPoint.Y() + ( ( aPixRect.Top() - aPixPoint.Y() ) / nHeight ) * nHeight; + const long nBottom = aPixRect.Bottom(); + const long nRight = aPixRect.Right(); + const long nLeft = nXPos; + const BOOL bNoSize = ( aPixSize == rBmpEx.GetSizePixel() ); + + pOutDev->Push(); + pOutDev->SetMapMode( MapMode() ); + + // ggf. neue ClipRegion berechnen und setzen + if ( pOutDev->IsClipRegion() ) + aPixRect.Intersection( aClipRect ); + + pOutDev->SetClipRegion( aPixRect ); + + while( nYPos <= nBottom ) + { + while( nXPos <= nRight ) + { + if ( bNoSize ) + rBmpEx.Draw( pOutDev, Point( nXPos, nYPos ) ); + else + rBmpEx.Draw( pOutDev, Point( nXPos, nYPos ), aPixSize ); + + nXPos += nWidth; + } + + nXPos = nLeft; + nYPos += nHeight; + } + + pOutDev->Pop(); +} + +// ------------------------------------------------------------------------ + +Animation XOutBitmap::MirrorAnimation( const Animation& rAnimation, BOOL bHMirr, BOOL bVMirr ) +{ + Animation aNewAnim( rAnimation ); + + if( bHMirr || bVMirr ) + { + const Size& rGlobalSize = aNewAnim.GetDisplaySizePixel(); + ULONG nMirrorFlags = 0L; + + if( bHMirr ) + nMirrorFlags |= BMP_MIRROR_HORZ; + + if( bVMirr ) + nMirrorFlags |= BMP_MIRROR_VERT; + + for( USHORT i = 0, nCount = aNewAnim.Count(); i < nCount; i++ ) + { + AnimationBitmap aAnimBmp( aNewAnim.Get( i ) ); + + // BitmapEx spiegeln + aAnimBmp.aBmpEx.Mirror( nMirrorFlags ); + + // Die Positionen innerhalb der Gesamtbitmap + // muessen natuerlich auch angepasst werden + if( bHMirr ) + aAnimBmp.aPosPix.X() = rGlobalSize.Width() - aAnimBmp.aPosPix.X() - + aAnimBmp.aSizePix.Width(); + + if( bVMirr ) + aAnimBmp.aPosPix.Y() = rGlobalSize.Height() - aAnimBmp.aPosPix.Y() - + aAnimBmp.aSizePix.Height(); + + aNewAnim.Replace( aAnimBmp, i ); + } + } + + return aNewAnim; +} + +// ------------------------------------------------------------------------ + +Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const ULONG nMirrorFlags ) +{ + Graphic aRetGraphic; + + if( nMirrorFlags ) + { + if( rGraphic.IsAnimated() ) + { + aRetGraphic = MirrorAnimation( rGraphic.GetAnimation(), + ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ, + ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT ); + } + else + { + if( rGraphic.IsTransparent() ) + { + BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); + + aBmpEx.Mirror( nMirrorFlags ); + aRetGraphic = aBmpEx; + } + else + { + Bitmap aBmp( rGraphic.GetBitmap() ); + + aBmp.Mirror( nMirrorFlags ); + aRetGraphic = aBmp; + } + } + } + else + aRetGraphic = rGraphic; + + return aRetGraphic; +} + +// ------------------------------------------------------------------------ + +USHORT XOutBitmap::WriteGraphic( const Graphic& rGraphic, String& rFileName, + const String& rFilterName, const ULONG nFlags, + const Size* pMtfSize_100TH_MM ) +{ + if( rGraphic.GetType() != GRAPHIC_NONE ) + { + INetURLObject aURL( rFileName ); + Graphic aGraphic; + String aExt; + GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); + USHORT nErr = GRFILTER_FILTERERROR, nFilter = GRFILTER_FORMAT_NOTFOUND; + BOOL bTransparent = rGraphic.IsTransparent(), bAnimated = rGraphic.IsAnimated(); + + DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "XOutBitmap::WriteGraphic(...): invalid URL" ); + + // calculate correct file name + if( !( nFlags & XOUTBMP_DONT_EXPAND_FILENAME ) ) + { + String aName( aURL.getBase() ); + aName += '_'; + aName += String(aURL.getExtension()); + aName += '_'; + String aStr( String::CreateFromInt32( rGraphic.GetChecksum(), 16 ) ); + if ( aStr.GetChar(0) == '-' ) + aStr.SetChar(0,'m'); + aName += aStr; + aURL.setBase( aName ); + } + + if( ( nFlags & XOUTBMP_USE_NATIVE_IF_POSSIBLE ) && + !( nFlags & XOUTBMP_MIRROR_HORZ ) && + !( nFlags & XOUTBMP_MIRROR_VERT ) && + ( rGraphic.GetType() != GRAPHIC_GDIMETAFILE ) && rGraphic.IsLink() ) + { + // try to write native link + const GfxLink aGfxLink( ( (Graphic&) rGraphic ).GetLink() ); + + switch( aGfxLink.GetType() ) + { + case( GFX_LINK_TYPE_NATIVE_GIF ): aExt = FORMAT_GIF; break; + case( GFX_LINK_TYPE_NATIVE_JPG ): aExt = FORMAT_JPG; break; + case( GFX_LINK_TYPE_NATIVE_PNG ): aExt = FORMAT_PNG; break; + + default: + break; + } + + if( aExt.Len() ) + { + aURL.setExtension( aExt ); + rFileName = aURL.GetMainURL( INetURLObject::NO_DECODE ); + + SfxMedium aMedium( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_SHARE_DENYNONE | STREAM_TRUNC, TRUE ); + SvStream* pOStm = aMedium.GetOutStream(); + + if( pOStm && aGfxLink.GetDataSize() && aGfxLink.GetData() ) + { + pOStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() ); + aMedium.Commit(); + + if( !aMedium.GetError() ) + nErr = GRFILTER_OK; + } + } + } + + if( GRFILTER_OK != nErr ) + { + String aFilter( rFilterName ); + BOOL bWriteTransGrf = ( aFilter.EqualsIgnoreCaseAscii( "transgrf" ) ) || + ( aFilter.EqualsIgnoreCaseAscii( "gif" ) ) || + ( nFlags & XOUTBMP_USE_GIF_IF_POSSIBLE ) || + ( ( nFlags & XOUTBMP_USE_GIF_IF_SENSIBLE ) && ( bAnimated || bTransparent ) ); + + // get filter and extension + if( bWriteTransGrf ) + aFilter = FORMAT_GIF; + + nFilter = pFilter->GetExportFormatNumberForShortName( aFilter ); + + if( GRFILTER_FORMAT_NOTFOUND == nFilter ) + { + nFilter = pFilter->GetExportFormatNumberForShortName( FORMAT_JPG ); + + if( GRFILTER_FORMAT_NOTFOUND == nFilter ) + nFilter = pFilter->GetExportFormatNumberForShortName( FORMAT_BMP ); + } + + if( GRFILTER_FORMAT_NOTFOUND != nFilter ) + { + aExt = pFilter->GetExportFormatShortName( nFilter ).ToLowerAscii(); + + if( bWriteTransGrf ) + { + if( bAnimated ) + aGraphic = rGraphic; + else + { + if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GRAPHIC_BITMAP ) ) + { + VirtualDevice aVDev; + const Size aSize( aVDev.LogicToPixel( *pMtfSize_100TH_MM, MAP_100TH_MM ) ); + + if( aVDev.SetOutputSizePixel( aSize ) ) + { + const Wallpaper aWallpaper( aVDev.GetBackground() ); + const Point aPt; + + aVDev.SetBackground( Wallpaper( Color( COL_BLACK ) ) ); + aVDev.Erase(); + rGraphic.Draw( &aVDev, aPt, aSize ); + + const Bitmap aBitmap( aVDev.GetBitmap( aPt, aSize ) ); + + aVDev.SetBackground( aWallpaper ); + aVDev.Erase(); + rGraphic.Draw( &aVDev, aPt, aSize ); + + aVDev.SetRasterOp( ROP_XOR ); + aVDev.DrawBitmap( aPt, aSize, aBitmap ); + aGraphic = BitmapEx( aBitmap, aVDev.GetBitmap( aPt, aSize ) ); + } + else + aGraphic = rGraphic.GetBitmapEx(); + } + else + aGraphic = rGraphic.GetBitmapEx(); + } + } + else + { + if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GRAPHIC_BITMAP ) ) + { + VirtualDevice aVDev; + const Size aSize( aVDev.LogicToPixel( *pMtfSize_100TH_MM, MAP_100TH_MM ) ); + + if( aVDev.SetOutputSizePixel( aSize ) ) + { + rGraphic.Draw( &aVDev, Point(), aSize ); + aGraphic = aVDev.GetBitmap( Point(), aSize ); + } + else + aGraphic = rGraphic.GetBitmap(); + } + else + aGraphic = rGraphic.GetBitmap(); + } + + // mirror? + if( ( nFlags & XOUTBMP_MIRROR_HORZ ) || ( nFlags & XOUTBMP_MIRROR_VERT ) ) + aGraphic = MirrorGraphic( aGraphic, nFlags ); + + if( ( GRFILTER_FORMAT_NOTFOUND != nFilter ) && ( aGraphic.GetType() != GRAPHIC_NONE ) ) + { + aURL.setExtension( aExt ); + rFileName = aURL.GetMainURL( INetURLObject::NO_DECODE ); + nErr = ExportGraphic( aGraphic, aURL, *pFilter, nFilter, NULL ); + } + } + } + + return nErr; + } + else + { + return GRFILTER_OK; + } +} + +// ------------------------------------------------------------------------ + +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + +USHORT XOutBitmap::ExportGraphic( const Graphic& rGraphic, const INetURLObject& rURL, + GraphicFilter& rFilter, const USHORT nFormat, + const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData ) +{ + DBG_ASSERT( rURL.GetProtocol() != INET_PROT_NOT_VALID, "XOutBitmap::ExportGraphic(...): invalid URL" ); + + SfxMedium aMedium( rURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_SHARE_DENYNONE | STREAM_TRUNC, TRUE ); + SvStream* pOStm = aMedium.GetOutStream(); + USHORT nRet = GRFILTER_IOERROR; + + if( pOStm ) + { + pGrfFilter = &rFilter; + + nRet = rFilter.ExportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::NO_DECODE ), *pOStm, nFormat, pFilterData ); + + pGrfFilter = NULL; + aMedium.Commit(); + + if( aMedium.GetError() && ( GRFILTER_OK == nRet ) ) + nRet = GRFILTER_IOERROR; + } + + return nRet; +} + +#ifdef _MSC_VER +#pragma optimize ( "", on ) +#endif + +// ------------------------------------------------------------------------ + +Bitmap XOutBitmap::DetectEdges( const Bitmap& rBmp, const BYTE cThreshold ) +{ + const Size aSize( rBmp.GetSizePixel() ); + Bitmap aRetBmp; + BOOL bRet = FALSE; + + if( ( aSize.Width() > 2L ) && ( aSize.Height() > 2L ) ) + { + Bitmap aWorkBmp( rBmp ); + + if( aWorkBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) ) + { + Bitmap aDstBmp( aSize, 1 ); + BitmapReadAccess* pReadAcc = aWorkBmp.AcquireReadAccess(); + BitmapWriteAccess* pWriteAcc = aDstBmp.AcquireWriteAccess(); + + if( pReadAcc && pWriteAcc ) + { + const long nWidth = aSize.Width(); + const long nWidth2 = nWidth - 2L; + const long nHeight = aSize.Height(); + const long nHeight2 = nHeight - 2L; + const long lThres2 = (long) cThreshold * cThreshold; + const BitmapColor aWhite = (BYTE) pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ); + const BitmapColor aBlack = (BYTE) pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ); + long nSum1; + long nSum2; + long lGray; + + // Rand mit Weiss init. + pWriteAcc->SetLineColor( Color( COL_WHITE) ); + pWriteAcc->DrawLine( Point(), Point( nWidth - 1L, 0L ) ); + pWriteAcc->DrawLine( Point( nWidth - 1L, 0L ), Point( nWidth - 1L, nHeight - 1L ) ); + pWriteAcc->DrawLine( Point( nWidth - 1L, nHeight - 1L ), Point( 0L, nHeight - 1L ) ); + pWriteAcc->DrawLine( Point( 0, nHeight - 1L ), Point() ); + + for( long nY = 0L, nY1 = 1L, nY2 = 2; nY < nHeight2; nY++, nY1++, nY2++ ) + { + for( long nX = 0L, nXDst = 1L, nXTmp; nX < nWidth2; nX++, nXDst++ ) + { + nXTmp = nX; + + nSum1 = -( nSum2 = lGray = (BYTE) pReadAcc->GetPixel( nY, nXTmp++ ) ); + nSum2 += ( (long) (BYTE) pReadAcc->GetPixel( nY, nXTmp++ ) ) << 1; + nSum1 += ( lGray = pReadAcc->GetPixel( nY, nXTmp ) ); + nSum2 += lGray; + + nSum1 += ( (long) (BYTE) pReadAcc->GetPixel( nY1, nXTmp ) ) << 1; + nSum1 -= ( (long) (BYTE) pReadAcc->GetPixel( nY1, nXTmp -= 2 ) ) << 1; + + nSum1 += ( lGray = -(long) (BYTE) pReadAcc->GetPixel( nY2, nXTmp++ ) ); + nSum2 += lGray; + nSum2 -= ( (long) (BYTE) pReadAcc->GetPixel( nY2, nXTmp++ ) ) << 1; + nSum1 += ( lGray = (long) (BYTE) pReadAcc->GetPixel( nY2, nXTmp ) ); + nSum2 -= lGray; + + if( ( nSum1 * nSum1 + nSum2 * nSum2 ) < lThres2 ) + pWriteAcc->SetPixel( nY1, nXDst, aWhite ); + else + pWriteAcc->SetPixel( nY1, nXDst, aBlack ); + } + } + + bRet = TRUE; + } + + aWorkBmp.ReleaseAccess( pReadAcc ); + aDstBmp.ReleaseAccess( pWriteAcc ); + + if( bRet ) + aRetBmp = aDstBmp; + } + } + + if( !aRetBmp ) + aRetBmp = rBmp; + else + { + aRetBmp.SetPrefMapMode( rBmp.GetPrefMapMode() ); + aRetBmp.SetPrefSize( rBmp.GetPrefSize() ); + } + + return aRetBmp; +}; + +// ------------------------------------------------------------------------ + +Polygon XOutBitmap::GetCountour( const Bitmap& rBmp, const ULONG nFlags, + const BYTE cEdgeDetectThreshold, const Rectangle* pWorkRectPixel ) +{ + Bitmap aWorkBmp; + Polygon aRetPoly; + Point aTmpPoint; + Rectangle aWorkRect( aTmpPoint, rBmp.GetSizePixel() ); + + if( pWorkRectPixel ) + aWorkRect.Intersection( *pWorkRectPixel ); + + aWorkRect.Justify(); + + if( ( aWorkRect.GetWidth() > 4 ) && ( aWorkRect.GetHeight() > 4 ) ) + { + // falls Flag gesetzt, muessen wir Kanten detektieren + if( nFlags & XOUTBMP_CONTOUR_EDGEDETECT ) + aWorkBmp = DetectEdges( rBmp, cEdgeDetectThreshold ); + else + aWorkBmp = rBmp; + + BitmapReadAccess* pAcc = aWorkBmp.AcquireReadAccess(); + + if( pAcc ) + { + const Size& rPrefSize = aWorkBmp.GetPrefSize(); + const long nWidth = pAcc->Width(); + const long nHeight = pAcc->Height(); + const double fFactorX = (double) rPrefSize.Width() / nWidth; + const double fFactorY = (double) rPrefSize.Height() / nHeight; + const long nStartX1 = aWorkRect.Left() + 1L; + const long nEndX1 = aWorkRect.Right(); + const long nStartX2 = nEndX1 - 1L; +// const long nEndX2 = nStartX1 - 1L; + const long nStartY1 = aWorkRect.Top() + 1L; + const long nEndY1 = aWorkRect.Bottom(); + const long nStartY2 = nEndY1 - 1L; +// const long nEndY2 = nStartY1 - 1L; + Point* pPoints1 = NULL; + Point* pPoints2 = NULL; + long nX, nY; + USHORT nPolyPos = 0; + const BitmapColor aBlack = pAcc->GetBestMatchingColor( Color( COL_BLACK ) ); + + if( nFlags & XOUTBMP_CONTOUR_VERT ) + { + pPoints1 = new Point[ nWidth ]; + pPoints2 = new Point[ nWidth ]; + + for( nX = nStartX1; nX < nEndX1; nX++ ) + { + nY = nStartY1; + + // zunaechst Zeile von Links nach Rechts durchlaufen + while( nY < nEndY1 ) + { + if( aBlack == pAcc->GetPixel( nY, nX ) ) + { + pPoints1[ nPolyPos ] = Point( nX, nY ); + nY = nStartY2; + + // diese Schleife wird immer gebreaked da hier ja min. ein Pixel ist + while( TRUE ) + { + if( aBlack == pAcc->GetPixel( nY, nX ) ) + { + pPoints2[ nPolyPos ] = Point( nX, nY ); + break; + } + + nY--; + } + + nPolyPos++; + break; + } + + nY++; + } + } + } + else + { + pPoints1 = new Point[ nHeight ]; + pPoints2 = new Point[ nHeight ]; + + for ( nY = nStartY1; nY < nEndY1; nY++ ) + { + nX = nStartX1; + + // zunaechst Zeile von Links nach Rechts durchlaufen + while( nX < nEndX1 ) + { + if( aBlack == pAcc->GetPixel( nY, nX ) ) + { + pPoints1[ nPolyPos ] = Point( nX, nY ); + nX = nStartX2; + + // diese Schleife wird immer gebreaked da hier ja min. ein Pixel ist + while( TRUE ) + { + if( aBlack == pAcc->GetPixel( nY, nX ) ) + { + pPoints2[ nPolyPos ] = Point( nX, nY ); + break; + } + + nX--; + } + + nPolyPos++; + break; + } + + nX++; + } + } + } + + const USHORT nNewSize1 = nPolyPos << 1; + + aRetPoly = Polygon( nPolyPos, pPoints1 ); + aRetPoly.SetSize( nNewSize1 + 1 ); + aRetPoly[ nNewSize1 ] = aRetPoly[ 0 ]; + + for( USHORT j = nPolyPos; nPolyPos < nNewSize1; ) + aRetPoly[ nPolyPos++ ] = pPoints2[ --j ]; + + if( ( fFactorX != 0. ) && ( fFactorY != 0. ) ) + aRetPoly.Scale( fFactorX, fFactorY ); + + delete[] pPoints1; + delete[] pPoints2; + } + } + + return aRetPoly; +}; + +// ---------------- +// - DitherBitmap - +// ---------------- + +BOOL DitherBitmap( Bitmap& rBitmap ) +{ + BOOL bRet = FALSE; + + if( ( rBitmap.GetBitCount() >= 8 ) && ( Application::GetDefaultDevice()->GetColorCount() < 257 ) ) + bRet = rBitmap.Dither( BMP_DITHER_FLOYD ); + else + bRet = FALSE; + + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |