1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: vclhelperbitmaptransform.cxx,v $
9 * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <vclhelperbitmaptransform.hxx>
40 #include <vcl/bmpacc.hxx>
41 #include <basegfx/point/b2dpoint.hxx>
42 #include <basegfx/color/bcolormodifier.hxx>
44 //////////////////////////////////////////////////////////////////////////////
45 // support for rendering Bitmap and BitmapEx contents
47 namespace drawinglayer
51 void impSmoothPoint(BitmapColor
& rValue
, const basegfx::B2DPoint
& rSource
, sal_Int32 nIntX
, sal_Int32 nIntY
, BitmapReadAccess
& rRead
)
53 double fDeltaX(rSource
.getX() - nIntX
);
54 double fDeltaY(rSource
.getY() - nIntY
);
58 if(fDeltaX
> 0.0 && nIntX
+ 1L < rRead
.Width())
62 else if(fDeltaX
< 0.0 && nIntX
>= 1L)
68 if(fDeltaY
> 0.0 && nIntY
+ 1L < rRead
.Height())
72 else if(fDeltaY
< 0.0 && nIntY
>= 1L)
80 const double fColorToReal(1.0 / 255.0);
81 double fR(rValue
.GetRed() * fColorToReal
);
82 double fG(rValue
.GetGreen() * fColorToReal
);
83 double fB(rValue
.GetBlue() * fColorToReal
);
84 double fRBottom(0.0), fGBottom(0.0), fBBottom(0.0);
88 const double fMulA(fDeltaX
* fColorToReal
);
89 double fMulB(1.0 - fDeltaX
);
90 const BitmapColor
aTopPartner(rRead
.GetColor(nIntY
, nIntX
+ nIndX
));
92 fR
= (fR
* fMulB
) + (aTopPartner
.GetRed() * fMulA
);
93 fG
= (fG
* fMulB
) + (aTopPartner
.GetGreen() * fMulA
);
94 fB
= (fB
* fMulB
) + (aTopPartner
.GetBlue() * fMulA
);
98 fMulB
*= fColorToReal
;
99 const BitmapColor
aBottom(rRead
.GetColor(nIntY
+ nIndY
, nIntX
));
100 const BitmapColor
aBottomPartner(rRead
.GetColor(nIntY
+ nIndY
, nIntX
+ nIndX
));
102 fRBottom
= (aBottom
.GetRed() * fMulB
) + (aBottomPartner
.GetRed() * fMulA
);
103 fGBottom
= (aBottom
.GetGreen() * fMulB
) + (aBottomPartner
.GetGreen() * fMulA
);
104 fBBottom
= (aBottom
.GetBlue() * fMulB
) + (aBottomPartner
.GetBlue() * fMulA
);
112 const BitmapColor
aBottom(rRead
.GetColor(nIntY
+ nIndY
, nIntX
));
114 fRBottom
= aBottom
.GetRed() * fColorToReal
;
115 fGBottom
= aBottom
.GetGreen() * fColorToReal
;
116 fBBottom
= aBottom
.GetBlue() * fColorToReal
;
119 const double fMulB(1.0 - fDeltaY
);
121 fR
= (fR
* fMulB
) + (fRBottom
* fDeltaY
);
122 fG
= (fG
* fMulB
) + (fGBottom
* fDeltaY
);
123 fB
= (fB
* fMulB
) + (fBBottom
* fDeltaY
);
126 rValue
.SetRed((sal_uInt8
)(fR
* 255.0));
127 rValue
.SetGreen((sal_uInt8
)(fG
* 255.0));
128 rValue
.SetBlue((sal_uInt8
)(fB
* 255.0));
132 void impSmoothIndex(BitmapColor
& rValue
, const basegfx::B2DPoint
& rSource
, sal_Int32 nIntX
, sal_Int32 nIntY
, BitmapReadAccess
& rRead
)
134 double fDeltaX(rSource
.getX() - nIntX
);
135 double fDeltaY(rSource
.getY() - nIntY
);
139 if(fDeltaX
> 0.0 && nIntX
+ 1L < rRead
.Width())
143 else if(fDeltaX
< 0.0 && nIntX
>= 1L)
149 if(fDeltaY
> 0.0 && nIntY
+ 1L < rRead
.Height())
153 else if(fDeltaY
< 0.0 && nIntY
>= 1L)
161 const double fColorToReal(1.0 / 255.0);
162 double fVal(rValue
.GetIndex() * fColorToReal
);
163 double fValBottom(0.0);
167 const double fMulA(fDeltaX
* fColorToReal
);
168 double fMulB(1.0 - fDeltaX
);
169 const BitmapColor
aTopPartner(rRead
.GetPixel(nIntY
, nIntX
+ nIndX
));
171 fVal
= (fVal
* fMulB
) + (aTopPartner
.GetIndex() * fMulA
);
175 fMulB
*= fColorToReal
;
176 const BitmapColor
aBottom(rRead
.GetPixel(nIntY
+ nIndY
, nIntX
));
177 const BitmapColor
aBottomPartner(rRead
.GetPixel(nIntY
+ nIndY
, nIntX
+ nIndX
));
179 fValBottom
= (aBottom
.GetIndex() * fMulB
) + (aBottomPartner
.GetIndex() * fMulA
);
187 const BitmapColor
aBottom(rRead
.GetPixel(nIntY
+ nIndY
, nIntX
));
189 fValBottom
= aBottom
.GetIndex() * fColorToReal
;
192 const double fMulB(1.0 - fDeltaY
);
194 fVal
= (fVal
* fMulB
) + (fValBottom
* fDeltaY
);
197 rValue
.SetIndex((sal_uInt8
)(fVal
* 255.0));
201 void impTransformBitmap(const Bitmap
& rSource
, Bitmap
& rDestination
, const basegfx::B2DHomMatrix
& rTransform
, bool bSmooth
)
203 BitmapWriteAccess
* pWrite
= rDestination
.AcquireWriteAccess();
207 const Size
aContentSizePixel(rSource
.GetSizePixel());
208 BitmapReadAccess
* pRead
= (const_cast< Bitmap
& >(rSource
)).AcquireReadAccess();
212 const Size
aDestinationSizePixel(rDestination
.GetSizePixel());
213 bool bWorkWithIndex(rDestination
.GetBitCount() <= 8);
214 BitmapColor
aOutside(pRead
->GetBestMatchingColor(BitmapColor(0xff, 0xff, 0xff)));
216 for(sal_Int32
y(0L); y
< aDestinationSizePixel
.getHeight(); y
++)
218 for(sal_Int32
x(0L); x
< aDestinationSizePixel
.getWidth(); x
++)
220 const basegfx::B2DPoint
aSourceCoor(rTransform
* basegfx::B2DPoint(x
, y
));
221 const sal_Int32
nIntX(basegfx::fround(aSourceCoor
.getX()));
223 if(nIntX
>= 0L && nIntX
< aContentSizePixel
.getWidth())
225 const sal_Int32
nIntY(basegfx::fround(aSourceCoor
.getY()));
227 if(nIntY
>= 0L && nIntY
< aContentSizePixel
.getHeight())
231 BitmapColor
aValue(pRead
->GetPixel(nIntY
, nIntX
));
235 impSmoothIndex(aValue
, aSourceCoor
, nIntX
, nIntY
, *pRead
);
238 pWrite
->SetPixel(y
, x
, aValue
);
242 BitmapColor
aValue(pRead
->GetColor(nIntY
, nIntX
));
246 impSmoothPoint(aValue
, aSourceCoor
, nIntX
, nIntY
, *pRead
);
249 pWrite
->SetPixel(y
, x
, aValue
.IsIndex() ? aValue
: pWrite
->GetBestMatchingColor(aValue
));
256 // here are outside pixels. Complete mask
259 pWrite
->SetPixel(y
, x
, aOutside
);
271 Bitmap
impCreateEmptyBitmapWithPattern(const Bitmap
& rSource
, const Size
& aTargetSizePixel
)
274 BitmapReadAccess
* pReadAccess
= (const_cast< Bitmap
& >(rSource
)).AcquireReadAccess();
278 if(rSource
.GetBitCount() <= 8)
280 BitmapPalette
aPalette(pReadAccess
->GetPalette());
281 aRetval
= Bitmap(aTargetSizePixel
, rSource
.GetBitCount(), &aPalette
);
285 aRetval
= Bitmap(aTargetSizePixel
, rSource
.GetBitCount());
293 } // end of anonymous namespace
294 } // end of namespace drawinglayer
296 namespace drawinglayer
298 BitmapEx
impTransformBitmapEx(
299 const BitmapEx
& rSource
,
300 const Rectangle
& rCroppedRectPixel
,
301 const basegfx::B2DHomMatrix
& rTransform
)
303 // force destination to 24 bit, we want to smooth output
304 const Size
aDestinationSize(rCroppedRectPixel
.GetSize());
305 Bitmap
aDestination(impCreateEmptyBitmapWithPattern(rSource
.GetBitmap(), aDestinationSize
));
306 static bool bDoSmoothAtAll(true);
307 impTransformBitmap(rSource
.GetBitmap(), aDestination
, rTransform
, bDoSmoothAtAll
);
310 if(rSource
.IsTransparent())
312 if(rSource
.IsAlpha())
314 Bitmap
aAlpha(impCreateEmptyBitmapWithPattern(rSource
.GetAlpha().GetBitmap(), aDestinationSize
));
315 impTransformBitmap(rSource
.GetAlpha().GetBitmap(), aAlpha
, rTransform
, bDoSmoothAtAll
);
316 return BitmapEx(aDestination
, AlphaMask(aAlpha
));
320 Bitmap
aMask(impCreateEmptyBitmapWithPattern(rSource
.GetMask(), aDestinationSize
));
321 impTransformBitmap(rSource
.GetMask(), aMask
, rTransform
, false);
322 return BitmapEx(aDestination
, aMask
);
326 return BitmapEx(aDestination
);
329 BitmapEx
impModifyBitmapEx(
330 const basegfx::BColorModifierStack
& rBColorModifierStack
,
331 const BitmapEx
& rSource
)
333 Bitmap
aChangedBitmap(rSource
.GetBitmap());
336 for(sal_uInt32
a(rBColorModifierStack
.count()); a
&& !bDone
; )
338 const basegfx::BColorModifier
& rModifier
= rBColorModifierStack
.getBColorModifier(--a
);
340 switch(rModifier
.getMode())
342 case basegfx::BCOLORMODIFYMODE_REPLACE
:
345 if(rSource
.IsTransparent())
347 // clear bitmap with dest color
348 if(aChangedBitmap
.GetBitCount() <= 8)
350 // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
351 // erase color is determined and used -> this may be different from what is
352 // wanted here. Better create a new bitmap with the needed color explicitely
353 BitmapReadAccess
* pReadAccess
= aChangedBitmap
.AcquireReadAccess();
354 OSL_ENSURE(pReadAccess
, "Got no Bitmap ReadAccess ?!?");
358 BitmapPalette
aNewPalette(pReadAccess
->GetPalette());
359 aNewPalette
[0] = BitmapColor(Color(rModifier
.getBColor()));
360 aChangedBitmap
= Bitmap(
361 aChangedBitmap
.GetSizePixel(),
362 aChangedBitmap
.GetBitCount(),
369 aChangedBitmap
.Erase(Color(rModifier
.getBColor()));
374 // erase bitmap, caller will know to paint direct
375 aChangedBitmap
.SetEmpty();
382 default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
384 BitmapWriteAccess
* pContent
= aChangedBitmap
.AcquireWriteAccess();
388 const double fConvertColor(1.0 / 255.0);
390 for(sal_uInt32
y(0L); y
< (sal_uInt32
)pContent
->Height(); y
++)
392 for(sal_uInt32
x(0L); x
< (sal_uInt32
)pContent
->Width(); x
++)
394 const BitmapColor
aBMCol(pContent
->GetColor(y
, x
));
395 const basegfx::BColor
aBSource(
396 (double)aBMCol
.GetRed() * fConvertColor
,
397 (double)aBMCol
.GetGreen() * fConvertColor
,
398 (double)aBMCol
.GetBlue() * fConvertColor
);
399 const basegfx::BColor
aBDest(rModifier
.getModifiedColor(aBSource
));
401 pContent
->SetPixel(y
, x
, BitmapColor(Color(aBDest
)));
413 if(aChangedBitmap
.IsEmpty())
419 if(rSource
.IsTransparent())
421 if(rSource
.IsAlpha())
423 return BitmapEx(aChangedBitmap
, rSource
.GetAlpha());
427 return BitmapEx(aChangedBitmap
, rSource
.GetMask());
432 return BitmapEx(aChangedBitmap
);
436 } // end of namespace drawinglayer
438 //////////////////////////////////////////////////////////////////////////////