xref: /trunk/main/vcl/source/gdi/bitmap.cxx (revision 0399a9fd)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <rtl/crc.h>
28 #include <tools/stream.hxx>
29 #include <tools/poly.hxx>
30 #include <tools/rc.h>
31 
32 #include <vcl/salbtype.hxx>
33 #include <vcl/bmpacc.hxx>
34 #include <vcl/outdev.hxx>
35 #include <vcl/bitmap.hxx>
36 #include <vcl/bitmapex.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/image.hxx>
39 
40 #include <impbmp.hxx>
41 #include <salbmp.hxx>
42 
43 // ----------
44 // - Bitmap -
45 // ----------
46 
Bitmap()47 Bitmap::Bitmap() :
48 	mpImpBmp( NULL )
49 {
50 }
51 
52 // ------------------------------------------------------------------
53 
Bitmap(const ResId & rResId)54 Bitmap::Bitmap( const ResId& rResId ) :
55 	mpImpBmp( NULL )
56 {
57 	const BitmapEx aBmpEx( rResId );
58 
59 	if( !aBmpEx.IsEmpty() )
60 		*this = aBmpEx.GetBitmap();
61 }
62 
63 // ------------------------------------------------------------------
64 
Bitmap(const Bitmap & rBitmap)65 Bitmap::Bitmap( const Bitmap& rBitmap ) :
66 	maPrefMapMode	( rBitmap.maPrefMapMode ),
67 	maPrefSize		( rBitmap.maPrefSize )
68 {
69 	mpImpBmp = rBitmap.mpImpBmp;
70 
71 	if ( mpImpBmp )
72 		mpImpBmp->ImplIncRefCount();
73 }
74 
75 // ------------------------------------------------------------------
76 
Bitmap(SalBitmap * pSalBitmap)77 Bitmap::Bitmap( SalBitmap* pSalBitmap )
78 {
79 	mpImpBmp = new ImpBitmap();
80 	mpImpBmp->ImplSetSalBitmap( pSalBitmap );
81 	maPrefMapMode = MapMode( MAP_PIXEL );
82 	maPrefSize = mpImpBmp->ImplGetSize();
83 }
84 
85 // ------------------------------------------------------------------
86 
Bitmap(const Size & rSizePixel,sal_uInt16 nBitCount,const BitmapPalette * pPal)87 Bitmap::Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal )
88 {
89 	if( rSizePixel.Width() && rSizePixel.Height() )
90 	{
91 		BitmapPalette	aPal;
92 		BitmapPalette*	pRealPal = NULL;
93 
94 		if( nBitCount <= 8 )
95 		{
96 			if( !pPal )
97 			{
98 				if( 1 == nBitCount )
99 				{
100 					aPal.SetEntryCount( 2 );
101 					aPal[ 0 ] = Color( COL_BLACK );
102 					aPal[ 1 ] = Color( COL_WHITE );
103 				}
104 				else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
105 				{
106 					aPal.SetEntryCount( 1 << nBitCount );
107 					aPal[ 0 ] = Color( COL_BLACK );
108 					aPal[ 1 ] = Color( COL_BLUE );
109 					aPal[ 2 ] = Color( COL_GREEN );
110 					aPal[ 3 ] = Color( COL_CYAN );
111 					aPal[ 4 ] = Color( COL_RED );
112 					aPal[ 5 ] = Color( COL_MAGENTA );
113 					aPal[ 6 ] = Color( COL_BROWN );
114 					aPal[ 7 ] = Color( COL_GRAY );
115 					aPal[ 8 ] = Color( COL_LIGHTGRAY );
116 					aPal[ 9 ] = Color( COL_LIGHTBLUE );
117 					aPal[ 10 ] = Color( COL_LIGHTGREEN );
118 					aPal[ 11 ] = Color( COL_LIGHTCYAN );
119 					aPal[ 12 ] = Color( COL_LIGHTRED );
120 					aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
121 					aPal[ 14 ] = Color( COL_YELLOW );
122 					aPal[ 15 ] = Color( COL_WHITE );
123 
124 					// Dither-Palette erzeugen
125 					if( 8 == nBitCount )
126 					{
127 						sal_uInt16 nActCol = 16;
128 
129 						for( sal_uInt16 nB = 0; nB < 256; nB += 51 )
130 							for( sal_uInt16 nG = 0; nG < 256; nG += 51 )
131 								for( sal_uInt16 nR = 0; nR < 256; nR += 51 )
132 									aPal[ nActCol++ ] = BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB );
133 
134 						// Standard-Office-Farbe setzen
135 						aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
136 					}
137 				}
138 			}
139 			else
140 				pRealPal = (BitmapPalette*) pPal;
141 		}
142 
143 		mpImpBmp = new ImpBitmap;
144 		mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
145 	}
146 	else
147 		mpImpBmp = NULL;
148 }
149 
150 // ------------------------------------------------------------------
151 
~Bitmap()152 Bitmap::~Bitmap()
153 {
154 	ImplReleaseRef();
155 }
156 
157 // ------------------------------------------------------------------
158 
GetGreyPalette(int nEntries)159 const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
160 {
161 	static BitmapPalette aGreyPalette2;
162 	static BitmapPalette aGreyPalette4;
163 	static BitmapPalette aGreyPalette16;
164 	static BitmapPalette aGreyPalette256;
165 
166 	// create greyscale palette with 2, 4, 16 or 256 entries
167 	if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
168 	{
169 		if( 2 == nEntries )
170 		{
171 			if( !aGreyPalette2.GetEntryCount() )
172 			{
173 				aGreyPalette2.SetEntryCount( 2 );
174 				aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
175 				aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
176 			}
177 
178 			return aGreyPalette2;
179 		}
180 		else if( 4 == nEntries )
181 		{
182 			if( !aGreyPalette4.GetEntryCount() )
183 			{
184 				aGreyPalette4.SetEntryCount( 4 );
185 				aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
186 				aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
187 				aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
188 				aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
189 			}
190 
191 			return aGreyPalette4;
192 		}
193 		else if( 16 == nEntries )
194 		{
195 			if( !aGreyPalette16.GetEntryCount() )
196 			{
197 				sal_uInt8 cGrey = 0, cGreyInc = 17;
198 
199 				aGreyPalette16.SetEntryCount( 16 );
200 
201 				for( sal_uInt16 i = 0; i < 16; i++, cGrey = sal::static_int_cast<sal_uInt8>(cGrey + cGreyInc) )
202 					aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
203 			}
204 
205 			return aGreyPalette16;
206 		}
207 		else
208 		{
209 			if( !aGreyPalette256.GetEntryCount() )
210 			{
211 				aGreyPalette256.SetEntryCount( 256 );
212 
213 				for( sal_uInt16 i = 0; i < 256; i++ )
214 					aGreyPalette256[ i ] = BitmapColor( (sal_uInt8) i, (sal_uInt8) i, (sal_uInt8) i );
215 			}
216 
217 			return aGreyPalette256;
218 		}
219 	}
220 	else
221 	{
222 		DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
223 		return aGreyPalette2;
224 	}
225 }
226 
227 // ------------------------------------------------------------------
228 
IsGreyPalette() const229 bool BitmapPalette::IsGreyPalette() const
230 {
231 	// TODO: add an IsGreyPalette flag to BitmapPalette
232 	// TODO: unless this causes problems binary compatibility
233 	const int nEntryCount = GetEntryCount();
234 	if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
235 		return true;
236 	// see above: only certain entry values will result in a valid call to GetGreyPalette
237 	if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 )
238 	{
239 		const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
240 		if( rGreyPalette == *this )
241 			return true;
242 	}
243 	// TODO: is it worth to compare the entries?
244 	return false;
245 }
246 
247 // ------------------------------------------------------------------
248 
operator =(const Bitmap & rBitmap)249 Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
250 {
251 	maPrefSize = rBitmap.maPrefSize;
252 	maPrefMapMode = rBitmap.maPrefMapMode;
253 
254 	if ( rBitmap.mpImpBmp )
255 		rBitmap.mpImpBmp->ImplIncRefCount();
256 
257 	ImplReleaseRef();
258 	mpImpBmp = rBitmap.mpImpBmp;
259 
260 	return *this;
261 }
262 
263 // ------------------------------------------------------------------
264 
IsEqual(const Bitmap & rBmp) const265 sal_Bool Bitmap::IsEqual( const Bitmap& rBmp ) const
266 {
267 	return( IsSameInstance( rBmp ) ||
268 			( rBmp.GetSizePixel() == GetSizePixel() &&
269 			  rBmp.GetBitCount() == GetBitCount() &&
270 			  rBmp.GetChecksum() == GetChecksum() ) );
271 }
272 
273 // ------------------------------------------------------------------
274 
SetEmpty()275 void Bitmap::SetEmpty()
276 {
277 	maPrefMapMode = MapMode();
278 	maPrefSize = Size();
279 
280 	ImplReleaseRef();
281 	mpImpBmp = NULL;
282 }
283 
284 // ------------------------------------------------------------------
285 
GetSizePixel() const286 Size Bitmap::GetSizePixel() const
287 {
288 	return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
289 }
290 // ------------------------------------------------------------------
291 
SetSizePixel(const Size & rNewSize,sal_uInt32 nScaleFlag)292 void Bitmap::SetSizePixel( const Size& rNewSize, sal_uInt32 nScaleFlag )
293 {
294 	if(GetSizePixel() != rNewSize)
295 	{
296 		Scale( rNewSize, nScaleFlag );
297 	}
298 }
299 
300 // ------------------------------------------------------------------
301 
GetSourceSizePixel() const302 Size Bitmap::GetSourceSizePixel() const
303 {
304 	return( mpImpBmp ? mpImpBmp->ImplGetSourceSize() : Size() );
305 }
306 
307 // ------------------------------------------------------------------
308 
SetSourceSizePixel(const Size & rSize)309 void Bitmap::SetSourceSizePixel( const Size& rSize)
310 {
311 	if( mpImpBmp )
312 		mpImpBmp->ImplSetSourceSize( rSize);
313 }
314 
315 // ------------------------------------------------------------------
316 
GetBitCount() const317 sal_uInt16 Bitmap::GetBitCount() const
318 {
319 	return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
320 }
321 
322 // ------------------------------------------------------------------
323 
HasGreyPalette() const324 sal_Bool Bitmap::HasGreyPalette() const
325 {
326 	const sal_uInt16	nBitCount = GetBitCount();
327 	sal_Bool			bRet = sal_False;
328 
329 	if( 1 == nBitCount )
330 	{
331 		BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
332 
333 		if( pRAcc )
334 		{
335 			const BitmapColor& rCol0( pRAcc->GetPaletteColor( 0 ) );
336 			const BitmapColor& rCol1( pRAcc->GetPaletteColor( 1 ) );
337 			if( rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() &&
338 				rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue() )
339 			{
340 				bRet = sal_True;
341 			}
342 			 ( (Bitmap*) this )->ReleaseAccess( pRAcc );
343 		}
344 		else
345 			bRet = sal_True;
346 	}
347 	else if( 4 == nBitCount || 8 == nBitCount )
348 	{
349 		BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
350 
351 		if( pRAcc )
352 		{
353 			if( pRAcc->HasPalette() && ( (BitmapPalette&) pRAcc->GetPalette() == GetGreyPalette( 1 << nBitCount ) ) )
354 				bRet = sal_True;
355 
356 			 ( (Bitmap*) this )->ReleaseAccess( pRAcc );
357 		}
358 	}
359 
360 	return bRet;
361 }
362 
363 // ------------------------------------------------------------------
364 
GetChecksum() const365 sal_uLong Bitmap::GetChecksum() const
366 {
367 	sal_uLong nRet = 0UL;
368 
369 	if( mpImpBmp )
370 	{
371 		nRet = mpImpBmp->ImplGetChecksum();
372 
373 		if( !nRet )
374 		{
375 			BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
376 
377 			if( pRAcc && pRAcc->Width() && pRAcc->Height() )
378 			{
379 				sal_uInt32	nCrc = 0;
380 				SVBT32		aBT32;
381 
382 				pRAcc->ImplZeroInitUnusedBits();
383 
384 				UInt32ToSVBT32( pRAcc->Width(), aBT32 );
385 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
386 
387 				UInt32ToSVBT32( pRAcc->Height(), aBT32 );
388 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
389 
390 				UInt32ToSVBT32( pRAcc->GetBitCount(), aBT32 );
391 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
392 
393 				UInt32ToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
394 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
395 
396 				UInt32ToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
397 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
398 
399 				UInt32ToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
400 				nCrc = rtl_crc32( nCrc, aBT32, 4 );
401 
402 				if( pRAcc->HasPalette() )
403 				{
404 					nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
405 									  pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
406 				}
407 
408 				nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
409 
410 				mpImpBmp->ImplSetChecksum( nRet = nCrc );
411 			}
412 
413 			if (pRAcc) ( (Bitmap*) this )->ReleaseAccess( pRAcc );
414 		}
415 	}
416 
417 	return nRet;
418 }
419 
420 // ------------------------------------------------------------------
421 
ImplReleaseRef()422 void Bitmap::ImplReleaseRef()
423 {
424 	if( mpImpBmp )
425 	{
426 		if( mpImpBmp->ImplGetRefCount() > 1UL )
427 			mpImpBmp->ImplDecRefCount();
428 		else
429 		{
430 			delete mpImpBmp;
431 			mpImpBmp = NULL;
432 		}
433 	}
434 }
435 
436 // ------------------------------------------------------------------
437 
ImplMakeUnique()438 void Bitmap::ImplMakeUnique()
439 {
440 	if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
441 	{
442 		ImpBitmap* pOldImpBmp = mpImpBmp;
443 
444 		pOldImpBmp->ImplDecRefCount();
445 
446 		mpImpBmp = new ImpBitmap;
447 		mpImpBmp->ImplCreate( *pOldImpBmp );
448 	}
449 }
450 
451 // ------------------------------------------------------------------
452 
ImplAssignWithSize(const Bitmap & rBitmap)453 void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
454 {
455 	const Size		aOldSizePix( GetSizePixel() );
456 	const Size		aNewSizePix( rBitmap.GetSizePixel() );
457 	const MapMode	aOldMapMode( maPrefMapMode );
458 	Size			aNewPrefSize;
459 
460 	if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
461 	{
462 		aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
463 		aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
464 	}
465 	else
466 		aNewPrefSize = maPrefSize;
467 
468 	*this = rBitmap;
469 
470 	maPrefSize = aNewPrefSize;
471 	maPrefMapMode = aOldMapMode;
472 }
473 
474 // ------------------------------------------------------------------
475 
ImplGetImpBitmap() const476 ImpBitmap* Bitmap::ImplGetImpBitmap() const
477 {
478 	return mpImpBmp;
479 }
480 
481 // ------------------------------------------------------------------
482 
ImplSetImpBitmap(ImpBitmap * pImpBmp)483 void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
484 {
485 	if( pImpBmp != mpImpBmp )
486 	{
487 		ImplReleaseRef();
488 		mpImpBmp = pImpBmp;
489 	}
490 }
491 
492 // ------------------------------------------------------------------
493 
AcquireReadAccess()494 BitmapReadAccess* Bitmap::AcquireReadAccess()
495 {
496 	BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
497 
498 	if( !*pReadAccess )
499 	{
500 		delete pReadAccess;
501 		pReadAccess = NULL;
502 	}
503 
504 	return pReadAccess;
505 }
506 
507 // ------------------------------------------------------------------
508 
AcquireWriteAccess()509 BitmapWriteAccess* Bitmap::AcquireWriteAccess()
510 {
511 	BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
512 
513 	if( !*pWriteAccess )
514 	{
515 		delete pWriteAccess;
516 		pWriteAccess = NULL;
517 	}
518 
519 	return pWriteAccess;
520 }
521 
522 // ------------------------------------------------------------------
523 
ReleaseAccess(BitmapReadAccess * pBitmapAccess)524 void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
525 {
526 	delete pBitmapAccess;
527 }
528 
529 // ------------------------------------------------------------------
530 
Erase(const Color & rFillColor)531 sal_Bool Bitmap::Erase( const Color& rFillColor )
532 {
533 	if( !(*this) )
534 		return sal_True;
535 
536 	BitmapWriteAccess*	pWriteAcc = AcquireWriteAccess();
537 	sal_Bool				bRet = sal_False;
538 
539 	if( pWriteAcc )
540 	{
541 		const sal_uLong nFormat = pWriteAcc->GetScanlineFormat();
542 		sal_uInt8		cIndex = 0;
543 		sal_Bool		bFast = sal_False;
544 
545 		switch( nFormat )
546 		{
547 			case( BMP_FORMAT_1BIT_MSB_PAL ):
548 			case( BMP_FORMAT_1BIT_LSB_PAL ):
549 			{
550 				cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
551 				cIndex = ( cIndex ? 255 : 0 );
552 				bFast = sal_True;
553 			}
554 			break;
555 
556 			case( BMP_FORMAT_4BIT_MSN_PAL ):
557 			case( BMP_FORMAT_4BIT_LSN_PAL ):
558 			{
559 				cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
560 				cIndex = cIndex | ( cIndex << 4 );
561 				bFast = sal_True;
562 			}
563 			break;
564 
565 			case( BMP_FORMAT_8BIT_PAL ):
566 			{
567 				cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
568 				bFast = sal_True;
569 			}
570 			break;
571 
572 			case( BMP_FORMAT_24BIT_TC_BGR ):
573 			case( BMP_FORMAT_24BIT_TC_RGB ):
574 			{
575 				if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
576 					( rFillColor.GetRed() == rFillColor.GetBlue() ) )
577 				{
578 					cIndex = rFillColor.GetRed();
579 					bFast = sal_True;
580 				}
581 				else
582 					bFast = sal_False;
583 			}
584 			break;
585 
586 			default:
587 				bFast = sal_False;
588 			break;
589 		}
590 
591 		if( bFast )
592 		{
593 			const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
594 			memset( pWriteAcc->GetBuffer(), cIndex, nBufSize );
595 		}
596 		else
597 		{
598 			Point aTmpPoint;
599 			const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
600 			pWriteAcc->SetFillColor( rFillColor );
601 			pWriteAcc->FillRect( aRect );
602 		}
603 
604 		ReleaseAccess( pWriteAcc );
605 		bRet = sal_True;
606 	}
607 
608 	return bRet;
609 }
610 
611 // ------------------------------------------------------------------
612 
Invert()613 sal_Bool Bitmap::Invert()
614 {
615 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
616 	sal_Bool				bRet = sal_False;
617 
618 	if( pAcc )
619 	{
620 		if( pAcc->HasPalette() )
621 		{
622 			BitmapPalette	aBmpPal( pAcc->GetPalette() );
623 			const sal_uInt16	nCount = aBmpPal.GetEntryCount();
624 
625 			for( sal_uInt16 i = 0; i < nCount; i++ )
626 				aBmpPal[ i ].Invert();
627 
628 			pAcc->SetPalette( aBmpPal );
629 		}
630 		else
631 		{
632 			const long	nWidth = pAcc->Width();
633 			const long	nHeight = pAcc->Height();
634 
635 			for( long nX = 0L; nX < nWidth; nX++ )
636 				for( long nY = 0L; nY < nHeight; nY++ )
637 					pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
638 		}
639 
640 		ReleaseAccess( pAcc );
641 		bRet = sal_True;
642 	}
643 
644 	return bRet;
645 }
646 
647 // ------------------------------------------------------------------
648 
Mirror(sal_uLong nMirrorFlags)649 sal_Bool Bitmap::Mirror( sal_uLong nMirrorFlags )
650 {
651 	sal_Bool bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
652 	sal_Bool bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
653 	sal_Bool bRet = sal_False;
654 
655 	if( bHorz && !bVert )
656 	{
657 		BitmapWriteAccess*	pAcc = AcquireWriteAccess();
658 
659 		if( pAcc )
660 		{
661 			const long	nWidth = pAcc->Width();
662 			const long	nHeight = pAcc->Height();
663 			const long	nWidth1 = nWidth - 1L;
664 			const long	nWidth_2 = nWidth >> 1L;
665 
666 			for( long nY = 0L; nY < nHeight; nY++ )
667 			{
668 				for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
669 				{
670 					const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
671 
672 					pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
673 					pAcc->SetPixel( nY, nOther, aTemp );
674 				}
675 			}
676 
677 			ReleaseAccess( pAcc );
678 			bRet = sal_True;
679 		}
680 	}
681 	else if( bVert && !bHorz )
682 	{
683 		BitmapWriteAccess*	pAcc = AcquireWriteAccess();
684 
685 		if( pAcc )
686 		{
687 			const long	nScanSize = pAcc->GetScanlineSize();
688 			sal_uInt8*		pBuffer = new sal_uInt8[ nScanSize ];
689 			const long	nHeight = pAcc->Height();
690 			const long	nHeight1 = nHeight - 1L;
691 			const long	nHeight_2 = nHeight >> 1L;
692 
693 			for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
694 			{
695 				memcpy( pBuffer, pAcc->GetScanline( nY ), nScanSize );
696 				memcpy( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
697 				memcpy( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
698 			}
699 
700 			delete[] pBuffer;
701 			ReleaseAccess( pAcc );
702 			bRet = sal_True;
703 		}
704 	}
705 	else if( bHorz && bVert )
706 	{
707 		BitmapWriteAccess*	pAcc = AcquireWriteAccess();
708 
709 		if( pAcc )
710 		{
711 			const long	nWidth = pAcc->Width();
712 			const long	nWidth1 = nWidth - 1L;
713 			const long	nHeight = pAcc->Height();
714 			long		nHeight_2 = nHeight >> 1;
715 
716 			for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
717 			{
718 				for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
719 				{
720 					const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
721 
722 					pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
723 					pAcc->SetPixel( nOtherY, nOtherX, aTemp );
724 				}
725 			}
726 
727 			// ggf. noch mittlere Zeile horizontal spiegeln
728 			if( nHeight & 1 )
729 			{
730 				for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
731 				{
732 					const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
733 					pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
734 					pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
735 				}
736 			}
737 
738 			ReleaseAccess( pAcc );
739 			bRet = sal_True;
740 		}
741 	}
742 	else
743 		bRet = sal_True;
744 
745 	return bRet;
746 }
747 
748 // ------------------------------------------------------------------
749 
Rotate(long nAngle10,const Color & rFillColor)750 sal_Bool Bitmap::Rotate( long nAngle10, const Color& rFillColor )
751 {
752 	sal_Bool bRet = sal_False;
753 
754 	nAngle10 %= 3600L;
755 	nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
756 
757 	if( !nAngle10	 )
758 		bRet = sal_True;
759 	else if( 1800L == nAngle10 )
760 		bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
761 	else
762 	{
763 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
764 		Bitmap				aRotatedBmp;
765 
766 		if( pReadAcc )
767 		{
768 			const Size	aSizePix( GetSizePixel() );
769 
770 			if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
771 			{
772 				const Size			aNewSizePix( aSizePix.Height(), aSizePix.Width() );
773 				Bitmap				aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
774 				BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
775 
776 				if( pWriteAcc )
777 				{
778 					const long	nWidth = aSizePix.Width();
779 					const long	nWidth1 = nWidth - 1L;
780 					const long	nHeight = aSizePix.Height();
781 					const long	nHeight1 = nHeight - 1L;
782 					const long	nNewWidth = aNewSizePix.Width();
783 					const long	nNewHeight = aNewSizePix.Height();
784 
785 					if( 900L == nAngle10 )
786 					{
787 						for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
788 							for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
789 								pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
790 					}
791 					else if( 2700L == nAngle10 )
792 					{
793 						for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
794 							for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
795 								pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
796 					}
797 
798 					aNewBmp.ReleaseAccess( pWriteAcc );
799 				}
800 
801 				aRotatedBmp = aNewBmp;
802 			}
803 			else
804 			{
805 				Point		aTmpPoint;
806 				Rectangle	aTmpRectangle( aTmpPoint, aSizePix );
807 				Polygon 	aPoly( aTmpRectangle );
808 				aPoly.Rotate( aTmpPoint, (sal_uInt16) nAngle10 );
809 
810 				Rectangle			aNewBound( aPoly.GetBoundRect() );
811 				const Size			aNewSizePix( aNewBound.GetSize() );
812 				Bitmap				aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
813 				BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
814 
815 				if( pWriteAcc )
816 				{
817 					const BitmapColor	aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
818 					const double		fCosAngle = cos( nAngle10 * F_PI1800 );
819 					const double		fSinAngle = sin( nAngle10 * F_PI1800 );
820 					const double		fXMin = aNewBound.Left();
821 					const double		fYMin = aNewBound.Top();
822 					const long			nWidth = aSizePix.Width();
823 					const long			nHeight = aSizePix.Height();
824 					const long			nNewWidth = aNewSizePix.Width();
825 					const long			nNewHeight = aNewSizePix.Height();
826 					long				nX;
827 					long				nY;
828 					long				nRotX;
829 					long				nRotY;
830 					long				nSinY;
831 					long				nCosY;
832 					long*				pCosX = new long[ nNewWidth ];
833 					long*				pSinX = new long[ nNewWidth ];
834 					long*				pCosY = new long[ nNewHeight ];
835 					long*				pSinY = new long[ nNewHeight ];
836 
837 					for ( nX = 0; nX < nNewWidth; nX++ )
838 					{
839 						const double fTmp = ( fXMin + nX ) * 64.;
840 
841 						pCosX[ nX ] = FRound( fCosAngle * fTmp );
842 						pSinX[ nX ] = FRound( fSinAngle * fTmp );
843 					}
844 
845 					for ( nY = 0; nY < nNewHeight; nY++ )
846 					{
847 						const double fTmp = ( fYMin + nY ) * 64.;
848 
849 						pCosY[ nY ] = FRound( fCosAngle * fTmp );
850 						pSinY[ nY ] = FRound( fSinAngle * fTmp );
851 					}
852 
853 					for( nY = 0L; nY < nNewHeight; nY++ )
854 					{
855 						nSinY = pSinY[ nY ];
856 						nCosY = pCosY[ nY ];
857 
858 						for( nX = 0L; nX < nNewWidth; nX++ )
859 						{
860 							nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
861 							nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
862 
863 							if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
864 								pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
865 							else
866 								pWriteAcc->SetPixel( nY, nX, aFillColor );
867 						}
868 					}
869 
870 					delete[] pSinX;
871 					delete[] pCosX;
872 					delete[] pSinY;
873 					delete[] pCosY;
874 
875 					aNewBmp.ReleaseAccess( pWriteAcc );
876 				}
877 
878 				aRotatedBmp = aNewBmp;
879 			}
880 
881 			ReleaseAccess( pReadAcc );
882 		}
883 
884 		if( ( bRet = !!aRotatedBmp ) == sal_True )
885 			ImplAssignWithSize( aRotatedBmp );
886 	}
887 
888 	return bRet;
889 };
890 
891 // ------------------------------------------------------------------
892 
Crop(const Rectangle & rRectPixel)893 sal_Bool Bitmap::Crop( const Rectangle& rRectPixel )
894 {
895 	const Size			aSizePix( GetSizePixel() );
896 	Rectangle			aRect( rRectPixel );
897 	sal_Bool				bRet = sal_False;
898 
899 	aRect.Intersection( Rectangle( Point(), aSizePix ) );
900 
901 	if( !aRect.IsEmpty() )
902 	{
903 		BitmapReadAccess* pReadAcc = AcquireReadAccess();
904 
905 		if( pReadAcc )
906 		{
907 			Point				aTmpPoint;
908 			const Rectangle 	aNewRect( aTmpPoint, aRect.GetSize() );
909 			Bitmap				aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
910 			BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
911 
912 			if( pWriteAcc )
913 			{
914 				const long nOldX = aRect.Left();
915 				const long nOldY = aRect.Top();
916 				const long nNewWidth = aNewRect.GetWidth();
917 				const long nNewHeight = aNewRect.GetHeight();
918 
919 				for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
920 					for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
921 						pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
922 
923 				aNewBmp.ReleaseAccess( pWriteAcc );
924 				bRet = sal_True;
925 			}
926 
927 			ReleaseAccess( pReadAcc );
928 
929 			if( bRet )
930 				ImplAssignWithSize( aNewBmp );
931 		}
932 	}
933 
934 	return bRet;
935 };
936 
937 // ------------------------------------------------------------------
938 
CopyPixel(const Rectangle & rRectDst,const Rectangle & rRectSrc,const Bitmap * pBmpSrc)939 sal_Bool Bitmap::CopyPixel( const Rectangle& rRectDst,
940 						const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
941 {
942 	const Size	aSizePix( GetSizePixel() );
943 	Rectangle	aRectDst( rRectDst );
944 	sal_Bool		bRet = sal_False;
945 
946 	aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
947 
948 	if( !aRectDst.IsEmpty() )
949 	{
950 		if( pBmpSrc && ( *pBmpSrc != *this ) )
951 		{
952 			Bitmap* 		pSrc = (Bitmap*) pBmpSrc;
953 			const Size		aCopySizePix( pSrc->GetSizePixel() );
954 			Rectangle		aRectSrc( rRectSrc );
955 			const sal_uInt16	nSrcBitCount = pBmpSrc->GetBitCount();
956 			const sal_uInt16	nDstBitCount = GetBitCount();
957 
958 			if( nSrcBitCount > nDstBitCount )
959 			{
960 				long nNextIndex = 0L;
961 
962 				if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
963 					Convert( BMP_CONVERSION_24BIT );
964 				else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
965 				{
966 					Convert( BMP_CONVERSION_8BIT_COLORS );
967 					nNextIndex = 16;
968 				}
969 				else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
970 				{
971 					Convert( BMP_CONVERSION_4BIT_COLORS );
972 					nNextIndex = 2;
973 				}
974 
975 				if( nNextIndex )
976 				{
977 					BitmapReadAccess*	pSrcAcc = pSrc->AcquireReadAccess();
978 					BitmapWriteAccess*	pDstAcc = AcquireWriteAccess();
979 
980 					if( pSrcAcc && pDstAcc )
981 					{
982 						const long		nSrcCount = pDstAcc->GetPaletteEntryCount();
983 						const long		nDstCount = 1 << nDstBitCount;
984 						sal_Bool			bFound;
985 
986 						for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
987 						{
988 							const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (sal_uInt16) i );
989 
990 							bFound = sal_False;
991 
992 							for( long j = 0L; j < nDstCount; j++ )
993 							{
994 								if( rSrcCol == pDstAcc->GetPaletteColor( (sal_uInt16) j ) )
995 								{
996 									bFound = sal_True;
997 									break;
998 								}
999 							}
1000 
1001 							if( !bFound )
1002 								pDstAcc->SetPaletteColor( (sal_uInt16) nNextIndex++, rSrcCol );
1003 						}
1004 					}
1005 
1006 					if( pSrcAcc )
1007 						pSrc->ReleaseAccess( pSrcAcc );
1008 
1009 					if( pDstAcc )
1010 						ReleaseAccess( pDstAcc );
1011 				}
1012 			}
1013 
1014 			aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
1015 
1016 			if( !aRectSrc.IsEmpty() )
1017 			{
1018 				BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
1019 
1020 				if( pReadAcc )
1021 				{
1022 					BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
1023 
1024 					if( pWriteAcc )
1025 					{
1026 						const long	nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
1027 						const long	nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
1028 						const long	nSrcEndX = aRectSrc.Left() + nWidth;
1029 						const long	nSrcEndY = aRectSrc.Top() + nHeight;
1030 						long		nDstY = aRectDst.Top();
1031 
1032 						if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
1033 						{
1034 							const sal_uInt16	nCount = pReadAcc->GetPaletteEntryCount();
1035 							sal_uInt8*			pMap = new sal_uInt8[ nCount ];
1036 
1037 							// Index-Map fuer Farbtabelle
1038 							// aufbauen, da das Bild ja (relativ) farbgenau
1039 							// kopiert werden soll
1040 							for( sal_uInt16 i = 0; i < nCount; i++ )
1041 								pMap[ i ] = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
1042 
1043 							for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1044 								for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1045 									pWriteAcc->SetPixelIndex( nDstY, nDstX, pMap[ pReadAcc->GetPixelIndex( nSrcY, nSrcX ) ] );
1046 
1047 							delete[] pMap;
1048 						}
1049 						else if( pReadAcc->HasPalette() )
1050 						{
1051 							for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1052 								for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1053 									pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nSrcY, nSrcX ) ) );
1054 						}
1055 						else
1056 							for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1057 								for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1058 									pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
1059 
1060 						ReleaseAccess( pWriteAcc );
1061 						bRet = ( nWidth > 0L ) && ( nHeight > 0L );
1062 					}
1063 
1064 					pSrc->ReleaseAccess( pReadAcc );
1065 				}
1066 			}
1067 		}
1068 		else
1069 		{
1070 			Rectangle aRectSrc( rRectSrc );
1071 
1072 			aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
1073 
1074 			if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
1075 			{
1076 				BitmapWriteAccess*	pWriteAcc = AcquireWriteAccess();
1077 
1078 				if( pWriteAcc )
1079 				{
1080 					const long	nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
1081 					const long	nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
1082 					const long	nSrcX = aRectSrc.Left();
1083 					const long	nSrcY = aRectSrc.Top();
1084 					const long	nSrcEndX1 = nSrcX + nWidth - 1L;
1085 					const long	nSrcEndY1 = nSrcY + nHeight - 1L;
1086 					const long	nDstX = aRectDst.Left();
1087 					const long	nDstY = aRectDst.Top();
1088 					const long	nDstEndX1 = nDstX + nWidth - 1L;
1089 					const long	nDstEndY1 = nDstY + nHeight - 1L;
1090 
1091 					if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
1092 					{
1093 						for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
1094 							for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
1095 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1096 					}
1097 					else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
1098 					{
1099 						for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
1100 							for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
1101 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1102 					}
1103 					else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
1104 					{
1105 						for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
1106 							for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
1107 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1108 					}
1109 					else
1110 					{
1111 						for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
1112 							for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
1113 								pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1114 					}
1115 
1116 					ReleaseAccess( pWriteAcc );
1117 					bRet = sal_True;
1118 				}
1119 			}
1120 		}
1121 	}
1122 
1123 	return bRet;
1124 }
1125 
1126 // ------------------------------------------------------------------
1127 
Expand(sal_uLong nDX,sal_uLong nDY,const Color * pInitColor)1128 sal_Bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor )
1129 {
1130 	sal_Bool bRet = sal_False;
1131 
1132 	if( nDX || nDY )
1133 	{
1134 		const Size			aSizePixel( GetSizePixel() );
1135 		const long			nWidth = aSizePixel.Width();
1136 		const long			nHeight = aSizePixel.Height();
1137 		const Size			aNewSize( nWidth + nDX, nHeight + nDY );
1138 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1139 
1140 		if( pReadAcc )
1141 		{
1142 			BitmapPalette		aBmpPal( pReadAcc->GetPalette() );
1143 			Bitmap				aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
1144 			BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1145 
1146 			if( pWriteAcc )
1147 			{
1148 				BitmapColor aColor;
1149 				const long	nNewX = nWidth;
1150 				const long	nNewY = nHeight;
1151 				const long	nNewWidth = pWriteAcc->Width();
1152 				const long	nNewHeight = pWriteAcc->Height();
1153 				long		nX;
1154 				long		nY;
1155 
1156 				if( pInitColor )
1157 					aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
1158 
1159 				for( nY = 0L; nY < nHeight; nY++ )
1160 				{
1161 					pWriteAcc->CopyScanline( nY, *pReadAcc );
1162 
1163 					if( pInitColor && nDX )
1164 						for( nX = nNewX; nX < nNewWidth; nX++ )
1165 							pWriteAcc->SetPixel( nY, nX, aColor );
1166 				}
1167 
1168 				if( pInitColor && nDY )
1169 					for( nY = nNewY; nY < nNewHeight; nY++ )
1170 						for( nX = 0; nX < nNewWidth; nX++ )
1171 							pWriteAcc->SetPixel( nY, nX, aColor );
1172 
1173 				aNewBmp.ReleaseAccess( pWriteAcc );
1174 				bRet = sal_True;
1175 			}
1176 
1177 			ReleaseAccess( pReadAcc );
1178 
1179 			if( bRet )
1180 				ImplAssignWithSize( aNewBmp );
1181 		}
1182 	}
1183 
1184 	return bRet;
1185 }
1186 
1187 // ------------------------------------------------------------------
1188 
CreateMask(const Color & rTransColor,sal_uLong nTol) const1189 Bitmap Bitmap::CreateMask( const Color& rTransColor, sal_uLong nTol ) const
1190 {
1191 	Bitmap				aNewBmp( GetSizePixel(), 1 );
1192 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1193 	sal_Bool				bRet = sal_False;
1194 
1195 	if( pWriteAcc )
1196 	{
1197 		BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
1198 
1199 		if( pReadAcc )
1200 		{
1201 			const long			nWidth = pReadAcc->Width();
1202 			const long			nHeight = pReadAcc->Height();
1203 			const BitmapColor	aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
1204 			const BitmapColor	aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1205 
1206 			if( !nTol )
1207 			{
1208 				const BitmapColor	aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
1209 				long				nX, nY, nShift;
1210 
1211 				if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
1212 					pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
1213 				{
1214 					// optimized for 4Bit-MSN/LSN source palette
1215 					const sal_uInt8 cTest = aTest.GetIndex();
1216 					const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
1217 
1218 					if(	pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1219 						aWhite.GetIndex() == 1 )
1220 					{
1221 						// optimized for 1Bit-MSB destination palette
1222 						for( nY = 0L; nY < nHeight; nY++ )
1223 						{
1224 							Scanline pSrc = pReadAcc->GetScanline( nY );
1225 							Scanline pDst = pWriteAcc->GetScanline( nY );
1226 							for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
1227 							{
1228 								if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
1229 									pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1230 								else
1231 									pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1232 							}
1233 						}
1234 					}
1235 					else
1236 					{
1237 						for( nY = 0L; nY < nHeight; nY++ )
1238 						{
1239 							Scanline pSrc = pReadAcc->GetScanline( nY );
1240 							for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
1241 							{
1242 								if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
1243 									pWriteAcc->SetPixel( nY, nX, aWhite );
1244 								else
1245 									pWriteAcc->SetPixel( nY, nX, aBlack );
1246 							}
1247 						}
1248 					}
1249 				}
1250 				else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1251 				{
1252 					// optimized for 8Bit source palette
1253 					const sal_uInt8 cTest = aTest.GetIndex();
1254 
1255 					if(	pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1256 						aWhite.GetIndex() == 1 )
1257 					{
1258 						// optimized for 1Bit-MSB destination palette
1259 						for( nY = 0L; nY < nHeight; nY++ )
1260 						{
1261 							Scanline pSrc = pReadAcc->GetScanline( nY );
1262 							Scanline pDst = pWriteAcc->GetScanline( nY );
1263 							for( nX = 0L; nX < nWidth; nX++ )
1264 							{
1265 								if( cTest == pSrc[ nX ] )
1266 									pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1267 								else
1268 									pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1269 							}
1270 						}
1271 					}
1272 					else
1273 					{
1274 						for( nY = 0L; nY < nHeight; nY++ )
1275 						{
1276 							Scanline pSrc = pReadAcc->GetScanline( nY );
1277 							for( nX = 0L; nX < nWidth; nX++ )
1278 							{
1279 								if( cTest == pSrc[ nX ] )
1280 									pWriteAcc->SetPixel( nY, nX, aWhite );
1281 								else
1282 									pWriteAcc->SetPixel( nY, nX, aBlack );
1283 							}
1284 						}
1285 					}
1286 				}
1287 				else
1288 				{
1289 					// not optimized
1290 					for( nY = 0L; nY < nHeight; nY++ )
1291 					{
1292 						for( nX = 0L; nX < nWidth; nX++ )
1293 						{
1294 							if( aTest == pReadAcc->GetPixel( nY, nX ) )
1295 								pWriteAcc->SetPixel( nY, nX, aWhite );
1296 							else
1297 								pWriteAcc->SetPixel( nY, nX, aBlack );
1298 						}
1299 					}
1300 				}
1301 			}
1302 			else
1303 			{
1304 				BitmapColor aCol;
1305 				long		nR, nG, nB;
1306 				const long	nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
1307 				const long	nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
1308 				const long	nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
1309 				const long	nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
1310 				const long	nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
1311 				const long	nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
1312 
1313 				if( pReadAcc->HasPalette() )
1314 				{
1315 					for( long nY = 0L; nY < nHeight; nY++ )
1316 					{
1317 						for( long nX = 0L; nX < nWidth; nX++ )
1318 						{
1319 							aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) );
1320 							nR = aCol.GetRed();
1321 							nG = aCol.GetGreen();
1322 							nB = aCol.GetBlue();
1323 
1324 							if( nMinR <= nR && nMaxR >= nR &&
1325 								nMinG <= nG && nMaxG >= nG &&
1326 								nMinB <= nB && nMaxB >= nB )
1327 							{
1328 								pWriteAcc->SetPixel( nY, nX, aWhite );
1329 							}
1330 							else
1331 								pWriteAcc->SetPixel( nY, nX, aBlack );
1332 						}
1333 					}
1334 				}
1335 				else
1336 				{
1337 					for( long nY = 0L; nY < nHeight; nY++ )
1338 					{
1339 						for( long nX = 0L; nX < nWidth; nX++ )
1340 						{
1341 							aCol = pReadAcc->GetPixel( nY, nX );
1342 							nR = aCol.GetRed();
1343 							nG = aCol.GetGreen();
1344 							nB = aCol.GetBlue();
1345 
1346 							if( nMinR <= nR && nMaxR >= nR &&
1347 								nMinG <= nG && nMaxG >= nG &&
1348 								nMinB <= nB && nMaxB >= nB )
1349 							{
1350 								pWriteAcc->SetPixel( nY, nX, aWhite );
1351 							}
1352 							else
1353 								pWriteAcc->SetPixel( nY, nX, aBlack );
1354 						}
1355 					}
1356 				}
1357 			}
1358 
1359 			( (Bitmap*) this )->ReleaseAccess( pReadAcc );
1360 			bRet = sal_True;
1361 		}
1362 
1363 		aNewBmp.ReleaseAccess( pWriteAcc );
1364 	}
1365 
1366 	if( bRet )
1367 	{
1368 		aNewBmp.maPrefSize = maPrefSize;
1369 		aNewBmp.maPrefMapMode = maPrefMapMode;
1370 	}
1371 	else
1372 		aNewBmp = Bitmap();
1373 
1374 	return aNewBmp;
1375 }
1376 
1377 // ------------------------------------------------------------------
1378 
CreateRegion(const Color & rColor,const Rectangle & rRect) const1379 Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
1380 {
1381 	Region				aRegion;
1382 	Rectangle			aRect( rRect );
1383 	BitmapReadAccess*	pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
1384 
1385 	aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
1386 	aRect.Justify();
1387 
1388 	if( pReadAcc )
1389 	{
1390 		//Rectangle			aSubRect;
1391 		const long			nLeft = aRect.Left();
1392 		const long			nTop = aRect.Top();
1393 		const long			nRight = aRect.Right();
1394 		const long			nBottom = aRect.Bottom();
1395 		const BitmapColor	aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
1396 
1397 		//RectangleVector aRectangles;
1398 		//aRegion.ImplBeginAddRect();
1399 		std::vector< long > aLine;
1400 		long nYStart(nTop);
1401 		long nY(nTop);
1402 
1403 		for( ; nY <= nBottom; nY++ )
1404 		{
1405 			//aSubRect.Top() = aSubRect.Bottom() = nY;
1406 			std::vector< long > aNewLine;
1407 			long nX(nLeft);
1408 
1409 			for( ; nX <= nRight; )
1410 			{
1411 				while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
1412 					nX++;
1413 
1414 				if( nX <= nRight )
1415 				{
1416 					aNewLine.push_back(nX);
1417 					//aSubRect.Left() = nX;
1418 
1419 					while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
1420 						nX++;
1421 
1422 					//aSubRect.Right() = nX - 1L;
1423 					aNewLine.push_back(nX - 1);
1424 
1425 					//aRegion.ImplAddRect( aSubRect );
1426 					//aRectangles.push_back(aSubRect);
1427 					//aRegion.Union(aSubRect);
1428 				}
1429 			}
1430 
1431 			if(aNewLine != aLine)
1432 			{
1433 				// need to write aLine, it's different from the next line
1434 				if(aLine.size())
1435 				{
1436 					Rectangle aSubRect;
1437 
1438 					// enter y values and proceed ystart
1439 					aSubRect.Top() = nYStart;
1440 					aSubRect.Bottom() = nY ? nY - 1 : 0;
1441 
1442 					for(sal_uInt32 a(0); a < aLine.size();)
1443 					{
1444 						aSubRect.Left() = aLine[a++];
1445 						aSubRect.Right() = aLine[a++];
1446 						aRegion.Union(aSubRect);
1447 					}
1448 				}
1449 
1450 				// copy line as new line
1451 				aLine = aNewLine;
1452 				nYStart = nY;
1453 			}
1454 		}
1455 
1456 		// write last line if used
1457 		if(aLine.size())
1458 		{
1459 			Rectangle aSubRect;
1460 
1461 			// enter y values
1462 			aSubRect.Top() = nYStart;
1463 			aSubRect.Bottom() = nY ? nY - 1 : 0;
1464 
1465 			for(sal_uInt32 a(0); a < aLine.size();)
1466 			{
1467 				aSubRect.Left() = aLine[a++];
1468 				aSubRect.Right() = aLine[a++];
1469 				aRegion.Union(aSubRect);
1470 			}
1471 		}
1472 
1473 		//aRegion.ImplEndAddRect();
1474 		//aRegion.SetRegionRectangles(aRectangles);
1475 
1476 		( (Bitmap*) this )->ReleaseAccess( pReadAcc );
1477 	}
1478 	else
1479 		aRegion = aRect;
1480 
1481 	return aRegion;
1482 }
1483 
1484 // ------------------------------------------------------------------
1485 
Replace(const Bitmap & rMask,const Color & rReplaceColor)1486 sal_Bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
1487 {
1488 	BitmapReadAccess*	pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
1489 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1490 	sal_Bool				bRet = sal_False;
1491 
1492 	if( pMaskAcc && pAcc )
1493 	{
1494 		const long			nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
1495 		const long			nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
1496 		const BitmapColor	aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1497 		BitmapColor 		aReplace;
1498 
1499 		if( pAcc->HasPalette() )
1500 		{
1501 			const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount();
1502 			const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount();
1503 
1504 			// default to the nearest color
1505 			aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
1506 
1507 			// for paletted images without a matching palette entry
1508 			// look for an unused palette entry (NOTE: expensive!)
1509 			if( pAcc->GetPaletteColor( aReplace.GetIndex() ) != BitmapColor( rReplaceColor ) )
1510 			{
1511 				// if the palette has empty entries use the last one
1512 				if( nActColors < nMaxColors )
1513 				{
1514 					pAcc->SetPaletteEntryCount( nActColors + 1 );
1515 					pAcc->SetPaletteColor( nActColors, rReplaceColor );
1516 					aReplace = BitmapColor( (sal_uInt8) nActColors );
1517 				}
1518 				else
1519 				{
1520 					sal_Bool* pFlags = new sal_Bool[ nMaxColors ];
1521 
1522 					// alle Eintraege auf 0 setzen
1523 					memset( pFlags, 0, nMaxColors );
1524 
1525 					for( long nY = 0L; nY < nHeight; nY++ )
1526 						for( long nX = 0L; nX < nWidth; nX++ )
1527 							pFlags[ pAcc->GetPixelIndex( nY, nX ) ] = sal_True;
1528 
1529 					for( sal_uInt16 i = 0UL; i < nMaxColors; i++ )
1530 					{
1531 						// Hurra, wir haben einen unbenutzten Eintrag
1532 						if( !pFlags[ i ] )
1533 						{
1534 							pAcc->SetPaletteColor( (sal_uInt16) i, rReplaceColor );
1535 							aReplace = BitmapColor( (sal_uInt8) i );
1536 						}
1537 					}
1538 
1539 					delete[] pFlags;
1540 				}
1541 			}
1542 		}
1543 		else
1544 			aReplace = rReplaceColor;
1545 
1546 		for( long nY = 0L; nY < nHeight; nY++ )
1547 			for( long nX = 0L; nX < nWidth; nX++ )
1548 				if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
1549 					pAcc->SetPixel( nY, nX, aReplace );
1550 
1551 		bRet = sal_True;
1552 	}
1553 
1554 	( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
1555 	ReleaseAccess( pAcc );
1556 
1557 	return bRet;
1558 }
1559 
1560 // ------------------------------------------------------------------
1561 
Replace(const AlphaMask & rAlpha,const Color & rMergeColor)1562 sal_Bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
1563 {
1564 	Bitmap				aNewBmp( GetSizePixel(), 24 );
1565 	BitmapReadAccess*	pAcc = AcquireReadAccess();
1566 	BitmapReadAccess*	pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
1567 	BitmapWriteAccess*	pNewAcc = aNewBmp.AcquireWriteAccess();
1568 	sal_Bool				bRet = sal_False;
1569 
1570 	if( pAcc && pAlphaAcc && pNewAcc )
1571 	{
1572 		BitmapColor	aCol;
1573 		const long	nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
1574 		const long	nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
1575 
1576 		for( long nY = 0L; nY < nHeight; nY++ )
1577 		{
1578 			for( long nX = 0L; nX < nWidth; nX++ )
1579 			{
1580 				aCol = pAcc->GetColor( nY, nX );
1581 				pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - pAlphaAcc->GetPixelIndex( nY, nX ) ) );
1582 			}
1583 		}
1584 
1585 		bRet = sal_True;
1586 	}
1587 
1588 	ReleaseAccess( pAcc );
1589 	( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
1590 	aNewBmp.ReleaseAccess( pNewAcc );
1591 
1592 	if( bRet )
1593 	{
1594 		const MapMode	aMap( maPrefMapMode );
1595 		const Size		aSize( maPrefSize );
1596 
1597 		*this = aNewBmp;
1598 
1599 		maPrefMapMode = aMap;
1600 		maPrefSize = aSize;
1601 	}
1602 
1603 	return bRet;
1604 }
1605 
1606 // ------------------------------------------------------------------
1607 
Replace(const Color & rSearchColor,const Color & rReplaceColor,sal_uLong nTol)1608 sal_Bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
1609 {
1610 	// Bitmaps with 1 bit color depth can cause problems
1611 	// if they have other entries than black/white in their palette
1612 	if( 1 == GetBitCount() )
1613 		Convert( BMP_CONVERSION_4BIT_COLORS );
1614 
1615 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1616 	sal_Bool				bRet = sal_False;
1617 
1618 	if( pAcc )
1619 	{
1620 		const long	nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
1621 		const long	nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
1622 		const long	nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
1623 		const long	nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
1624 		const long	nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
1625 		const long	nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
1626 
1627 		if( pAcc->HasPalette() )
1628 		{
1629 			for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
1630 			{
1631 				const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1632 
1633 				if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
1634 					nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
1635 					nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
1636 				{
1637 					pAcc->SetPaletteColor( i, rReplaceColor );
1638 				}
1639 			}
1640 		}
1641 		else
1642 		{
1643 			BitmapColor 		aCol;
1644 			const BitmapColor	aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
1645 
1646 			for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
1647 			{
1648 				for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
1649 				{
1650 					aCol = pAcc->GetPixel( nY, nX );
1651 
1652 					if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
1653 						nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
1654 						nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
1655 					{
1656 						pAcc->SetPixel( nY, nX, aReplace );
1657 					}
1658 				}
1659 			}
1660 		}
1661 
1662 		ReleaseAccess( pAcc );
1663 		bRet = sal_True;
1664 	}
1665 
1666 	return bRet;
1667 }
1668 
1669 // ------------------------------------------------------------------
1670 
Replace(const Color * pSearchColors,const Color * pReplaceColors,sal_uLong nColorCount,sal_uLong * _pTols)1671 sal_Bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
1672 					  sal_uLong nColorCount, sal_uLong* _pTols )
1673 {
1674 	// Bitmaps with 1 bit color depth can cause problems
1675 	// if they have other entries than black/white in their palette
1676 	if( 1 == GetBitCount() )
1677 		Convert( BMP_CONVERSION_4BIT_COLORS );
1678 
1679 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1680 	sal_Bool				bRet = sal_False;
1681 
1682 	if( pAcc )
1683 	{
1684 		long*	pMinR = new long[ nColorCount ];
1685 		long*	pMaxR = new long[ nColorCount ];
1686 		long*	pMinG = new long[ nColorCount ];
1687 		long*	pMaxG = new long[ nColorCount ];
1688 		long*	pMinB = new long[ nColorCount ];
1689 		long*	pMaxB = new long[ nColorCount ];
1690 		long*	pTols;
1691 		sal_uLong	i;
1692 
1693 		if( !_pTols )
1694 		{
1695 			pTols = new long[ nColorCount ];
1696 			memset( pTols, 0, nColorCount * sizeof( long ) );
1697 		}
1698 		else
1699 			pTols = (long*) _pTols;
1700 
1701 		for( i = 0UL; i < nColorCount; i++ )
1702 		{
1703 			const Color&	rCol = pSearchColors[ i ];
1704 			const long		nTol = pTols[ i ];
1705 
1706 			pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
1707 			pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
1708 			pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
1709 			pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
1710 			pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
1711 			pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
1712 		}
1713 
1714 		if( pAcc->HasPalette() )
1715 		{
1716 			for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
1717 			{
1718 				const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
1719 
1720 				for( i = 0UL; i < nColorCount; i++ )
1721 				{
1722 					if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
1723 						pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
1724 						pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
1725 					{
1726 						pAcc->SetPaletteColor( (sal_uInt16)nEntry, pReplaceColors[ i ] );
1727 						break;
1728 					}
1729 				}
1730 			}
1731 		}
1732 		else
1733 		{
1734 			BitmapColor 	aCol;
1735 			BitmapColor*	pReplaces = new BitmapColor[ nColorCount ];
1736 
1737 			for( i = 0UL; i < nColorCount; i++ )
1738 				pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
1739 
1740 			for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
1741 			{
1742 				for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
1743 				{
1744 					aCol = pAcc->GetPixel( nY, nX );
1745 
1746 					for( i = 0UL; i < nColorCount; i++ )
1747 					{
1748 						if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
1749 							pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
1750 							pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
1751 						{
1752 							pAcc->SetPixel( nY, nX, pReplaces[ i ] );
1753 							break;
1754 						}
1755 					}
1756 				}
1757 			}
1758 
1759 			delete[] pReplaces;
1760 		}
1761 
1762 		if( !_pTols )
1763 			delete[] pTols;
1764 
1765 		delete[] pMinR;
1766 		delete[] pMaxR;
1767 		delete[] pMinG;
1768 		delete[] pMaxG;
1769 		delete[] pMinB;
1770 		delete[] pMaxB;
1771 		ReleaseAccess( pAcc );
1772 		bRet = sal_True;
1773 	}
1774 
1775 	return bRet;
1776 }
1777 
1778 // ------------------------------------------------------------------
1779 
CreateDisplayBitmap(OutputDevice * pDisplay)1780 Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
1781 {
1782 	Bitmap aDispBmp( *this );
1783 
1784 	if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
1785 	{
1786 		ImpBitmap* pImpDispBmp = new ImpBitmap;
1787 
1788 		if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
1789 			aDispBmp.ImplSetImpBitmap( pImpDispBmp );
1790 		else
1791 			delete pImpDispBmp;
1792 	}
1793 
1794 	return aDispBmp;
1795 }
1796 
1797 // ------------------------------------------------------------------
1798 
GetColorTransformedBitmap(BmpColorMode eColorMode) const1799 Bitmap Bitmap::GetColorTransformedBitmap( BmpColorMode eColorMode ) const
1800 {
1801 	Bitmap  aRet;
1802 
1803 	if( BMP_COLOR_HIGHCONTRAST == eColorMode )
1804 	{
1805 		Color*  pSrcColors = NULL;
1806 		Color*  pDstColors = NULL;
1807 		sal_uLong   nColorCount = 0;
1808 
1809 		aRet = *this;
1810 
1811 		Image::GetColorTransformArrays( (ImageColorTransform) eColorMode, pSrcColors, pDstColors, nColorCount );
1812 
1813 		if( nColorCount && pSrcColors && pDstColors )
1814 			aRet.Replace( pSrcColors, pDstColors, nColorCount );
1815 
1816 		delete[] pSrcColors;
1817 		delete[] pDstColors;
1818 	}
1819 	else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode ||
1820 			 BMP_COLOR_MONOCHROME_WHITE == eColorMode )
1821 	{
1822 		aRet = *this;
1823 		aRet.MakeMono( BMP_COLOR_MONOCHROME_THRESHOLD );
1824 	}
1825 
1826 	return aRet;
1827 }
1828 
1829 // ------------------------------------------------------------------
1830 
CombineSimple(const Bitmap & rMask,BmpCombine eCombine)1831 sal_Bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
1832 {
1833 	BitmapReadAccess*	pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
1834 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1835 	sal_Bool				bRet = sal_False;
1836 
1837 	if( pMaskAcc && pAcc )
1838 	{
1839 		const long			nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
1840 		const long			nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
1841 		const Color 		aColBlack( COL_BLACK );
1842 		BitmapColor 		aPixel;
1843 		BitmapColor 		aMaskPixel;
1844 		const BitmapColor	aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1845 		const BitmapColor	aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
1846 		const BitmapColor	aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
1847 
1848 		switch( eCombine )
1849 		{
1850 			case( BMP_COMBINE_COPY ):
1851 			{
1852 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1853 				{
1854 					if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
1855 						pAcc->SetPixel( nY, nX, aBlack );
1856 					else
1857 						pAcc->SetPixel( nY, nX, aWhite );
1858 				}
1859 			}
1860 			break;
1861 
1862 			case( BMP_COMBINE_INVERT ):
1863 			{
1864 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1865 				{
1866 					if( pAcc->GetPixel( nY, nX ) == aBlack )
1867 						pAcc->SetPixel( nY, nX, aWhite );
1868 					else
1869 						pAcc->SetPixel( nY, nX, aBlack );
1870 				}
1871 			}
1872 			break;
1873 
1874 			case( BMP_COMBINE_AND ):
1875 			{
1876 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1877 				{
1878 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
1879 						pAcc->SetPixel( nY, nX, aWhite );
1880 					else
1881 						pAcc->SetPixel( nY, nX, aBlack );
1882 				}
1883 			}
1884 			break;
1885 
1886 			case( BMP_COMBINE_NAND ):
1887 			{
1888 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1889 				{
1890 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
1891 						pAcc->SetPixel( nY, nX, aBlack );
1892 					else
1893 						pAcc->SetPixel( nY, nX, aWhite );
1894 				}
1895 			}
1896 			break;
1897 
1898 			case( BMP_COMBINE_OR ):
1899 			{
1900 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1901 				{
1902 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
1903 						pAcc->SetPixel( nY, nX, aWhite );
1904 					else
1905 						pAcc->SetPixel( nY, nX, aBlack );
1906 				}
1907 			}
1908 			break;
1909 
1910 			case( BMP_COMBINE_NOR ):
1911 			{
1912 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1913 				{
1914 					if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
1915 						pAcc->SetPixel( nY, nX, aBlack );
1916 					else
1917 						pAcc->SetPixel( nY, nX, aWhite );
1918 				}
1919 			}
1920 			break;
1921 
1922 			case( BMP_COMBINE_XOR ):
1923 			{
1924 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1925 				{
1926 					aPixel = pAcc->GetPixel( nY, nX );
1927 					aMaskPixel = pMaskAcc->GetPixel( nY, nX );
1928 
1929 					if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
1930 						( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
1931 					{
1932 						pAcc->SetPixel( nY, nX, aWhite );
1933 					}
1934 					else
1935 						pAcc->SetPixel( nY, nX, aBlack );
1936 				}
1937 			}
1938 			break;
1939 
1940 			case( BMP_COMBINE_NXOR ):
1941 			{
1942 				for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1943 				{
1944 					aPixel = pAcc->GetPixel( nY, nX );
1945 					aMaskPixel = pMaskAcc->GetPixel( nY, nX );
1946 
1947 					if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
1948 						( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
1949 					{
1950 						pAcc->SetPixel( nY, nX, aBlack );
1951 					}
1952 					else
1953 						pAcc->SetPixel( nY, nX, aWhite );
1954 				}
1955 			}
1956 			break;
1957 		}
1958 
1959 		bRet = sal_True;
1960 	}
1961 
1962 	( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
1963 	ReleaseAccess( pAcc );
1964 
1965 	return bRet;
1966 }
1967 
1968 // ------------------------------------------------------------------
1969 
Blend(const AlphaMask & rAlpha,const Color & rBackgroundColor)1970 sal_Bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor )
1971 {
1972 	// TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
1973 	// optimizations. Might even consolidate the code here and there.
1974 
1975 	// convert to a truecolor bitmap, if we're a paletted one. There's
1976 	// room for tradeoff decision here, maybe later for an overload (or a flag)
1977 	if( GetBitCount() <= 8 )
1978 		Convert( BMP_CONVERSION_24BIT );
1979 
1980 	BitmapReadAccess*	pAlphaAcc = const_cast<AlphaMask&>(rAlpha).AcquireReadAccess();
1981 	BitmapWriteAccess*	pAcc = AcquireWriteAccess();
1982 	sal_Bool				bRet = sal_False;
1983 
1984 	if( pAlphaAcc && pAcc )
1985 	{
1986 		const long			nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
1987 		const long			nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
1988 
1989 		for( long nY = 0L; nY < nHeight; ++nY )
1990 			for( long nX = 0L; nX < nWidth; ++nX )
1991 				pAcc->SetPixel( nY, nX,
1992 								pAcc->GetPixel( nY, nX ).Merge( rBackgroundColor,
1993 																255 - pAlphaAcc->GetPixelIndex( nY, nX ) ) );
1994 
1995 		bRet = sal_True;
1996 	}
1997 
1998 	const_cast<AlphaMask&>(rAlpha).ReleaseAccess( pAlphaAcc );
1999 	ReleaseAccess( pAcc );
2000 
2001 	return bRet;
2002 }
2003 
2004 // ------------------------------------------------------------------
2005 
MakeMono(sal_uInt8 cThreshold)2006 sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold )
2007 {
2008 	return ImplMakeMono( cThreshold );
2009 }
2010 
2011 // ------------------------------------------------------------------
2012 
GetSystemData(BitmapSystemData & rData) const2013 bool Bitmap::GetSystemData( BitmapSystemData& rData ) const
2014 {
2015 	bool bRet = false;
2016 	if( mpImpBmp )
2017 	{
2018 		SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap();
2019 		if( pSalBitmap )
2020 			bRet = pSalBitmap->GetSystemData( rData );
2021 	}
2022 
2023 	return bRet;
2024 }
2025 
2026 /* vim: set noet sw=4 ts=4: */
2027