1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/log.hxx>
21 #include <rtl/math.hxx>
22 #include <o3tl/underlyingenumvalue.hxx>
23 #include <osl/diagnose.h>
24 #include <basegfx/matrix/b2dhommatrixtools.hxx>
25 #include <basegfx/color/bcolormodifier.hxx>
27 #include <vcl/ImageTree.hxx>
28 #include <vcl/outdev.hxx>
29 #include <vcl/alpha.hxx>
30 #include <vcl/bitmapex.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/BitmapMonochromeFilter.hxx>
38 #include <salinst.hxx>
40 #include <bitmap/BitmapWriteAccess.hxx>
41 #include <bitmap/BitmapMaskToAlphaFilter.hxx>
43 #include <o3tl/any.hxx>
45 #include <com/sun/star/beans/XFastPropertySet.hpp>
49 using namespace ::com::sun::star
;
55 BitmapEx::BitmapEx( const BitmapEx
& ) = default;
57 BitmapEx::BitmapEx( const BitmapEx
& rBitmapEx
, Point aSrc
, Size aSize
)
59 if( rBitmapEx
.IsEmpty() || aSize
.IsEmpty() )
62 maBitmap
= Bitmap(aSize
, rBitmapEx
.maBitmap
.getPixelFormat());
64 if( rBitmapEx
.IsAlpha() )
65 maAlphaMask
= AlphaMask( aSize
).ImplGetBitmap();
67 tools::Rectangle
aDestRect( Point( 0, 0 ), aSize
);
68 tools::Rectangle
aSrcRect( aSrc
, aSize
);
69 CopyPixel( aDestRect
, aSrcRect
, &rBitmapEx
);
72 BitmapEx::BitmapEx(Size aSize
, vcl::PixelFormat ePixelFormat
)
74 maBitmap
= Bitmap(aSize
, ePixelFormat
);
78 BitmapEx::BitmapEx( const OUString
& rIconName
)
80 loadFromIconTheme( rIconName
);
83 void BitmapEx::loadFromIconTheme( const OUString
& rIconName
)
90 aIconTheme
= Application::GetSettings().GetStyleSettings().DetermineIconTheme();
91 bSuccess
= ImageTree::get().loadImage(rIconName
, aIconTheme
, *this, true);
98 SAL_WARN_IF( !bSuccess
, "vcl", "BitmapEx::BitmapEx(): could not load image " << rIconName
<< " via icon theme " << aIconTheme
);
101 BitmapEx::BitmapEx( const Bitmap
& rBmp
) :
103 maBitmapSize ( maBitmap
.GetSizePixel() )
107 BitmapEx::BitmapEx( const Bitmap
& rBmp
, const Bitmap
& rMask
) :
109 maBitmapSize ( maBitmap
.GetSizePixel() )
114 if( rMask
.getPixelFormat() == vcl::PixelFormat::N8_BPP
&& rMask
.HasGreyPalette8Bit() )
116 else if (rMask
.getPixelFormat() == vcl::PixelFormat::N1_BPP
)
118 // convert 1-bit mask to alpha bitmap
119 BitmapEx
aBmpEx(rMask
);
120 BitmapFilter::Filter(aBmpEx
, BitmapMaskToAlphaFilter());
121 maAlphaMask
= aBmpEx
.GetBitmap();
125 // convert to alpha bitmap
126 SAL_WARN( "vcl", "BitmapEx: forced mask to monochrome");
127 BitmapEx
aMaskEx(rMask
);
128 BitmapFilter::Filter(aMaskEx
, BitmapMonochromeFilter(255));
129 BitmapFilter::Filter(aMaskEx
, BitmapMaskToAlphaFilter());
130 maAlphaMask
= aMaskEx
.GetBitmap();
133 if (!maBitmap
.IsEmpty() && maBitmap
.GetSizePixel() != maAlphaMask
.GetSizePixel())
135 OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)");
136 maAlphaMask
.Scale(maBitmap
.GetSizePixel());
140 BitmapEx::BitmapEx( const Bitmap
& rBmp
, const AlphaMask
& rAlphaMask
) :
142 maAlphaMask ( rAlphaMask
.ImplGetBitmap() ),
143 maBitmapSize ( maBitmap
.GetSizePixel() )
145 if (!maBitmap
.IsEmpty() && !maAlphaMask
.IsEmpty() && maBitmap
.GetSizePixel() != maAlphaMask
.GetSizePixel())
147 OSL_ENSURE(false, "Alpha size differs from Bitmap size, corrected Mask (!)");
148 maAlphaMask
.Scale(rBmp
.GetSizePixel());
153 BitmapEx::BitmapEx( const Bitmap
& rBmp
, const Color
& rTransparentColor
) :
155 maBitmapSize ( maBitmap
.GetSizePixel() )
157 maAlphaMask
= maBitmap
.CreateMask( rTransparentColor
);
159 SAL_WARN_IF(rBmp
.GetSizePixel() != maAlphaMask
.GetSizePixel(), "vcl",
160 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask.");
164 BitmapEx
& BitmapEx::operator=( const BitmapEx
& ) = default;
166 bool BitmapEx::operator==( const BitmapEx
& rBitmapEx
) const
168 if (GetSizePixel() != rBitmapEx
.GetSizePixel())
171 if (maBitmap
!= rBitmapEx
.maBitmap
)
174 return maAlphaMask
== rBitmapEx
.maAlphaMask
;
177 bool BitmapEx::IsEmpty() const
179 return( maBitmap
.IsEmpty() && maAlphaMask
.IsEmpty() );
182 void BitmapEx::SetEmpty()
185 maAlphaMask
.SetEmpty();
188 void BitmapEx::Clear()
193 bool BitmapEx::IsAlpha() const
195 return !maAlphaMask
.IsEmpty();
198 const Bitmap
& BitmapEx::GetBitmap() const
203 Bitmap
BitmapEx::GetBitmap( Color aTransparentReplaceColor
) const
205 Bitmap
aRetBmp( maBitmap
);
207 if( !maAlphaMask
.IsEmpty() )
209 aRetBmp
.Replace( maAlphaMask
, aTransparentReplaceColor
);
215 AlphaMask
BitmapEx::GetAlpha() const
217 return AlphaMask(maAlphaMask
);
220 sal_Int64
BitmapEx::GetSizeBytes() const
222 sal_Int64 nSizeBytes
= maBitmap
.GetSizeBytes();
224 if( !maAlphaMask
.IsEmpty() )
225 nSizeBytes
+= maAlphaMask
.GetSizeBytes();
230 BitmapChecksum
BitmapEx::GetChecksum() const
232 BitmapChecksum nCrc
= maBitmap
.GetChecksum();
234 if( !maAlphaMask
.IsEmpty() )
236 BitmapChecksumOctetArray aBCOA
;
237 BCToBCOA( maAlphaMask
.GetChecksum(), aBCOA
);
238 nCrc
= vcl_get_checksum( nCrc
, aBCOA
, BITMAP_CHECKSUM_SIZE
);
244 void BitmapEx::SetSizePixel(const Size
& rNewSize
)
246 maBitmapSize
= rNewSize
;
249 bool BitmapEx::Invert()
253 if (!maBitmap
.IsEmpty())
254 bRet
= maBitmap
.Invert();
259 bool BitmapEx::Mirror( BmpMirrorFlags nMirrorFlags
)
263 if( !maBitmap
.IsEmpty() )
265 bRet
= maBitmap
.Mirror( nMirrorFlags
);
267 if( bRet
&& !maAlphaMask
.IsEmpty() )
268 maAlphaMask
.Mirror( nMirrorFlags
);
274 bool BitmapEx::Scale( const double& rScaleX
, const double& rScaleY
, BmpScaleFlag nScaleFlag
)
278 if( !maBitmap
.IsEmpty() )
280 bRet
= maBitmap
.Scale( rScaleX
, rScaleY
, nScaleFlag
);
282 if( bRet
&& !maAlphaMask
.IsEmpty() )
284 maAlphaMask
.Scale( rScaleX
, rScaleY
, nScaleFlag
);
287 SetSizePixel(maBitmap
.GetSizePixel());
289 SAL_WARN_IF( !maAlphaMask
.IsEmpty() && maBitmap
.GetSizePixel() != maAlphaMask
.GetSizePixel(), "vcl",
290 "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
296 bool BitmapEx::Scale( const Size
& rNewSize
, BmpScaleFlag nScaleFlag
)
300 if (GetSizePixel().Width() && GetSizePixel().Height()
301 && (rNewSize
.Width() != GetSizePixel().Width()
302 || rNewSize
.Height() != GetSizePixel().Height() ) )
304 bRet
= Scale( static_cast<double>(rNewSize
.Width()) / GetSizePixel().Width(),
305 static_cast<double>(rNewSize
.Height()) / GetSizePixel().Height(),
316 bool BitmapEx::Rotate( Degree10 nAngle10
, const Color
& rFillColor
)
320 if( !maBitmap
.IsEmpty() )
322 const bool bTransRotate
= ( COL_TRANSPARENT
== rFillColor
);
326 bRet
= maBitmap
.Rotate( nAngle10
, COL_BLACK
);
328 if( maAlphaMask
.IsEmpty() )
330 maAlphaMask
= Bitmap(GetSizePixel(), vcl::PixelFormat::N8_BPP
, &Bitmap::GetGreyPalette(256));
331 maAlphaMask
.Erase( COL_BLACK
);
334 if( bRet
&& !maAlphaMask
.IsEmpty() )
335 maAlphaMask
.Rotate( nAngle10
, COL_WHITE
);
339 bRet
= maBitmap
.Rotate( nAngle10
, rFillColor
);
341 if( bRet
&& !maAlphaMask
.IsEmpty() )
342 maAlphaMask
.Rotate( nAngle10
, COL_WHITE
);
345 SetSizePixel(maBitmap
.GetSizePixel());
347 SAL_WARN_IF(!maAlphaMask
.IsEmpty() && maBitmap
.GetSizePixel() != maAlphaMask
.GetSizePixel(), "vcl",
348 "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask.");
354 bool BitmapEx::Crop( const tools::Rectangle
& rRectPixel
)
358 if( !maBitmap
.IsEmpty() )
360 bRet
= maBitmap
.Crop( rRectPixel
);
362 if( bRet
&& !maAlphaMask
.IsEmpty() )
363 maAlphaMask
.Crop( rRectPixel
);
365 SetSizePixel(maBitmap
.GetSizePixel());
367 SAL_WARN_IF(!maAlphaMask
.IsEmpty() && maBitmap
.GetSizePixel() != maAlphaMask
.GetSizePixel(), "vcl",
368 "BitmapEx::Crop(): size mismatch for bitmap and alpha mask.");
374 bool BitmapEx::Convert( BmpConversion eConversion
)
376 return !maBitmap
.IsEmpty() && maBitmap
.Convert( eConversion
);
379 void BitmapEx::Expand( sal_Int32 nDX
, sal_Int32 nDY
, bool bExpandTransparent
)
383 if( maBitmap
.IsEmpty() )
386 bRet
= maBitmap
.Expand( nDX
, nDY
);
388 if( bRet
&& !maAlphaMask
.IsEmpty() )
390 Color
aColor( bExpandTransparent
? COL_WHITE
: COL_BLACK
);
391 maAlphaMask
.Expand( nDX
, nDY
, &aColor
);
394 SetSizePixel(maBitmap
.GetSizePixel());
396 SAL_WARN_IF(!maAlphaMask
.IsEmpty() && maBitmap
.GetSizePixel() != maAlphaMask
.GetSizePixel(), "vcl",
397 "BitmapEx::Expand(): size mismatch for bitmap and alpha mask.");
400 bool BitmapEx::CopyPixel( const tools::Rectangle
& rRectDst
, const tools::Rectangle
& rRectSrc
,
401 const BitmapEx
* pBmpExSrc
)
405 if( !pBmpExSrc
|| pBmpExSrc
->IsEmpty() )
407 if( !maBitmap
.IsEmpty() )
409 bRet
= maBitmap
.CopyPixel( rRectDst
, rRectSrc
);
411 if( bRet
&& !maAlphaMask
.IsEmpty() )
412 maAlphaMask
.CopyPixel( rRectDst
, rRectSrc
);
417 if( !maBitmap
.IsEmpty() )
419 bRet
= maBitmap
.CopyPixel( rRectDst
, rRectSrc
, &pBmpExSrc
->maBitmap
);
423 if( pBmpExSrc
->IsAlpha() )
426 // cast to use the optimized AlphaMask::CopyPixel
427 maAlphaMask
.CopyPixel_AlphaOptimized( rRectDst
, rRectSrc
, &pBmpExSrc
->maAlphaMask
);
430 sal_uInt8 cBlack
= 0;
431 std::unique_ptr
<AlphaMask
> pAlpha(new AlphaMask(GetSizePixel(), &cBlack
));
433 maAlphaMask
= pAlpha
->ImplGetBitmap();
435 maAlphaMask
.CopyPixel( rRectDst
, rRectSrc
, &pBmpExSrc
->maAlphaMask
);
440 sal_uInt8 cBlack
= 0;
441 const AlphaMask
aAlphaSrc(pBmpExSrc
->GetSizePixel(), &cBlack
);
443 maAlphaMask
.CopyPixel( rRectDst
, rRectSrc
, &aAlphaSrc
.ImplGetBitmap() );
452 bool BitmapEx::Erase( const Color
& rFillColor
)
456 if( !maBitmap
.IsEmpty() )
458 bRet
= maBitmap
.Erase( rFillColor
);
460 if( bRet
&& !maAlphaMask
.IsEmpty() )
462 // Respect transparency on fill color
463 if( rFillColor
.IsTransparent() )
465 const Color
aFill( 255 - rFillColor
.GetAlpha(), 255 - rFillColor
.GetAlpha(), 255 - rFillColor
.GetAlpha() );
466 maAlphaMask
.Erase( aFill
);
470 const Color
aBlack( COL_BLACK
);
471 maAlphaMask
.Erase( aBlack
);
479 void BitmapEx::Replace( const Color
& rSearchColor
, const Color
& rReplaceColor
)
481 if (!maBitmap
.IsEmpty())
482 maBitmap
.Replace( rSearchColor
, rReplaceColor
);
485 void BitmapEx::Replace( const Color
* pSearchColors
, const Color
* pReplaceColors
, size_t nColorCount
)
487 if (!maBitmap
.IsEmpty())
488 maBitmap
.Replace( pSearchColors
, pReplaceColors
, nColorCount
, /*pTols*/nullptr );
491 bool BitmapEx::Adjust( short nLuminancePercent
, short nContrastPercent
,
492 short nChannelRPercent
, short nChannelGPercent
, short nChannelBPercent
,
493 double fGamma
, bool bInvert
, bool msoBrightness
)
495 return !maBitmap
.IsEmpty() && maBitmap
.Adjust( nLuminancePercent
, nContrastPercent
,
496 nChannelRPercent
, nChannelGPercent
, nChannelBPercent
,
497 fGamma
, bInvert
, msoBrightness
);
500 void BitmapEx::Draw( OutputDevice
* pOutDev
, const Point
& rDestPt
) const
502 pOutDev
->DrawBitmapEx( rDestPt
, *this );
505 void BitmapEx::Draw( OutputDevice
* pOutDev
,
506 const Point
& rDestPt
, const Size
& rDestSize
) const
508 pOutDev
->DrawBitmapEx( rDestPt
, rDestSize
, *this );
511 BitmapEx
BitmapEx:: AutoScaleBitmap(BitmapEx
const & aBitmap
, const tools::Long aStandardSize
)
513 Point
aEmptyPoint(0,0);
516 BitmapEx aRet
= aBitmap
;
517 double imgOldWidth
= aRet
.GetSizePixel().Width();
518 double imgOldHeight
= aRet
.GetSizePixel().Height();
520 if (imgOldWidth
>= aStandardSize
|| imgOldHeight
>= aStandardSize
)
522 sal_Int32 imgNewWidth
= 0;
523 sal_Int32 imgNewHeight
= 0;
524 if (imgOldWidth
>= imgOldHeight
)
526 imgNewWidth
= aStandardSize
;
527 imgNewHeight
= sal_Int32(imgOldHeight
/ (imgOldWidth
/ aStandardSize
) + 0.5);
529 imgposY
= (aStandardSize
- (imgOldHeight
/ (imgOldWidth
/ aStandardSize
) + 0.5)) / 2 + 0.5;
533 imgNewHeight
= aStandardSize
;
534 imgNewWidth
= sal_Int32(imgOldWidth
/ (imgOldHeight
/ aStandardSize
) + 0.5);
536 imgposX
= (aStandardSize
- (imgOldWidth
/ (imgOldHeight
/ aStandardSize
) + 0.5)) / 2 + 0.5;
539 Size
aScaledSize( imgNewWidth
, imgNewHeight
);
540 aRet
.Scale( aScaledSize
, BmpScaleFlag::BestQuality
);
544 imgposX
= (aStandardSize
- imgOldWidth
) / 2 + 0.5;
545 imgposY
= (aStandardSize
- imgOldHeight
) / 2 + 0.5;
548 Size
aStdSize( aStandardSize
, aStandardSize
);
549 tools::Rectangle
aRect(aEmptyPoint
, aStdSize
);
551 ScopedVclPtrInstance
< VirtualDevice
> aVirDevice(*Application::GetDefaultDevice());
552 aVirDevice
->SetOutputSizePixel( aStdSize
);
553 aVirDevice
->SetFillColor( COL_TRANSPARENT
);
554 aVirDevice
->SetLineColor( COL_TRANSPARENT
);
556 // Draw a rect into virDevice
557 aVirDevice
->DrawRect( aRect
);
558 Point
aPointPixel( static_cast<tools::Long
>(imgposX
), static_cast<tools::Long
>(imgposY
) );
559 aVirDevice
->DrawBitmapEx( aPointPixel
, aRet
);
560 aRet
= aVirDevice
->GetBitmapEx( aEmptyPoint
, aStdSize
);
565 sal_uInt8
BitmapEx::GetAlpha(sal_Int32 nX
, sal_Int32 nY
) const
567 if(maBitmap
.IsEmpty())
570 if (nX
< 0 || nX
>= GetSizePixel().Width() || nY
< 0 || nY
>= GetSizePixel().Height())
573 if (maBitmap
.getPixelFormat() == vcl::PixelFormat::N32_BPP
)
574 return GetPixelColor(nX
, nY
).GetAlpha();
577 if (maAlphaMask
.IsEmpty())
579 // Not transparent, ergo all covered
584 Bitmap
aTestBitmap(maAlphaMask
);
585 Bitmap::ScopedReadAccess
pRead(aTestBitmap
);
589 const BitmapColor
aBitmapColor(pRead
->GetPixel(nY
, nX
));
590 nAlpha
= 255 - aBitmapColor
.GetIndex();
597 Color
BitmapEx::GetPixelColor(sal_Int32 nX
, sal_Int32 nY
) const
599 Bitmap::ScopedReadAccess
pReadAccess( const_cast<Bitmap
&>(maBitmap
) );
602 BitmapColor aColor
= pReadAccess
->GetColor(nY
, nX
);
606 AlphaMask aAlpha
= GetAlpha();
607 AlphaMask::ScopedReadAccess
pAlphaReadAccess(aAlpha
);
608 aColor
.SetAlpha(255 - pAlphaReadAccess
->GetPixel(nY
, nX
).GetIndex());
610 else if (maBitmap
.getPixelFormat() != vcl::PixelFormat::N32_BPP
)
612 aColor
.SetAlpha(255);
617 // Shift alpha transparent pixels between cppcanvas/ implementations
618 // and vcl in a generally grotesque and under-performing fashion
619 bool BitmapEx::Create( const css::uno::Reference
< css::rendering::XBitmapCanvas
> &xBitmapCanvas
,
622 uno::Reference
< beans::XFastPropertySet
> xFastPropertySet( xBitmapCanvas
, uno::UNO_QUERY
);
623 if( xFastPropertySet
)
625 // 0 means get BitmapEx
626 uno::Any aAny
= xFastPropertySet
->getFastPropertyValue( 0 );
627 std::unique_ptr
<BitmapEx
> xBitmapEx(reinterpret_cast<BitmapEx
*>(*o3tl::doAccess
<sal_Int64
>(aAny
)));
635 std::shared_ptr
<SalBitmap
> pSalBmp
;
636 std::shared_ptr
<SalBitmap
> pSalMask
;
638 pSalBmp
= ImplGetSVData()->mpDefInst
->CreateSalBitmap();
640 Size
aLocalSize(rSize
);
641 if( pSalBmp
->Create( xBitmapCanvas
, aLocalSize
) )
643 pSalMask
= ImplGetSVData()->mpDefInst
->CreateSalBitmap();
644 if ( pSalMask
->Create( xBitmapCanvas
, aLocalSize
, true ) )
646 *this = BitmapEx(Bitmap(pSalBmp
), Bitmap(pSalMask
) );
651 *this = BitmapEx(Bitmap(pSalBmp
));
661 Bitmap
impTransformBitmap(
662 const Bitmap
& rSource
,
663 const Size
& rDestinationSize
,
664 const basegfx::B2DHomMatrix
& rTransform
,
667 Bitmap
aDestination(rDestinationSize
, vcl::PixelFormat::N24_BPP
);
668 BitmapScopedWriteAccess
xWrite(aDestination
);
672 Bitmap::ScopedReadAccess
xRead(const_cast< Bitmap
& >(rSource
));
676 const Size
aDestinationSizePixel(aDestination
.GetSizePixel());
677 const BitmapColor
aOutside(BitmapColor(0xff, 0xff, 0xff));
679 for(tools::Long
y(0); y
< aDestinationSizePixel
.getHeight(); y
++)
681 Scanline pScanline
= xWrite
->GetScanline( y
);
682 for(tools::Long
x(0); x
< aDestinationSizePixel
.getWidth(); x
++)
684 const basegfx::B2DPoint
aSourceCoor(rTransform
* basegfx::B2DPoint(x
, y
));
688 xWrite
->SetPixelOnData(
691 xRead
->GetInterpolatedColorWithFallback(
698 // this version does the correct <= 0.0 checks, so no need
699 // to do the static_cast< sal_Int32 > self and make an error
700 xWrite
->SetPixelOnData(
703 xRead
->GetColorWithFallback(
714 rSource
.AdaptBitCount(aDestination
);
719 /// Decides if rTransformation needs smoothing or not (e.g. 180 deg rotation doesn't need it).
720 bool implTransformNeedsSmooth(const basegfx::B2DHomMatrix
& rTransformation
)
722 basegfx::B2DVector aScale
, aTranslate
;
723 double fRotate
, fShearX
;
724 rTransformation
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
725 if (aScale
!= basegfx::B2DVector(1, 1))
730 fRotate
= fmod( fRotate
, F_2PI
);
735 if (!rtl::math::approxEqual(fRotate
, 0)
736 && !rtl::math::approxEqual(fRotate
, F_PI2
)
737 && !rtl::math::approxEqual(fRotate
, F_PI
)
738 && !rtl::math::approxEqual(fRotate
, 3 * F_PI2
))
743 if (!rtl::math::approxEqual(fShearX
, 0))
750 } // end of anonymous namespace
752 BitmapEx
BitmapEx::TransformBitmapEx(
755 const basegfx::B2DHomMatrix
& rTransformation
) const
757 if(fWidth
<= 1 || fHeight
<= 1)
760 // force destination to 24 bit, we want to smooth output
761 const Size
aDestinationSize(basegfx::fround(fWidth
), basegfx::fround(fHeight
));
762 bool bSmooth
= implTransformNeedsSmooth(rTransformation
);
763 const Bitmap
aDestination(impTransformBitmap(GetBitmap(), aDestinationSize
, rTransformation
, bSmooth
));
768 const Bitmap
aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize
, rTransformation
, bSmooth
));
769 return BitmapEx(aDestination
, AlphaMask(aAlpha
));
772 return BitmapEx(aDestination
);
775 BitmapEx
BitmapEx::getTransformed(
776 const basegfx::B2DHomMatrix
& rTransformation
,
777 const basegfx::B2DRange
& rVisibleRange
,
778 double fMaximumArea
) const
785 const sal_uInt32
nSourceWidth(GetSizePixel().Width());
786 const sal_uInt32
nSourceHeight(GetSizePixel().Height());
788 if(!nSourceWidth
|| !nSourceHeight
)
792 basegfx::B2DRange
aOutlineRange(0.0, 0.0, 1.0, 1.0);
794 aOutlineRange
.transform(rTransformation
);
796 // create visible range from it by moving from relative to absolute
797 basegfx::B2DRange
aVisibleRange(rVisibleRange
);
799 aVisibleRange
.transform(
800 basegfx::utils::createScaleTranslateB2DHomMatrix(
801 aOutlineRange
.getRange(),
802 aOutlineRange
.getMinimum()));
804 // get target size (which is visible range's size)
805 double fWidth(aVisibleRange
.getWidth());
806 double fHeight(aVisibleRange
.getHeight());
808 if(fWidth
< 1.0 || fHeight
< 1.0)
813 // test if discrete size (pixel) maybe too big and limit it
814 const double fArea(fWidth
* fHeight
);
815 const bool bNeedToReduce(basegfx::fTools::more(fArea
, fMaximumArea
));
816 double fReduceFactor(1.0);
820 fReduceFactor
= sqrt(fMaximumArea
/ fArea
);
821 fWidth
*= fReduceFactor
;
822 fHeight
*= fReduceFactor
;
825 // Build complete transform from source pixels to target pixels.
826 // Start by scaling from source pixel size to unit coordinates
827 basegfx::B2DHomMatrix
aTransform(
828 basegfx::utils::createScaleB2DHomMatrix(
830 1.0 / nSourceHeight
));
832 // multiply with given transform which leads from unit coordinates inside
834 aTransform
= rTransformation
* aTransform
;
836 // subtract top-left of absolute VisibleRange
837 aTransform
.translate(
838 -aVisibleRange
.getMinX(),
839 -aVisibleRange
.getMinY());
841 // scale to target pixels (if needed)
844 aTransform
.scale(fReduceFactor
, fReduceFactor
);
847 // invert to get transformation from target pixel coordinates to source pixels
850 // create bitmap using source, destination and linear back-transformation
851 aRetval
= TransformBitmapEx(fWidth
, fHeight
, aTransform
);
856 BitmapEx
BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack
& rBColorModifierStack
) const
858 Bitmap
aChangedBitmap(GetBitmap());
861 for(sal_uInt32
a(rBColorModifierStack
.count()); a
&& !bDone
; )
863 const basegfx::BColorModifierSharedPtr
& rModifier
= rBColorModifierStack
.getBColorModifier(--a
);
864 const basegfx::BColorModifier_replace
* pReplace
= dynamic_cast< const basegfx::BColorModifier_replace
* >(rModifier
.get());
871 // clear bitmap with dest color
872 if (vcl::isPalettePixelFormat(aChangedBitmap
.getPixelFormat()))
874 // For e.g. 8bit Bitmaps, the nearest color to the given erase color is
875 // determined and used -> this may be different from what is wanted here.
876 // Better create a new bitmap with the needed color explicitly.
877 Bitmap::ScopedReadAccess
xReadAccess(aChangedBitmap
);
878 OSL_ENSURE(xReadAccess
, "Got no Bitmap ReadAccess ?!?");
882 BitmapPalette
aNewPalette(xReadAccess
->GetPalette());
883 aNewPalette
[0] = BitmapColor(Color(pReplace
->getBColor()));
884 aChangedBitmap
= Bitmap(
885 aChangedBitmap
.GetSizePixel(),
886 aChangedBitmap
.getPixelFormat(),
890 aChangedBitmap
.Erase(Color(pReplace
->getBColor()));
894 // erase bitmap, caller will know to paint direct
895 aChangedBitmap
.SetEmpty();
902 BitmapScopedWriteAccess
xContent(aChangedBitmap
);
906 const double fConvertColor(1.0 / 255.0);
908 if(xContent
->HasPalette())
910 const sal_uInt16
nCount(xContent
->GetPaletteEntryCount());
912 for(sal_uInt16
b(0); b
< nCount
; b
++)
914 const BitmapColor
& rCol
= xContent
->GetPaletteColor(b
);
915 const basegfx::BColor
aBSource(
916 rCol
.GetRed() * fConvertColor
,
917 rCol
.GetGreen() * fConvertColor
,
918 rCol
.GetBlue() * fConvertColor
);
919 const basegfx::BColor
aBDest(rModifier
->getModifiedColor(aBSource
));
920 xContent
->SetPaletteColor(b
, BitmapColor(Color(aBDest
)));
923 else if(ScanlineFormat::N24BitTcBgr
== xContent
->GetScanlineFormat())
925 for(tools::Long
y(0); y
< xContent
->Height(); y
++)
927 Scanline pScan
= xContent
->GetScanline(y
);
929 for(tools::Long
x(0); x
< xContent
->Width(); x
++)
931 const basegfx::BColor
aBSource(
932 *(pScan
+ 2)* fConvertColor
,
933 *(pScan
+ 1) * fConvertColor
,
934 *pScan
* fConvertColor
);
935 const basegfx::BColor
aBDest(rModifier
->getModifiedColor(aBSource
));
936 *pScan
++ = static_cast< sal_uInt8
>(aBDest
.getBlue() * 255.0);
937 *pScan
++ = static_cast< sal_uInt8
>(aBDest
.getGreen() * 255.0);
938 *pScan
++ = static_cast< sal_uInt8
>(aBDest
.getRed() * 255.0);
942 else if(ScanlineFormat::N24BitTcRgb
== xContent
->GetScanlineFormat())
944 for(tools::Long
y(0); y
< xContent
->Height(); y
++)
946 Scanline pScan
= xContent
->GetScanline(y
);
948 for(tools::Long
x(0); x
< xContent
->Width(); x
++)
950 const basegfx::BColor
aBSource(
951 *pScan
* fConvertColor
,
952 *(pScan
+ 1) * fConvertColor
,
953 *(pScan
+ 2) * fConvertColor
);
954 const basegfx::BColor
aBDest(rModifier
->getModifiedColor(aBSource
));
955 *pScan
++ = static_cast< sal_uInt8
>(aBDest
.getRed() * 255.0);
956 *pScan
++ = static_cast< sal_uInt8
>(aBDest
.getGreen() * 255.0);
957 *pScan
++ = static_cast< sal_uInt8
>(aBDest
.getBlue() * 255.0);
963 for(tools::Long
y(0); y
< xContent
->Height(); y
++)
965 Scanline pScanline
= xContent
->GetScanline( y
);
966 for(tools::Long
x(0); x
< xContent
->Width(); x
++)
968 const BitmapColor
aBMCol(xContent
->GetColor(y
, x
));
969 const basegfx::BColor
aBSource(
970 static_cast<double>(aBMCol
.GetRed()) * fConvertColor
,
971 static_cast<double>(aBMCol
.GetGreen()) * fConvertColor
,
972 static_cast<double>(aBMCol
.GetBlue()) * fConvertColor
);
973 const basegfx::BColor
aBDest(rModifier
->getModifiedColor(aBSource
));
975 xContent
->SetPixelOnData(pScanline
, x
, BitmapColor(Color(aBDest
)));
983 if(aChangedBitmap
.IsEmpty())
991 return BitmapEx(aChangedBitmap
, GetAlpha());
995 return BitmapEx(aChangedBitmap
);
1000 BitmapEx
createBlendFrame(
1003 Color aColorTopLeft
,
1004 Color aColorBottomRight
)
1006 const sal_uInt32
nW(rSize
.Width());
1007 const sal_uInt32
nH(rSize
.Height());
1011 Color
aColTopRight(aColorTopLeft
);
1012 Color
aColBottomLeft(aColorTopLeft
);
1013 const sal_uInt32
nDE(nW
+ nH
);
1015 aColTopRight
.Merge(aColorBottomRight
, 255 - sal_uInt8((nW
* 255) / nDE
));
1016 aColBottomLeft
.Merge(aColorBottomRight
, 255 - sal_uInt8((nH
* 255) / nDE
));
1018 return createBlendFrame(rSize
, nAlpha
, aColorTopLeft
, aColTopRight
, aColorBottomRight
, aColBottomLeft
);
1024 BitmapEx
createBlendFrame(
1027 Color aColorTopLeft
,
1028 Color aColorTopRight
,
1029 Color aColorBottomRight
,
1030 Color aColorBottomLeft
)
1032 BlendFrameCache
* pBlendFrameCache
= ImplGetBlendFrameCache();
1034 if(pBlendFrameCache
->m_aLastSize
== rSize
1035 && pBlendFrameCache
->m_nLastAlpha
== nAlpha
1036 && pBlendFrameCache
->m_aLastColorTopLeft
== aColorTopLeft
1037 && pBlendFrameCache
->m_aLastColorTopRight
== aColorTopRight
1038 && pBlendFrameCache
->m_aLastColorBottomRight
== aColorBottomRight
1039 && pBlendFrameCache
->m_aLastColorBottomLeft
== aColorBottomLeft
)
1041 return pBlendFrameCache
->m_aLastResult
;
1044 pBlendFrameCache
->m_aLastSize
= rSize
;
1045 pBlendFrameCache
->m_nLastAlpha
= nAlpha
;
1046 pBlendFrameCache
->m_aLastColorTopLeft
= aColorTopLeft
;
1047 pBlendFrameCache
->m_aLastColorTopRight
= aColorTopRight
;
1048 pBlendFrameCache
->m_aLastColorBottomRight
= aColorBottomRight
;
1049 pBlendFrameCache
->m_aLastColorBottomLeft
= aColorBottomLeft
;
1050 pBlendFrameCache
->m_aLastResult
.Clear();
1052 const tools::Long
nW(rSize
.Width());
1053 const tools::Long
nH(rSize
.Height());
1055 if(nW
> 1 && nH
> 1)
1057 sal_uInt8
aEraseTrans(0xff);
1058 Bitmap
aContent(rSize
, vcl::PixelFormat::N24_BPP
);
1059 AlphaMask
aAlpha(rSize
, &aEraseTrans
);
1061 aContent
.Erase(COL_BLACK
);
1063 BitmapScopedWriteAccess
pContent(aContent
);
1064 AlphaScopedWriteAccess
pAlpha(aAlpha
);
1066 if(pContent
&& pAlpha
)
1070 Scanline pScanContent
= pContent
->GetScanline( 0 );
1071 Scanline pScanAlpha
= pContent
->GetScanline( 0 );
1073 // x == 0, y == 0, top-left corner
1074 pContent
->SetPixelOnData(pScanContent
, 0, aColorTopLeft
);
1075 pAlpha
->SetPixelOnData(pScanAlpha
, 0, BitmapColor(nAlpha
));
1077 // y == 0, top line left to right
1078 for(x
= 1; x
< nW
- 1; x
++)
1080 Color
aMix(aColorTopLeft
);
1082 aMix
.Merge(aColorTopRight
, 255 - sal_uInt8((x
* 255) / nW
));
1083 pContent
->SetPixelOnData(pScanContent
, x
, aMix
);
1084 pAlpha
->SetPixelOnData(pScanAlpha
, x
, BitmapColor(nAlpha
));
1087 // x == nW - 1, y == 0, top-right corner
1088 // #i123690# Caution! When nW is 1, x == nW is possible (!)
1091 pContent
->SetPixelOnData(pScanContent
, x
, aColorTopRight
);
1092 pAlpha
->SetPixelOnData(pScanAlpha
, x
, BitmapColor(nAlpha
));
1095 // x == 0 and nW - 1, left and right line top-down
1096 for(y
= 1; y
< nH
- 1; y
++)
1098 pScanContent
= pContent
->GetScanline( y
);
1099 pScanAlpha
= pContent
->GetScanline( y
);
1100 Color
aMixA(aColorTopLeft
);
1102 aMixA
.Merge(aColorBottomLeft
, 255 - sal_uInt8((y
* 255) / nH
));
1103 pContent
->SetPixelOnData(pScanContent
, 0, aMixA
);
1104 pAlpha
->SetPixelOnData(pScanAlpha
, 0, BitmapColor(nAlpha
));
1106 // #i123690# Caution! When nW is 1, x == nW is possible (!)
1109 Color
aMixB(aColorTopRight
);
1111 aMixB
.Merge(aColorBottomRight
, 255 - sal_uInt8((y
* 255) / nH
));
1112 pContent
->SetPixelOnData(pScanContent
, x
, aMixB
);
1113 pAlpha
->SetPixelOnData(pScanAlpha
, x
, BitmapColor(nAlpha
));
1117 // #i123690# Caution! When nH is 1, y == nH is possible (!)
1120 // x == 0, y == nH - 1, bottom-left corner
1121 pContent
->SetPixelOnData(pScanContent
, 0, aColorBottomLeft
);
1122 pAlpha
->SetPixelOnData(pScanAlpha
, 0, BitmapColor(nAlpha
));
1124 // y == nH - 1, bottom line left to right
1125 for(x
= 1; x
< nW
- 1; x
++)
1127 Color
aMix(aColorBottomLeft
);
1129 aMix
.Merge(aColorBottomRight
, 255 - sal_uInt8(((x
- 0)* 255) / nW
));
1130 pContent
->SetPixelOnData(pScanContent
, x
, aMix
);
1131 pAlpha
->SetPixelOnData(pScanAlpha
, x
, BitmapColor(nAlpha
));
1134 // x == nW - 1, y == nH - 1, bottom-right corner
1135 // #i123690# Caution! When nW is 1, x == nW is possible (!)
1138 pContent
->SetPixelOnData(pScanContent
, x
, aColorBottomRight
);
1139 pAlpha
->SetPixelOnData(pScanAlpha
, x
, BitmapColor(nAlpha
));
1146 pBlendFrameCache
->m_aLastResult
= BitmapEx(aContent
, aAlpha
);
1150 return pBlendFrameCache
->m_aLastResult
;
1153 void BitmapEx::Replace(const Color
& rSearchColor
,
1154 const Color
& rReplaceColor
,
1155 sal_uInt8 nTolerance
)
1157 maBitmap
.Replace(rSearchColor
, rReplaceColor
, nTolerance
);
1160 void BitmapEx::Replace( const Color
* pSearchColors
,
1161 const Color
* pReplaceColors
,
1163 sal_uInt8
const * pTols
)
1165 maBitmap
.Replace( pSearchColors
, pReplaceColors
, nColorCount
, pTols
);
1168 void BitmapEx::ReplaceTransparency(const Color
& rColor
)
1172 maBitmap
.Replace( GetAlpha(), rColor
);
1173 maAlphaMask
= Bitmap();
1174 maBitmapSize
= maBitmap
.GetSizePixel();
1178 static Bitmap
DetectEdges( const Bitmap
& rBmp
)
1180 constexpr sal_uInt8 cEdgeDetectThreshold
= 128;
1181 const Size
aSize( rBmp
.GetSizePixel() );
1184 if( ( aSize
.Width() > 2 ) && ( aSize
.Height() > 2 ) )
1186 Bitmap
aWorkBmp( rBmp
);
1188 if( aWorkBmp
.Convert( BmpConversion::N8BitGreys
) )
1192 ScopedVclPtr
<VirtualDevice
> pVirDev(VclPtr
<VirtualDevice
>::Create());
1193 pVirDev
->SetOutputSizePixel(aSize
);
1194 Bitmap::ScopedReadAccess
pReadAcc(aWorkBmp
);
1198 const tools::Long nWidth
= aSize
.Width();
1199 const tools::Long nWidth2
= nWidth
- 2;
1200 const tools::Long nHeight
= aSize
.Height();
1201 const tools::Long nHeight2
= nHeight
- 2;
1202 const tools::Long lThres2
= static_cast<tools::Long
>(cEdgeDetectThreshold
) * cEdgeDetectThreshold
;
1207 // initialize border with white pixels
1208 pVirDev
->SetLineColor( COL_WHITE
);
1209 pVirDev
->DrawLine( Point(), Point( nWidth
- 1, 0L ) );
1210 pVirDev
->DrawLine( Point( nWidth
- 1, 0L ), Point( nWidth
- 1, nHeight
- 1 ) );
1211 pVirDev
->DrawLine( Point( nWidth
- 1, nHeight
- 1 ), Point( 0L, nHeight
- 1 ) );
1212 pVirDev
->DrawLine( Point( 0, nHeight
- 1 ), Point() );
1214 for( tools::Long nY
= 0, nY1
= 1, nY2
= 2; nY
< nHeight2
; nY
++, nY1
++, nY2
++ )
1216 Scanline pScanlineRead
= pReadAcc
->GetScanline( nY
);
1217 Scanline pScanlineRead1
= pReadAcc
->GetScanline( nY1
);
1218 Scanline pScanlineRead2
= pReadAcc
->GetScanline( nY2
);
1219 for( tools::Long nX
= 0, nXDst
= 1, nXTmp
; nX
< nWidth2
; nX
++, nXDst
++ )
1223 nSum2
= pReadAcc
->GetIndexFromData( pScanlineRead
, nXTmp
++ );
1225 nSum2
+= static_cast<tools::Long
>(pReadAcc
->GetIndexFromData( pScanlineRead
, nXTmp
++ )) << 1;
1226 lGray
= pReadAcc
->GetIndexFromData( pScanlineRead
, nXTmp
);
1230 nSum1
+= static_cast<tools::Long
>(pReadAcc
->GetIndexFromData( pScanlineRead1
, nXTmp
)) << 1;
1232 nSum1
-= static_cast<tools::Long
>(pReadAcc
->GetIndexFromData( pScanlineRead1
, nXTmp
)) << 1;
1234 lGray
= -static_cast<tools::Long
>(pReadAcc
->GetIndexFromData( pScanlineRead2
, nXTmp
++ ));
1237 nSum2
-= static_cast<tools::Long
>(pReadAcc
->GetIndexFromData( pScanlineRead2
, nXTmp
++ )) << 1;
1238 lGray
= static_cast<tools::Long
>(pReadAcc
->GetIndexFromData( pScanlineRead2
, nXTmp
));
1242 if( ( nSum1
* nSum1
+ nSum2
* nSum2
) < lThres2
)
1243 pVirDev
->DrawPixel( Point(nXDst
, nY
), COL_WHITE
);
1245 pVirDev
->DrawPixel( Point(nXDst
, nY
), COL_BLACK
);
1255 aRetBmp
= pVirDev
->GetBitmap(Point(0,0), aSize
);
1259 if( aRetBmp
.IsEmpty() )
1263 aRetBmp
.SetPrefMapMode( rBmp
.GetPrefMapMode() );
1264 aRetBmp
.SetPrefSize( rBmp
.GetPrefSize() );
1270 /** Get contours in image */
1271 tools::Polygon
BitmapEx::GetContour( bool bContourEdgeDetect
,
1272 const tools::Rectangle
* pWorkRectPixel
)
1275 tools::Polygon aRetPoly
;
1276 tools::Rectangle
aWorkRect( Point(), maBitmap
.GetSizePixel() );
1278 if( pWorkRectPixel
)
1279 aWorkRect
.Intersection( *pWorkRectPixel
);
1281 aWorkRect
.Justify();
1283 if( ( aWorkRect
.GetWidth() > 4 ) && ( aWorkRect
.GetHeight() > 4 ) )
1285 // if the flag is set, we need to detect edges
1286 if( bContourEdgeDetect
)
1287 aWorkBmp
= DetectEdges( maBitmap
);
1289 aWorkBmp
= maBitmap
;
1291 BitmapReadAccess
* pAcc
= aWorkBmp
.AcquireReadAccess();
1293 const tools::Long nWidth
= pAcc
? pAcc
->Width() : 0;
1294 const tools::Long nHeight
= pAcc
? pAcc
->Height() : 0;
1296 if (pAcc
&& nWidth
&& nHeight
)
1298 const Size
& rPrefSize
= aWorkBmp
.GetPrefSize();
1299 const double fFactorX
= static_cast<double>(rPrefSize
.Width()) / nWidth
;
1300 const double fFactorY
= static_cast<double>(rPrefSize
.Height()) / nHeight
;
1301 const tools::Long nStartX1
= aWorkRect
.Left() + 1;
1302 const tools::Long nEndX1
= aWorkRect
.Right();
1303 const tools::Long nStartX2
= nEndX1
- 1;
1304 const tools::Long nStartY1
= aWorkRect
.Top() + 1;
1305 const tools::Long nEndY1
= aWorkRect
.Bottom();
1306 std::unique_ptr
<Point
[]> pPoints1
;
1307 std::unique_ptr
<Point
[]> pPoints2
;
1309 sal_uInt16 nPolyPos
= 0;
1310 const BitmapColor aBlack
= pAcc
->GetBestMatchingColor( COL_BLACK
);
1312 pPoints1
.reset(new Point
[ nHeight
]);
1313 pPoints2
.reset(new Point
[ nHeight
]);
1315 for ( nY
= nStartY1
; nY
< nEndY1
; nY
++ )
1318 Scanline pScanline
= pAcc
->GetScanline( nY
);
1320 // scan row from left to right
1321 while( nX
< nEndX1
)
1323 if( aBlack
== pAcc
->GetPixelFromData( pScanline
, nX
) )
1325 pPoints1
[ nPolyPos
] = Point( nX
, nY
);
1328 // this loop always breaks eventually as there is at least one pixel
1331 if( aBlack
== pAcc
->GetPixelFromData( pScanline
, nX
) )
1333 pPoints2
[ nPolyPos
] = Point( nX
, nY
);
1348 const sal_uInt16 nNewSize1
= nPolyPos
<< 1;
1350 aRetPoly
= tools::Polygon( nPolyPos
, pPoints1
.get() );
1351 aRetPoly
.SetSize( nNewSize1
+ 1 );
1352 aRetPoly
[ nNewSize1
] = aRetPoly
[ 0 ];
1354 for( sal_uInt16 j
= nPolyPos
; nPolyPos
< nNewSize1
; )
1355 aRetPoly
[ nPolyPos
++ ] = pPoints2
[ --j
];
1357 if( ( fFactorX
!= 0. ) && ( fFactorY
!= 0. ) )
1358 aRetPoly
.Scale( fFactorX
, fFactorY
);
1361 Bitmap::ReleaseAccess(pAcc
);
1367 void BitmapEx::setAlphaFrom( sal_uInt8 cIndexFrom
, sal_Int8 nAlphaTo
)
1369 AlphaMask
aAlphaMask(GetAlpha());
1370 BitmapScopedWriteAccess
pWriteAccess(aAlphaMask
);
1371 Bitmap::ScopedReadAccess
pReadAccess(maBitmap
);
1372 assert( pReadAccess
.get() && pWriteAccess
.get() );
1373 if ( !(pReadAccess
.get() && pWriteAccess
.get()) )
1376 for ( tools::Long nY
= 0; nY
< pReadAccess
->Height(); nY
++ )
1378 Scanline pScanline
= pWriteAccess
->GetScanline( nY
);
1379 Scanline pScanlineRead
= pReadAccess
->GetScanline( nY
);
1380 for ( tools::Long nX
= 0; nX
< pReadAccess
->Width(); nX
++ )
1382 const sal_uInt8 cIndex
= pReadAccess
->GetPixelFromData( pScanlineRead
, nX
).GetIndex();
1383 if ( cIndex
== cIndexFrom
)
1384 pWriteAccess
->SetPixelOnData( pScanline
, nX
, BitmapColor(nAlphaTo
) );
1387 *this = BitmapEx( GetBitmap(), aAlphaMask
);
1390 void BitmapEx::AdjustTransparency(sal_uInt8 cTrans
)
1396 aAlpha
= AlphaMask(GetSizePixel(), &cTrans
);
1400 aAlpha
= GetAlpha();
1401 BitmapScopedWriteAccess
pA(aAlpha
);
1407 sal_uLong nTrans
= cTrans
, nNewTrans
;
1408 const tools::Long nWidth
= pA
->Width(), nHeight
= pA
->Height();
1410 if( pA
->GetScanlineFormat() == ScanlineFormat::N8BitPal
)
1412 for( tools::Long nY
= 0; nY
< nHeight
; nY
++ )
1414 Scanline pAScan
= pA
->GetScanline( nY
);
1416 for( tools::Long nX
= 0; nX
< nWidth
; nX
++ )
1418 nNewTrans
= nTrans
+ *pAScan
;
1419 *pAScan
++ = static_cast<sal_uInt8
>( ( nNewTrans
& 0xffffff00 ) ? 255 : nNewTrans
);
1425 BitmapColor
aAlphaValue( 0 );
1427 for( tools::Long nY
= 0; nY
< nHeight
; nY
++ )
1429 Scanline pScanline
= pA
->GetScanline( nY
);
1430 for( tools::Long nX
= 0; nX
< nWidth
; nX
++ )
1432 nNewTrans
= nTrans
+ pA
->GetIndexFromData( pScanline
, nX
);
1433 aAlphaValue
.SetIndex( static_cast<sal_uInt8
>( ( nNewTrans
& 0xffffff00 ) ? 255 : nNewTrans
) );
1434 pA
->SetPixelOnData( pScanline
, nX
, aAlphaValue
);
1439 *this = BitmapEx( GetBitmap(), aAlpha
);
1442 void BitmapEx::CombineMaskOr(Color maskColor
, sal_uInt8 nTol
)
1444 Bitmap aNewMask
= maBitmap
.CreateMask( maskColor
, nTol
);
1446 aNewMask
.CombineSimple( maAlphaMask
, BmpCombine::Or
);
1447 maAlphaMask
= aNewMask
;
1451 * Retrieves the color model data we need for the XImageConsumer stuff.
1453 void BitmapEx::GetColorModel(css::uno::Sequence
< sal_Int32
>& rRGBPalette
,
1454 sal_uInt32
& rnRedMask
, sal_uInt32
& rnGreenMask
, sal_uInt32
& rnBlueMask
, sal_uInt32
& rnAlphaMask
, sal_uInt32
& rnTransparencyIndex
,
1455 sal_uInt32
& rnWidth
, sal_uInt32
& rnHeight
, sal_uInt8
& rnBitCount
)
1457 Bitmap::ScopedReadAccess
pReadAccess( maBitmap
);
1458 assert( pReadAccess
);
1460 if( pReadAccess
->HasPalette() )
1462 sal_uInt16 nPalCount
= pReadAccess
->GetPaletteEntryCount();
1466 rRGBPalette
= css::uno::Sequence
< sal_Int32
>( nPalCount
+ 1 );
1468 sal_Int32
* pTmp
= rRGBPalette
.getArray();
1470 for( sal_uInt32 i
= 0; i
< nPalCount
; i
++, pTmp
++ )
1472 const BitmapColor
& rCol
= pReadAccess
->GetPaletteColor( static_cast<sal_uInt16
>(i
) );
1474 *pTmp
= static_cast<sal_Int32
>(rCol
.GetRed()) << sal_Int32(24);
1475 *pTmp
|= static_cast<sal_Int32
>(rCol
.GetGreen()) << sal_Int32(16);
1476 *pTmp
|= static_cast<sal_Int32
>(rCol
.GetBlue()) << sal_Int32(8);
1477 *pTmp
|= sal_Int32(0x000000ffL
);
1482 // append transparent entry
1483 *pTmp
= sal_Int32(0xffffff00L
);
1484 rnTransparencyIndex
= nPalCount
;
1488 rnTransparencyIndex
= 0;
1493 rnRedMask
= 0xff000000UL
;
1494 rnGreenMask
= 0x00ff0000UL
;
1495 rnBlueMask
= 0x0000ff00UL
;
1496 rnAlphaMask
= 0x000000ffUL
;
1497 rnTransparencyIndex
= 0;
1500 rnWidth
= pReadAccess
->Width();
1501 rnHeight
= pReadAccess
->Height();
1502 rnBitCount
= pReadAccess
->GetBitCount();
1505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */