xref: /aoo42x/main/vcl/source/gdi/alpha.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 #include <tools/debug.hxx>
31 #include <vcl/bmpacc.hxx>
32 #include <tools/color.hxx>
33 #include <vcl/alpha.hxx>
34 
35 // -------------
36 // - AlphaMask -
37 // -------------
38 
39 AlphaMask::AlphaMask()
40 {
41 }
42 
43 // -----------------------------------------------------------------------------
44 
45 AlphaMask::AlphaMask( const Bitmap& rBitmap ) :
46 	Bitmap( rBitmap )
47 {
48 	if( !!rBitmap )
49 		Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
50 }
51 
52 // -----------------------------------------------------------------------------
53 
54 AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) :
55 	Bitmap( rAlphaMask )
56 {
57 }
58 
59 // -----------------------------------------------------------------------------
60 
61 AlphaMask::AlphaMask( const Size& rSizePixel, sal_uInt8* pEraseTransparency ) :
62 	Bitmap( rSizePixel, 8, &Bitmap::GetGreyPalette( 256 ) )
63 {
64 	if( pEraseTransparency )
65 		Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, *pEraseTransparency ) );
66 }
67 
68 // -----------------------------------------------------------------------------
69 
70 AlphaMask::~AlphaMask()
71 {
72 }
73 
74 // -----------------------------------------------------------------------------
75 
76 AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap )
77 {
78 	*(Bitmap*) this = rBitmap;
79 
80 	if( !!rBitmap )
81 		Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
82 
83 	return *this;
84 }
85 
86 // -----------------------------------------------------------------------------
87 
88 const Bitmap& AlphaMask::ImplGetBitmap() const
89 {
90 	return( (const Bitmap&) *this );
91 }
92 
93 // -----------------------------------------------------------------------------
94 
95 void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap )
96 {
97     DBG_ASSERT( ( 8 == rBitmap.GetBitCount() ) && rBitmap.HasGreyPalette(), "AlphaMask::ImplSetBitmap: invalid bitmap" );
98 	*(Bitmap*) this = rBitmap;
99 }
100 
101 // -----------------------------------------------------------------------------
102 
103 Bitmap AlphaMask::GetBitmap() const
104 {
105 	return ImplGetBitmap();
106 }
107 
108 // -----------------------------------------------------------------------------
109 
110 sal_Bool AlphaMask::Crop( const Rectangle& rRectPixel )
111 {
112 	return Bitmap::Crop( rRectPixel );
113 }
114 
115 // -----------------------------------------------------------------------------
116 
117 sal_Bool AlphaMask::Expand( sal_uLong nDX, sal_uLong nDY, sal_uInt8* pInitTransparency )
118 {
119 	Color aColor;
120 
121 	if( pInitTransparency )
122 		aColor = Color( *pInitTransparency, *pInitTransparency, *pInitTransparency );
123 
124 	return Bitmap::Expand( nDX, nDY, pInitTransparency ? &aColor : NULL );
125 }
126 
127 // -----------------------------------------------------------------------------
128 
129 sal_Bool AlphaMask::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
130 						   const AlphaMask* pAlphaSrc )
131 {
132     // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
133     // this optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
134 
135 	const Size	aSizePix( GetSizePixel() );
136 	Rectangle	aRectDst( rRectDst );
137 	sal_Bool		bRet = sal_False;
138 
139 	aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
140 
141 	if( !aRectDst.IsEmpty() )
142 	{
143 		if( pAlphaSrc && ( *pAlphaSrc != *this ) )
144 		{
145 			Bitmap* 		pSrc = (Bitmap*) pAlphaSrc;
146 			const Size		aCopySizePix( pSrc->GetSizePixel() );
147 			Rectangle		aRectSrc( rRectSrc );
148 
149 			aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
150 
151 			if( !aRectSrc.IsEmpty() )
152 			{
153 				BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
154 
155 				if( pReadAcc )
156 				{
157 					BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
158 
159 					if( pWriteAcc )
160 					{
161 						const long	nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
162 						const long	nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
163 						const long	nSrcEndX = aRectSrc.Left() + nWidth;
164 						const long	nSrcEndY = aRectSrc.Top() + nHeight;
165 						long		nDstY = aRectDst.Top();
166 
167 						for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
168 							for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
169 								pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
170 
171 						ReleaseAccess( pWriteAcc );
172 						bRet = ( nWidth > 0L ) && ( nHeight > 0L );
173 					}
174 
175 					pSrc->ReleaseAccess( pReadAcc );
176 				}
177 			}
178 		}
179 		else
180 		{
181 			Rectangle aRectSrc( rRectSrc );
182 
183 			aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
184 
185 			if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
186 			{
187 				BitmapWriteAccess*	pWriteAcc = AcquireWriteAccess();
188 
189 				if( pWriteAcc )
190 				{
191 					const long	nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
192 					const long	nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
193 					const long	nSrcX = aRectSrc.Left();
194 					const long	nSrcY = aRectSrc.Top();
195 					const long	nSrcEndX1 = nSrcX + nWidth - 1L;
196 					const long	nSrcEndY1 = nSrcY + nHeight - 1L;
197 					const long	nDstX = aRectDst.Left();
198 					const long	nDstY = aRectDst.Top();
199 					const long	nDstEndX1 = nDstX + nWidth - 1L;
200 					const long	nDstEndY1 = nDstY + nHeight - 1L;
201 
202 					if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
203 					{
204 						for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
205 							for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
206 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
207 					}
208 					else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
209 					{
210 						for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
211 							for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
212 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
213 					}
214 					else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
215 					{
216 						for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
217 							for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
218 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
219 					}
220 					else
221 					{
222 						for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
223 							for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
224 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
225 					}
226 
227 					ReleaseAccess( pWriteAcc );
228 					bRet = sal_True;
229 				}
230 			}
231 		}
232 	}
233 
234 	return bRet;
235 
236 }
237 
238 // -----------------------------------------------------------------------------
239 
240 sal_Bool AlphaMask::Erase( sal_uInt8 cTransparency )
241 {
242 	return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) );
243 }
244 
245 // -----------------------------------------------------------------------------
246 
247 sal_Bool AlphaMask::Invert()
248 {
249 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
250 	sal_Bool				bRet = sal_False;
251 
252 	if( pAcc && pAcc->GetBitCount() == 8 )
253 	{
254 		BitmapColor	aCol( 0 );
255 		const long	nWidth = pAcc->Width(),	nHeight = pAcc->Height();
256 		sal_uInt8*		pMap = new sal_uInt8[ 256 ];
257 
258 		for( long i = 0; i < 256; i++ )
259 			pMap[ i ] = ~(sal_uInt8) i;
260 
261 		for( long nY = 0L; nY < nHeight; nY++ )
262 		{
263 			for( long nX = 0L; nX < nWidth; nX++ )
264 			{
265 				aCol.SetIndex( pMap[ pAcc->GetPixel( nY, nX ).GetIndex() ] );
266 				pAcc->SetPixel( nY, nX, aCol );
267 			}
268 		}
269 
270 		delete[] pMap;
271 		bRet = sal_True;
272 	}
273 
274 	if( pAcc )
275 		ReleaseAccess( pAcc );
276 
277 	return bRet;
278 }
279 
280 // -----------------------------------------------------------------------------
281 
282 sal_Bool AlphaMask::Mirror( sal_uLong nMirrorFlags )
283 {
284 	return Bitmap::Mirror( nMirrorFlags );
285 }
286 
287 // -----------------------------------------------------------------------------
288 
289 sal_Bool AlphaMask::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
290 {
291 	sal_Bool bRet = Bitmap::Scale( rNewSize, nScaleFlag );
292 
293 	if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
294 		Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
295 
296 	return bRet;
297 }
298 
299 // -----------------------------------------------------------------------------
300 
301 sal_Bool AlphaMask::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
302 {
303 	sal_Bool bRet = Bitmap::Scale( rScaleX, rScaleY, nScaleFlag );
304 
305 	if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
306 		Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
307 
308 	return bRet;
309 }
310 
311 // -----------------------------------------------------------------------------
312 
313 sal_Bool AlphaMask::Rotate( long nAngle10, sal_uInt8 cFillTransparency )
314 {
315 	return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) );
316 }
317 
318 // -----------------------------------------------------------------------------
319 
320 sal_Bool AlphaMask::Replace( const Bitmap& rMask, sal_uInt8 cReplaceTransparency )
321 {
322 	BitmapReadAccess*	pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
323 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
324 	sal_Bool				bRet = sal_False;
325 
326 	if( pMaskAcc && pAcc )
327 	{
328 		const BitmapColor	aReplace( cReplaceTransparency );
329 		const long			nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
330 		const long			nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
331 		const BitmapColor	aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
332 
333 		for( long nY = 0L; nY < nHeight; nY++ )
334 			for( long nX = 0L; nX < nWidth; nX++ )
335 				if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
336 					pAcc->SetPixel( nY, nX, aReplace );
337 	}
338 
339 	( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
340 	ReleaseAccess( pAcc );
341 
342 	return bRet;
343 }
344 
345 // -----------------------------------------------------------------------------
346 
347 sal_Bool AlphaMask::Replace( sal_uInt8 cSearchTransparency, sal_uInt8 cReplaceTransparency, sal_uLong
348 #ifdef DBG_UTIL
349 nTol
350 #endif
351 )
352 {
353 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
354 	sal_Bool				bRet = sal_False;
355 
356 	DBG_ASSERT( !nTol, "AlphaMask::Replace: nTol not used yet" );
357 
358 	if( pAcc && pAcc->GetBitCount() == 8 )
359 	{
360 		const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
361 
362 		if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
363 		{
364 			for( long nY = 0L; nY < nHeight; nY++ )
365 			{
366 				Scanline pScan = pAcc->GetScanline( nY );
367 
368 				for( long nX = 0L; nX < nWidth; nX++, pScan++ )
369 				{
370 					if( *pScan == cSearchTransparency )
371 						*pScan = cReplaceTransparency;
372 				}
373 			}
374 		}
375 		else
376 		{
377 			BitmapColor	aReplace( cReplaceTransparency );
378 
379 			for( long nY = 0L; nY < nHeight; nY++ )
380 			{
381 				for( long nX = 0L; nX < nWidth; nX++ )
382 				{
383 					if( pAcc->GetPixel( nY, nX ).GetIndex() == cSearchTransparency )
384 						pAcc->SetPixel( nY, nX, aReplace );
385 				}
386 			}
387 		}
388 
389 		bRet = sal_True;
390 	}
391 
392 	if( pAcc )
393 		ReleaseAccess( pAcc );
394 
395 	return bRet;
396 }
397 
398 // -----------------------------------------------------------------------------
399 
400 sal_Bool AlphaMask::Replace( sal_uInt8* pSearchTransparencies, sal_uInt8* pReplaceTransparencies,
401 						 sal_uLong nColorCount, sal_uLong* pTols )
402 {
403 	Color*	pSearchColors = new Color[ nColorCount ];
404 	Color*	pReplaceColors = new Color[ nColorCount ];
405 	sal_Bool	bRet;
406 
407 	for( sal_uLong i = 0; i < nColorCount; i++ )
408 	{
409 		const sal_uInt8 cSearchTransparency = pSearchTransparencies[ i ];
410 		const sal_uInt8 cReplaceTransparency = pReplaceTransparencies[ i ];
411 
412 		pSearchColors[ i ] = Color( cSearchTransparency, cSearchTransparency, cSearchTransparency );
413 		pReplaceColors[ i ] = Color( cReplaceTransparency, cReplaceTransparency, cReplaceTransparency );
414 	}
415 
416 	bRet = Bitmap::Replace( pSearchColors, pReplaceColors, nColorCount, pTols ) &&
417 		   Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
418 
419 	delete[] pSearchColors;
420 	delete[] pReplaceColors;
421 
422 	return bRet;
423 }
424 
425 // -----------------------------------------------------------------------------
426 
427 void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess )
428 {
429 	if( pAccess )
430 	{
431 		Bitmap::ReleaseAccess( pAccess );
432 		Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
433 	}
434 }
435