1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svx.hxx" 26 27 #include <sot/factory.hxx> 28 #include <tools/urlobj.hxx> 29 #include <unotools/ucbstreamhelper.hxx> 30 #include <vcl/bmpacc.hxx> 31 #include <tools/poly.hxx> 32 #include <vcl/virdev.hxx> 33 #include <vcl/wrkwin.hxx> 34 #include <svl/solar.hrc> 35 #include <sfx2/docfile.hxx> 36 #include <sfx2/app.hxx> 37 #include "svx/xoutbmp.hxx" 38 #include <svtools/FilterConfigItem.hxx> 39 #include <svtools/filter.hxx> 40 41 // ----------- 42 // - Defines - 43 // ----------- 44 45 #define FORMAT_BMP String(RTL_CONSTASCII_USTRINGPARAM("bmp")) 46 #define FORMAT_GIF String(RTL_CONSTASCII_USTRINGPARAM("gif")) 47 #define FORMAT_JPG String(RTL_CONSTASCII_USTRINGPARAM("jpg")) 48 #define FORMAT_PNG String(RTL_CONSTASCII_USTRINGPARAM("png")) 49 50 // -------------- 51 // - XOutBitmap - 52 // -------------- 53 54 GraphicFilter* XOutBitmap::pGrfFilter = NULL; 55 56 // ----------------------------------------------------------------------------- 57 58 BitmapEx XOutBitmap::CreateQuickDrawBitmapEx( const Graphic& rGraphic, const OutputDevice& rCompDev, 59 const MapMode& rMapMode, const Size& rLogSize, 60 const Point& rPoint, const Size& rSize ) 61 { 62 BitmapEx aRetBmp; 63 64 if( rGraphic.IsAlpha() ) 65 aRetBmp = rGraphic.GetBitmapEx(); 66 else 67 { 68 VirtualDevice aVDev( rCompDev ); 69 MapMode aMap( rMapMode ); 70 71 aMap.SetOrigin( Point() ); 72 aVDev.SetMapMode( aMap ); 73 74 Point aPoint( aVDev.LogicToPixel( rPoint ) ); 75 Size aOldSize( aVDev.LogicToPixel( rSize ) ); 76 Size aAbsSize( aOldSize ); 77 Size aQSizePix( aVDev.LogicToPixel( rLogSize ) ); 78 79 aVDev.SetMapMode( MapMode() ); 80 81 if( aOldSize.Width() < 0 ) 82 aAbsSize.Width() = -aAbsSize.Width(); 83 84 if( aOldSize.Height() < 0 ) 85 aAbsSize.Height() = -aAbsSize.Height(); 86 87 if( aVDev.SetOutputSizePixel( aAbsSize ) ) 88 { 89 Point aNewOrg( -aPoint.X(), -aPoint.Y() ); 90 const Point aNullPoint; 91 92 // horizontale Spiegelung ggf. beruecksichtigen 93 if( aOldSize.Width() < 0 ) 94 { 95 aNewOrg.X() -= aOldSize.Width(); 96 97 // und jetzt noch einen abziehen 98 aNewOrg.X()--; 99 } 100 101 // vertikale Spiegelung ggf. beruecksichtigen 102 if( rSize.Height() < 0 ) 103 { 104 aNewOrg.Y() -= aOldSize.Height(); 105 106 // und jetzt noch einen abziehen 107 aNewOrg.Y()--; 108 } 109 110 if( rGraphic.GetType() != GRAPHIC_BITMAP ) 111 { 112 rGraphic.Draw( &aVDev, aNewOrg, aQSizePix ); 113 114 const Bitmap aBmp( aVDev.GetBitmap( aNullPoint, aAbsSize ) ); 115 Bitmap aMask; 116 117 Graphic( rGraphic.GetGDIMetaFile().GetMonochromeMtf( COL_BLACK ) ).Draw( &aVDev, aNewOrg, aQSizePix ); 118 aMask = aVDev.GetBitmap( aNullPoint, aAbsSize ); 119 aRetBmp = BitmapEx( aBmp, aMask ); 120 } 121 else 122 { 123 Bitmap aBmp( rGraphic.GetBitmap() ); 124 125 // UNX has got problems with 1x1 bitmaps which are transparent (KA 02.11.1998) 126 #ifdef UNX 127 const Size aBmpSize( aBmp.GetSizePixel() ); 128 sal_Bool bFullTrans = sal_False; 129 130 if( aBmpSize.Width() == 1 && aBmpSize.Height() == 1 && rGraphic.IsTransparent() ) 131 { 132 Bitmap aTrans( rGraphic.GetBitmapEx().GetMask() ); 133 BitmapReadAccess* pMAcc = aBmp.AcquireReadAccess(); 134 135 if( pMAcc ) 136 { 137 if( pMAcc->GetColor( 0, 0 ) == BitmapColor( Color( COL_WHITE ) ) ) 138 bFullTrans = sal_True; 139 140 aTrans.ReleaseAccess( pMAcc ); 141 } 142 } 143 144 if( !bFullTrans ) 145 #endif // UNX 146 147 { 148 DitherBitmap( aBmp ); 149 aVDev.DrawBitmap( aNewOrg, aQSizePix, aBmp ); 150 aBmp = aVDev.GetBitmap( aNullPoint, aAbsSize ); 151 152 if( !rGraphic.IsTransparent() ) 153 aRetBmp = BitmapEx( aBmp ); 154 else 155 { 156 Bitmap aTrans( rGraphic.GetBitmapEx().GetMask() ); 157 158 if( !aTrans ) 159 aRetBmp = BitmapEx( aBmp, rGraphic.GetBitmapEx().GetTransparentColor() ); 160 else 161 { 162 aVDev.DrawBitmap( aNewOrg, aQSizePix, aTrans ); 163 aRetBmp = BitmapEx( aBmp, aVDev.GetBitmap( Point(), aAbsSize ) ); 164 } 165 } 166 } 167 } 168 } 169 } 170 171 return aRetBmp; 172 } 173 174 // ------------------------------------------------------------------------ 175 176 void XOutBitmap::DrawQuickDrawBitmapEx( OutputDevice* pOutDev, const Point& rPt, 177 const Size& rSize, const BitmapEx& rBmpEx ) 178 { 179 const Size aBmpSizePix( rBmpEx.GetSizePixel() ); 180 const Size aSizePix( pOutDev->LogicToPixel( rSize ) ); 181 182 if ( ( aSizePix.Width() - aBmpSizePix.Width() ) || ( aSizePix.Height() - aBmpSizePix.Height() ) ) 183 rBmpEx.Draw( pOutDev, rPt, rSize ); 184 else 185 rBmpEx.Draw( pOutDev, rPt ); 186 } 187 188 // ------------------------------------------------------------------------ 189 190 void XOutBitmap::DrawTiledBitmapEx( OutputDevice* pOutDev, 191 const Point& rStartPt, const Size& rGrfSize, 192 const Rectangle& rTileRect, const BitmapEx& rBmpEx ) 193 { 194 Rectangle aClipRect( pOutDev->LogicToPixel( pOutDev->GetClipRegion().GetBoundRect() ) ); 195 Rectangle aPixRect( pOutDev->LogicToPixel( rTileRect ) ); 196 const Size aPixSize( pOutDev->LogicToPixel( rGrfSize ) ); 197 const Point aPixPoint( pOutDev->LogicToPixel( rStartPt ) ); 198 Point aOrg; 199 const long nWidth = aPixSize.Width(); 200 const long nHeight = aPixSize.Height(); 201 long nXPos = aPixPoint.X() + ( ( aPixRect.Left() - aPixPoint.X() ) / nWidth ) * nWidth; 202 long nYPos = aPixPoint.Y() + ( ( aPixRect.Top() - aPixPoint.Y() ) / nHeight ) * nHeight; 203 const long nBottom = aPixRect.Bottom(); 204 const long nRight = aPixRect.Right(); 205 const long nLeft = nXPos; 206 const sal_Bool bNoSize = ( aPixSize == rBmpEx.GetSizePixel() ); 207 208 pOutDev->Push(); 209 pOutDev->SetMapMode( MapMode() ); 210 211 // ggf. neue ClipRegion berechnen und setzen 212 if ( pOutDev->IsClipRegion() ) 213 aPixRect.Intersection( aClipRect ); 214 215 pOutDev->SetClipRegion( aPixRect ); 216 217 while( nYPos <= nBottom ) 218 { 219 while( nXPos <= nRight ) 220 { 221 if ( bNoSize ) 222 rBmpEx.Draw( pOutDev, Point( nXPos, nYPos ) ); 223 else 224 rBmpEx.Draw( pOutDev, Point( nXPos, nYPos ), aPixSize ); 225 226 nXPos += nWidth; 227 } 228 229 nXPos = nLeft; 230 nYPos += nHeight; 231 } 232 233 pOutDev->Pop(); 234 } 235 236 // ------------------------------------------------------------------------ 237 238 Animation XOutBitmap::MirrorAnimation( const Animation& rAnimation, sal_Bool bHMirr, sal_Bool bVMirr ) 239 { 240 Animation aNewAnim( rAnimation ); 241 242 if( bHMirr || bVMirr ) 243 { 244 const Size& rGlobalSize = aNewAnim.GetDisplaySizePixel(); 245 sal_uIntPtr nMirrorFlags = 0L; 246 247 if( bHMirr ) 248 nMirrorFlags |= BMP_MIRROR_HORZ; 249 250 if( bVMirr ) 251 nMirrorFlags |= BMP_MIRROR_VERT; 252 253 for( sal_uInt16 i = 0, nCount = aNewAnim.Count(); i < nCount; i++ ) 254 { 255 AnimationBitmap aAnimBmp( aNewAnim.Get( i ) ); 256 257 // BitmapEx spiegeln 258 aAnimBmp.aBmpEx.Mirror( nMirrorFlags ); 259 260 // Die Positionen innerhalb der Gesamtbitmap 261 // muessen natuerlich auch angepasst werden 262 if( bHMirr ) 263 aAnimBmp.aPosPix.X() = rGlobalSize.Width() - aAnimBmp.aPosPix.X() - 264 aAnimBmp.aSizePix.Width(); 265 266 if( bVMirr ) 267 aAnimBmp.aPosPix.Y() = rGlobalSize.Height() - aAnimBmp.aPosPix.Y() - 268 aAnimBmp.aSizePix.Height(); 269 270 aNewAnim.Replace( aAnimBmp, i ); 271 } 272 } 273 274 return aNewAnim; 275 } 276 277 // ------------------------------------------------------------------------ 278 279 Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const sal_uIntPtr nMirrorFlags ) 280 { 281 Graphic aRetGraphic; 282 283 if( nMirrorFlags ) 284 { 285 if( rGraphic.IsAnimated() ) 286 { 287 aRetGraphic = MirrorAnimation( rGraphic.GetAnimation(), 288 ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ, 289 ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT ); 290 } 291 else 292 { 293 if( rGraphic.IsTransparent() ) 294 { 295 BitmapEx aBmpEx( rGraphic.GetBitmapEx() ); 296 297 aBmpEx.Mirror( nMirrorFlags ); 298 aRetGraphic = aBmpEx; 299 } 300 else 301 { 302 Bitmap aBmp( rGraphic.GetBitmap() ); 303 304 aBmp.Mirror( nMirrorFlags ); 305 aRetGraphic = aBmp; 306 } 307 } 308 } 309 else 310 aRetGraphic = rGraphic; 311 312 return aRetGraphic; 313 } 314 315 // ------------------------------------------------------------------------ 316 317 sal_uInt16 XOutBitmap::WriteGraphic( const Graphic& rGraphic, String& rFileName, 318 const String& rFilterName, const sal_uIntPtr nFlags, 319 const Size* pMtfSize_100TH_MM ) 320 { 321 if( rGraphic.GetType() != GRAPHIC_NONE ) 322 { 323 INetURLObject aURL( rFileName ); 324 Graphic aGraphic; 325 String aExt; 326 GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); 327 sal_uInt16 nErr = GRFILTER_FILTERERROR, nFilter = GRFILTER_FORMAT_NOTFOUND; 328 sal_Bool bTransparent = rGraphic.IsTransparent(), bAnimated = rGraphic.IsAnimated(); 329 330 DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "XOutBitmap::WriteGraphic(...): invalid URL" ); 331 332 // calculate correct file name 333 if( !( nFlags & XOUTBMP_DONT_EXPAND_FILENAME ) ) 334 { 335 String aName( aURL.getBase() ); 336 aName += '_'; 337 aName += String(aURL.getExtension()); 338 aName += '_'; 339 String aStr( String::CreateFromInt32( rGraphic.GetChecksum(), 16 ) ); 340 if ( aStr.GetChar(0) == '-' ) 341 aStr.SetChar(0,'m'); 342 aName += aStr; 343 aURL.setBase( aName ); 344 } 345 346 if( ( nFlags & XOUTBMP_USE_NATIVE_IF_POSSIBLE ) && 347 !( nFlags & XOUTBMP_MIRROR_HORZ ) && 348 !( nFlags & XOUTBMP_MIRROR_VERT ) && 349 ( rGraphic.GetType() != GRAPHIC_GDIMETAFILE ) && rGraphic.IsLink() ) 350 { 351 // try to write native link 352 const GfxLink aGfxLink( ( (Graphic&) rGraphic ).GetLink() ); 353 354 switch( aGfxLink.GetType() ) 355 { 356 case( GFX_LINK_TYPE_NATIVE_GIF ): aExt = FORMAT_GIF; break; 357 case( GFX_LINK_TYPE_NATIVE_JPG ): aExt = FORMAT_JPG; break; 358 case( GFX_LINK_TYPE_NATIVE_PNG ): aExt = FORMAT_PNG; break; 359 360 default: 361 break; 362 } 363 364 if( aExt.Len() ) 365 { 366 if( 0 == (nFlags & XOUTBMP_DONT_ADD_EXTENSION)) 367 aURL.setExtension( aExt ); 368 rFileName = aURL.GetMainURL( INetURLObject::NO_DECODE ); 369 370 SfxMedium aMedium( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_SHARE_DENYNONE | STREAM_TRUNC, sal_True ); 371 SvStream* pOStm = aMedium.GetOutStream(); 372 373 if( pOStm && aGfxLink.GetDataSize() && aGfxLink.GetData() ) 374 { 375 pOStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() ); 376 aMedium.Commit(); 377 378 if( !aMedium.GetError() ) 379 nErr = GRFILTER_OK; 380 } 381 } 382 } 383 384 if( GRFILTER_OK != nErr ) 385 { 386 String aFilter( rFilterName ); 387 sal_Bool bWriteTransGrf = ( aFilter.EqualsIgnoreCaseAscii( "transgrf" ) ) || 388 ( aFilter.EqualsIgnoreCaseAscii( "gif" ) ) || 389 ( nFlags & XOUTBMP_USE_GIF_IF_POSSIBLE ) || 390 ( ( nFlags & XOUTBMP_USE_GIF_IF_SENSIBLE ) && ( bAnimated || bTransparent ) ); 391 392 // get filter and extension 393 if( bWriteTransGrf ) 394 aFilter = FORMAT_GIF; 395 396 nFilter = pFilter->GetExportFormatNumberForShortName( aFilter ); 397 398 if( GRFILTER_FORMAT_NOTFOUND == nFilter ) 399 { 400 nFilter = pFilter->GetExportFormatNumberForShortName( FORMAT_JPG ); 401 402 if( GRFILTER_FORMAT_NOTFOUND == nFilter ) 403 nFilter = pFilter->GetExportFormatNumberForShortName( FORMAT_BMP ); 404 } 405 406 if( GRFILTER_FORMAT_NOTFOUND != nFilter ) 407 { 408 aExt = pFilter->GetExportFormatShortName( nFilter ).ToLowerAscii(); 409 410 if( bWriteTransGrf ) 411 { 412 if( bAnimated ) 413 aGraphic = rGraphic; 414 else 415 { 416 if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GRAPHIC_BITMAP ) ) 417 { 418 VirtualDevice aVDev; 419 const Size aSize( aVDev.LogicToPixel( *pMtfSize_100TH_MM, MAP_100TH_MM ) ); 420 421 if( aVDev.SetOutputSizePixel( aSize ) ) 422 { 423 const Wallpaper aWallpaper( aVDev.GetBackground() ); 424 const Point aPt; 425 426 aVDev.SetBackground( Wallpaper( Color( COL_BLACK ) ) ); 427 aVDev.Erase(); 428 rGraphic.Draw( &aVDev, aPt, aSize ); 429 430 const Bitmap aBitmap( aVDev.GetBitmap( aPt, aSize ) ); 431 432 aVDev.SetBackground( aWallpaper ); 433 aVDev.Erase(); 434 rGraphic.Draw( &aVDev, aPt, aSize ); 435 436 aVDev.SetRasterOp( ROP_XOR ); 437 aVDev.DrawBitmap( aPt, aSize, aBitmap ); 438 aGraphic = BitmapEx( aBitmap, aVDev.GetBitmap( aPt, aSize ) ); 439 } 440 else 441 aGraphic = rGraphic.GetBitmapEx(); 442 } 443 else 444 aGraphic = rGraphic.GetBitmapEx(); 445 } 446 } 447 else 448 { 449 if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GRAPHIC_BITMAP ) ) 450 { 451 VirtualDevice aVDev; 452 const Size aSize( aVDev.LogicToPixel( *pMtfSize_100TH_MM, MAP_100TH_MM ) ); 453 454 if( aVDev.SetOutputSizePixel( aSize ) ) 455 { 456 rGraphic.Draw( &aVDev, Point(), aSize ); 457 aGraphic = aVDev.GetBitmap( Point(), aSize ); 458 } 459 else 460 aGraphic = rGraphic.GetBitmap(); 461 } 462 else 463 aGraphic = rGraphic.GetBitmap(); 464 } 465 466 // mirror? 467 if( ( nFlags & XOUTBMP_MIRROR_HORZ ) || ( nFlags & XOUTBMP_MIRROR_VERT ) ) 468 aGraphic = MirrorGraphic( aGraphic, nFlags ); 469 470 if( ( GRFILTER_FORMAT_NOTFOUND != nFilter ) && ( aGraphic.GetType() != GRAPHIC_NONE ) ) 471 { 472 if( 0 == (nFlags & XOUTBMP_DONT_ADD_EXTENSION)) 473 aURL.setExtension( aExt ); 474 rFileName = aURL.GetMainURL( INetURLObject::NO_DECODE ); 475 nErr = ExportGraphic( aGraphic, aURL, *pFilter, nFilter, NULL ); 476 } 477 } 478 } 479 480 return nErr; 481 } 482 else 483 { 484 return GRFILTER_OK; 485 } 486 } 487 488 // ------------------------------------------------------------------------ 489 490 #ifdef _MSC_VER 491 #pragma optimize ( "", off ) 492 #endif 493 494 sal_uInt16 XOutBitmap::ExportGraphic( const Graphic& rGraphic, const INetURLObject& rURL, 495 GraphicFilter& rFilter, const sal_uInt16 nFormat, 496 const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData ) 497 { 498 DBG_ASSERT( rURL.GetProtocol() != INET_PROT_NOT_VALID, "XOutBitmap::ExportGraphic(...): invalid URL" ); 499 500 SfxMedium aMedium( rURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_SHARE_DENYNONE | STREAM_TRUNC, sal_True ); 501 SvStream* pOStm = aMedium.GetOutStream(); 502 sal_uInt16 nRet = GRFILTER_IOERROR; 503 504 if( pOStm ) 505 { 506 pGrfFilter = &rFilter; 507 508 nRet = rFilter.ExportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::NO_DECODE ), *pOStm, nFormat, pFilterData ); 509 510 pGrfFilter = NULL; 511 aMedium.Commit(); 512 513 if( aMedium.GetError() && ( GRFILTER_OK == nRet ) ) 514 nRet = GRFILTER_IOERROR; 515 } 516 517 return nRet; 518 } 519 520 #ifdef _MSC_VER 521 #pragma optimize ( "", on ) 522 #endif 523 524 // ------------------------------------------------------------------------ 525 526 Bitmap XOutBitmap::DetectEdges( const Bitmap& rBmp, const sal_uInt8 cThreshold ) 527 { 528 const Size aSize( rBmp.GetSizePixel() ); 529 Bitmap aRetBmp; 530 sal_Bool bRet = sal_False; 531 532 if( ( aSize.Width() > 2L ) && ( aSize.Height() > 2L ) ) 533 { 534 Bitmap aWorkBmp( rBmp ); 535 536 if( aWorkBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) ) 537 { 538 Bitmap aDstBmp( aSize, 1 ); 539 BitmapReadAccess* pReadAcc = aWorkBmp.AcquireReadAccess(); 540 BitmapWriteAccess* pWriteAcc = aDstBmp.AcquireWriteAccess(); 541 542 if( pReadAcc && pWriteAcc ) 543 { 544 const long nWidth = aSize.Width(); 545 const long nWidth2 = nWidth - 2L; 546 const long nHeight = aSize.Height(); 547 const long nHeight2 = nHeight - 2L; 548 const long lThres2 = (long) cThreshold * cThreshold; 549 const BitmapColor aWhite = (sal_uInt8) pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ); 550 const BitmapColor aBlack = (sal_uInt8) pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ); 551 long nSum1; 552 long nSum2; 553 long lGray; 554 555 // Rand mit Weiss init. 556 pWriteAcc->SetLineColor( Color( COL_WHITE) ); 557 pWriteAcc->DrawLine( Point(), Point( nWidth - 1L, 0L ) ); 558 pWriteAcc->DrawLine( Point( nWidth - 1L, 0L ), Point( nWidth - 1L, nHeight - 1L ) ); 559 pWriteAcc->DrawLine( Point( nWidth - 1L, nHeight - 1L ), Point( 0L, nHeight - 1L ) ); 560 pWriteAcc->DrawLine( Point( 0, nHeight - 1L ), Point() ); 561 562 for( long nY = 0L, nY1 = 1L, nY2 = 2; nY < nHeight2; nY++, nY1++, nY2++ ) 563 { 564 for( long nX = 0L, nXDst = 1L, nXTmp; nX < nWidth2; nX++, nXDst++ ) 565 { 566 nXTmp = nX; 567 568 nSum1 = -( nSum2 = lGray = (sal_uInt8) pReadAcc->GetPixel( nY, nXTmp++ ) ); 569 nSum2 += ( (long) (sal_uInt8) pReadAcc->GetPixel( nY, nXTmp++ ) ) << 1; 570 nSum1 += ( lGray = pReadAcc->GetPixel( nY, nXTmp ) ); 571 nSum2 += lGray; 572 573 nSum1 += ( (long) (sal_uInt8) pReadAcc->GetPixel( nY1, nXTmp ) ) << 1; 574 nSum1 -= ( (long) (sal_uInt8) pReadAcc->GetPixel( nY1, nXTmp -= 2 ) ) << 1; 575 576 nSum1 += ( lGray = -(long) (sal_uInt8) pReadAcc->GetPixel( nY2, nXTmp++ ) ); 577 nSum2 += lGray; 578 nSum2 -= ( (long) (sal_uInt8) pReadAcc->GetPixel( nY2, nXTmp++ ) ) << 1; 579 nSum1 += ( lGray = (long) (sal_uInt8) pReadAcc->GetPixel( nY2, nXTmp ) ); 580 nSum2 -= lGray; 581 582 if( ( nSum1 * nSum1 + nSum2 * nSum2 ) < lThres2 ) 583 pWriteAcc->SetPixel( nY1, nXDst, aWhite ); 584 else 585 pWriteAcc->SetPixel( nY1, nXDst, aBlack ); 586 } 587 } 588 589 bRet = sal_True; 590 } 591 592 aWorkBmp.ReleaseAccess( pReadAcc ); 593 aDstBmp.ReleaseAccess( pWriteAcc ); 594 595 if( bRet ) 596 aRetBmp = aDstBmp; 597 } 598 } 599 600 if( !aRetBmp ) 601 aRetBmp = rBmp; 602 else 603 { 604 aRetBmp.SetPrefMapMode( rBmp.GetPrefMapMode() ); 605 aRetBmp.SetPrefSize( rBmp.GetPrefSize() ); 606 } 607 608 return aRetBmp; 609 }; 610 611 // ------------------------------------------------------------------------ 612 613 Polygon XOutBitmap::GetCountour( const Bitmap& rBmp, const sal_uIntPtr nFlags, 614 const sal_uInt8 cEdgeDetectThreshold, const Rectangle* pWorkRectPixel ) 615 { 616 Bitmap aWorkBmp; 617 Polygon aRetPoly; 618 Point aTmpPoint; 619 Rectangle aWorkRect( aTmpPoint, rBmp.GetSizePixel() ); 620 621 if( pWorkRectPixel ) 622 aWorkRect.Intersection( *pWorkRectPixel ); 623 624 aWorkRect.Justify(); 625 626 if( ( aWorkRect.GetWidth() > 4 ) && ( aWorkRect.GetHeight() > 4 ) ) 627 { 628 // falls Flag gesetzt, muessen wir Kanten detektieren 629 if( nFlags & XOUTBMP_CONTOUR_EDGEDETECT ) 630 aWorkBmp = DetectEdges( rBmp, cEdgeDetectThreshold ); 631 else 632 aWorkBmp = rBmp; 633 634 BitmapReadAccess* pAcc = aWorkBmp.AcquireReadAccess(); 635 636 if( pAcc ) 637 { 638 const Size& rPrefSize = aWorkBmp.GetPrefSize(); 639 const long nWidth = pAcc->Width(); 640 const long nHeight = pAcc->Height(); 641 const double fFactorX = (double) rPrefSize.Width() / nWidth; 642 const double fFactorY = (double) rPrefSize.Height() / nHeight; 643 const long nStartX1 = aWorkRect.Left() + 1L; 644 const long nEndX1 = aWorkRect.Right(); 645 const long nStartX2 = nEndX1 - 1L; 646 // const long nEndX2 = nStartX1 - 1L; 647 const long nStartY1 = aWorkRect.Top() + 1L; 648 const long nEndY1 = aWorkRect.Bottom(); 649 const long nStartY2 = nEndY1 - 1L; 650 // const long nEndY2 = nStartY1 - 1L; 651 Point* pPoints1 = NULL; 652 Point* pPoints2 = NULL; 653 long nX, nY; 654 sal_uInt16 nPolyPos = 0; 655 const BitmapColor aBlack = pAcc->GetBestMatchingColor( Color( COL_BLACK ) ); 656 657 if( nFlags & XOUTBMP_CONTOUR_VERT ) 658 { 659 pPoints1 = new Point[ nWidth ]; 660 pPoints2 = new Point[ nWidth ]; 661 662 for( nX = nStartX1; nX < nEndX1; nX++ ) 663 { 664 nY = nStartY1; 665 666 // zunaechst Zeile von Links nach Rechts durchlaufen 667 while( nY < nEndY1 ) 668 { 669 if( aBlack == pAcc->GetPixel( nY, nX ) ) 670 { 671 pPoints1[ nPolyPos ] = Point( nX, nY ); 672 nY = nStartY2; 673 674 // diese Schleife wird immer gebreaked da hier ja min. ein Pixel ist 675 while( sal_True ) 676 { 677 if( aBlack == pAcc->GetPixel( nY, nX ) ) 678 { 679 pPoints2[ nPolyPos ] = Point( nX, nY ); 680 break; 681 } 682 683 nY--; 684 } 685 686 nPolyPos++; 687 break; 688 } 689 690 nY++; 691 } 692 } 693 } 694 else 695 { 696 pPoints1 = new Point[ nHeight ]; 697 pPoints2 = new Point[ nHeight ]; 698 699 for ( nY = nStartY1; nY < nEndY1; nY++ ) 700 { 701 nX = nStartX1; 702 703 // zunaechst Zeile von Links nach Rechts durchlaufen 704 while( nX < nEndX1 ) 705 { 706 if( aBlack == pAcc->GetPixel( nY, nX ) ) 707 { 708 pPoints1[ nPolyPos ] = Point( nX, nY ); 709 nX = nStartX2; 710 711 // diese Schleife wird immer gebreaked da hier ja min. ein Pixel ist 712 while( sal_True ) 713 { 714 if( aBlack == pAcc->GetPixel( nY, nX ) ) 715 { 716 pPoints2[ nPolyPos ] = Point( nX, nY ); 717 break; 718 } 719 720 nX--; 721 } 722 723 nPolyPos++; 724 break; 725 } 726 727 nX++; 728 } 729 } 730 } 731 732 const sal_uInt16 nNewSize1 = nPolyPos << 1; 733 734 aRetPoly = Polygon( nPolyPos, pPoints1 ); 735 aRetPoly.SetSize( nNewSize1 + 1 ); 736 aRetPoly[ nNewSize1 ] = aRetPoly[ 0 ]; 737 738 for( sal_uInt16 j = nPolyPos; nPolyPos < nNewSize1; ) 739 aRetPoly[ nPolyPos++ ] = pPoints2[ --j ]; 740 741 if( ( fFactorX != 0. ) && ( fFactorY != 0. ) ) 742 aRetPoly.Scale( fFactorX, fFactorY ); 743 744 delete[] pPoints1; 745 delete[] pPoints2; 746 } 747 } 748 749 return aRetPoly; 750 }; 751 752 // ---------------- 753 // - DitherBitmap - 754 // ---------------- 755 756 sal_Bool DitherBitmap( Bitmap& rBitmap ) 757 { 758 sal_Bool bRet = sal_False; 759 760 if( ( rBitmap.GetBitCount() >= 8 ) && ( Application::GetDefaultDevice()->GetColorCount() < 257 ) ) 761 bRet = rBitmap.Dither( BMP_DITHER_FLOYD ); 762 else 763 bRet = sal_False; 764 765 return bRet; 766 } 767