LibreOffice Module vcl (master)  1
bitmapex.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/log.hxx>
22 #include <osl/diagnose.h>
25 
26 #include <vcl/ImageTree.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/alpha.hxx>
29 #include <vcl/bitmapex.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/bitmapaccess.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/settings.hxx>
35 
36 // BitmapEx::Create
37 #include <salbmp.hxx>
38 #include <salinst.hxx>
39 #include <svdata.hxx>
40 #include <bitmapwriteaccess.hxx>
41 
42 #include <o3tl/any.hxx>
43 
44 #include <com/sun/star/beans/XFastPropertySet.hpp>
45 
46 #include <memory>
47 
48 using namespace ::com::sun::star;
49 
51  : meTransparent(TransparentType::NONE)
52  , mbAlpha(false)
53 {
54 }
55 
56 BitmapEx::BitmapEx( const BitmapEx& ) = default;
57 
58 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize )
59  : meTransparent(TransparentType::NONE)
60  , mbAlpha(false)
61 {
62  if( rBitmapEx.IsEmpty() )
63  return;
64 
65  maBitmap = Bitmap( aSize, rBitmapEx.maBitmap.GetBitCount() );
66  SetSizePixel(aSize);
67  if( rBitmapEx.IsAlpha() )
68  {
69  mbAlpha = true;
70  maMask = AlphaMask( aSize ).ImplGetBitmap();
71  }
72  else if( rBitmapEx.IsTransparent() )
73  maMask = Bitmap( aSize, rBitmapEx.maMask.GetBitCount() );
74 
75  tools::Rectangle aDestRect( Point( 0, 0 ), aSize );
76  tools::Rectangle aSrcRect( aSrc, aSize );
77  CopyPixel( aDestRect, aSrcRect, &rBitmapEx );
78 }
79 
80 BitmapEx::BitmapEx( Size aSize, sal_uInt16 nBitCount )
81  : meTransparent(TransparentType::NONE)
82  , mbAlpha(false)
83 {
84  maBitmap = Bitmap( aSize, nBitCount );
85  SetSizePixel(aSize);
86 }
87 
88 BitmapEx::BitmapEx( const OUString& rIconName )
89  : meTransparent(TransparentType::NONE)
90  , mbAlpha(false)
91 {
92  loadFromIconTheme( rIconName );
93 }
94 
95 void BitmapEx::loadFromIconTheme( const OUString& rIconName )
96 {
97  bool bSuccess;
98  OUString aIconTheme;
99 
100  try
101  {
103  bSuccess = ImageTree::get().loadImage(rIconName, aIconTheme, *this, true);
104  }
105  catch (...)
106  {
107  bSuccess = false;
108  }
109 
110  SAL_WARN_IF( !bSuccess, "vcl", "BitmapEx::BitmapEx(): could not load image " << rIconName << " via icon theme " << aIconTheme);
111 }
112 
113 BitmapEx::BitmapEx( const Bitmap& rBmp ) :
114  maBitmap ( rBmp ),
115  maBitmapSize ( maBitmap.GetSizePixel() ),
116  meTransparent( TransparentType::NONE ),
117  mbAlpha ( false )
118 {
119 }
120 
121 BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
122  maBitmap ( rBmp ),
123  maMask ( rMask ),
124  maBitmapSize ( maBitmap.GetSizePixel() ),
125  meTransparent ( !rMask ? TransparentType::NONE : TransparentType::Bitmap ),
126  mbAlpha ( false )
127 {
128  // Ensure a mask is exactly one bit deep
129  if( !!maMask && maMask.GetBitCount() != 1 )
130  {
131  SAL_WARN( "vcl", "BitmapEx: forced mask to monochrome");
132  BitmapEx aMaskEx(maMask);
134  maMask = aMaskEx.GetBitmap();
135  }
136 
138  {
139  OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)");
141  }
142 }
143 
144 BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
145  maBitmap ( rBmp ),
146  maMask ( rAlphaMask.ImplGetBitmap() ),
147  maBitmapSize ( maBitmap.GetSizePixel() ),
148  meTransparent ( !rAlphaMask ? TransparentType::NONE : TransparentType::Bitmap ),
149  mbAlpha ( !rAlphaMask.IsEmpty() )
150 {
152  {
153  OSL_ENSURE(false, "Alpha size differs from Bitmap size, corrected Mask (!)");
154  maMask.Scale(rBmp.GetSizePixel());
155  }
156 
157  // #i75531# the workaround below can go when
158  // X11SalGraphics::drawAlphaBitmap()'s render acceleration
159  // can handle the bitmap depth mismatch directly
162 }
163 
164 BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
165  maBitmap ( rBmp ),
166  maBitmapSize ( maBitmap.GetSizePixel() ),
167  maTransparentColor ( rTransparentColor ),
168  meTransparent ( TransparentType::Bitmap ),
169  mbAlpha ( false )
170 {
172 
173  SAL_WARN_IF(rBmp.GetSizePixel() != maMask.GetSizePixel(), "vcl",
174  "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask.");
175 }
176 
177 BitmapEx& BitmapEx::operator=( const BitmapEx& ) = default;
178 
179 bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
180 {
181  if (meTransparent != rBitmapEx.meTransparent)
182  return false;
183 
184  if (GetSizePixel() != rBitmapEx.GetSizePixel())
185  return false;
186 
187  if (meTransparent != rBitmapEx.meTransparent)
188  return false;
189 
191  && maTransparentColor != rBitmapEx.maTransparentColor)
192  return false;
193 
194  if (mbAlpha != rBitmapEx.mbAlpha)
195  return false;
196 
197  if (maBitmap != rBitmapEx.maBitmap)
198  return false;
199 
200  return maMask == rBitmapEx.maMask;
201 }
202 
203 bool BitmapEx::IsEmpty() const
204 {
205  return( maBitmap.IsEmpty() && maMask.IsEmpty() );
206 }
207 
209 {
210  maBitmap.SetEmpty();
211  maMask.SetEmpty();
213  mbAlpha = false;
214 }
215 
217 {
218  SetEmpty();
219 }
220 
222 {
224 }
225 
226 bool BitmapEx::IsAlpha() const
227 {
228  return( IsTransparent() && mbAlpha );
229 }
230 
232 {
233  return maBitmap;
234 }
235 
236 Bitmap BitmapEx::GetBitmap( Color aTransparentReplaceColor ) const
237 {
238  Bitmap aRetBmp( maBitmap );
239 
241  {
242  Bitmap aTempMask;
243 
245  aTempMask = maBitmap.CreateMask( maTransparentColor );
246  else
247  aTempMask = maMask;
248 
249  if( !IsAlpha() )
250  aRetBmp.Replace( aTempMask, aTransparentReplaceColor );
251  else
252  aRetBmp.Replace( GetAlpha(), aTransparentReplaceColor );
253  }
254 
255  return aRetBmp;
256 }
257 
259 {
260  if (!IsAlpha())
261  return maMask;
262 
263  BitmapEx aMaskEx(maMask);
265  return aMaskEx.GetBitmap();
266 }
267 
269 {
270  if( IsAlpha() )
271  {
272  AlphaMask aAlpha;
273  aAlpha.ImplSetBitmap( maMask );
274  return aAlpha;
275  }
276  else
277  {
278  return AlphaMask(maMask);
279  }
280 }
281 
283 {
284  sal_uLong nSizeBytes = maBitmap.GetSizeBytes();
285 
287  nSizeBytes += maMask.GetSizeBytes();
288 
289  return nSizeBytes;
290 }
291 
293 {
295  SVBT32 aBT32;
297 
298  UInt32ToSVBT32( o3tl::underlyingEnumValue(meTransparent), aBT32 );
299  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
300 
301  UInt32ToSVBT32( sal_uInt32(mbAlpha), aBT32 );
302  nCrc = vcl_get_checksum( nCrc, aBT32, 4 );
303 
305  {
306  BCToBCOA( maMask.GetChecksum(), aBCOA );
307  nCrc = vcl_get_checksum( nCrc, aBCOA, BITMAP_CHECKSUM_SIZE );
308  }
309 
310  return nCrc;
311 }
312 
313 void BitmapEx::SetSizePixel(const Size& rNewSize)
314 {
315  maBitmapSize = rNewSize;
316 }
317 
319 {
320  bool bRet = false;
321 
322  if (!!maBitmap)
323  {
324  bRet = maBitmap.Invert();
325 
326  if (bRet && (meTransparent == TransparentType::Color))
328  }
329 
330  return bRet;
331 }
332 
333 bool BitmapEx::Mirror( BmpMirrorFlags nMirrorFlags )
334 {
335  bool bRet = false;
336 
337  if( !!maBitmap )
338  {
339  bRet = maBitmap.Mirror( nMirrorFlags );
340 
341  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
342  maMask.Mirror( nMirrorFlags );
343  }
344 
345  return bRet;
346 }
347 
348 bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
349 {
350  bool bRet = false;
351 
352  if( !!maBitmap )
353  {
354  bRet = maBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
355 
356  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
357  {
358  maMask.Scale( rScaleX, rScaleY, nScaleFlag );
359  }
360 
362 
364  "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
365  }
366 
367  return bRet;
368 }
369 
370 bool BitmapEx::Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag )
371 {
372  bool bRet;
373 
374  if (GetSizePixel().Width() && GetSizePixel().Height()
375  && (rNewSize.Width() != GetSizePixel().Width()
376  || rNewSize.Height() != GetSizePixel().Height() ) )
377  {
378  bRet = Scale( static_cast<double>(rNewSize.Width()) / GetSizePixel().Width(),
379  static_cast<double>(rNewSize.Height()) / GetSizePixel().Height(),
380  nScaleFlag );
381  }
382  else
383  {
384  bRet = true;
385  }
386 
387  return bRet;
388 }
389 
390 bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
391 {
392  bool bRet = false;
393 
394  if( !!maBitmap )
395  {
396  const bool bTransRotate = ( COL_TRANSPARENT == rFillColor );
397 
398  if( bTransRotate )
399  {
401  bRet = maBitmap.Rotate( nAngle10, maTransparentColor );
402  else
403  {
404  bRet = maBitmap.Rotate( nAngle10, COL_BLACK );
405 
407  {
408  maMask = Bitmap(GetSizePixel(), 1);
411  }
412 
413  if( bRet && !!maMask )
414  maMask.Rotate( nAngle10, COL_WHITE );
415  }
416  }
417  else
418  {
419  bRet = maBitmap.Rotate( nAngle10, rFillColor );
420 
421  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
422  maMask.Rotate( nAngle10, COL_WHITE );
423  }
424 
426 
428  "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask.");
429  }
430 
431  return bRet;
432 }
433 
434 bool BitmapEx::Crop( const tools::Rectangle& rRectPixel )
435 {
436  bool bRet = false;
437 
438  if( !!maBitmap )
439  {
440  bRet = maBitmap.Crop( rRectPixel );
441 
442  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
443  maMask.Crop( rRectPixel );
444 
446 
448  "BitmapEx::Crop(): size mismatch for bitmap and alpha mask.");
449  }
450 
451  return bRet;
452 }
453 
454 bool BitmapEx::Convert( BmpConversion eConversion )
455 {
456  return !!maBitmap && maBitmap.Convert( eConversion );
457 }
458 
459 void BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, bool bExpandTransparent )
460 {
461  bool bRet = false;
462 
463  if( !!maBitmap )
464  {
465  bRet = maBitmap.Expand( nDX, nDY );
466 
467  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
468  {
469  Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
470  maMask.Expand( nDX, nDY, &aColor );
471  }
472 
474 
476  "BitmapEx::Expand(): size mismatch for bitmap and alpha mask.");
477  }
478 }
479 
480 bool BitmapEx::CopyPixel( const tools::Rectangle& rRectDst, const tools::Rectangle& rRectSrc,
481  const BitmapEx* pBmpExSrc )
482 {
483  bool bRet = false;
484 
485  if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
486  {
487  if( !maBitmap.IsEmpty() )
488  {
489  bRet = maBitmap.CopyPixel( rRectDst, rRectSrc );
490 
491  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
492  maMask.CopyPixel( rRectDst, rRectSrc );
493  }
494  }
495  else
496  {
497  if( !maBitmap.IsEmpty() )
498  {
499  bRet = maBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->maBitmap );
500 
501  if( bRet )
502  {
503  if( pBmpExSrc->IsAlpha() )
504  {
505  if( IsAlpha() )
506  // cast to use the optimized AlphaMask::CopyPixel
507  maMask.CopyPixel_AlphaOptimized( rRectDst, rRectSrc, &pBmpExSrc->maMask );
508  else if( IsTransparent() )
509  {
510  std::unique_ptr<AlphaMask> pAlpha(new AlphaMask( maMask ));
511 
512  maMask = pAlpha->ImplGetBitmap();
513  pAlpha.reset();
514  mbAlpha = true;
515  maMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->maMask );
516  }
517  else
518  {
519  sal_uInt8 cBlack = 0;
520  std::unique_ptr<AlphaMask> pAlpha(new AlphaMask(GetSizePixel(), &cBlack));
521 
522  maMask = pAlpha->ImplGetBitmap();
523  pAlpha.reset();
525  mbAlpha = true;
526  maMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->maMask );
527  }
528  }
529  else if( pBmpExSrc->IsTransparent() )
530  {
531  if (IsAlpha())
532  {
533  AlphaMask aAlpha( pBmpExSrc->maMask );
534  maMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
535  }
536  else if (IsTransparent())
537  {
538  maMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->maMask );
539  }
540  else
541  {
542  maMask = Bitmap(GetSizePixel(), 1);
545  maMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->maMask );
546  }
547  }
548  else if (IsAlpha())
549  {
550  sal_uInt8 cBlack = 0;
551  const AlphaMask aAlphaSrc(pBmpExSrc->GetSizePixel(), &cBlack);
552 
553  maMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
554  }
555  else if (IsTransparent())
556  {
557  Bitmap aMaskSrc(pBmpExSrc->GetSizePixel(), 1);
558 
559  aMaskSrc.Erase( COL_BLACK );
560  maMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
561  }
562  }
563  }
564  }
565 
566  return bRet;
567 }
568 
569 bool BitmapEx::Erase( const Color& rFillColor )
570 {
571  bool bRet = false;
572 
573  if( !!maBitmap )
574  {
575  bRet = maBitmap.Erase( rFillColor );
576 
577  if( bRet && ( meTransparent == TransparentType::Bitmap ) && !!maMask )
578  {
579  // Respect transparency on fill color
580  if( rFillColor.GetTransparency() )
581  {
582  const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
583  maMask.Erase( aFill );
584  }
585  else
586  {
587  const Color aBlack( COL_BLACK );
588  maMask.Erase( aBlack );
589  }
590  }
591  }
592 
593  return bRet;
594 }
595 
596 void BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor )
597 {
598  if (!!maBitmap)
599  maBitmap.Replace( rSearchColor, rReplaceColor );
600 }
601 
602 void BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount )
603 {
604  if (!!maBitmap)
605  maBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, /*pTols*/nullptr );
606 }
607 
608 bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
609  short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
610  double fGamma, bool bInvert, bool msoBrightness )
611 {
612  return !!maBitmap && maBitmap.Adjust( nLuminancePercent, nContrastPercent,
613  nChannelRPercent, nChannelGPercent, nChannelBPercent,
614  fGamma, bInvert, msoBrightness );
615 }
616 
617 void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
618 {
619  pOutDev->DrawBitmapEx( rDestPt, *this );
620 }
621 
623  const Point& rDestPt, const Size& rDestSize ) const
624 {
625  pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
626 }
627 
628 BitmapEx BitmapEx:: AutoScaleBitmap(BitmapEx const & aBitmap, const long aStandardSize)
629 {
630  Point aEmptyPoint(0,0);
631  double imgposX = 0;
632  double imgposY = 0;
633  BitmapEx aRet = aBitmap;
634  double imgOldWidth = aRet.GetSizePixel().Width();
635  double imgOldHeight = aRet.GetSizePixel().Height();
636 
637  Size aScaledSize;
638  if (imgOldWidth >= aStandardSize || imgOldHeight >= aStandardSize)
639  {
640  sal_Int32 imgNewWidth = 0;
641  sal_Int32 imgNewHeight = 0;
642  if (imgOldWidth >= imgOldHeight)
643  {
644  imgNewWidth = aStandardSize;
645  imgNewHeight = sal_Int32(imgOldHeight / (imgOldWidth / aStandardSize) + 0.5);
646  imgposX = 0;
647  imgposY = (aStandardSize - (imgOldHeight / (imgOldWidth / aStandardSize) + 0.5)) / 2 + 0.5;
648  }
649  else
650  {
651  imgNewHeight = aStandardSize;
652  imgNewWidth = sal_Int32(imgOldWidth / (imgOldHeight / aStandardSize) + 0.5);
653  imgposY = 0;
654  imgposX = (aStandardSize - (imgOldWidth / (imgOldHeight / aStandardSize) + 0.5)) / 2 + 0.5;
655  }
656 
657  aScaledSize = Size( imgNewWidth, imgNewHeight );
658  aRet.Scale( aScaledSize, BmpScaleFlag::BestQuality );
659  }
660  else
661  {
662  imgposX = (aStandardSize - imgOldWidth) / 2 + 0.5;
663  imgposY = (aStandardSize - imgOldHeight) / 2 + 0.5;
664  }
665 
666  Size aStdSize( aStandardSize, aStandardSize );
667  tools::Rectangle aRect(aEmptyPoint, aStdSize );
668 
671  aVirDevice->SetOutputSizePixel( aStdSize );
672  aVirDevice->SetFillColor( COL_TRANSPARENT );
673  aVirDevice->SetLineColor( COL_TRANSPARENT );
674 
675  // Draw a rect into virDevice
676  aVirDevice->DrawRect( aRect );
677  Point aPointPixel( static_cast<long>(imgposX), static_cast<long>(imgposY) );
678  aVirDevice->DrawBitmapEx( aPointPixel, aRet );
679  aRet = aVirDevice->GetBitmapEx( aEmptyPoint, aStdSize );
680 
681  return aRet;
682 }
683 
684 sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
685 {
686  sal_uInt8 nTransparency(0xff);
687 
688  if(!maBitmap.IsEmpty())
689  {
690  if (nX >= 0 && nX < GetSizePixel().Width() && nY >= 0 && nY < GetSizePixel().Height())
691  {
692  if (maBitmap.GetBitCount() == 32)
693  return GetPixelColor(nX, nY).GetTransparency();
694  switch(meTransparent)
695  {
697  {
698  // Not transparent, ergo all covered
699  nTransparency = 0x00;
700  break;
701  }
703  {
704  Bitmap aTestBitmap(maBitmap);
705  Bitmap::ScopedReadAccess pRead(aTestBitmap);
706 
707  if(pRead)
708  {
709  const BitmapColor aBmpColor = pRead->GetColor(nY, nX);
710 
711  // If color is not equal to TransparentColor, we are not transparent
712  if (aBmpColor != maTransparentColor)
713  nTransparency = 0x00;
714 
715  }
716  break;
717  }
719  {
720  if(!maMask.IsEmpty())
721  {
722  Bitmap aTestBitmap(maMask);
723  Bitmap::ScopedReadAccess pRead(aTestBitmap);
724 
725  if(pRead)
726  {
727  const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
728 
729  if(mbAlpha)
730  {
731  nTransparency = aBitmapColor.GetIndex();
732  }
733  else
734  {
735  if(0x00 == aBitmapColor.GetIndex())
736  {
737  nTransparency = 0x00;
738  }
739  }
740  }
741  }
742  break;
743  }
744  }
745  }
746  }
747 
748  return nTransparency;
749 }
750 
751 
752 Color BitmapEx::GetPixelColor(sal_Int32 nX, sal_Int32 nY) const
753 {
754  Bitmap::ScopedReadAccess pReadAccess( const_cast<Bitmap&>(maBitmap) );
755  assert(pReadAccess);
756 
757  BitmapColor aColor = pReadAccess->GetColor(nY, nX);
758 
759  if (IsAlpha())
760  {
761  AlphaMask aAlpha = GetAlpha();
762  AlphaMask::ScopedReadAccess pAlphaReadAccess(aAlpha);
763  aColor.SetTransparency(pAlphaReadAccess->GetPixel(nY, nX).GetIndex());
764  }
765  else if (maBitmap.GetBitCount() != 32)
766  {
767  aColor.SetTransparency(0);
768  }
769  return aColor;
770 }
771 
772 // Shift alpha transparent pixels between cppcanvas/ implementations
773 // and vcl in a generally grotesque and under-performing fashion
774 bool BitmapEx::Create( const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas,
775  const Size &rSize )
776 {
777  uno::Reference< beans::XFastPropertySet > xFastPropertySet( xBitmapCanvas, uno::UNO_QUERY );
778  if( xFastPropertySet.get() )
779  {
780  // 0 means get BitmapEx
781  uno::Any aAny = xFastPropertySet->getFastPropertyValue( 0 );
782  std::unique_ptr<BitmapEx> xBitmapEx(reinterpret_cast<BitmapEx*>(*o3tl::doAccess<sal_Int64>(aAny)));
783  if( xBitmapEx )
784  {
785  *this = *xBitmapEx;
786  return true;
787  }
788  }
789 
790  std::shared_ptr<SalBitmap> pSalBmp;
791  std::shared_ptr<SalBitmap> pSalMask;
792 
793  pSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap();
794 
795  Size aLocalSize(rSize);
796  if( pSalBmp->Create( xBitmapCanvas, aLocalSize ) )
797  {
798  pSalMask = ImplGetSVData()->mpDefInst->CreateSalBitmap();
799  if ( pSalMask->Create( xBitmapCanvas, aLocalSize, true ) )
800  {
801  *this = BitmapEx(Bitmap(pSalBmp), Bitmap(pSalMask) );
802  return true;
803  }
804  else
805  {
806  *this = BitmapEx(Bitmap(pSalBmp));
807  return true;
808  }
809  }
810 
811  return false;
812 }
813 
814 namespace
815 {
816  Bitmap impTransformBitmap(
817  const Bitmap& rSource,
818  const Size& rDestinationSize,
819  const basegfx::B2DHomMatrix& rTransform,
820  bool bSmooth)
821  {
822  Bitmap aDestination(rDestinationSize, 24);
823  BitmapScopedWriteAccess xWrite(aDestination);
824 
825  if(xWrite)
826  {
827  Bitmap::ScopedReadAccess xRead(const_cast< Bitmap& >(rSource));
828 
829  if (xRead)
830  {
831  const Size aDestinationSizePixel(aDestination.GetSizePixel());
832  const BitmapColor aOutside(BitmapColor(0xff, 0xff, 0xff));
833 
834  for(long y(0); y < aDestinationSizePixel.getHeight(); y++)
835  {
836  Scanline pScanline = xWrite->GetScanline( y );
837  for(long x(0); x < aDestinationSizePixel.getWidth(); x++)
838  {
839  const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
840 
841  if(bSmooth)
842  {
843  xWrite->SetPixelOnData(
844  pScanline,
845  x,
846  xRead->GetInterpolatedColorWithFallback(
847  aSourceCoor.getY(),
848  aSourceCoor.getX(),
849  aOutside));
850  }
851  else
852  {
853  // this version does the correct <= 0.0 checks, so no need
854  // to do the static_cast< sal_Int32 > self and make an error
855  xWrite->SetPixelOnData(
856  pScanline,
857  x,
858  xRead->GetColorWithFallback(
859  aSourceCoor.getY(),
860  aSourceCoor.getX(),
861  aOutside));
862  }
863  }
864  }
865  }
866  }
867  xWrite.reset();
868 
869  rSource.AdaptBitCount(aDestination);
870 
871  return aDestination;
872  }
873 
875  bool implTransformNeedsSmooth(const basegfx::B2DHomMatrix& rTransformation)
876  {
877  basegfx::B2DVector aScale, aTranslate;
878  double fRotate, fShearX;
879  rTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
880  if (aScale != basegfx::B2DVector(1, 1))
881  {
882  return true;
883  }
884 
885  fRotate = fmod( fRotate, F_2PI );
886  if (fRotate < 0)
887  {
888  fRotate += F_2PI;
889  }
890  if (!rtl::math::approxEqual(fRotate, 0)
891  && !rtl::math::approxEqual(fRotate, F_PI2)
892  && !rtl::math::approxEqual(fRotate, F_PI)
893  && !rtl::math::approxEqual(fRotate, 3 * F_PI2))
894  {
895  return true;
896  }
897 
898  if (!rtl::math::approxEqual(fShearX, 0))
899  {
900  return true;
901  }
902 
903  return false;
904  }
905 } // end of anonymous namespace
906 
908  double fWidth,
909  double fHeight,
910  const basegfx::B2DHomMatrix& rTransformation) const
911 {
912  if(fWidth <= 1 || fHeight <= 1)
913  return BitmapEx();
914 
915  // force destination to 24 bit, we want to smooth output
916  const Size aDestinationSize(basegfx::fround(fWidth), basegfx::fround(fHeight));
917  bool bSmooth = implTransformNeedsSmooth(rTransformation);
918  const Bitmap aDestination(impTransformBitmap(GetBitmap(), aDestinationSize, rTransformation, bSmooth));
919 
920  // create mask
921  if(IsTransparent())
922  {
923  if(IsAlpha())
924  {
925  const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, bSmooth));
926  return BitmapEx(aDestination, AlphaMask(aAlpha));
927  }
928  else
929  {
930  const Bitmap aLclMask(impTransformBitmap(GetMask(), aDestinationSize, rTransformation, false));
931  return BitmapEx(aDestination, aLclMask);
932  }
933  }
934 
935  return BitmapEx(aDestination);
936 }
937 
939  const basegfx::B2DHomMatrix& rTransformation,
940  const basegfx::B2DRange& rVisibleRange,
941  double fMaximumArea) const
942 {
943  BitmapEx aRetval;
944 
945  if(IsEmpty())
946  return aRetval;
947 
948  const sal_uInt32 nSourceWidth(GetSizePixel().Width());
949  const sal_uInt32 nSourceHeight(GetSizePixel().Height());
950 
951  if(!nSourceWidth || !nSourceHeight)
952  return aRetval;
953 
954  // Get aOutlineRange
955  basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
956 
957  aOutlineRange.transform(rTransformation);
958 
959  // create visible range from it by moving from relative to absolute
960  basegfx::B2DRange aVisibleRange(rVisibleRange);
961 
962  aVisibleRange.transform(
964  aOutlineRange.getRange(),
965  aOutlineRange.getMinimum()));
966 
967  // get target size (which is visible range's size)
968  double fWidth(aVisibleRange.getWidth());
969  double fHeight(aVisibleRange.getHeight());
970 
971  if(fWidth < 1.0 || fHeight < 1.0)
972  {
973  return aRetval;
974  }
975 
976  // test if discrete size (pixel) maybe too big and limit it
977  const double fArea(fWidth * fHeight);
978  const bool bNeedToReduce(basegfx::fTools::more(fArea, fMaximumArea));
979  double fReduceFactor(1.0);
980 
981  if(bNeedToReduce)
982  {
983  fReduceFactor = sqrt(fMaximumArea / fArea);
984  fWidth *= fReduceFactor;
985  fHeight *= fReduceFactor;
986  }
987 
988  // Build complete transform from source pixels to target pixels.
989  // Start by scaling from source pixel size to unit coordinates
990  basegfx::B2DHomMatrix aTransform(
992  1.0 / nSourceWidth,
993  1.0 / nSourceHeight));
994 
995  // multiply with given transform which leads from unit coordinates inside
996  // aOutlineRange
997  aTransform = rTransformation * aTransform;
998 
999  // subtract top-left of absolute VisibleRange
1000  aTransform.translate(
1001  -aVisibleRange.getMinX(),
1002  -aVisibleRange.getMinY());
1003 
1004  // scale to target pixels (if needed)
1005  if(bNeedToReduce)
1006  {
1007  aTransform.scale(fReduceFactor, fReduceFactor);
1008  }
1009 
1010  // invert to get transformation from target pixel coordinates to source pixels
1011  aTransform.invert();
1012 
1013  // create bitmap using source, destination and linear back-transformation
1014  aRetval = TransformBitmapEx(fWidth, fHeight, aTransform);
1015 
1016  return aRetval;
1017 }
1018 
1020 {
1021  Bitmap aChangedBitmap(GetBitmap());
1022  bool bDone(false);
1023 
1024  for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
1025  {
1026  const basegfx::BColorModifierSharedPtr& rModifier = rBColorModifierStack.getBColorModifier(--a);
1027  const basegfx::BColorModifier_replace* pReplace = dynamic_cast< const basegfx::BColorModifier_replace* >(rModifier.get());
1028 
1029  if(pReplace)
1030  {
1031  // complete replace
1032  if(IsTransparent())
1033  {
1034  // clear bitmap with dest color
1035  if(aChangedBitmap.GetBitCount() <= 8)
1036  {
1037  // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
1038  // erase color is determined and used -> this may be different from what is
1039  // wanted here. Better create a new bitmap with the needed color explicitly
1040  Bitmap::ScopedReadAccess xReadAccess(aChangedBitmap);
1041  OSL_ENSURE(xReadAccess, "Got no Bitmap ReadAccess ?!?");
1042 
1043  if(xReadAccess)
1044  {
1045  BitmapPalette aNewPalette(xReadAccess->GetPalette());
1046  aNewPalette[0] = BitmapColor(Color(pReplace->getBColor()));
1047  aChangedBitmap = Bitmap(
1048  aChangedBitmap.GetSizePixel(),
1049  aChangedBitmap.GetBitCount(),
1050  &aNewPalette);
1051  }
1052  }
1053  else
1054  {
1055  aChangedBitmap.Erase(Color(pReplace->getBColor()));
1056  }
1057  }
1058  else
1059  {
1060  // erase bitmap, caller will know to paint direct
1061  aChangedBitmap.SetEmpty();
1062  }
1063 
1064  bDone = true;
1065  }
1066  else
1067  {
1068  BitmapScopedWriteAccess xContent(aChangedBitmap);
1069 
1070  if(xContent)
1071  {
1072  const double fConvertColor(1.0 / 255.0);
1073 
1074  if(xContent->HasPalette())
1075  {
1076  const sal_uInt16 nCount(xContent->GetPaletteEntryCount());
1077 
1078  for(sal_uInt16 b(0); b < nCount; b++)
1079  {
1080  const BitmapColor& rCol = xContent->GetPaletteColor(b);
1081  const basegfx::BColor aBSource(
1082  rCol.GetRed() * fConvertColor,
1083  rCol.GetGreen() * fConvertColor,
1084  rCol.GetBlue() * fConvertColor);
1085  const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1086  xContent->SetPaletteColor(b, BitmapColor(Color(aBDest)));
1087  }
1088  }
1089  else if(ScanlineFormat::N24BitTcBgr == xContent->GetScanlineFormat())
1090  {
1091  for(sal_uInt32 y(0); y < static_cast<sal_uInt32>(xContent->Height()); y++)
1092  {
1093  Scanline pScan = xContent->GetScanline(y);
1094 
1095  for(sal_uInt32 x(0); x < static_cast<sal_uInt32>(xContent->Width()); x++)
1096  {
1097  const basegfx::BColor aBSource(
1098  *(pScan + 2)* fConvertColor,
1099  *(pScan + 1) * fConvertColor,
1100  *pScan * fConvertColor);
1101  const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1102  *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 255.0);
1103  *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() * 255.0);
1104  *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 255.0);
1105  }
1106  }
1107  }
1108  else if(ScanlineFormat::N24BitTcRgb == xContent->GetScanlineFormat())
1109  {
1110  for(sal_uInt32 y(0); y < static_cast<sal_uInt32>(xContent->Height()); y++)
1111  {
1112  Scanline pScan = xContent->GetScanline(y);
1113 
1114  for(sal_uInt32 x(0); x < static_cast<sal_uInt32>(xContent->Width()); x++)
1115  {
1116  const basegfx::BColor aBSource(
1117  *pScan * fConvertColor,
1118  *(pScan + 1) * fConvertColor,
1119  *(pScan + 2) * fConvertColor);
1120  const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1121  *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 255.0);
1122  *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() * 255.0);
1123  *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 255.0);
1124  }
1125  }
1126  }
1127  else
1128  {
1129  for(sal_uInt32 y(0); y < static_cast<sal_uInt32>(xContent->Height()); y++)
1130  {
1131  Scanline pScanline = xContent->GetScanline( y );
1132  for(sal_uInt32 x(0); x < static_cast<sal_uInt32>(xContent->Width()); x++)
1133  {
1134  const BitmapColor aBMCol(xContent->GetColor(y, x));
1135  const basegfx::BColor aBSource(
1136  static_cast<double>(aBMCol.GetRed()) * fConvertColor,
1137  static_cast<double>(aBMCol.GetGreen()) * fConvertColor,
1138  static_cast<double>(aBMCol.GetBlue()) * fConvertColor);
1139  const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1140 
1141  xContent->SetPixelOnData(pScanline, x, BitmapColor(Color(aBDest)));
1142  }
1143  }
1144  }
1145  }
1146  }
1147  }
1148 
1149  if(aChangedBitmap.IsEmpty())
1150  {
1151  return BitmapEx();
1152  }
1153  else
1154  {
1155  if(IsTransparent())
1156  {
1157  if(IsAlpha())
1158  {
1159  return BitmapEx(aChangedBitmap, GetAlpha());
1160  }
1161  else
1162  {
1163  return BitmapEx(aChangedBitmap, GetMask());
1164  }
1165  }
1166  else
1167  {
1168  return BitmapEx(aChangedBitmap);
1169  }
1170  }
1171 }
1172 
1174  const Size& rSize,
1175  sal_uInt8 nAlpha,
1176  Color aColorTopLeft,
1177  Color aColorBottomRight)
1178 {
1179  const sal_uInt32 nW(rSize.Width());
1180  const sal_uInt32 nH(rSize.Height());
1181 
1182  if(nW || nH)
1183  {
1184  Color aColTopRight(aColorTopLeft);
1185  Color aColBottomLeft(aColorTopLeft);
1186  const sal_uInt32 nDE(nW + nH);
1187 
1188  aColTopRight.Merge(aColorBottomRight, 255 - sal_uInt8((nW * 255) / nDE));
1189  aColBottomLeft.Merge(aColorBottomRight, 255 - sal_uInt8((nH * 255) / nDE));
1190 
1191  return createBlendFrame(rSize, nAlpha, aColorTopLeft, aColTopRight, aColorBottomRight, aColBottomLeft);
1192  }
1193 
1194  return BitmapEx();
1195 }
1196 
1198  const Size& rSize,
1199  sal_uInt8 nAlpha,
1200  Color aColorTopLeft,
1201  Color aColorTopRight,
1202  Color aColorBottomRight,
1203  Color aColorBottomLeft)
1204 {
1205  BlendFrameCache* pBlendFrameCache = ImplGetBlendFrameCache();
1206 
1207  if(pBlendFrameCache->m_aLastSize == rSize
1208  && pBlendFrameCache->m_nLastAlpha == nAlpha
1209  && pBlendFrameCache->m_aLastColorTopLeft == aColorTopLeft
1210  && pBlendFrameCache->m_aLastColorTopRight == aColorTopRight
1211  && pBlendFrameCache->m_aLastColorBottomRight == aColorBottomRight
1212  && pBlendFrameCache->m_aLastColorBottomLeft == aColorBottomLeft)
1213  {
1214  return pBlendFrameCache->m_aLastResult;
1215  }
1216 
1217  pBlendFrameCache->m_aLastSize = rSize;
1218  pBlendFrameCache->m_nLastAlpha = nAlpha;
1219  pBlendFrameCache->m_aLastColorTopLeft = aColorTopLeft;
1220  pBlendFrameCache->m_aLastColorTopRight = aColorTopRight;
1221  pBlendFrameCache->m_aLastColorBottomRight = aColorBottomRight;
1222  pBlendFrameCache->m_aLastColorBottomLeft = aColorBottomLeft;
1223  pBlendFrameCache->m_aLastResult.Clear();
1224 
1225  const long nW(rSize.Width());
1226  const long nH(rSize.Height());
1227 
1228  if(nW > 1 && nH > 1)
1229  {
1230  sal_uInt8 aEraseTrans(0xff);
1231  Bitmap aContent(rSize, 24);
1232  AlphaMask aAlpha(rSize, &aEraseTrans);
1233 
1234  aContent.Erase(COL_BLACK);
1235 
1237  AlphaScopedWriteAccess pAlpha(aAlpha);
1238 
1239  if(pContent && pAlpha)
1240  {
1241  long x(0);
1242  long y(0);
1243  Scanline pScanContent = pContent->GetScanline( 0 );
1244  Scanline pScanAlpha = pContent->GetScanline( 0 );
1245 
1246  // x == 0, y == 0, top-left corner
1247  pContent->SetPixelOnData(pScanContent, 0, aColorTopLeft);
1248  pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha));
1249 
1250  // y == 0, top line left to right
1251  for(x = 1; x < nW - 1; x++)
1252  {
1253  Color aMix(aColorTopLeft);
1254 
1255  aMix.Merge(aColorTopRight, 255 - sal_uInt8((x * 255) / nW));
1256  pContent->SetPixelOnData(pScanContent, x, aMix);
1257  pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha));
1258  }
1259 
1260  // x == nW - 1, y == 0, top-right corner
1261  // #i123690# Caution! When nW is 1, x == nW is possible (!)
1262  if(x < nW)
1263  {
1264  pContent->SetPixelOnData(pScanContent, x, aColorTopRight);
1265  pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha));
1266  }
1267 
1268  // x == 0 and nW - 1, left and right line top-down
1269  for(y = 1; y < nH - 1; y++)
1270  {
1271  pScanContent = pContent->GetScanline( y );
1272  pScanAlpha = pContent->GetScanline( y );
1273  Color aMixA(aColorTopLeft);
1274 
1275  aMixA.Merge(aColorBottomLeft, 255 - sal_uInt8((y * 255) / nH));
1276  pContent->SetPixelOnData(pScanContent, 0, aMixA);
1277  pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha));
1278 
1279  // #i123690# Caution! When nW is 1, x == nW is possible (!)
1280  if(x < nW)
1281  {
1282  Color aMixB(aColorTopRight);
1283 
1284  aMixB.Merge(aColorBottomRight, 255 - sal_uInt8((y * 255) / nH));
1285  pContent->SetPixelOnData(pScanContent, x, aMixB);
1286  pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha));
1287  }
1288  }
1289 
1290  // #i123690# Caution! When nH is 1, y == nH is possible (!)
1291  if(y < nH)
1292  {
1293  // x == 0, y == nH - 1, bottom-left corner
1294  pContent->SetPixelOnData(pScanContent, 0, aColorBottomLeft);
1295  pAlpha->SetPixelOnData(pScanAlpha, 0, BitmapColor(nAlpha));
1296 
1297  // y == nH - 1, bottom line left to right
1298  for(x = 1; x < nW - 1; x++)
1299  {
1300  Color aMix(aColorBottomLeft);
1301 
1302  aMix.Merge(aColorBottomRight, 255 - sal_uInt8(((x - 0)* 255) / nW));
1303  pContent->SetPixelOnData(pScanContent, x, aMix);
1304  pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha));
1305  }
1306 
1307  // x == nW - 1, y == nH - 1, bottom-right corner
1308  // #i123690# Caution! When nW is 1, x == nW is possible (!)
1309  if(x < nW)
1310  {
1311  pContent->SetPixelOnData(pScanContent, x, aColorBottomRight);
1312  pAlpha->SetPixelOnData(pScanAlpha, x, BitmapColor(nAlpha));
1313  }
1314  }
1315 
1316  pContent.reset();
1317  pAlpha.reset();
1318 
1319  pBlendFrameCache->m_aLastResult = BitmapEx(aContent, aAlpha);
1320  }
1321  }
1322 
1323  return pBlendFrameCache->m_aLastResult;
1324 }
1325 
1326 void BitmapEx::Replace(const Color& rSearchColor,
1327  const Color& rReplaceColor,
1328  sal_uInt8 nTolerance)
1329 {
1330  maBitmap.Replace(rSearchColor, rReplaceColor, nTolerance);
1331 }
1332 
1333 void BitmapEx::Replace( const Color* pSearchColors,
1334  const Color* pReplaceColors,
1335  sal_uLong nColorCount,
1336  sal_uInt8 const * pTols )
1337 {
1338  maBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, pTols );
1339 }
1340 
1342 {
1343  if( IsTransparent() )
1344  {
1345  maBitmap.Replace( GetMask(), rColor );
1346  maMask = Bitmap();
1350  mbAlpha = false;
1351  }
1352 }
1353 
1354 static Bitmap DetectEdges( const Bitmap& rBmp )
1355 {
1356  constexpr sal_uInt8 cEdgeDetectThreshold = 128;
1357  const Size aSize( rBmp.GetSizePixel() );
1358  Bitmap aRetBmp;
1359 
1360  if( ( aSize.Width() > 2 ) && ( aSize.Height() > 2 ) )
1361  {
1362  Bitmap aWorkBmp( rBmp );
1363 
1364  if( aWorkBmp.Convert( BmpConversion::N8BitGreys ) )
1365  {
1366  bool bRet = false;
1367 
1369  pVirDev->SetOutputSizePixel(aSize);
1370  Bitmap::ScopedReadAccess pReadAcc(aWorkBmp);
1371 
1372  if( pReadAcc )
1373  {
1374  const long nWidth = aSize.Width();
1375  const long nWidth2 = nWidth - 2;
1376  const long nHeight = aSize.Height();
1377  const long nHeight2 = nHeight - 2;
1378  const long lThres2 = static_cast<long>(cEdgeDetectThreshold) * cEdgeDetectThreshold;
1379  long nSum1;
1380  long nSum2;
1381  long lGray;
1382 
1383  // initialize border with white pixels
1384  pVirDev->SetLineColor( COL_WHITE );
1385  pVirDev->DrawLine( Point(), Point( nWidth - 1, 0L ) );
1386  pVirDev->DrawLine( Point( nWidth - 1, 0L ), Point( nWidth - 1, nHeight - 1 ) );
1387  pVirDev->DrawLine( Point( nWidth - 1, nHeight - 1 ), Point( 0L, nHeight - 1 ) );
1388  pVirDev->DrawLine( Point( 0, nHeight - 1 ), Point() );
1389 
1390  for( long nY = 0, nY1 = 1, nY2 = 2; nY < nHeight2; nY++, nY1++, nY2++ )
1391  {
1392  Scanline pScanlineRead = pReadAcc->GetScanline( nY );
1393  Scanline pScanlineRead1 = pReadAcc->GetScanline( nY1 );
1394  Scanline pScanlineRead2 = pReadAcc->GetScanline( nY2 );
1395  for( long nX = 0, nXDst = 1, nXTmp; nX < nWidth2; nX++, nXDst++ )
1396  {
1397  nXTmp = nX;
1398 
1399  nSum2 = lGray = pReadAcc->GetIndexFromData( pScanlineRead, nXTmp++ );
1400  nSum1 = -nSum2;
1401  nSum2 += static_cast<long>(pReadAcc->GetIndexFromData( pScanlineRead, nXTmp++ )) << 1;
1402  lGray = pReadAcc->GetIndexFromData( pScanlineRead, nXTmp );
1403  nSum1 += lGray;
1404  nSum2 += lGray;
1405 
1406  nSum1 += static_cast<long>(pReadAcc->GetIndexFromData( pScanlineRead1, nXTmp )) << 1;
1407  nXTmp -= 2;
1408  nSum1 -= static_cast<long>(pReadAcc->GetIndexFromData( pScanlineRead1, nXTmp )) << 1;
1409 
1410  lGray = -static_cast<long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp++ ));
1411  nSum1 += lGray;
1412  nSum2 += lGray;
1413  nSum2 -= static_cast<long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp++ )) << 1;
1414  lGray = static_cast<long>(pReadAcc->GetIndexFromData( pScanlineRead2, nXTmp ));
1415  nSum1 += lGray;
1416  nSum2 -= lGray;
1417 
1418  if( ( nSum1 * nSum1 + nSum2 * nSum2 ) < lThres2 )
1419  pVirDev->DrawPixel( Point(nXDst, nY), COL_WHITE );
1420  else
1421  pVirDev->DrawPixel( Point(nXDst, nY), COL_BLACK );
1422  }
1423  }
1424 
1425  bRet = true;
1426  }
1427 
1428  pReadAcc.reset();
1429 
1430  if( bRet )
1431  aRetBmp = pVirDev->GetBitmap(Point(0,0), aSize);
1432  }
1433  }
1434 
1435  if( !aRetBmp )
1436  aRetBmp = rBmp;
1437  else
1438  {
1439  aRetBmp.SetPrefMapMode( rBmp.GetPrefMapMode() );
1440  aRetBmp.SetPrefSize( rBmp.GetPrefSize() );
1441  }
1442 
1443  return aRetBmp;
1444 }
1445 
1447 tools::Polygon BitmapEx::GetContour( bool bContourEdgeDetect,
1448  const tools::Rectangle* pWorkRectPixel )
1449 {
1450  Bitmap aWorkBmp;
1451  tools::Polygon aRetPoly;
1452  tools::Rectangle aWorkRect( Point(), maBitmap.GetSizePixel() );
1453 
1454  if( pWorkRectPixel )
1455  aWorkRect.Intersection( *pWorkRectPixel );
1456 
1457  aWorkRect.Justify();
1458 
1459  if( ( aWorkRect.GetWidth() > 4 ) && ( aWorkRect.GetHeight() > 4 ) )
1460  {
1461  // if the flag is set, we need to detect edges
1462  if( bContourEdgeDetect )
1463  aWorkBmp = DetectEdges( maBitmap );
1464  else
1465  aWorkBmp = maBitmap;
1466 
1467  BitmapReadAccess* pAcc = aWorkBmp.AcquireReadAccess();
1468 
1469  const long nWidth = pAcc ? pAcc->Width() : 0;
1470  const long nHeight = pAcc ? pAcc->Height() : 0;
1471 
1472  if (pAcc && nWidth && nHeight)
1473  {
1474  const Size& rPrefSize = aWorkBmp.GetPrefSize();
1475  const double fFactorX = static_cast<double>(rPrefSize.Width()) / nWidth;
1476  const double fFactorY = static_cast<double>(rPrefSize.Height()) / nHeight;
1477  const long nStartX1 = aWorkRect.Left() + 1;
1478  const long nEndX1 = aWorkRect.Right();
1479  const long nStartX2 = nEndX1 - 1;
1480  const long nStartY1 = aWorkRect.Top() + 1;
1481  const long nEndY1 = aWorkRect.Bottom();
1482  std::unique_ptr<Point[]> pPoints1;
1483  std::unique_ptr<Point[]> pPoints2;
1484  long nX, nY;
1485  sal_uInt16 nPolyPos = 0;
1486  const BitmapColor aBlack = pAcc->GetBestMatchingColor( COL_BLACK );
1487 
1488  pPoints1.reset(new Point[ nHeight ]);
1489  pPoints2.reset(new Point[ nHeight ]);
1490 
1491  for ( nY = nStartY1; nY < nEndY1; nY++ )
1492  {
1493  nX = nStartX1;
1494  Scanline pScanline = pAcc->GetScanline( nY );
1495 
1496  // scan row from left to right
1497  while( nX < nEndX1 )
1498  {
1499  if( aBlack == pAcc->GetPixelFromData( pScanline, nX ) )
1500  {
1501  pPoints1[ nPolyPos ] = Point( nX, nY );
1502  nX = nStartX2;
1503 
1504  // this loop always breaks eventually as there is at least one pixel
1505  while( true )
1506  {
1507  if( aBlack == pAcc->GetPixelFromData( pScanline, nX ) )
1508  {
1509  pPoints2[ nPolyPos ] = Point( nX, nY );
1510  break;
1511  }
1512 
1513  nX--;
1514  }
1515 
1516  nPolyPos++;
1517  break;
1518  }
1519 
1520  nX++;
1521  }
1522  }
1523 
1524  const sal_uInt16 nNewSize1 = nPolyPos << 1;
1525 
1526  aRetPoly = tools::Polygon( nPolyPos, pPoints1.get() );
1527  aRetPoly.SetSize( nNewSize1 + 1 );
1528  aRetPoly[ nNewSize1 ] = aRetPoly[ 0 ];
1529 
1530  for( sal_uInt16 j = nPolyPos; nPolyPos < nNewSize1; )
1531  aRetPoly[ nPolyPos++ ] = pPoints2[ --j ];
1532 
1533  if( ( fFactorX != 0. ) && ( fFactorY != 0. ) )
1534  aRetPoly.Scale( fFactorX, fFactorY );
1535  }
1536 
1537  Bitmap::ReleaseAccess(pAcc);
1538  }
1539 
1540  return aRetPoly;
1541 }
1542 
1543 void BitmapEx::setAlphaFrom( sal_uInt8 cIndexFrom, sal_Int8 nAlphaTo )
1544 {
1545  AlphaMask aAlphaMask(GetAlpha());
1546  BitmapScopedWriteAccess pWriteAccess(aAlphaMask);
1547  Bitmap::ScopedReadAccess pReadAccess(maBitmap);
1548  assert( pReadAccess.get() && pWriteAccess.get() );
1549  if ( pReadAccess.get() && pWriteAccess.get() )
1550  {
1551  for ( long nY = 0; nY < pReadAccess->Height(); nY++ )
1552  {
1553  Scanline pScanline = pWriteAccess->GetScanline( nY );
1554  Scanline pScanlineRead = pReadAccess->GetScanline( nY );
1555  for ( long nX = 0; nX < pReadAccess->Width(); nX++ )
1556  {
1557  const sal_uInt8 cIndex = pReadAccess->GetPixelFromData( pScanlineRead, nX ).GetIndex();
1558  if ( cIndex == cIndexFrom )
1559  pWriteAccess->SetPixelOnData( pScanline, nX, BitmapColor(nAlphaTo) );
1560  }
1561  }
1562  }
1563 }
1564 
1566 {
1567  AlphaMask aAlpha;
1568 
1569  if (!IsTransparent())
1570  {
1571  aAlpha = AlphaMask(GetSizePixel(), &cTrans);
1572  }
1573  else if( !IsAlpha() )
1574  {
1575  aAlpha = GetMask();
1576  aAlpha.Replace( 0, cTrans );
1577  }
1578  else
1579  {
1580  aAlpha = GetAlpha();
1581  BitmapScopedWriteAccess pA(aAlpha);
1582  assert(pA);
1583 
1584  if( !pA )
1585  return;
1586 
1587  sal_uLong nTrans = cTrans, nNewTrans;
1588  const long nWidth = pA->Width(), nHeight = pA->Height();
1589 
1591  {
1592  for( long nY = 0; nY < nHeight; nY++ )
1593  {
1594  Scanline pAScan = pA->GetScanline( nY );
1595 
1596  for( long nX = 0; nX < nWidth; nX++ )
1597  {
1598  nNewTrans = nTrans + *pAScan;
1599  *pAScan++ = static_cast<sal_uInt8>( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans );
1600  }
1601  }
1602  }
1603  else
1604  {
1605  BitmapColor aAlphaValue( 0 );
1606 
1607  for( long nY = 0; nY < nHeight; nY++ )
1608  {
1609  Scanline pScanline = pA->GetScanline( nY );
1610  for( long nX = 0; nX < nWidth; nX++ )
1611  {
1612  nNewTrans = nTrans + pA->GetIndexFromData( pScanline, nX );
1613  aAlphaValue.SetIndex( static_cast<sal_uInt8>( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ) );
1614  pA->SetPixelOnData( pScanline, nX, aAlphaValue );
1615  }
1616  }
1617  }
1618  }
1619  *this = BitmapEx( GetBitmap(), aAlpha );
1620 }
1621 
1622 // AS: Because JPEGs require the alpha channel provided separately (JPEG does not
1623 // natively support alpha channel, but SWF lets you provide it separately), we
1624 // extract the alpha channel into a separate array here.
1625 void BitmapEx::GetSplitData( std::vector<sal_uInt8>& rvColorData, std::vector<sal_uInt8>& rvAlphaData ) const
1626 {
1627  if( IsEmpty() )
1628  return;
1629 
1630  Bitmap::ScopedReadAccess pRAcc(const_cast<Bitmap&>(maBitmap));
1631 
1632  assert( pRAcc );
1633 
1634  AlphaMask aAlpha;
1635  sal_uInt32 nWidth = pRAcc->Width();
1636  sal_uInt32 nHeight = pRAcc->Height();
1637  rvColorData.resize(nWidth*nHeight*4);
1638  rvAlphaData.resize(nWidth*nHeight);
1639  sal_uInt8* p = rvColorData.data(), *pAlpha = rvAlphaData.data();
1640 
1641 
1642  if (IsAlpha())
1643  {
1644  aAlpha = GetAlpha();
1645  }
1646  else if (IsTransparent())
1647  {
1648  aAlpha = GetMask();
1649  }
1650  else
1651  {
1652  sal_uInt8 cAlphaVal = 0;
1653  aAlpha = AlphaMask(maBitmap.GetSizePixel(), &cAlphaVal);
1654  }
1655 
1656  AlphaMask::ScopedReadAccess pAAcc(aAlpha);
1657 
1658  assert( pAAcc );
1659 
1660  for( sal_uInt32 nY = 0; nY < nHeight; nY++ )
1661  {
1662  Scanline pScanlineAA = pAAcc->GetScanline( nY );
1663  for( sal_uInt32 nX = 0; nX < nWidth; nX++ )
1664  {
1665  const sal_uInt8 nAlpha = pAAcc->GetIndexFromData( pScanlineAA, nX );
1666  const BitmapColor aPixelColor( pRAcc->GetColor( nY, nX ) );
1667 
1668  if( nAlpha == 0xff )
1669  {
1670  *p++ = 0;
1671  *p++ = 0;
1672  *p++ = 0;
1673  *p++ = 0;
1674  }
1675  else
1676  {
1677  *p++ = 0xff-nAlpha;
1678  *p++ = aPixelColor.GetRed();
1679  *p++ = aPixelColor.GetGreen();
1680  *p++ = aPixelColor.GetBlue();
1681  }
1682  *pAlpha++ = 0xff - nAlpha;
1683  }
1684  }
1685 }
1686 
1688 {
1689  Bitmap aNewMask = maBitmap.CreateMask( maskColor, nTol );
1690  if ( IsTransparent() )
1691  aNewMask.CombineSimple( maMask, BmpCombine::Or );
1692  maMask = aNewMask;
1694 }
1695 
1699 void BitmapEx::GetColorModel(css::uno::Sequence< sal_Int32 >& rRGBPalette,
1700  sal_uInt32& rnRedMask, sal_uInt32& rnGreenMask, sal_uInt32& rnBlueMask, sal_uInt32& rnAlphaMask, sal_uInt32& rnTransparencyIndex,
1701  sal_uInt32& rnWidth, sal_uInt32& rnHeight, sal_uInt8& rnBitCount)
1702 {
1703  Bitmap::ScopedReadAccess pReadAccess( maBitmap );
1704  assert( pReadAccess );
1705 
1706  if( pReadAccess->HasPalette() )
1707  {
1708  sal_uInt16 nPalCount = pReadAccess->GetPaletteEntryCount();
1709 
1710  if( nPalCount )
1711  {
1712  rRGBPalette = css::uno::Sequence< sal_Int32 >( nPalCount + 1 );
1713 
1714  sal_Int32* pTmp = rRGBPalette.getArray();
1715 
1716  for( sal_uInt32 i = 0; i < nPalCount; i++, pTmp++ )
1717  {
1718  const BitmapColor& rCol = pReadAccess->GetPaletteColor( static_cast<sal_uInt16>(i) );
1719 
1720  *pTmp = static_cast<sal_Int32>(rCol.GetRed()) << sal_Int32(24);
1721  *pTmp |= static_cast<sal_Int32>(rCol.GetGreen()) << sal_Int32(16);
1722  *pTmp |= static_cast<sal_Int32>(rCol.GetBlue()) << sal_Int32(8);
1723  *pTmp |= sal_Int32(0x000000ffL);
1724  }
1725 
1726  if( IsTransparent() )
1727  {
1728  // append transparent entry
1729  *pTmp = sal_Int32(0xffffff00L);
1730  rnTransparencyIndex = nPalCount;
1731  nPalCount++;
1732  }
1733  else
1734  rnTransparencyIndex = 0;
1735  }
1736  }
1737  else
1738  {
1739  rnRedMask = 0xff000000UL;
1740  rnGreenMask = 0x00ff0000UL;
1741  rnBlueMask = 0x0000ff00UL;
1742  rnAlphaMask = 0x000000ffUL;
1743  rnTransparencyIndex = 0;
1744  }
1745 
1746  rnWidth = pReadAccess->Width();
1747  rnHeight = pReadAccess->Height();
1748  rnBitCount = pReadAccess->GetBitCount();
1749 }
1750 
1751 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool operator==(const BitmapEx &rBitmapEx) const
Definition: bitmapex.cxx:179
long Width() const
Color m_aLastColorBottomLeft
Definition: svdata.hxx:312
void Replace(const Bitmap &rMask, sal_uInt8 rReplaceTransparency)
Definition: alpha.cxx:80
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmapex.cxx:569
Bitmap GetMask() const
Definition: bitmapex.cxx:258
sal_uInt64 BitmapChecksum
Definition: checksum.hxx:30
bool Adjust(short nLuminancePercent, short nContrastPercent=0, short nChannelRPercent=0, short nChannelGPercent=0, short nChannelBPercent=0, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Change various global color characteristics.
Definition: bitmap3.cxx:1060
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:61
BitmapEx TransformBitmapEx(double fWidth, double fHeight, const basegfx::B2DHomMatrix &rTransformation) const
Create transformed Bitmap.
Definition: bitmapex.cxx:907
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
sal_uInt8 GetRed() const
void SetTransparency(sal_uInt8 nTransparency)
void SetSizePixel(const Size &rNewSize)
Definition: bitmapex.cxx:313
double getHeight() const
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
Scanline GetScanline(long nY) const
OUString DetermineIconTheme() const
Determine which icon theme should be used.
bool Adjust(short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Change various global color characteristics.
Definition: bitmapex.cxx:608
void Replace(const Color &rSearchColor, const Color &rReplaceColor)
Replace all pixel having the search color with the specified color.
Definition: bitmapex.cxx:596
Bitmap maMask
Definition: bitmapex.hxx:480
void Merge(const Color &rMergeColor, sal_uInt8 cTransparency)
BitmapEx createBlendFrame(const Size &rSize, sal_uInt8 nAlpha, Color aColorTopLeft, Color aColorBottomRight)
Create a blend frame as BitmapEx.
Definition: bitmapex.cxx:1173
static bool more(const double &rfValA, const double &rfValB)
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: button.hxx:32
long Height() const
signed char sal_Int8
TransparentType
Definition: bitmapex.hxx:36
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
This is an overloaded member function, provided for convenience. It differs from the above function o...
BitmapEx m_aLastResult
Definition: svdata.hxx:313
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmapex.cxx:370
sal_uInt8 GetTransparency() const
sal_uIntPtr sal_uLong
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:705
tools::Polygon GetContour(bool bContourEdgeDetect, const tools::Rectangle *pWorkRect)
Get contours in image.
Definition: bitmapex.cxx:1447
void Expand(sal_uLong nDX, sal_uLong nDY, bool bExpandTransparent=false)
Expand the bitmap by pixel padding.
Definition: bitmapex.cxx:459
BitmapEx getTransformed(const basegfx::B2DHomMatrix &rTransformation, const basegfx::B2DRange &rVisibleRange, double fMaximumArea) const
Create transformed Bitmap.
Definition: bitmapex.cxx:938
constexpr std::underlying_type_t< T > underlyingEnumValue(T e)
sal_uInt16 GetBitCount() const
B2DVector getRange() const
void SetSize(sal_uInt16 nNewSize)
BitmapChecksum vcl_get_checksum(BitmapChecksum Checksum, const void *Data, sal_uInt32 DatLen)
Definition: checksum.hxx:72
BitmapReadAccess * AcquireReadAccess()
SAL_DLLPRIVATE void ImplSetBitmap(const Bitmap &rBitmap)
Definition: alpha.cxx:63
Size GetSizePixel() const
Size m_aLastSize
Definition: svdata.hxx:307
long Width() const
bool Expand(sal_uLong nDX, sal_uLong nDY, const Color *pInitColor=nullptr)
Expand the bitmap by pixel padding.
float x
BlendFrameCache * ImplGetBlendFrameCache()
Definition: svdata.cxx:316
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: bitmapex.cxx:454
BitmapChecksum GetChecksum() const
Definition: bitmapex.cxx:292
static Bitmap DetectEdges(const Bitmap &rBmp)
Definition: bitmapex.cxx:1354
Size maBitmapSize
Definition: bitmapex.hxx:481
void Scale(double fScaleX, double fScaleY)
sal_uInt8 SVBT32[4]
static BitmapEx AutoScaleBitmap(BitmapEx const &aBitmap, const long aStandardSize)
Definition: bitmapex.cxx:628
NONE
const Size & GetPrefSize() const
Definition: bitmap.hxx:567
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1050
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
static VCL_DLLPUBLIC ImageTree & get()
Definition: ImageTree.cxx:16
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
bool IsAlpha() const
Definition: bitmapex.cxx:226
bool CombineSimple(const Bitmap &rMask, BmpCombine eCombine)
Perform boolean operations with another bitmap.
bool Mirror(BmpMirrorFlags nMirrorFlags)
Mirror the bitmap.
double getWidth() const
BASEGFX_DLLPUBLIC void transform(const B2DHomMatrix &rMatrix)
std::shared_ptr< BColorModifier > BColorModifierSharedPtr
BitmapEx & operator=(const BitmapEx &rBitmapEx)
B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
bool mbAlpha
Definition: bitmapex.hxx:484
int nCount
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
B2DHomMatrix createScaleTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fTranslateX, double fTranslateY)
void SetPixelOnData(sal_uInt8 *pData, long nX, const BitmapColor &rBitmapColor)
void loadFromIconTheme(const OUString &rIconName)
Definition: bitmapex.cxx:95
sal_uInt8 m_nLastAlpha
Definition: svdata.hxx:308
sal_uInt8 GetBlue() const
B2IRange fround(const B2DRange &rRange)
void Clear()
Definition: bitmapex.cxx:216
float y
bool Mirror(BmpMirrorFlags nMirrorFlags)
Mirror the bitmap.
Definition: bitmapex.cxx:333
void CombineMaskOr(Color maskColor, sal_uInt8 nTol)
Definition: bitmapex.cxx:1687
BitmapEx ModifyBitmapEx(const basegfx::BColorModifierStack &rBColorModifierStack) const
Create ColorStack-modified version of this BitmapEx.
Definition: bitmapex.cxx:1019
Color m_aLastColorTopRight
Definition: svdata.hxx:310
void AdjustTransparency(sal_uInt8 cTrans)
Definition: bitmapex.cxx:1565
void Invert()
void SetEmpty()
Definition: bitmapex.cxx:208
bool IsEmpty() const
Definition: bitmapex.cxx:203
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:75
const MapMode & GetPrefMapMode() const
Definition: bitmap.hxx:557
VCL_DLLPUBLIC bool loadImage(OUString const &name, OUString const &style, BitmapEx &bitmap, bool localized, const ImageLoadFlags eFlags=ImageLoadFlags::NONE)
Definition: ImageTree.cxx:45
void SetPrefMapMode(const MapMode &rMapMode)
Definition: bitmap.hxx:562
bool Create(const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas, const Size &rSize)
populate from a canvas implementation
Definition: bitmapex.cxx:774
#define BITMAP_CHECKSUM_SIZE
Definition: checksum.hxx:28
Bitmap maBitmap
Definition: bitmapex.hxx:479
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
void GetSplitData(std::vector< sal_uInt8 > &rvColorData, std::vector< sal_uInt8 > &rvAlphaData) const
extract the bitmap and alpha data separately.
Definition: bitmapex.cxx:1625
Color m_aLastColorTopLeft
Definition: svdata.hxx:309
bool HasPalette() const
uno_Any a
ScanlineFormat GetScanlineFormat() const
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
Color m_aLastColorBottomRight
Definition: svdata.hxx:311
BitmapChecksum GetChecksum() const
bool Invert()
Perform the Invert operation on every pixel.
Definition: bitmapex.cxx:318
const ::basegfx::BColor & getBColor() const
int i
sal_uLong GetSizeBytes() const
Definition: bitmap.hxx:582
const BColorModifierSharedPtr & getBColorModifier(sal_uInt32 nIndex) const
#define F_2PI
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
sal_uLong GetSizeBytes() const
Definition: bitmapex.cxx:282
::rtl::Reference< Content > pContent
BmpMirrorFlags
Definition: bitmap.hxx:36
bool Invert()
Perform the Invert operation on every pixel.
BmpScaleFlag
Definition: bitmap.hxx:48
static void ReleaseAccess(BitmapInfoAccess *pAccess)
::Color GetPixelColor(sal_Int32 nX, sal_Int32 nY) const
Get pixel color (including alpha) at given position.
Definition: bitmapex.cxx:752
bool CopyPixel(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const BitmapEx *pBmpExSrc)
Copy a rectangular area from another bitmap.
Definition: bitmapex.cxx:480
BmpConversion
Definition: bitmap.hxx:65
bool IsTransparent() const
Definition: bitmapex.cxx:221
const Bitmap & GetBitmap() const
Gives direct access to the contained bitmap.
Definition: bitmapex.cxx:231
bool CopyPixel_AlphaOptimized(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const Bitmap *pBmpSrc)
void Draw(OutputDevice *pOutDev, const Point &rDestPt) const
Definition: bitmapex.cxx:617
BitmapColor GetPixel(long nY, long nX) const
sal_uInt16 GetPaletteEntryCount() const
void SetIndex(sal_uInt8 cIndex)
Definition: BitmapColor.hxx:66
void SetEmpty()
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: bitmapex.cxx:236
sal_uInt8 GetGreen() const
SAL_DLLPRIVATE const Bitmap & ImplGetBitmap() const
Definition: alpha.cxx:58
double getMinY() const
bool Rotate(long nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
virtual std::shared_ptr< SalBitmap > CreateSalBitmap()=0
AlphaMask GetAlpha() const
Definition: bitmapex.cxx:268
long Height() const
#define SAL_WARN_IF(condition, area, stream)
unsigned char sal_uInt8
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmap3.cxx:828
void BCToBCOA(BitmapChecksum n, BitmapChecksumOctetArray p)
Definition: checksum.hxx:34
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: bitmap3.cxx:226
BitmapColor GetColor(long nY, long nX) const
const BitmapPalette & GetPalette() const
B2DPoint getMinimum() const
bool IsEmpty() const
Definition: bitmap.hxx:552
void GetColorModel(css::uno::Sequence< sal_Int32 > &rRGBPalette, sal_uInt32 &rnRedMask, sal_uInt32 &rnGreenMask, sal_uInt32 &rnBlueMask, sal_uInt32 &rnAlphaMask, sal_uInt32 &rnTransparencyIndex, sal_uInt32 &rnWidth, sal_uInt32 &rnHeight, sal_uInt8 &rnBitCount)
Retrieves the color model data we need for the XImageConsumer stuff.
Definition: bitmapex.cxx:1699
void * p
BitmapEx()
Definition: bitmapex.cxx:50
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
void translate(double fX, double fY)
BitmapColor GetPixelFromData(const sal_uInt8 *pData, long nX) const
void AdaptBitCount(Bitmap &rNew) const
Definition: bitmap3.cxx:855
TransparentType meTransparent
Definition: bitmapex.hxx:483
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
uno::Reference< ucb::XContent > xContent
void setAlphaFrom(sal_uInt8 cIndexFrom, sal_Int8 nAlphaTo)
Definition: bitmapex.cxx:1543
#define SAL_WARN(area, stream)
sal_uInt8 BitmapChecksumOctetArray[BITMAP_CHECKSUM_SIZE]
Definition: checksum.hxx:31
double getMinX() const
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
void ReplaceTransparency(const Color &rColor)
Replace transparency with given color.
Definition: bitmapex.cxx:1341
sal_uInt16 GetBitCount() const
sal_uInt32 count() const
bool CopyPixel(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const Bitmap *pBmpSrc=nullptr)
Copy a rectangular area from another bitmap.
bool Replace(const Bitmap &rMask, const Color &rReplaceColor)
Replace all pixel where the given mask is on with the specified color.
const Size & GetSizePixel() const
Definition: bitmapex.hxx:83
Color maTransparentColor
Definition: bitmapex.hxx:482
sal_uInt8 GetTransparency(sal_Int32 nX, sal_Int32 nY) const
Get transparency at given position.
Definition: bitmapex.cxx:684
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: bitmapex.cxx:434
Bitmap CreateMask(const Color &rTransColor, sal_uInt8 nTol=0) const
Create on-off mask from bitmap.
void SetPaletteColor(sal_uInt16 nColor, const BitmapColor &rBitmapColor)
SalInstance * mpDefInst
Definition: svdata.hxx:344
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, long nX) const
bool Rotate(long nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: bitmapex.cxx:390